mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Make isDefinition aware of declaring symbol (#45920)
* Make isDefinition aware of target symbol
Initial code, haven't fixed any tests yet.
* Update baselines
This commit includes a regression for commonjs aliases:
```js
// @filename: a.js
function f() { }
module.exports.f = f
// @filename: b.js
const { f } = require('./a')
f/**/
```
Now says that `f` in b.js has 1 reference --
the alias `module.exports.f = f`. This is not correct (or not exactly
correct), but correctly fixing will involve re-creating the ad-hoc
commonjs alias resolution code from the checker. I don't think it's
worth it for an edge case like this.
* update more unit tests
* Fix symbol lookup for constructors
* More baselines + two fixes
1. Fix `default` support.
2. Add a secondary declaration location for commonjs assignment
declarations.
* Update rest of baselines
* Switch a few more tests over to baselines
This commit is contained in:
@@ -208,11 +208,12 @@ namespace ts.FindAllReferences {
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, { use: FindReferencesUse.References });
|
||||
const checker = program.getTypeChecker();
|
||||
const symbol = checker.getSymbolAtLocation(node);
|
||||
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined<SymbolAndEntries, ReferencedSymbol>(referencedSymbols, ({ definition, references }) =>
|
||||
// Only include referenced symbols that have a valid definition.
|
||||
definition && {
|
||||
definition: checker.runWithCancellationToken(cancellationToken, checker => definitionToReferencedSymbolDefinitionInfo(definition, checker, node)),
|
||||
references: references.map(toReferenceEntry)
|
||||
references: references.map(r => toReferenceEntry(r, symbol))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -387,7 +388,7 @@ namespace ts.FindAllReferences {
|
||||
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) };
|
||||
}
|
||||
|
||||
export function toReferenceEntry(entry: Entry): ReferenceEntry {
|
||||
export function toReferenceEntry(entry: Entry, symbol: Symbol | undefined): ReferenceEntry {
|
||||
const documentSpan = entryToDocumentSpan(entry);
|
||||
if (entry.kind === EntryKind.Span) {
|
||||
return { ...documentSpan, isWriteAccess: false, isDefinition: false };
|
||||
@@ -396,7 +397,7 @@ namespace ts.FindAllReferences {
|
||||
return {
|
||||
...documentSpan,
|
||||
isWriteAccess: isWriteAccessForReference(node),
|
||||
isDefinition: isDefinitionForReference(node),
|
||||
isDefinition: isDeclarationOfSymbol(node, symbol),
|
||||
isInString: kind === EntryKind.StringLiteral ? true : undefined,
|
||||
};
|
||||
}
|
||||
@@ -544,11 +545,16 @@ namespace ts.FindAllReferences {
|
||||
return !!decl && declarationIsWriteAccess(decl) || node.kind === SyntaxKind.DefaultKeyword || isWriteAccess(node);
|
||||
}
|
||||
|
||||
function isDefinitionForReference(node: Node): boolean {
|
||||
return node.kind === SyntaxKind.DefaultKeyword
|
||||
|| !!getDeclarationFromName(node)
|
||||
|| isLiteralComputedPropertyDeclarationName(node)
|
||||
|| (node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent));
|
||||
/** Whether a reference, `node`, is a definition of the `target` symbol */
|
||||
function isDeclarationOfSymbol(node: Node, target: Symbol | undefined): boolean {
|
||||
if (!target) return false;
|
||||
const source = getDeclarationFromName(node) ||
|
||||
(node.kind === SyntaxKind.DefaultKeyword ? node.parent
|
||||
: isLiteralComputedPropertyDeclarationName(node) ? node.parent.parent
|
||||
: node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent) ? node.parent.parent
|
||||
: undefined);
|
||||
const commonjsSource = source && isBinaryExpression(source) ? source.left as unknown as Declaration : undefined;
|
||||
return !!(source && target.declarations?.some(d => d === source || d === commonjsSource));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1763,7 +1763,7 @@ namespace ts {
|
||||
|
||||
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
|
||||
synchronizeHostData();
|
||||
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, FindAllReferences.toReferenceEntry);
|
||||
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, (entry, node, checker) => FindAllReferences.toReferenceEntry(entry, checker.getSymbolAtLocation(node)));
|
||||
}
|
||||
|
||||
function getReferencesWorker<T>(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry<T>): T[] | undefined {
|
||||
@@ -1784,7 +1784,8 @@ namespace ts {
|
||||
|
||||
function getFileReferences(fileName: string): ReferenceEntry[] {
|
||||
synchronizeHostData();
|
||||
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry);
|
||||
const moduleSymbol = program.getSourceFile(fileName)?.symbol;
|
||||
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(r => FindAllReferences.toReferenceEntry(r, moduleSymbol));
|
||||
}
|
||||
|
||||
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {
|
||||
|
||||
@@ -32,7 +32,8 @@ ${exportNestedObject}
|
||||
const referenceMainTs = (mainTs: File, text: string): protocol.ReferencesResponseItem =>
|
||||
makeReferenceItem({
|
||||
file: mainTs,
|
||||
isDefinition: true,
|
||||
isDefinition: false,
|
||||
isWriteAccess: true,
|
||||
lineText: mainTs.content,
|
||||
contextText: mainTs.content,
|
||||
text,
|
||||
@@ -113,8 +114,11 @@ ${exportNestedObject}
|
||||
referenceMainTs(mainTs, "valueC"),
|
||||
referenceModTs(
|
||||
{ text: "valueC", lineText: exportObjectDestructured, contextText: "valueC: 0" },
|
||||
{ options: { index: 1 } },
|
||||
),
|
||||
{
|
||||
options: { index: 1 },
|
||||
isDefinition: false,
|
||||
isWriteAccess: true,
|
||||
}),
|
||||
],
|
||||
symbolDisplayString: "const valueC: number",
|
||||
symbolName: "valueC",
|
||||
@@ -171,7 +175,11 @@ ${exportNestedObject}
|
||||
lineText: exportNestedObject,
|
||||
contextText: "valueF: 1",
|
||||
},
|
||||
{ options: { index: 1 } },
|
||||
{
|
||||
options: { index: 1 },
|
||||
isDefinition: false,
|
||||
isWriteAccess: true,
|
||||
},
|
||||
),
|
||||
],
|
||||
symbolDisplayString: "const valueF: number",
|
||||
|
||||
@@ -186,7 +186,8 @@ function foo() {
|
||||
file: keyboardTestTs,
|
||||
text: searchStr,
|
||||
contextText: importStr,
|
||||
isDefinition: true,
|
||||
isDefinition: false,
|
||||
isWriteAccess: true,
|
||||
lineText: importStr
|
||||
}),
|
||||
makeReferenceItem({
|
||||
@@ -200,7 +201,8 @@ function foo() {
|
||||
file: terminalTs,
|
||||
text: searchStr,
|
||||
contextText: importStr,
|
||||
isDefinition: true,
|
||||
isDefinition: false,
|
||||
isWriteAccess: true,
|
||||
lineText: importStr
|
||||
}),
|
||||
makeReferenceItem({
|
||||
|
||||
Reference in New Issue
Block a user