mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-12-12 11:50:54 -06:00
Make findAllReferences work on triple-slash reference paths that resolve to scripts (#41936)
* Support find-all-references on triple-slash references that resolve to scripts * Rename terrible name * Add test for <reference types="..." /> * Actually accept baselines
This commit is contained in:
parent
9dfbf07d8a
commit
78ded6577e
@ -5,13 +5,14 @@ namespace ts.FindAllReferences {
|
||||
readonly references: readonly Entry[];
|
||||
}
|
||||
|
||||
export const enum DefinitionKind { Symbol, Label, Keyword, This, String }
|
||||
export const enum DefinitionKind { Symbol, Label, Keyword, This, String, TripleSlashReference }
|
||||
export type Definition =
|
||||
| { readonly type: DefinitionKind.Symbol; readonly symbol: Symbol }
|
||||
| { readonly type: DefinitionKind.Label; readonly node: Identifier }
|
||||
| { readonly type: DefinitionKind.Keyword; readonly node: Node }
|
||||
| { readonly type: DefinitionKind.This; readonly node: Node }
|
||||
| { readonly type: DefinitionKind.String; readonly node: StringLiteralLike };
|
||||
| { readonly type: DefinitionKind.String; readonly node: StringLiteralLike }
|
||||
| { readonly type: DefinitionKind.TripleSlashReference; readonly reference: FileReference, readonly file: SourceFile };
|
||||
|
||||
export const enum EntryKind { Span, Node, StringLiteral, SearchedLocalFoundProperty, SearchedPropertyFoundLocal }
|
||||
export type NodeEntryKind = EntryKind.Node | EntryKind.StringLiteral | EntryKind.SearchedLocalFoundProperty | EntryKind.SearchedPropertyFoundLocal;
|
||||
@ -298,17 +299,16 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
|
||||
function definitionToReferencedSymbolDefinitionInfo(def: Definition, checker: TypeChecker, originalNode: Node): ReferencedSymbolDefinitionInfo {
|
||||
const info = (() => {
|
||||
const info = ((): { sourceFile: SourceFile, textSpan: TextSpan, name: string, kind: ScriptElementKind, displayParts: SymbolDisplayPart[], context?: Node | ContextWithStartAndEndNode } => {
|
||||
switch (def.type) {
|
||||
case DefinitionKind.Symbol: {
|
||||
const { symbol } = def;
|
||||
const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, checker, originalNode);
|
||||
const name = displayParts.map(p => p.text).join("");
|
||||
const declaration = symbol.declarations && firstOrUndefined(symbol.declarations);
|
||||
const node = declaration ? (getNameOfDeclaration(declaration) || declaration) : originalNode;
|
||||
return {
|
||||
node: declaration ?
|
||||
getNameOfDeclaration(declaration) || declaration :
|
||||
originalNode,
|
||||
...getFileAndTextSpanFromNode(node),
|
||||
name,
|
||||
kind,
|
||||
displayParts,
|
||||
@ -317,32 +317,44 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
case DefinitionKind.Label: {
|
||||
const { node } = def;
|
||||
return { node, name: node.text, kind: ScriptElementKind.label, displayParts: [displayPart(node.text, SymbolDisplayPartKind.text)] };
|
||||
return { ...getFileAndTextSpanFromNode(node), name: node.text, kind: ScriptElementKind.label, displayParts: [displayPart(node.text, SymbolDisplayPartKind.text)] };
|
||||
}
|
||||
case DefinitionKind.Keyword: {
|
||||
const { node } = def;
|
||||
const name = tokenToString(node.kind)!;
|
||||
return { node, name, kind: ScriptElementKind.keyword, displayParts: [{ text: name, kind: ScriptElementKind.keyword }] };
|
||||
return { ...getFileAndTextSpanFromNode(node), name, kind: ScriptElementKind.keyword, displayParts: [{ text: name, kind: ScriptElementKind.keyword }] };
|
||||
}
|
||||
case DefinitionKind.This: {
|
||||
const { node } = def;
|
||||
const symbol = checker.getSymbolAtLocation(node);
|
||||
const displayParts = symbol && SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(
|
||||
checker, symbol, node.getSourceFile(), getContainerNode(node), node).displayParts || [textPart("this")];
|
||||
return { node, name: "this", kind: ScriptElementKind.variableElement, displayParts };
|
||||
return { ...getFileAndTextSpanFromNode(node), name: "this", kind: ScriptElementKind.variableElement, displayParts };
|
||||
}
|
||||
case DefinitionKind.String: {
|
||||
const { node } = def;
|
||||
return { node, name: node.text, kind: ScriptElementKind.variableElement, displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)] };
|
||||
return {
|
||||
...getFileAndTextSpanFromNode(node),
|
||||
name: node.text,
|
||||
kind: ScriptElementKind.variableElement,
|
||||
displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)]
|
||||
};
|
||||
}
|
||||
case DefinitionKind.TripleSlashReference: {
|
||||
return {
|
||||
textSpan: createTextSpanFromRange(def.reference),
|
||||
sourceFile: def.file,
|
||||
name: def.reference.fileName,
|
||||
kind: ScriptElementKind.string,
|
||||
displayParts: [displayPart(`"${def.reference.fileName}"`, SymbolDisplayPartKind.stringLiteral)]
|
||||
};
|
||||
}
|
||||
default:
|
||||
return Debug.assertNever(def);
|
||||
}
|
||||
})();
|
||||
|
||||
const { node, name, kind, displayParts, context } = info;
|
||||
const sourceFile = node.getSourceFile();
|
||||
const textSpan = getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile);
|
||||
const { sourceFile, textSpan, name, kind, displayParts, context } = info;
|
||||
return {
|
||||
containerKind: ScriptElementKind.unknown,
|
||||
containerName: "",
|
||||
@ -355,6 +367,14 @@ namespace ts.FindAllReferences {
|
||||
};
|
||||
}
|
||||
|
||||
function getFileAndTextSpanFromNode(node: Node) {
|
||||
const sourceFile = node.getSourceFile();
|
||||
return {
|
||||
sourceFile,
|
||||
textSpan: getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile)
|
||||
};
|
||||
}
|
||||
|
||||
function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker, node: Node): { displayParts: SymbolDisplayPart[], kind: ScriptElementKind } {
|
||||
const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol);
|
||||
const enclosingDeclaration = symbol.declarations && firstOrUndefined(symbol.declarations) || node;
|
||||
@ -603,9 +623,22 @@ namespace ts.FindAllReferences {
|
||||
node = getAdjustedRenameLocation(node);
|
||||
}
|
||||
if (isSourceFile(node)) {
|
||||
const reference = GoToDefinition.getReferenceAtPosition(node, position, program);
|
||||
const moduleSymbol = reference && program.getTypeChecker().getMergedSymbol(reference.file.symbol);
|
||||
return moduleSymbol && getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet);
|
||||
const resolvedRef = GoToDefinition.getReferenceAtPosition(node, position, program);
|
||||
if (!resolvedRef) {
|
||||
return undefined;
|
||||
}
|
||||
const moduleSymbol = program.getTypeChecker().getMergedSymbol(resolvedRef.file.symbol);
|
||||
if (moduleSymbol) {
|
||||
return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet);
|
||||
}
|
||||
const fileIncludeReasons = program.getFileIncludeReasons();
|
||||
if (!fileIncludeReasons) {
|
||||
return undefined;
|
||||
}
|
||||
return [{
|
||||
definition: { type: DefinitionKind.TripleSlashReference, reference: resolvedRef.reference, file: node },
|
||||
references: getReferencesForNonModule(resolvedRef.file, fileIncludeReasons, program) || emptyArray
|
||||
}];
|
||||
}
|
||||
|
||||
if (!options.implementations) {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
/* @internal */
|
||||
namespace ts.GoToDefinition {
|
||||
export function getDefinitionAtPosition(program: Program, sourceFile: SourceFile, position: number): readonly DefinitionInfo[] | undefined {
|
||||
const reference = getReferenceAtPosition(sourceFile, position, program);
|
||||
if (reference) {
|
||||
return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)];
|
||||
const resolvedRef = getReferenceAtPosition(sourceFile, position, program);
|
||||
if (resolvedRef) {
|
||||
return [getDefinitionInfoForFileReference(resolvedRef.reference.fileName, resolvedRef.file.fileName)];
|
||||
}
|
||||
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
@ -108,24 +108,24 @@ namespace ts.GoToDefinition {
|
||||
|| (!isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol);
|
||||
}
|
||||
|
||||
export function getReferenceAtPosition(sourceFile: SourceFile, position: number, program: Program): { fileName: string, file: SourceFile } | undefined {
|
||||
export function getReferenceAtPosition(sourceFile: SourceFile, position: number, program: Program): { reference: FileReference, file: SourceFile } | undefined {
|
||||
const referencePath = findReferenceInPosition(sourceFile.referencedFiles, position);
|
||||
if (referencePath) {
|
||||
const file = program.getSourceFileFromReference(sourceFile, referencePath);
|
||||
return file && { fileName: referencePath.fileName, file };
|
||||
return file && { reference: referencePath, file };
|
||||
}
|
||||
|
||||
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
|
||||
if (typeReferenceDirective) {
|
||||
const reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName);
|
||||
const file = reference && program.getSourceFile(reference.resolvedFileName!); // TODO:GH#18217
|
||||
return file && { fileName: typeReferenceDirective.fileName, file };
|
||||
return file && { reference: typeReferenceDirective, file };
|
||||
}
|
||||
|
||||
const libReferenceDirective = findReferenceInPosition(sourceFile.libReferenceDirectives, position);
|
||||
if (libReferenceDirective) {
|
||||
const file = program.getLibFileFromReference(libReferenceDirective);
|
||||
return file && { fileName: libReferenceDirective.fileName, file };
|
||||
return file && { reference: libReferenceDirective, file };
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
// === /c.js ===
|
||||
// require([|"./b"|]);
|
||||
// require("globals");
|
||||
|
||||
// === /a.ts ===
|
||||
// /// <reference path="[|b.ts|]/*FIND ALL REFS*/" />
|
||||
// /// <reference types="globals" />
|
||||
|
||||
[
|
||||
{
|
||||
"definition": {
|
||||
"containerKind": "",
|
||||
"containerName": "",
|
||||
"fileName": "/a.ts",
|
||||
"kind": "string",
|
||||
"name": "b.ts",
|
||||
"textSpan": {
|
||||
"start": 21,
|
||||
"length": 4
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "\"b.ts\"",
|
||||
"kind": "stringLiteral"
|
||||
}
|
||||
]
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"textSpan": {
|
||||
"start": 21,
|
||||
"length": 4
|
||||
},
|
||||
"fileName": "/a.ts",
|
||||
"isWriteAccess": false,
|
||||
"isDefinition": false
|
||||
},
|
||||
{
|
||||
"textSpan": {
|
||||
"start": 8,
|
||||
"length": 5
|
||||
},
|
||||
"fileName": "/c.js",
|
||||
"isWriteAccess": false,
|
||||
"isDefinition": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
// === /c.js ===
|
||||
// require("./b");
|
||||
// require([|"globals"|]);
|
||||
|
||||
// === /a.ts ===
|
||||
// /// <reference path="b.ts" />
|
||||
// /// <reference types="[|globals|]/*FIND ALL REFS*/" />
|
||||
|
||||
[
|
||||
{
|
||||
"definition": {
|
||||
"containerKind": "",
|
||||
"containerName": "",
|
||||
"fileName": "/a.ts",
|
||||
"kind": "string",
|
||||
"name": "globals",
|
||||
"textSpan": {
|
||||
"start": 52,
|
||||
"length": 7
|
||||
},
|
||||
"displayParts": [
|
||||
{
|
||||
"text": "\"globals\"",
|
||||
"kind": "stringLiteral"
|
||||
}
|
||||
]
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"textSpan": {
|
||||
"start": 52,
|
||||
"length": 7
|
||||
},
|
||||
"fileName": "/a.ts",
|
||||
"isWriteAccess": false,
|
||||
"isDefinition": false
|
||||
},
|
||||
{
|
||||
"textSpan": {
|
||||
"start": 24,
|
||||
"length": 9
|
||||
},
|
||||
"fileName": "/c.js",
|
||||
"isWriteAccess": false,
|
||||
"isDefinition": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
19
tests/cases/fourslash/findAllReferencesTripleSlash.ts
Normal file
19
tests/cases/fourslash/findAllReferencesTripleSlash.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: /node_modules/@types/globals/index.d.ts
|
||||
//// declare const someAmbientGlobal: unknown;
|
||||
|
||||
// @Filename: /a.ts
|
||||
//// /// <reference path="b.ts/*1*/" />
|
||||
//// /// <reference types="globals/*2*/" />
|
||||
|
||||
// @Filename: /b.ts
|
||||
//// console.log("b.ts");
|
||||
|
||||
// @Filename: /c.js
|
||||
//// require("./b");
|
||||
//// require("globals");
|
||||
|
||||
verify.baselineFindAllReferences("1", "2");
|
||||
Loading…
x
Reference in New Issue
Block a user