Skip to content

Commit

Permalink
fix(remix-dev/cli/migrate): process named exports in `convert-to-java…
Browse files Browse the repository at this point in the history
…script` migration
  • Loading branch information
MichaelDeBoey committed Oct 14, 2022
1 parent a0823ed commit b153619
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/serious-lamps-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": patch
---

Process named exports in `convert-to-javascript` migration
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@ const checkMigrationRanSuccessfully = async (projectDir: string) => {
expect(exportDefaultResult.stdout.trim()).toBe("");
expect(exportDefaultResult.stderr).toBeNull();
expect(exportDefaultResult.code).toBe(0);
let exportClassResult = shell.grep("-l", 'export class "', JSFiles);
expect(exportClassResult.stdout.trim()).toBe("");
expect(exportClassResult.stderr).toBeNull();
expect(exportClassResult.code).toBe(0);
let exportConstResult = shell.grep("-l", 'export const "', JSFiles);
expect(exportConstResult.stdout.trim()).toBe("");
expect(exportConstResult.stderr).toBeNull();
expect(exportConstResult.code).toBe(0);
let exportFunctionResult = shell.grep("-l", 'export function "', JSFiles);
expect(exportFunctionResult.stdout.trim()).toBe("");
expect(exportFunctionResult.stderr).toBeNull();
expect(exportFunctionResult.code).toBe(0);
};

