From 010ef00a423f0d18eafb67cd211be26c6516c35d Mon Sep 17 00:00:00 2001 From: meixg Date: Thu, 15 Oct 2020 15:22:35 +0800 Subject: [PATCH] fix: imported function report unsupport --- src/emitter.ts | 33 ++++++++++++++------------------- src/features/global.ts | 11 +++++++---- src/utilities/nodeTest.ts | 10 ++++++++++ test/features/GlobalApi.md | 13 +++++++++++++ test/features/helper/export.ts | 2 ++ 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/emitter.ts b/src/emitter.ts index 3be2179..c4cdb0a 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -44,7 +44,8 @@ import { isClassInstance, isFunctionLike, isVariable, - shouldUseReference + shouldUseReference, + isFromImport } from './utilities/nodeTest'; import {CompilerState} from './types'; @@ -3059,25 +3060,19 @@ export function emitFile( * identifier from import may need add namespace */ function emitIdentifierFromImport(node: ts.Node): boolean { - if (ts.isIdentifier(node)) { - const type = typeChecker.getTypeAtLocation(node); - const symbol = typeChecker.getSymbolAtLocation(node); - - if (symbol) { - const declarations = symbol.getDeclarations(); - - if (declarations.length && ts.isImportSpecifier(declarations[0])) { - const specifier = declarations[0] as ts.ImportSpecifier; - const declaration = specifier.parent.parent.parent as ts.ImportDeclaration; - const moduleName = declaration.moduleSpecifier.getText().replace(/^['"]/, '').replace(/['"]$/, ''); - const namespace = state.modules[moduleName] && state.modules[moduleName].namespace; - namespace && writeBase(namespace); - emitExpression(specifier.propertyName || specifier.name); - return true; - } - } - + if (!(ts.isIdentifier(node) && isFromImport(node, typeChecker))) { + return false; } + + const symbol = typeChecker.getSymbolAtLocation(node); + const declarations = symbol.getDeclarations(); + const specifier = declarations[0] as ts.ImportSpecifier; + const declaration = specifier.parent.parent.parent as ts.ImportDeclaration; + const moduleName = declaration.moduleSpecifier.getText().replace(/^['"]/, '').replace(/['"]$/, ''); + const namespace = state.modules[moduleName] && state.modules[moduleName].namespace; + namespace && writeBase(namespace); + emitExpression(specifier.propertyName || specifier.name); + return true; } // function commitPendingSemicolonInternal() { diff --git a/src/features/global.ts b/src/features/global.ts index 7bab0f9..aeb3881 100644 --- a/src/features/global.ts +++ b/src/features/global.ts @@ -3,7 +3,7 @@ * @author cxtom(cxtom2008@gmail.com) */ -import { +import ts, { EmitHint, isCallExpression, isPropertyAccessExpression, @@ -26,6 +26,8 @@ import { createDiagnostic, getUnSupportedMessage } from '../utilities/error'; +import { isFromImport } from '../utilities/nodeTest'; +import { CompilerState } from '../types'; const map = { parseInt: method('intval', { @@ -75,8 +77,9 @@ const isDynamicImport = node => isCallExpression(node) && node.expression.kind = export default { - emit(hint, node, state) { + emit(hint: ts.EmitHint, node: ts.Node, state: CompilerState) { + // @ts-ignore const expNode = node.expression; let func; @@ -87,7 +90,7 @@ export default { if (func) { return func(node, helpers, {helperNamespace}); } - if (unSupportedGlobalMethods.has(expNode.escapedText)) { + if (!isFromImport(expNode, state.typeChecker) && unSupportedGlobalMethods.has(expNode.escapedText)) { state.errors.push(createDiagnostic( node, state.sourceFile, getUnSupportedMessage(expNode.escapedText) @@ -141,7 +144,7 @@ export default { } if (isDynamicImport(node)) { - const argu = node.arguments[0]; + const argu = (node as ts.CallExpression).arguments[0]; if (isStringLiteral(argu)) { const moduleName = argu.text; const moduleIt = modules[moduleName]; diff --git a/src/utilities/nodeTest.ts b/src/utilities/nodeTest.ts index f186643..4bbbe61 100644 --- a/src/utilities/nodeTest.ts +++ b/src/utilities/nodeTest.ts @@ -240,3 +240,13 @@ export function isRegExp(node: ts.Node, typeChecker: ts.TypeChecker) { const nodeType = typeChecker.getTypeAtLocation(node); return nodeType.symbol?.getEscapedName() === 'RegExp'; } + +export function isFromImport(node: ts.Node, typeChecker: ts.TypeChecker) { + const symbol = typeChecker.getSymbolAtLocation(node); + if (!symbol) { + return false; + } + + const declarations = symbol.getDeclarations(); + return declarations.length && ts.isImportSpecifier(declarations[0]); +} diff --git a/test/features/GlobalApi.md b/test/features/GlobalApi.md index 731624b..051a1c3 100644 --- a/test/features/GlobalApi.md +++ b/test/features/GlobalApi.md @@ -73,4 +73,17 @@ const h = __filename; ```php $g = dirname(__FILE__); $h = __FILE__; +``` + +## escape + +```ts +import {escape} from './helper/export'; + +escape(); +``` + +```php +require_once(dirname(__FILE__) . '/' . "./helper/export.php"); +\someModule\escape(); ``` \ No newline at end of file diff --git a/test/features/helper/export.ts b/test/features/helper/export.ts index c8783fa..53e63d8 100644 --- a/test/features/helper/export.ts +++ b/test/features/helper/export.ts @@ -4,3 +4,5 @@ export default function run(a: string) { } export {Some_Utils} from './some-utils'; + +export function escape() {}