Support finding references at module
in module.exports =
or export
in export =
(#28221)
* Support finding references at `module` in `module.exports =` or `export` in `export =` * Add json test
This commit is contained in:
parent
69c61cd166
commit
aaf1d8055b
|
@ -28100,6 +28100,9 @@ namespace ts {
|
|||
case SyntaxKind.ImportType:
|
||||
return isLiteralImportTypeNode(node) ? getSymbolAtLocation(node.argument.literal) : undefined;
|
||||
|
||||
case SyntaxKind.ExportKeyword:
|
||||
return isExportAssignment(node.parent) ? Debug.assertDefined(node.parent.symbol) : undefined;
|
||||
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -368,6 +368,10 @@ namespace ts.FindAllReferences.Core {
|
|||
return !options.implementations && isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined;
|
||||
}
|
||||
|
||||
if (symbol.escapedName === InternalSymbolName.ExportEquals) {
|
||||
return getReferencedSymbolsForModule(program, symbol.parent!, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet);
|
||||
}
|
||||
|
||||
let moduleReferences: SymbolAndEntries[] = emptyArray;
|
||||
const moduleSourceFile = isModuleSymbol(symbol);
|
||||
let referencedNode: Node | undefined = node;
|
||||
|
@ -427,6 +431,22 @@ namespace ts.FindAllReferences.Core {
|
|||
}
|
||||
}
|
||||
|
||||
const exported = symbol.exports!.get(InternalSymbolName.ExportEquals);
|
||||
if (exported) {
|
||||
for (const decl of exported.declarations) {
|
||||
const sourceFile = decl.getSourceFile();
|
||||
if (sourceFilesSet.has(sourceFile.fileName)) {
|
||||
// At `module.exports = ...`, reference node is `module`
|
||||
const node = isBinaryExpression(decl) && isPropertyAccessExpression(decl.left)
|
||||
? decl.left.expression
|
||||
: isExportAssignment(decl)
|
||||
? Debug.assertDefined(findChildOfKind(decl, SyntaxKind.ExportKeyword, sourceFile))
|
||||
: getNameOfDeclaration(decl) || decl;
|
||||
references.push(nodeEntry(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return references.length ? [{ definition: { type: DefinitionKind.Symbol, symbol }, references }] : emptyArray;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
// @Filename: /a.ts
|
||||
////type [|{| "isWriteAccess": true, "isDefinition": true |}T|] = number;
|
||||
////export = [|T|];
|
||||
////[|export|] = [|T|];
|
||||
|
||||
// @Filename: /b.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}T|] = require("[|./a|]");
|
||||
|
||||
const [r0, r1, r2, r3] = test.ranges();
|
||||
const mod = { definition: 'module "/a"', ranges: [r3] };
|
||||
const a = { definition: "type T = number", ranges: [r0, r1] };
|
||||
const b = { definition: '(alias) type T = number\nimport T = require("./a")', ranges: [r2] };
|
||||
verify.referenceGroups([r0, r1], [a, b]);
|
||||
verify.referenceGroups(r2, [b, a]);
|
||||
verify.referenceGroups(r3, [mod, a, b]);
|
||||
const [r0, r1, r2, r3, r4] = test.ranges();
|
||||
const mod = { definition: 'module "/a"', ranges: [r4, r1] };
|
||||
const a = { definition: "type T = number", ranges: [r0, r2] };
|
||||
const b = { definition: '(alias) type T = number\nimport T = require("./a")', ranges: [r3] };
|
||||
verify.referenceGroups([r0, r2], [a, b]);
|
||||
verify.referenceGroups(r3, [b, a]);
|
||||
verify.referenceGroups(r4, [mod, a, b]);
|
||||
verify.referenceGroups(r1, [mod]);
|
||||
|
|
24
tests/cases/fourslash/findAllRefsImportEqualsJsonFile.ts
Normal file
24
tests/cases/fourslash/findAllRefsImportEqualsJsonFile.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @resolveJsonModule: true
|
||||
|
||||
// @Filename: /a.ts
|
||||
////import [|{| "isWriteAccess": true, "isDefinition": true |}j|] = require("[|./j.json|]");
|
||||
////[|j|];
|
||||
|
||||
// @Filename: /b.js
|
||||
////const [|{| "isWriteAccess": true, "isDefinition": true |}j|] = require("[|./j.json|]");
|
||||
////[|j|];
|
||||
|
||||
// @Filename: /j.json
|
||||
////[|{ "x": 0 }|]
|
||||
|
||||
verify.noErrors();
|
||||
|
||||
const [r0, r1, r2, r3, r4, r5, r6] = test.ranges();
|
||||
verify.singleReferenceGroup('import j = require("./j.json")', [r0, r2]);
|
||||
verify.referenceGroups([r1, r4], [{ definition: 'module "/j"', ranges: [r1, r4, r6] }]);
|
||||
verify.singleReferenceGroup('const j: {\n "x": number;\n}', [r3, r5]);
|
||||
verify.referenceGroups(r6, undefined);
|
11
tests/cases/fourslash/findAllRefsModuleDotExports.ts
Normal file
11
tests/cases/fourslash/findAllRefsModuleDotExports.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @allowJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
////const b = require("[|./b|]");
|
||||
|
||||
// @Filename: /b.js
|
||||
////[|module|].exports = 0;
|
||||
|
||||
verify.singleReferenceGroup('module "/b"')
|
|
@ -5,7 +5,7 @@
|
|||
////namespace [|{| "isWriteAccess": true, "isDefinition": true |}T|] {
|
||||
//// export type U = string;
|
||||
////}
|
||||
////export = [|T|];
|
||||
////[|export|] = [|T|];
|
||||
|
||||
// @Filename: /b.ts
|
||||
////const x: import("[|./[|a|]|]") = 0;
|
||||
|
@ -13,14 +13,13 @@
|
|||
|
||||
verify.noErrors();
|
||||
|
||||
const [r0, r1, r2, r3, r3b, r4, r4b] = test.ranges();
|
||||
const [r0, r1, rExport, r2, r3, r3b, r4, r4b] = test.ranges();
|
||||
verify.referenceGroups(r0, [{ definition: "type T = number\nnamespace T", ranges: [r0, r2, r3] }]);
|
||||
verify.referenceGroups(r1, [{ definition: "namespace T", ranges: [r1, r2] }]);
|
||||
verify.referenceGroups(r2, [{ definition: "type T = number\nnamespace T", ranges: [r0, r1, r2, r3] }]);
|
||||
verify.referenceGroups([r3, r4], [
|
||||
{ definition: 'module "/a"', ranges: [r4] },
|
||||
{ definition: "type T = number\nnamespace T", ranges: [r0, r1, r2, r3] },
|
||||
]);
|
||||
const t: FourSlashInterface.ReferenceGroup = { definition: "type T = number\nnamespace T", ranges: [r0, r1, r2, r3] };
|
||||
verify.referenceGroups(r2, [t]);
|
||||
verify.referenceGroups([r3, r4], [{ definition: 'module "/a"', ranges: [r4, rExport] }, t]);
|
||||
verify.referenceGroups(rExport, [{ definition: 'module "/a"', ranges: [r3, r4, rExport] }]);
|
||||
|
||||
verify.renameLocations(r0, [r0, r2]);
|
||||
verify.renameLocations(r1, [r1, r2]);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// @checkJs: true
|
||||
|
||||
// @Filename: /a.js
|
||||
////module.exports = class [|{| "isWriteAccess": true, "isDefinition": true |}C|] {};
|
||||
////[|module|].exports = class [|{| "isWriteAccess": true, "isDefinition": true |}C|] {};
|
||||
////module.exports.[|{| "isWriteAccess": true, "isDefinition": true |}D|] = class [|{| "isWriteAccess": true, "isDefinition": true |}D|] {};
|
||||
|
||||
// @Filename: /b.js
|
||||
|
@ -17,7 +17,8 @@ verify.noErrors();
|
|||
|
||||
// TODO: GH#24025
|
||||
|
||||
const [r0, r1, r2, r3, r4, r5] = test.ranges();
|
||||
const [rModule, r0, r1, r2, r3, r4, r5] = test.ranges();
|
||||
verify.referenceGroups(rModule, [{ definition: 'module "/a"', ranges: [r3, r4, rModule] }]);
|
||||
verify.referenceGroups(r0, [
|
||||
{ definition: "(local class) C", ranges: [r0] },
|
||||
// TODO: This definition is really ugly
|
||||
|
@ -31,7 +32,7 @@ verify.referenceGroups(r2, [
|
|||
{ definition: "class D\n(property) D: typeof D", ranges: [r5] },
|
||||
]);
|
||||
verify.referenceGroups([r3, r4], [
|
||||
{ definition: 'module "/a"', ranges: [r4] },
|
||||
{ definition: 'module "/a"', ranges: [r4, rModule] },
|
||||
{ definition: "(local class) C", ranges: [r0] },
|
||||
{ definition: "(alias) (local class) export=\nimport export=", ranges: [r3] },
|
||||
]);
|
||||
|
|
|
@ -231,7 +231,7 @@ declare namespace FourSlashInterface {
|
|||
* For each of starts, asserts the ranges that are referenced from there.
|
||||
* This uses the 'findReferences' command instead of 'getReferencesAtPosition', so references are grouped by their definition.
|
||||
*/
|
||||
referenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<Range>, parts: Array<{ definition: ReferencesDefinition, ranges: Range[] }>): void;
|
||||
referenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<Range>, parts: ReadonlyArray<ReferenceGroup>): void;
|
||||
singleReferenceGroup(definition: ReferencesDefinition, ranges?: Range[]): void;
|
||||
rangesAreOccurrences(isWriteAccess?: boolean): void;
|
||||
rangesWithSameTextAreRenameLocations(): void;
|
||||
|
@ -487,6 +487,10 @@ declare namespace FourSlashInterface {
|
|||
};
|
||||
}
|
||||
|
||||
interface ReferenceGroup {
|
||||
readonly definition: ReferencesDefinition;
|
||||
readonly ranges: ReadonlyArray<Range>;
|
||||
}
|
||||
type ReferencesDefinition = string | {
|
||||
text: string;
|
||||
range: Range;
|
||||
|
|
Loading…
Reference in a new issue