const makeApp = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const createExportExpressionStatementFromExportDefaultDeclaration = (
exportDefaultDeclaration.declaration.type === "ExportDeclaration" ||
exportDefaultDeclaration.declaration.type === "ExportDefaultDeclaration" ||
exportDefaultDeclaration.declaration.type === "ExportNamedDeclaration" ||
exportDefaultDeclaration.declaration.type === "FunctionDeclaration" ||
exportDefaultDeclaration.declaration.type === "ImportDeclaration" ||
exportDefaultDeclaration.declaration.type === "InterfaceDeclaration" ||
exportDefaultDeclaration.declaration.type === "MethodDefinition" ||
Expand Down Expand Up @@ -68,9 +67,9 @@ export const createExportExpressionStatementFromExportDefaultDeclaration = (
let expressionKind =
exportDefaultDeclaration.declaration.type === "ClassDeclaration"
? j.classExpression.from(exportDefaultDeclaration.declaration)
: // : exportDefaultDeclaration.declaration.type === "FunctionDeclaration"
// ? j.functionExpression.from(exportDefaultDeclaration.declaration)
exportDefaultDeclaration.declaration;
: exportDefaultDeclaration.declaration.type === "FunctionDeclaration"
? j.functionExpression.from(exportDefaultDeclaration.declaration)
: exportDefaultDeclaration.declaration;
return j.expressionStatement(
j.assignmentExpression(
"=",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import type {
ClassDeclaration,
ExportNamedDeclaration,
FunctionDeclaration,
JSCodeshift,
VariableDeclaration,
} from "jscodeshift";

/**
* export class Foo {}
* export const foo = bar
* export function foo() {}
* =>
* module.Foo = class Foo {}
* module.foo = bar
* module.foo = function foo() {}
*/
export const createExportExpressionStatementFromExportNamedDeclaration = (
j: JSCodeshift,
exportNamedDeclaration: ExportNamedDeclaration
) => {
/**
* HACK: Can't use casts nor type guards in a `jscodeshift` transform
* https://github.com/facebook/jscodeshift/issues/467
*
* So to narrow declaration type, we check it against convertable values
* instead.
*/
if (
!(
exportNamedDeclaration.declaration?.type === "ClassDeclaration" ||
exportNamedDeclaration.declaration?.type === "FunctionDeclaration" ||
exportNamedDeclaration.declaration?.type === "VariableDeclaration"
)
) {
return exportNamedDeclaration;
}

// export class Foo {}
if (exportNamedDeclaration.declaration.type === "ClassDeclaration") {
return createExportExpressionStatementFromExportNamedClassDeclaration(
j,
exportNamedDeclaration.declaration
);
}

// export function foo() {}
if (exportNamedDeclaration.declaration.type === "FunctionDeclaration") {
return createExportExpressionStatementFromExportNamedFunctionDeclaration(
j,
exportNamedDeclaration.declaration
);
}

// export const foo = bar
if (exportNamedDeclaration.declaration.type === "VariableDeclaration") {
return createExportExpressionStatementFromExportNamedVariableDeclaration(
j,
exportNamedDeclaration.declaration
);
}
};

/**
* export class Foo {}
* =>
* module.Foo = class Foo {}
*/
const createExportExpressionStatementFromExportNamedClassDeclaration = (
j: JSCodeshift,
classDeclaration: ClassDeclaration
) =>
j.expressionStatement(
j.assignmentExpression(
"=",
j.memberExpression(
j.identifier("module"),
classDeclaration.id || j.identifier("")
),
j.classExpression.from(classDeclaration)
)
);

/**
* export function foo() {}
* =>
* module.foo = function foo() {}
*/
const createExportExpressionStatementFromExportNamedFunctionDeclaration = (
j: JSCodeshift,
functionDeclaration: FunctionDeclaration
) =>
j.expressionStatement(
j.assignmentExpression(
"=",
j.memberExpression(
j.identifier("module"),
functionDeclaration.id || j.identifier("")
),
j.functionExpression.from(functionDeclaration)
)
);

/**
* export const foo = bar
* export const foo = 5
* export const foo = []
* export const foo = function foo(){}
* =>
* module.foo = bar
* module.foo = 5
* module.foo = []
* module.foo = function foo(){}
*/
const createExportExpressionStatementFromExportNamedVariableDeclaration = (
j: JSCodeshift,
variableDeclaration: VariableDeclaration
) =>
variableDeclaration.declarations.flatMap((declaration) => {
/**
* HACK: Can't use casts nor type guards in a `jscodeshift` transform
* https://github.com/facebook/jscodeshift/issues/467
*
* So to narrow declaration id type, we check it against convertable values
* instead.
*/
if (
declaration.type !== "VariableDeclarator" ||
declaration.id.type === "ArrayPattern" ||
declaration.id.type === "AssignmentPattern" ||
declaration.id.type === "ObjectPattern" ||
declaration.id.type === "PropertyPattern" ||
declaration.id.type === "RestElement" ||
declaration.id.type === "SpreadElementPattern" ||
declaration.id.type === "SpreadPropertyPattern" ||
declaration.id.type === "TSParameterProperty" ||
!declaration.init
) {
return [];
}

return j.expressionStatement(
j.assignmentExpression(
"=",
j.memberExpression(j.identifier("module"), declaration.id),
declaration.init
)
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Transform } from "jscodeshift";

import { checkNoDifferentImportTypesCombined } from "./checkNoDifferentImportTypesCombined";
import { createExportExpressionStatementFromExportDefaultDeclaration } from "./createExportExpressionStatementFromExportDefaultDeclaration";
import { createExportExpressionStatementFromExportNamedDeclaration } from "./createExportExpressionStatementFromExportNamedDeclaration";
import { createImportExpressionStatement } from "./createImportExpressionStatement";
import { createVariableDeclarationIdentifier } from "./createVariableDeclarationIdentifier";
import { createVariableDeclarationObjectPattern } from "./createVariableDeclarationObjectPattern";
Expand All @@ -12,9 +13,11 @@ const transform: Transform = (file, api, options) => {

let allImportDeclarations = root.find(j.ImportDeclaration);
let allExportDefaultDeclarations = root.find(j.ExportDefaultDeclaration);
let allExportNamedDeclarations = root.find(j.ExportNamedDeclaration);
if (
allImportDeclarations.length === 0 &&
allExportDefaultDeclarations.length === 0
allExportDefaultDeclarations.length === 0 &&
allExportNamedDeclarations.length === 0
) {
// This transform doesn't need to run if there are no ES imports/exports
return null;
Expand Down Expand Up @@ -68,6 +71,16 @@ const transform: Transform = (file, api, options) => {
);
});

allExportNamedDeclarations.forEach((exportNamedDeclaration) => {
// export class Foo {} || export const foo = bar || export function foo() {}
j(exportNamedDeclaration).replaceWith(
createExportExpressionStatementFromExportNamedDeclaration(
j,
exportNamedDeclaration.node
)
);
});

// If the first node has been modified or deleted, reattach the comments
let newFirstNode = getFirstNode();
if (newFirstNode !== oldFirstNode) {
Expand Down

0 comments on commit b153619

Please sign in to comment.