From a80f7b6621eab87b30c6fe3c5041d164b30a65db Mon Sep 17 00:00:00 2001 From: Hajime-san Date: Sat, 9 Sep 2023 14:38:17 +0900 Subject: [PATCH 1/4] fix: integrate to getResolvedStringLiteral --- src/resolve_util.ts | 61 ++++++---------------------------------- src/resolve_util_test.ts | 52 ++++++---------------------------- 2 files changed, 17 insertions(+), 96 deletions(-) diff --git a/src/resolve_util.ts b/src/resolve_util.ts index 9a377f0..303b411 100644 --- a/src/resolve_util.ts +++ b/src/resolve_util.ts @@ -1,19 +1,6 @@ import { path, ts } from './deps.ts'; import { relativeFilePath } from './path.ts'; -type NodeLike = ts.Node | ts.Expression; - -type HasModuleSpecifierNode = ts.ImportDeclaration | ts.ExportDeclaration; - -type TokenObject = NodeLike & { - text: string; -}; - -export const isTokenObject = (node: NodeLike): node is TokenObject => { - // deno-lint-ignore no-prototype-builtins - return (node as unknown as Record).hasOwnProperty('text'); -}; - export const resolveModuleName = (args: { fileName: string; targetFileAbsPath: string; @@ -62,47 +49,15 @@ export const hasShouldResolveImportedFiles = (args: { return true; }; -type ModuleSpecifierReturnType = T extends - ts.ImportDeclaration ? string : string | undefined; - -export const getModuleSpecifier = (args: { - node: T; +export const getResolvedStringLiteral = (args: { + originalText: string; imports: ReturnType; -}): { - moduleSpecifier: ModuleSpecifierReturnType; -} => { - const { node, imports } = args; - let moduleSpecifier: ModuleSpecifierReturnType; - if (node.moduleSpecifier && isTokenObject(node.moduleSpecifier)) { - const _moduleSpecifier = node.moduleSpecifier; - moduleSpecifier = imports.find((v) => - v.original === _moduleSpecifier.text - )?.resolved ?? - _moduleSpecifier.text; - } - return { - // @ts-ignore Variable 'X' is used before being assigned. deno-ts(2454) - moduleSpecifier, - }; -}; - -export const getExpressionArguments = (args: { - node: ts.CallExpression; - imports: ReturnType; -}): { - expressionArguments: Array; -} => { - const { node, imports } = args; - const expressionArguments = node.arguments.map((argument) => { - if (isTokenObject(argument)) { - return imports.find((v) => v.original === argument.text)?.resolved ?? - argument.text; - } - }).filter((v) => typeof v !== 'undefined') as Array; - - return { - expressionArguments, - }; +}): string => { + const { originalText, imports } = args; + // trim quotes + const formattedText = originalText.slice(1, -1); + return imports.find((v) => v.original === formattedText)?.resolved ?? + formattedText; }; export type ResolvedModuleImport = { diff --git a/src/resolve_util_test.ts b/src/resolve_util_test.ts index 423133f..8e578f3 100644 --- a/src/resolve_util_test.ts +++ b/src/resolve_util_test.ts @@ -1,29 +1,15 @@ import { asserts } from './dev_deps.ts'; import { path } from './deps.ts'; import { - getExpressionArguments, - getModuleSpecifier, + getResolvedStringLiteral, hasShouldResolveImportedFiles, - isTokenObject, resolvedModules, resolveModuleName, } from './resolve_util.ts'; -import { - externalLibImportDeclaration, - localCallExpression, - localSourceImportDeclaration, - tsConfigMockObject, -} from './tests/fixture/mod.ts'; +import { tsConfigMockObject } from './tests/fixture/mod.ts'; const { assertEquals } = asserts; const __dirname = path.dirname(path.fromFileUrl(import.meta.url)); -Deno.test('isTokenObject', () => { - assertEquals( - isTokenObject(localSourceImportDeclaration.moduleSpecifier), - true, - ); -}); - Deno.test('resolveModuleName', async (t) => { await t.step('local module', () => { assertEquals( @@ -130,46 +116,26 @@ Deno.test('hasShouldResolveImportedFiles', async (t) => { }); }); -Deno.test('getModuleSpecifier', async (t) => { +Deno.test('getResolvedStringLiteral', async (t) => { await t.step('local module', () => { assertEquals( - getModuleSpecifier({ - node: localSourceImportDeclaration, + getResolvedStringLiteral({ + originalText: '"./ComponentA"', imports: [ { original: './ComponentA', resolved: './ComponentA.tsx' }, ], }), - { - moduleSpecifier: './ComponentA.tsx', - }, + './ComponentA.tsx', ); }); await t.step('node_module', () => { assertEquals( - getModuleSpecifier({ - node: externalLibImportDeclaration, + getResolvedStringLiteral({ + originalText: '\'react\'', imports: [], }), - { - moduleSpecifier: 'react', - }, - ); - }); -}); - -Deno.test('getExpressionArguments', async (t) => { - await t.step('local module', () => { - assertEquals( - getExpressionArguments({ - node: localCallExpression, - imports: [ - { original: './ComponentE', resolved: './ComponentE.tsx' }, - ], - }), - { - expressionArguments: ['./ComponentE.tsx'], - }, + 'react', ); }); }); From cbc233a3867cf33805375c7a15352deb3cb4de6f Mon Sep 17 00:00:00 2001 From: Hajime-san Date: Sat, 9 Sep 2023 14:39:56 +0900 Subject: [PATCH 2/4] fix: transform string literal --- src/transform.ts | 67 ++++++++++++++++--------------------------- src/transform_test.ts | 3 +- 2 files changed, 26 insertions(+), 44 deletions(-) diff --git a/src/transform.ts b/src/transform.ts index 4576d6c..46c93e6 100644 --- a/src/transform.ts +++ b/src/transform.ts @@ -1,7 +1,6 @@ import { ts } from './deps.ts'; import { - getExpressionArguments, - getModuleSpecifier, + getResolvedStringLiteral, ResolvedModuleImport, } from './resolve_util.ts'; import { hasUnicodeStr, unescapeUnicodeStr } from './str.ts'; @@ -42,62 +41,44 @@ const transformModuleSpecifier = ( // to // const foo = import('./foo.(ts|tsx)'); if ( - ts.isCallExpression(newNode) && - newNode.expression.kind === ts.SyntaxKind.ImportKeyword + ts.isStringLiteral(newNode) && + ts.isCallExpression(newNode.parent) && + newNode.parent.expression.kind === ts.SyntaxKind.ImportKeyword ) { - const { expressionArguments } = getExpressionArguments({ - node: newNode, + const resolvedStringLiteral = getResolvedStringLiteral({ + originalText: newNode.getText(sourceFile), imports, }); - return context.factory.updateCallExpression( - newNode, - newNode.expression, - newNode.typeArguments, - expressionArguments.map((argument) => - context.factory.createStringLiteral(argument) - ), - ); + return context.factory.createStringLiteral(resolvedStringLiteral); } + // Transform "aggregating modules" - if (ts.isExportDeclaration(newNode)) { - const { moduleSpecifier } = getModuleSpecifier({ - node: newNode, + // export { foo } from "./foo" + // to + // export { foo } from "./foo.(ts|tsx|d.ts)" + if ( + ts.isStringLiteral(newNode) && ts.isExportDeclaration(newNode.parent) + ) { + const resolvedStringLiteral = getResolvedStringLiteral({ + originalText: newNode.getText(sourceFile), imports, }); - // export { foo } from "./foo" - // to - // export { foo } from "./foo.(ts|tsx|d.ts)" - if (moduleSpecifier) { - return context.factory.updateExportDeclaration( - newNode, - newNode.modifiers, - newNode.isTypeOnly, - newNode.exportClause, - context.factory.createStringLiteral(moduleSpecifier), - newNode.assertClause, - ); - } - // - // export { foo } - return newNode; + return context.factory.createStringLiteral(resolvedStringLiteral); } + // Transform "static import" // // import { bar } from "./bar" // to // import { bar } from "./bar.(ts|tsx|d.ts)" - if (ts.isImportDeclaration(newNode)) { - const { moduleSpecifier } = getModuleSpecifier({ - node: newNode, + if ( + ts.isStringLiteral(newNode) && ts.isImportDeclaration(newNode.parent) + ) { + const resolvedStringLiteral = getResolvedStringLiteral({ + originalText: newNode.getText(sourceFile), imports, }); - return context.factory.updateImportDeclaration( - newNode, - newNode.modifiers, - newNode.importClause, - context.factory.createStringLiteral(moduleSpecifier), - newNode.assertClause, - ); + return context.factory.createStringLiteral(resolvedStringLiteral); } return newNode; }; diff --git a/src/transform_test.ts b/src/transform_test.ts index 3168a0e..e1b5db6 100644 --- a/src/transform_test.ts +++ b/src/transform_test.ts @@ -15,6 +15,7 @@ Deno.test('transform', async (t) => { `const bigIntLiterals = 0o777777777777n;\n` + `const numericSeparators = 100_000;\n`, ts.ScriptTarget.ESNext, + true, ), imports: [ { original: './ComponentA', resolved: './ComponentA.tsx' }, @@ -23,7 +24,7 @@ Deno.test('transform', async (t) => { printer: ts.createPrinter(), }), `import { ComponentA } from "./ComponentA.tsx";\n` + - `const str = "😎";\n` + + `const str = '😎';\n` + `const bigIntLiterals = 0o777777777777n;\n` + `const numericSeparators = 100_000;\n`, ); From af0869261eba5794e79fda3a32c735475ff66f92 Mon Sep 17 00:00:00 2001 From: Hajime-san Date: Sat, 9 Sep 2023 14:40:57 +0900 Subject: [PATCH 3/4] fix: should access parent node --- src/bin_internal.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin_internal.ts b/src/bin_internal.ts index 8661aed..a0c6a3f 100644 --- a/src/bin_internal.ts +++ b/src/bin_internal.ts @@ -75,6 +75,7 @@ export const main = async (args: { targetFileAbsPath, fileContent, ts.ScriptTarget.ESNext, + true, ); const result = restoreNewLine( From 3e0d95fb07092ff2a80ac3d9d0054d929afdafdd Mon Sep 17 00:00:00 2001 From: Hajime-san Date: Sat, 9 Sep 2023 14:41:51 +0900 Subject: [PATCH 4/4] feat(doc): update version --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9b79e2e..5446844 100644 --- a/README.md +++ b/README.md @@ -71,9 +71,9 @@ Please install [Deno](https://deno.land/manual@v1.30.3/getting_started/installat ## command ### remote - dry run - - `deno run --allow-env --allow-read --allow-write https://deno.land/x/module_specifier_resolver@v1.0.18/bin.ts -b=./src -c=./tsconfig.json -d` + - `deno run --allow-env --allow-read --allow-write https://deno.land/x/module_specifier_resolver@v1.0.19/bin.ts -b=./src -c=./tsconfig.json -d` - transform - - `deno run --allow-env --allow-read --allow-write https://deno.land/x/module_specifier_resolver@v1.0.18/bin.ts -b=./src -c=./tsconfig.json -r` + - `deno run --allow-env --allow-read --allow-write https://deno.land/x/module_specifier_resolver@v1.0.19/bin.ts -b=./src -c=./tsconfig.json -r` ### local - `deno task run-dry` - `deno task run`