diff --git a/packages/dev/codemods/package.json b/packages/dev/codemods/package.json
index e592eba0da1..18b2aaf2f65 100644
--- a/packages/dev/codemods/package.json
+++ b/packages/dev/codemods/package.json
@@ -33,6 +33,7 @@
"execa": "^5.1.1",
"jscodeshift": "^0.15.2",
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0",
+ "recast": "^0.23.9",
"ts-node": "^10.9.2",
"uuid": "^9.0.1"
},
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/imports.test.ts.snap b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/imports.test.ts.snap
index 46729b75825..4b07144fd42 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/imports.test.ts.snap
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/imports.test.ts.snap
@@ -92,7 +92,7 @@ exports[`should preserve leading comment if first line is removed 1`] = `
"/*
* Some comment
*/
-import { StatusLight } from "@react-spectrum/s2";
+import { Button, StatusLight } from "@react-spectrum/s2";
<>
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/styleProps.test.ts.snap b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/styleProps.test.ts.snap
index 6deb12d0017..a10e0dc3eb2 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/styleProps.test.ts.snap
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/__snapshots__/styleProps.test.ts.snap
@@ -225,6 +225,13 @@ import { style } from "@react-spectrum/s2/style" with { type: "macro" };
})}>Test"
`;
+exports[`Should leave existing style macros unaffected 1`] = `
+"import { TextField } from "@react-spectrum/s2";
+import { style } from "@react-spectrum/s2/style" with { type: "macro" };
+
+"
+`;
+
exports[`Updates left/right layout values to be start/end 1`] = `
"import { Button } from "@react-spectrum/s2";
import { style } from "@react-spectrum/s2/style" with { type: "macro" };
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/imports.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/imports.test.ts
index 539eb2404b7..8c6fe0ce5c5 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/imports.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/imports.test.ts
@@ -119,8 +119,7 @@ test('should preserve leading comment if first line is removed', `
/*
* Some comment
*/
-import {StatusLight} from '@adobe/react-spectrum';
-import {Button} from "@react-spectrum/s2";
+import {Button, StatusLight} from '@adobe/react-spectrum';
<>
diff --git a/packages/dev/codemods/src/s1-to-s2/__tests__/styleProps.test.ts b/packages/dev/codemods/src/s1-to-s2/__tests__/styleProps.test.ts
index 147c9b95ff6..ace130c4998 100644
--- a/packages/dev/codemods/src/s1-to-s2/__tests__/styleProps.test.ts
+++ b/packages/dev/codemods/src/s1-to-s2/__tests__/styleProps.test.ts
@@ -199,3 +199,10 @@ import {Button, Flex} from '@adobe/react-spectrum';
>
`);
+
+test('Should leave existing style macros unaffected', `
+import { TextField } from "@react-spectrum/s2";
+import { style } from "@react-spectrum/s2/style" with { type: "macro" };
+
+
+`);
diff --git a/packages/dev/codemods/src/s1-to-s2/src/codemods/codemod.ts b/packages/dev/codemods/src/s1-to-s2/src/codemods/codemod.ts
index 14a7a623ed6..e46144e991c 100644
--- a/packages/dev/codemods/src/s1-to-s2/src/codemods/codemod.ts
+++ b/packages/dev/codemods/src/s1-to-s2/src/codemods/codemod.ts
@@ -5,6 +5,7 @@ import {changes as changesJSON} from './changes';
import {functionMap} from './transforms';
import {getComponents} from '../getComponents';
import {iconMap} from '../iconMap';
+import {parse as recastParse} from 'recast';
import * as t from '@babel/types';
import {transformStyleProps} from './styleProps';
import traverse, {Binding, NodePath} from '@babel/traverse';
@@ -32,7 +33,13 @@ interface Options {
}
export default function transformer(file: FileInfo, api: API, options: Options) {
- let j = api.jscodeshift;
+ let j = api.jscodeshift.withParser({
+ parse(source: string) {
+ return recastParse(source, {
+ parser: require('recast/parsers/babel')
+ });
+ }
+ });
let root = j(file.source);
let componentsToTransform = options.components ? new Set(options.components.split(',').filter(s => availableComponents.has(s))) : availableComponents;
@@ -44,7 +51,7 @@ export default function transformer(file: FileInfo, api: API, options: Options)
const leadingComments = root.find(j.Program).get('body', 0).node.leadingComments;
traverse(root.paths()[0].node, {
ImportDeclaration(path) {
- if (path.node.source.value === '@adobe/react-spectrum' || path.node.source.value.startsWith('@react-spectrum/')) {
+ if (path.node.source.value === '@adobe/react-spectrum' || (path.node.source.value.startsWith('@react-spectrum/') && path.node.source.value !== '@react-spectrum/s2')) {
lastImportPath = path;
for (let specifier of path.node.specifiers) {
if (specifier.type === 'ImportNamespaceSpecifier') {
@@ -277,4 +284,3 @@ export default function transformer(file: FileInfo, api: API, options: Options)
return root.toSource().replace(/assert\s*\{\s*type:\s*"macro"\s*\}/g, 'with { type: "macro" }');
}
-transformer.parser = 'tsx';
diff --git a/yarn.lock b/yarn.lock
index a76d0be0397..c233f35de05 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6829,6 +6829,7 @@ __metadata:
jscodeshift: "npm:^0.15.2"
react: "npm:^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
react-dom: "npm:^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
+ recast: "npm:^0.23.9"
ts-node: "npm:^10.9.2"
typescript: "npm:^5.5.0"
uuid: "npm:^9.0.1"