Skip to content

Commit

Permalink
Add utility requireModule getImportSpecifiers (#781)
Browse files Browse the repository at this point in the history
  • Loading branch information
trivikr authored Feb 28, 2024
1 parent e1d5beb commit bee398b
Show file tree
Hide file tree
Showing 20 changed files with 172 additions and 139 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-hounds-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"aws-sdk-js-codemod": patch
---

Add utility requireModule getImportSpecifiers
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "jscodeshift";
import { DOCUMENT_CLIENT, DYNAMODB, OBJECT_PROPERTY_TYPE_LIST } from "../config";
import { ImportType } from "../modules";
import { getRequireDeclarators } from "../modules/requireModule";
import { getClientDeepImportPath } from "../utils";

export const getNodesWithDocClientNamedImportFromDeepPath = (
Expand All @@ -17,14 +18,7 @@ export const getNodesWithDocClientNamedImportFromDeepPath = (
const deepImportPath = getClientDeepImportPath(DYNAMODB);

if (importType === ImportType.REQUIRE) {
return source
.find(j.VariableDeclarator, {
init: {
type: "CallExpression",
callee: { type: "Identifier", name: "require" },
arguments: [{ value: deepImportPath }],
},
})
return getRequireDeclarators(j, source, deepImportPath)
.filter(
(variableDeclarator) =>
variableDeclarator.value.id.type === "ObjectPattern" &&
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import {
Collection,
Identifier,
JSCodeshift,
ObjectPattern,
ObjectProperty,
Property,
} from "jscodeshift";
import { Collection, JSCodeshift } from "jscodeshift";

import { CLIENT_NAMES, OBJECT_PROPERTY_TYPE_LIST, PACKAGE_NAME } from "../config";
import { getRequireDeclaratorsWithProperty } from "../modules";
import { CLIENT_NAMES, PACKAGE_NAME } from "../config";
import { ImportSpecifierDefault, ImportSpecifierPattern } from "../modules";
import { getImportSpecifiers } from "../modules/requireModule";
import { getClientDeepImportPath } from "../utils";
import { getRequireIds } from "./getRequireIds";

export const getClientNamesRecordFromRequire = (
j: JSCodeshift,
Expand All @@ -19,51 +12,23 @@ export const getClientNamesRecordFromRequire = (
) => {
const clientNamesRecord: Record<string, string> = {};

const idPropertiesFromObjectPattern = getRequireIds(j, source, PACKAGE_NAME)
.filter((id) => id.type === "ObjectPattern")
.map((objectPattern) => (objectPattern as ObjectPattern).properties)
.flat();
const idPropertiesFromObjectPattern = getImportSpecifiers(j, source, PACKAGE_NAME).filter(
(importSpecifier) => typeof importSpecifier === "object"
) as ImportSpecifierPattern[];

for (const idProperty of idPropertiesFromObjectPattern) {
if (!OBJECT_PROPERTY_TYPE_LIST.includes(idProperty.type)) {
continue;
}
const key = (idProperty as Property | ObjectProperty).key;
const value = (idProperty as Property | ObjectProperty).value;
if (key.type !== "Identifier" || value.type !== "Identifier") {
continue;
}
if (CLIENT_NAMES.includes(key.name)) {
clientNamesRecord[key.name] = value.name;
}
}

const declaratorsWithProperty = getRequireDeclaratorsWithProperty(j, source, {
sourceValue: PACKAGE_NAME,
}).nodes();

for (const declaratorWithProperty of declaratorsWithProperty) {
const { id, init } = declaratorWithProperty;
if (
id.type === "Identifier" &&
init != undefined &&
init.type === "MemberExpression" &&
init.property.type === "Identifier"
) {
const clientName = (init.property as Identifier).name;
if (CLIENT_NAMES.includes(clientName)) {
clientNamesRecord[clientName] = (id as Identifier).name;
}
for (const { importedName, localName } of idPropertiesFromObjectPattern) {
if (CLIENT_NAMES.includes(importedName)) {
clientNamesRecord[importedName] = localName || importedName;
}
}

for (const clientName of clientNamesFromDeepImport) {
const deepImportPath = getClientDeepImportPath(clientName);
const idsFromDefaultImport = getRequireIds(j, source, deepImportPath).filter(
(id) => id.type === "Identifier"
);
const idsFromDefaultImport = getImportSpecifiers(j, source, deepImportPath).filter(
(importSpecifier) => typeof importSpecifier === "string"
) as ImportSpecifierDefault[];
if (idsFromDefaultImport.length) {
clientNamesRecord[clientName] = (idsFromDefaultImport[0] as Identifier).name;
clientNamesRecord[clientName] = idsFromDefaultImport[0];
}
}

Expand Down
13 changes: 0 additions & 13 deletions src/transforms/v2-to-v3/client-names/getRequireIds.ts

This file was deleted.

12 changes: 3 additions & 9 deletions src/transforms/v2-to-v3/modules/getGlobalNameFromModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,14 @@ import { Collection, Identifier, JSCodeshift } from "jscodeshift";
import { PACKAGE_NAME } from "../config";
import { getImportEqualsDeclarationType } from "./getImportEqualsDeclarationType";
import { getImportSpecifiers } from "./getImportSpecifiers";
import { getRequireDeclarators } from "./requireModule";

export const getGlobalNameFromModule = (
j: JSCodeshift,
source: Collection<unknown>
): string | undefined => {
const requireIdentifiers = source
.find(j.VariableDeclarator, {
id: { type: "Identifier" },
init: {
type: "CallExpression",
callee: { type: "Identifier", name: "require" },
arguments: [{ value: PACKAGE_NAME }],
},
})
const requireIdentifiers = getRequireDeclarators(j, source, PACKAGE_NAME)
.filter((declarator) => declarator.value.id.type === "Identifier")
.nodes();

if (requireIdentifiers.length > 0) {
Expand Down
11 changes: 0 additions & 11 deletions src/transforms/v2-to-v3/modules/getImportSpecifier.ts

This file was deleted.

15 changes: 0 additions & 15 deletions src/transforms/v2-to-v3/modules/getRequireDeclarators.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Collection, JSCodeshift } from "jscodeshift";

import { getRequireDeclarators } from "./getRequireDeclarators";
import { getRequireDeclarators } from "./requireModule";

export interface GetRequireDeclaratorsWithIdentifier {
identifierName: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Collection, JSCodeshift, ObjectProperty, Property } from "jscodeshift";

import { OBJECT_PROPERTY_TYPE_LIST } from "../config";
import { getRequireDeclarators } from "./getRequireDeclarators";
import { getRequireDeclarators } from "./requireModule";

export interface GetRequireDeclaratorsWithObjectPattern {
identifierName: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Collection, JSCodeshift } from "jscodeshift";
import { Collection, Identifier, JSCodeshift } from "jscodeshift";
import { getRequireDeclarators } from "./requireModule";

export interface GetRequireDeclaratorsWithPropertyOptions {
localName?: string;
Expand All @@ -11,15 +12,19 @@ export const getRequireDeclaratorsWithProperty = (
source: Collection<unknown>,
{ localName, identifierName, sourceValue }: GetRequireDeclaratorsWithPropertyOptions
) =>
source.find(j.VariableDeclarator, {
id: { type: "Identifier", ...(localName && { name: localName }) },
init: {
type: "MemberExpression",
object: {
type: "CallExpression",
callee: { type: "Identifier", name: "require" },
arguments: [{ value: sourceValue }],
},
property: { type: "Identifier", ...(identifierName && { name: identifierName }) },
},
getRequireDeclarators(j, source, sourceValue).filter((varDeclarator) => {
const declaratorId = varDeclarator.value.id;
const declaratorInit = varDeclarator.value.init;

if (declaratorId.type === "Identifier") {
const declaratorIdName = declaratorId.name;
if (declaratorInit!.type === "MemberExpression") {
const importedName = (declaratorInit.property as Identifier).name;
if (localName === declaratorIdName && identifierName === importedName) {
return true;
}
}
}

return false;
});
4 changes: 2 additions & 2 deletions src/transforms/v2-to-v3/modules/getRequireProperty.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { JSCodeshift } from "jscodeshift";

import { ImportSpecifierOptions } from "./types";
import { ImportSpecifierPattern } from "./types";

export const getRequireProperty = (
j: JSCodeshift,
{ importedName, localName }: ImportSpecifierOptions
{ importedName, localName }: ImportSpecifierPattern
) =>
j.objectProperty.from({
key: j.identifier(importedName),
Expand Down
14 changes: 3 additions & 11 deletions src/transforms/v2-to-v3/modules/hasRequire.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { Collection, JSCodeshift, Literal } from "jscodeshift";
import { PACKAGE_NAME } from "../config";
import { Collection, JSCodeshift } from "jscodeshift";
import { getRequireDeclarators } from "./requireModule";

export const hasRequire = (j: JSCodeshift, source: Collection<unknown>) =>
source
.find(j.CallExpression, {
callee: { type: "Identifier", name: "require" },
})
.filter((callExpression) => {
const { value: sourceValue } = callExpression.value.arguments[0] as Literal;
return typeof sourceValue === "string" && sourceValue.startsWith(PACKAGE_NAME);
})
.size() > 0;
getRequireDeclarators(j, source).size() > 0;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
} from "jscodeshift";

import { OBJECT_PROPERTY_TYPE_LIST, PACKAGE_NAME } from "../../config";
import { getImportSpecifier } from "../getImportSpecifier";
import { getImportSpecifiers } from "../getImportSpecifiers";
import { getRequireProperty } from "../getRequireProperty";
import { importSpecifierCompareFn } from "../importSpecifierCompareFn";
Expand Down Expand Up @@ -101,15 +100,17 @@ export const addNamedModule = (
// Add named import to the first import declaration.
const firstImportDeclSpecifiers = importDeclarations.nodes()[0].specifiers;
if (firstImportDeclSpecifiers) {
firstImportDeclSpecifiers.push(getImportSpecifier(j, { importedName, localName }));
firstImportDeclSpecifiers.push(
j.importSpecifier(j.identifier(importedName), j.identifier(localName))
);
firstImportDeclSpecifiers.sort(importSpecifierCompareFn);
return;
}
}

// Build a new import declaration.
const v3ImportDeclaration = j.importDeclaration(
[getImportSpecifier(j, { importedName, localName })],
[j.importSpecifier(j.identifier(importedName), j.identifier(localName))],
j.stringLiteral(packageName)
);

Expand Down
2 changes: 2 additions & 0 deletions src/transforms/v2-to-v3/modules/removeRequireIdentifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export interface RemoveRequireIdentifierOptions {
sourceValue: string;
}

// ToDo: Write generic utility to remove unused modules
// Similar to https://github.com/aws/aws-sdk-js-codemod/pull/781
export const removeRequireIdentifier = (
j: JSCodeshift,
source: Collection<unknown>,
Expand Down
2 changes: 2 additions & 0 deletions src/transforms/v2-to-v3/modules/removeRequireProperty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export interface RemoveRequireObjectPropertyOptions {
sourceValue: string;
}

// ToDo: Write generic utility to remove unused modules
// Similar to https://github.com/aws/aws-sdk-js-codemod/pull/781
export const removeRequireProperty = (
j: JSCodeshift,
source: Collection<unknown>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import {
} from "jscodeshift";

import { OBJECT_PROPERTY_TYPE_LIST, PACKAGE_NAME, STRING_LITERAL_TYPE_LIST } from "../../config";
import { getRequireDeclarators } from "../getRequireDeclarators";
import { getRequireProperty } from "../getRequireProperty";
import { objectPatternPropertyCompareFn } from "../objectPatternPropertyCompareFn";
import { getRequireDeclarators } from "../requireModule";
import { ModulesOptions } from "../types";

export const addNamedModule = (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Collection, Identifier, JSCodeshift, ObjectProperty, Property } from "jscodeshift";
import { OBJECT_PROPERTY_TYPE_LIST } from "../../config";
import { ImportSpecifierPattern, ImportSpecifierType } from "../types";
import { getRequireDeclarators } from "./getRequireDeclarators";

const getImportSpecifiersFromObjectPattern = (properties: (Property | ObjectProperty)[]) => {
const importSpecifiers = new Set<ImportSpecifierPattern>();

for (const property of properties) {
if (!OBJECT_PROPERTY_TYPE_LIST.includes(property.type)) {
continue;
}
const objectProperty = property as Property | ObjectProperty;
const key = objectProperty.key;
const value = objectProperty.value;
if (key.type === "Identifier" && value.type === "Identifier") {
importSpecifiers.add({
importedName: key.name,
localName: value.name,
});
}
}

return Array.from(importSpecifiers);
};

export const getImportSpecifiers = (
j: JSCodeshift,
source: Collection<unknown>,
path?: string
): ImportSpecifierType[] => {
const importSpecifiers = new Set<ImportSpecifierType>();

for (const varDeclarator of getRequireDeclarators(j, source, path).nodes()) {
const declaratorId = varDeclarator.id;
const declaratorInit = varDeclarator.init;

if (declaratorId.type === "Identifier") {
const declaratorIdName = declaratorId.name;
if (declaratorInit!.type === "MemberExpression") {
importSpecifiers.add({
importedName: (declaratorInit.property as Identifier).name,
localName: declaratorIdName,
});
} else {
importSpecifiers.add(declaratorIdName);
}
}

if (declaratorId.type === "ObjectPattern") {
if (declaratorInit!.type !== "CallExpression") {
continue;
}
const properties = declaratorId.properties as (Property | ObjectProperty)[];
for (const importSpecifier of getImportSpecifiersFromObjectPattern(properties)) {
importSpecifiers.add(importSpecifier);
}
}
}

return Array.from(importSpecifiers);
};
Loading

0 comments on commit bee398b

Please sign in to comment.