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:
Nathan Shively-Sanders
2021-09-22 13:43:52 -07:00
committed by GitHub
parent 110b05987e
commit f0fe1b88ca
145 changed files with 3552 additions and 705 deletions
+14 -8
View File
@@ -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));
}
/**
+3 -2
View File
@@ -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({