зеркало из https://github.com/microsoft/lsif-node.git
Support exoprt as namespace
This commit is contained in:
Родитель
a38806383b
Коммит
4c9e31018d
|
@ -12,7 +12,7 @@
|
|||
"stopOnEntry": false,
|
||||
"args": [
|
||||
"--timeout", "999999",
|
||||
"-g", "JavaDoc"
|
||||
"-g", "Export\\ as\\ namespace"
|
||||
|
||||
],
|
||||
"cwd": "${workspaceRoot}/tsc-tests",
|
||||
|
|
|
@ -865,6 +865,40 @@ suite('Export Tests', () => {
|
|||
assertElement(emitter.elements.get(elem.id), elem);
|
||||
}
|
||||
});
|
||||
|
||||
test('Export as namespace', async () => {
|
||||
const emitter = await lsif('/@test', new Map([
|
||||
[
|
||||
'/@test/a.d.ts',
|
||||
[
|
||||
'export as namespace M;',
|
||||
'export = M;',
|
||||
'declare namespace M {',
|
||||
' function foo(): void;',
|
||||
'}'
|
||||
].join(os.EOL)
|
||||
],
|
||||
[
|
||||
'/@test/b.ts',
|
||||
[
|
||||
'import * as a from "./a";',
|
||||
'console.log(a.foo)'
|
||||
].join(os.EOL)
|
||||
]
|
||||
]), { });
|
||||
assert.deepEqual(emitter.lastId, 146);
|
||||
const validate: Element[] = [
|
||||
JSON.parse('{"id":23,"type":"vertex","label":"moniker","scheme":"tsc","identifier":":M","unique":"workspace","kind":"export"}'),
|
||||
JSON.parse('{"id":36,"type":"vertex","label":"moniker","scheme":"tsc","identifier":":M.foo","unique":"workspace","kind":"export"}'),
|
||||
JSON.parse('{"id":37,"type":"edge","label":"attach","outV":36,"inV":30}'),
|
||||
JSON.parse('{"id":40,"type":"vertex","label":"moniker","scheme":"tsc","identifier":"a:export=","unique":"workspace","kind":"export"}'),
|
||||
JSON.parse('{"id":44,"type":"vertex","label":"moniker","scheme":"tsc","identifier":"a:export=.foo","unique":"workspace","kind":"export"}'),
|
||||
JSON.parse('{"id":45,"type":"edge","label":"attach","outV":44,"inV":30}'),
|
||||
];
|
||||
for (const elem of validate) {
|
||||
assertElement(emitter.elements.get(elem.id), elem);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
suite('Export use cases', () => {
|
||||
|
|
|
@ -1249,6 +1249,8 @@ abstract class SymbolWalker {
|
|||
// First walk the type to handle unnamed types correctly
|
||||
this.walkType(type, mode, markOnly, this.symbols.getModuleSystemKind(symbol), newPath, level +1);
|
||||
}
|
||||
// Consider skipping the globalThis here since it contains a lot of exports
|
||||
// which we should have handled correctly before.
|
||||
if (symbol.exports !== undefined) {
|
||||
const iterator = symbol.exports.values();
|
||||
for (let item = iterator.next(); !item.done; item = iterator.next()) {
|
||||
|
@ -1532,15 +1534,17 @@ class Symbols {
|
|||
return symbol !== undefined && (symbol.getFlags() & ts.SymbolFlags.ExportStar) !== 0;
|
||||
}
|
||||
|
||||
public static isNamespaceExportDeclaration(symbol: ts.Symbol): boolean {
|
||||
const declarations = symbol.declarations;
|
||||
return declarations !== undefined && declarations.length === 1 && declarations[0].kind === ts.SyntaxKind.NamespaceExportDeclaration;
|
||||
}
|
||||
|
||||
public static isVariableDeclaration(symbol: ts.Symbol): boolean {
|
||||
if (!Symbols.isBlockScopedVariable(symbol)) {
|
||||
return false;
|
||||
}
|
||||
const declarations = symbol.declarations;
|
||||
if (declarations === undefined || declarations.length !== 1) {
|
||||
return false;
|
||||
}
|
||||
return declarations[0].kind === ts.SyntaxKind.VariableDeclaration;
|
||||
return declarations !== undefined && declarations.length === 1 && declarations[0].kind === ts.SyntaxKind.VariableDeclaration;
|
||||
}
|
||||
|
||||
public static isPrivate(symbol: ts.Symbol): boolean {
|
||||
|
@ -1884,6 +1888,11 @@ class Symbols {
|
|||
}
|
||||
return [undefined, moduleSystem];
|
||||
} else {
|
||||
// `export as namespace` create a global symbol also defined in a module file.
|
||||
// This is comparable to declare global.
|
||||
if (Symbols.isSourceFile(parent) && Symbols.isNamespaceExportDeclaration(symbol)) {
|
||||
return [this.getExportSymbolName(symbol), ModuleSystemKind.global];
|
||||
}
|
||||
const parentValue = this.getExportPath(parent);
|
||||
// The parent is not exported so any member isn't either
|
||||
if (parentValue === undefined) {
|
||||
|
@ -1916,9 +1925,9 @@ class Symbols {
|
|||
return escapedName;
|
||||
}
|
||||
|
||||
private static indirectExportFlags = ts.SymbolFlags.Property | ts.SymbolFlags.Function | ts.SymbolFlags.Method | ts.SymbolFlags.TypeAlias | ts.SymbolFlags.Interface | ts.SymbolFlags.Class;
|
||||
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() & Symbols.indirectExportFlags) !== 0 || Symbols.isVariableDeclaration(symbol) ||
|
||||
(symbol.name === ts.InternalSymbolName.ExportEquals && (symbol.getFlags() & ts.SymbolFlags.Assignment) !== 0);
|
||||
}
|
||||
|
||||
|
@ -3313,9 +3322,6 @@ export class DataManager implements SymbolDataContext, ProjectDataManagerContext
|
|||
}
|
||||
this.assertTSProject(this.currentTSProject);
|
||||
const symbolId = this.currentTSProject.getSymbolId(symbol);
|
||||
if (symbolId === "iQWPdWTR1/fAGhTmQ7r48g==") {
|
||||
debugger;
|
||||
}
|
||||
const factory = this.currentTSProject.getFactory(symbol);
|
||||
const sourceFiles = factory.getDeclarationSourceFiles(symbol);
|
||||
const useGlobalProjectDataManager = factory.useGlobalProjectDataManager(symbol);
|
||||
|
@ -3511,6 +3517,9 @@ class Visitor {
|
|||
case ts.SyntaxKind.ExpressionStatement:
|
||||
this.doVisit(this.visitExpressionStatement, this.endVisitExpressionStatement, node as ts.ExpressionStatement);
|
||||
break;
|
||||
case ts.SyntaxKind.NamespaceExportDeclaration:
|
||||
this.doVisit(this.visitNamespaceExportDeclaration, this.endVisitNamespaceExportDeclaration, node as ts.NamespaceExportDeclaration);
|
||||
break;
|
||||
case ts.SyntaxKind.VariableStatement:
|
||||
this.doVisit(this.visitGeneric, this.endVisitGeneric, node as ts.VariableStatement);
|
||||
break;
|
||||
|
@ -3862,6 +3871,31 @@ class Visitor {
|
|||
}
|
||||
}
|
||||
|
||||
private visitNamespaceExportDeclaration(_node: ts.NamespaceExportDeclaration): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
private endVisitNamespaceExportDeclaration(node: ts.NamespaceExportDeclaration): void {
|
||||
if (!ts.isSourceFile(node.parent)) {
|
||||
return;
|
||||
}
|
||||
const symbol = this.tsProject.getSymbolAtLocation(node.name);
|
||||
if (symbol === undefined || !Symbols.isAliasSymbol(symbol)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const symbolData = this.dataManager.getOrCreateSymbolData(symbol);
|
||||
if (symbolData.moduleSystem !== ModuleSystemKind.global) {
|
||||
return;
|
||||
}
|
||||
|
||||
const aliased = this.tsProject.getAliasedSymbol(symbol);
|
||||
if (aliased === undefined || aliased.escapedName !== symbol.escapedName) {
|
||||
return;
|
||||
}
|
||||
this.tsProject.exportSymbol(aliased, '', this.tsProject.getExportSymbolName(aliased), this.currentSourceFile);
|
||||
}
|
||||
|
||||
private visitArrayType(_node: ts.ArrayTypeNode): boolean {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ export function computeMonikerPath(from: string, to: string): string {
|
|||
export function createMonikerIdentifier(path: string, symbol: string | undefined): string;
|
||||
export function createMonikerIdentifier(path: string | undefined, symbol: string): string;
|
||||
export function createMonikerIdentifier(path: string | undefined, symbol: string | undefined): string {
|
||||
if (path === undefined) {
|
||||
if (path === undefined || path.length === 0) {
|
||||
if (symbol === undefined || symbol.length === 0) {
|
||||
throw new Error(`Either path or symbol must be provided.`);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче