This commit is contained in:
Dirk Baeumer 2021-05-23 18:37:19 +02:00
Родитель fe7a648d4a
Коммит cc5d7a1b26
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: DD95715335E91385
4 изменённых файлов: 94 добавлений и 8 удалений

2
.vscode/launch.json поставляемый
Просмотреть файл

@ -12,7 +12,7 @@
"stopOnEntry": false,
"args": [
"--timeout", "999999",
"-g", "Export computed property name"
"-g", "module.exports"
],
"cwd": "${workspaceRoot}/tsc-tests",

Просмотреть файл

@ -232,7 +232,7 @@ suite('Export Tests', () => {
[
'/@test/a.ts',
[
'function foo(): void { }',
'function foo(path: string): void { }',
'export = foo;'
].join(os.EOL)
],
@ -240,16 +240,16 @@ suite('Export Tests', () => {
'/@test/b.ts',
[
'import foo from "./a";',
'foo();'
'foo("p");'
].join(os.EOL)
]
]), compilerOptions);
const validate: Element[] = [
JSON.parse('{"id":14,"type":"vertex","label":"resultSet"}'),
JSON.parse('{"id":21,"type":"vertex","label":"resultSet"}'),
JSON.parse('{"id":22,"type":"edge","label":"next","outV":21,"inV":14}'),
JSON.parse('{"id":23,"type":"vertex","label":"moniker","scheme":"tsc","identifier":"a:export=","unique":"workspace","kind":"export"}'),
JSON.parse('{"id":24,"type":"edge","label":"moniker","outV":21,"inV":23}')
JSON.parse('{"id":28,"type":"vertex","label":"resultSet"}'),
JSON.parse('{"id":29,"type":"edge","label":"next","outV":28,"inV":14}'),
JSON.parse('{"id":30,"type":"vertex","label":"moniker","scheme":"tsc","identifier":"a:export=","unique":"workspace","kind":"export"}'),
JSON.parse('{"id":31,"type":"edge","label":"moniker","outV":28,"inV":30}')
];
for (const elem of validate) {
assertElement(emitter.elements.get(elem.id), elem);

45
tsc-tests/src/jsTests.ts Normal file
Просмотреть файл

@ -0,0 +1,45 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as os from 'os';
import { lsif, ts, assertElement } from './lsifs';
import { Element } from 'lsif-protocol';
suite('JavaScript Tests', () => {
const compilerOptions: ts.CompilerOptions = {
allowJs: true,
module: ts.ModuleKind.CommonJS,
target: ts.ScriptTarget.ES5,
esModuleInterop: true,
rootDir: '/@test'
};
test('module.exports', async () => {
const emitter = await lsif('/@test', new Map([
[
'/@test/a.js',
[
'module.exports = Route;',
'function Route(pppp) {',
' this.path = pppp;',
'}'
].join(os.EOL)
],
[
'/@test/b.js',
[
'const Route = require("./a");',
'new Route();'
].join(os.EOL)
]
]), compilerOptions);
const validate: Element[] = [
];
for (const elem of validate) {
assertElement(emitter.elements.get(elem.id), elem);
}
});
});

Просмотреть файл

@ -1872,7 +1872,8 @@ class Symbols {
public needsIndirectExportCheck(symbol: ts.Symbol): boolean {
const flags = ts.SymbolFlags.Property | ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.TypeAlias | ts.SymbolFlags.Interface | ts.SymbolFlags.Class;
return (symbol.getFlags() & flags) !== 0 || Symbols.isVariableDeclaration(symbol);
return (symbol.getFlags() & flags) !== 0 || Symbols.isVariableDeclaration(symbol) ||
(symbol.name === ts.InternalSymbolName.ExportEquals && (symbol.getFlags() & ts.SymbolFlags.Assignment) !== 0);
}
public isTopLevelSymbol(symbol: ts.Symbol): boolean {
@ -3423,6 +3424,9 @@ class Visitor {
case ts.SyntaxKind.ExportDeclaration:
this.doVisit(this.visitExportDeclaration, this.endVisitExportDeclaration, node as ts.ExportDeclaration);
break;
case ts.SyntaxKind.ExpressionStatement:
this.doVisit(this.visitExpressionStatement, this.endVisitExpressionStatement, node as ts.ExpressionStatement);
break;
case ts.SyntaxKind.VariableStatement:
this.doVisit(this.visitGeneric, this.endVisitGeneric, node as ts.VariableStatement);
break;
@ -3764,6 +3768,43 @@ class Visitor {
}
}
private visitExpressionStatement(_node: ts.ExpressionStatement): boolean {
return true;
}
private endVisitExpressionStatement(node: ts.ExpressionStatement): void {
// we only need to handle `module.exports = `
if (!ts.isSourceFile(node.parent) || !ts.isBinaryExpression(node.expression) || !ts.isPropertyAccessExpression(node.expression.left)) {
return;
}
const left = node.expression.left;
if (!ts.isIdentifier(left.expression) || left.expression.escapedText !== 'module' || left.name.escapedText !== 'exports') {
return;
}
// We do have module.exports =
const symbol = this.tsProject.getSymbolAtLocation(node.expression);
if (symbol === undefined) {
return;
}
// Make sure we have a symbol data;
this.dataManager.getOrCreateSymbolData(symbol);
const monikerPath = this.currentDocumentData.monikerPath;
if (monikerPath === undefined) {
return;
}
const aliasedSymbol = this.tsProject.getSymbolAtLocation(node.expression.right);
if (aliasedSymbol === undefined) {
return;
}
const aliasedSymbolData = this.dataManager.getOrCreateSymbolData(aliasedSymbol);
if (aliasedSymbolData === undefined) {
return;
}
aliasedSymbolData.changeVisibility(SymbolDataVisibility.indirectExported);
this.tsProject.exportSymbol(aliasedSymbol, monikerPath, this.tsProject.getExportSymbolName(symbol), this.currentSourceFile);
}
private visitArrayType(_node: ts.ArrayTypeNode): boolean {
return true;
}