mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Find references of a module by filename (#41805)
* Naive implementation enough to build and write a test * Add simple test * Add project references test * Add deduplication test, accept baselines * Add test for referencing a script (doesn’t do anything) * Update API baselines * Use refFileMap for non-module references * Fix find-all-refs on module specifier * Remove unused util * Don’t store text range on ts.RefFile * Ensure string literal could itself be a file reference * Remove unused utilities * Improve baseline format * Preserve old behavior of falling back to string literal references * Update baselines from master * Fix old RefFileMap code after merge * Add test for additional response info * Undo test change
This commit is contained in:
@@ -622,7 +622,21 @@ namespace ts.FindAllReferences {
|
||||
// Could not find a symbol e.g. unknown identifier
|
||||
if (!symbol) {
|
||||
// String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial.
|
||||
return !options.implementations && isStringLiteralLike(node) ? getReferencesForStringLiteral(node, sourceFiles, checker, cancellationToken) : undefined;
|
||||
if (!options.implementations && isStringLiteralLike(node)) {
|
||||
if (isRequireCall(node.parent, /*requireStringLiteralLikeArgument*/ true) || isExternalModuleReference(node.parent) || isImportDeclaration(node.parent) || isImportCall(node.parent)) {
|
||||
const fileIncludeReasons = program.getFileIncludeReasons();
|
||||
const referencedFileName = node.getSourceFile().resolvedModules?.get(node.text)?.resolvedFileName;
|
||||
const referencedFile = referencedFileName ? program.getSourceFile(referencedFileName) : undefined;
|
||||
if (referencedFile) {
|
||||
return [{ definition: { type: DefinitionKind.String, node }, references: getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray }];
|
||||
}
|
||||
// Fall through to string literal references. This is not very likely to return
|
||||
// anything useful, but I guess it's better than nothing, and there's an existing
|
||||
// test that expects this to happen (fourslash/cases/untypedModuleImport.ts).
|
||||
}
|
||||
return getReferencesForStringLiteral(node, sourceFiles, checker, cancellationToken);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (symbol.escapedName === InternalSymbolName.ExportEquals) {
|
||||
@@ -642,6 +656,35 @@ namespace ts.FindAllReferences {
|
||||
return mergeReferences(program, moduleReferences, references, moduleReferencesOfExportTarget);
|
||||
}
|
||||
|
||||
export function getReferencesForFileName(fileName: string, program: Program, sourceFiles: readonly SourceFile[], sourceFilesSet: ReadonlySet<string> = new Set(sourceFiles.map(f => f.fileName))): readonly Entry[] {
|
||||
const moduleSymbol = program.getSourceFile(fileName)?.symbol;
|
||||
if (moduleSymbol) {
|
||||
return getReferencedSymbolsForModule(program, moduleSymbol, /*excludeImportTypeOfExportEquals*/ false, sourceFiles, sourceFilesSet)[0]?.references || emptyArray;
|
||||
}
|
||||
const fileIncludeReasons = program.getFileIncludeReasons();
|
||||
const referencedFile = program.getSourceFile(fileName);
|
||||
return referencedFile && fileIncludeReasons && getReferencesForNonModule(referencedFile, fileIncludeReasons, program) || emptyArray;
|
||||
}
|
||||
|
||||
function getReferencesForNonModule(referencedFile: SourceFile, refFileMap: MultiMap<Path, FileIncludeReason>, program: Program): readonly SpanEntry[] | undefined {
|
||||
let entries: SpanEntry[] | undefined;
|
||||
const references = refFileMap.get(referencedFile.path) || emptyArray;
|
||||
for (const ref of references) {
|
||||
if (isReferencedFile(ref)) {
|
||||
const referencingFile = program.getSourceFileByPath(ref.file)!;
|
||||
const location = getReferencedFileLocation(program.getSourceFileByPath, ref);
|
||||
if (isReferenceFileLocation(location)) {
|
||||
entries = append(entries, {
|
||||
kind: EntryKind.Span,
|
||||
fileName: referencingFile.fileName,
|
||||
textSpan: createTextSpanFromRange(location)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
function getMergedAliasedSymbolOfNamespaceExportDeclaration(node: Node, symbol: Symbol, checker: TypeChecker) {
|
||||
if (node.parent && isNamespaceExportDeclaration(node.parent)) {
|
||||
const aliasedSymbol = checker.getAliasedSymbol(symbol);
|
||||
|
||||
@@ -1728,6 +1728,11 @@ namespace ts {
|
||||
return FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
|
||||
}
|
||||
|
||||
function getFileReferences(fileName: string): ReferenceEntry[] {
|
||||
synchronizeHostData();
|
||||
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry);
|
||||
}
|
||||
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
|
||||
synchronizeHostData();
|
||||
const sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles();
|
||||
@@ -2526,6 +2531,7 @@ namespace ts {
|
||||
getTypeDefinitionAtPosition,
|
||||
getReferencesAtPosition,
|
||||
findReferences,
|
||||
getFileReferences,
|
||||
getOccurrencesAtPosition,
|
||||
getDocumentHighlights,
|
||||
getNameOrDottedNameSpan,
|
||||
|
||||
@@ -208,6 +208,12 @@ namespace ts {
|
||||
*/
|
||||
findReferences(fileName: string, position: number): string;
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean, isDefinition?: boolean }[]
|
||||
*/
|
||||
getFileReferences(fileName: string): string;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Returns a JSON-encoded value of the type:
|
||||
@@ -916,6 +922,13 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
public getFileReferences(fileName: string) {
|
||||
return this.forwardJSONCall(
|
||||
`getFileReferences('${fileName})`,
|
||||
() => this.languageService.getFileReferences(fileName)
|
||||
);
|
||||
}
|
||||
|
||||
public getOccurrencesAtPosition(fileName: string, position: number): string {
|
||||
return this.forwardJSONCall(
|
||||
`getOccurrencesAtPosition('${fileName}', ${position})`,
|
||||
|
||||
@@ -468,6 +468,7 @@ namespace ts {
|
||||
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined;
|
||||
findReferences(fileName: string, position: number): ReferencedSymbol[] | undefined;
|
||||
getDocumentHighlights(fileName: string, position: number, filesToSearch: string[]): DocumentHighlights[] | undefined;
|
||||
getFileReferences(fileName: string): ReferenceEntry[];
|
||||
|
||||
/** @deprecated */
|
||||
getOccurrencesAtPosition(fileName: string, position: number): readonly ReferenceEntry[] | undefined;
|
||||
|
||||
Reference in New Issue
Block a user