Skip to content

Commit 76e7437

Browse files
authored
Only report isDefinition when FAR is triggered on a definition (#48566)
* Don't report isDefinition unless the starting node is a declaration * Drop isDefinition everywhere it isn't specifically needed * Fix tsserver tests * Update shim comment * Update baselines * Add tests for isDefinition * Update doc comment * Clear isDefinition from all references if the first one lacks it
1 parent f7c457d commit 76e7437

File tree

271 files changed

+4136
-4678
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

271 files changed

+4136
-4678
lines changed

src/harness/client.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,6 @@ namespace ts.server {
583583
fileName: entry.file,
584584
textSpan: this.decodeSpan(entry),
585585
isWriteAccess: entry.isWriteAccess,
586-
isDefinition: false
587586
}));
588587
}
589588

src/server/protocol.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,9 +1158,12 @@ namespace ts.server.protocol {
11581158
isWriteAccess: boolean;
11591159

11601160
/**
1161-
* True if reference is a definition, false otherwise.
1161+
* Present only if the search was triggered from a declaration.
1162+
* True indicates that the references refers to the same symbol
1163+
* (i.e. has the same meaning) as the declaration that began the
1164+
* search.
11621165
*/
1163-
isDefinition: boolean;
1166+
isDefinition?: boolean;
11641167
}
11651168

11661169
/**

src/server/session.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ namespace ts.server {
354354
logger.info(`Finding references to ${location.fileName} position ${location.pos} in project ${project.getProjectName()}`);
355355
const projectOutputs = project.getLanguageService().findReferences(location.fileName, location.pos);
356356
if (projectOutputs) {
357+
const clearIsDefinition = projectOutputs[0].references[0].isDefinition === undefined;
357358
for (const referencedSymbol of projectOutputs) {
358359
const mappedDefinitionFile = getMappedLocation(project, documentSpanLocation(referencedSymbol.definition));
359360
const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ?
@@ -374,6 +375,9 @@ namespace ts.server {
374375
for (const ref of referencedSymbol.references) {
375376
// If it's in a mapped file, that is added to the todo list by `getMappedLocation`.
376377
if (!contains(symbolToAddTo.references, ref, documentSpansEqual) && !getMappedLocation(project, documentSpanLocation(ref))) {
378+
if (clearIsDefinition) {
379+
delete ref.isDefinition;
380+
}
377381
symbolToAddTo.references.push(ref);
378382
}
379383
}
@@ -3260,7 +3264,7 @@ namespace ts.server {
32603264
return text;
32613265
}
32623266

3263-
function referenceEntryToReferencesResponseItem(projectService: ProjectService, { fileName, textSpan, contextSpan, isWriteAccess, isDefinition }: ReferenceEntry): protocol.ReferencesResponseItem {
3267+
function referenceEntryToReferencesResponseItem(projectService: ProjectService, { fileName, textSpan, contextSpan, isWriteAccess, isDefinition }: ReferencedSymbolEntry): protocol.ReferencesResponseItem {
32643268
const scriptInfo = Debug.checkDefined(projectService.getScriptInfo(fileName));
32653269
const span = toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo);
32663270
const lineSpan = scriptInfo.lineToTextSpan(span.start.line - 1);

src/services/findAllReferences.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,15 +209,24 @@ namespace ts.FindAllReferences {
209209
const options = { use: FindReferencesUse.References };
210210
const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options);
211211
const checker = program.getTypeChecker();
212-
const symbol = checker.getSymbolAtLocation(getAdjustedReferenceLocation(Core.getAdjustedNode(node, options)));
212+
// Unless the starting node is a declaration (vs e.g. JSDoc), don't attempt to compute isDefinition
213+
const adjustedNode = Core.getAdjustedNode(node, options);
214+
const symbol = isDefinitionForReference(adjustedNode) ? checker.getSymbolAtLocation(adjustedNode) : undefined;
213215
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined<SymbolAndEntries, ReferencedSymbol>(referencedSymbols, ({ definition, references }) =>
214216
// Only include referenced symbols that have a valid definition.
215217
definition && {
216218
definition: checker.runWithCancellationToken(cancellationToken, checker => definitionToReferencedSymbolDefinitionInfo(definition, checker, node)),
217-
references: references.map(r => toReferenceEntry(r, symbol))
219+
references: references.map(r => toReferencedSymbolEntry(r, symbol))
218220
});
219221
}
220222

223+
function isDefinitionForReference(node: Node): boolean {
224+
return node.kind === SyntaxKind.DefaultKeyword
225+
|| !!getDeclarationFromName(node)
226+
|| isLiteralComputedPropertyDeclarationName(node)
227+
|| (node.kind === SyntaxKind.ConstructorKeyword && isConstructorDeclaration(node.parent));
228+
}
229+
221230
export function getImplementationsAtPosition(program: Program, cancellationToken: CancellationToken, sourceFiles: readonly SourceFile[], sourceFile: SourceFile, position: number): ImplementationLocation[] | undefined {
222231
const node = getTouchingPropertyName(sourceFile, position);
223232
let referenceEntries: Entry[] | undefined;
@@ -389,16 +398,24 @@ namespace ts.FindAllReferences {
389398
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) };
390399
}
391400

392-
export function toReferenceEntry(entry: Entry, symbol: Symbol | undefined): ReferenceEntry {
401+
function toReferencedSymbolEntry(entry: Entry, symbol: Symbol | undefined): ReferencedSymbolEntry {
402+
const referenceEntry = toReferenceEntry(entry);
403+
if (!symbol) return referenceEntry;
404+
return {
405+
...referenceEntry,
406+
isDefinition: entry.kind !== EntryKind.Span && isDeclarationOfSymbol(entry.node, symbol)
407+
};
408+
}
409+
410+
export function toReferenceEntry(entry: Entry): ReferenceEntry {
393411
const documentSpan = entryToDocumentSpan(entry);
394412
if (entry.kind === EntryKind.Span) {
395-
return { ...documentSpan, isWriteAccess: false, isDefinition: false };
413+
return { ...documentSpan, isWriteAccess: false };
396414
}
397415
const { kind, node } = entry;
398416
return {
399417
...documentSpan,
400418
isWriteAccess: isWriteAccessForReference(node),
401-
isDefinition: isDeclarationOfSymbol(node, symbol),
402419
isInString: kind === EntryKind.StringLiteral ? true : undefined,
403420
};
404421
}

src/services/services.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,6 @@ namespace ts {
17981798
fileName: entry.fileName,
17991799
textSpan: highlightSpan.textSpan,
18001800
isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference,
1801-
isDefinition: false,
18021801
...highlightSpan.isInString && { isInString: true },
18031802
...highlightSpan.contextSpan && { contextSpan: highlightSpan.contextSpan }
18041803
}))
@@ -1838,7 +1837,7 @@ namespace ts {
18381837

18391838
function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] | undefined {
18401839
synchronizeHostData();
1841-
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, (entry, node, checker) => FindAllReferences.toReferenceEntry(entry, checker.getSymbolAtLocation(node)));
1840+
return getReferencesWorker(getTouchingPropertyName(getValidSourceFile(fileName), position), position, { use: FindAllReferences.FindReferencesUse.References }, FindAllReferences.toReferenceEntry);
18421841
}
18431842

18441843
function getReferencesWorker<T>(node: Node, position: number, options: FindAllReferences.Options, cb: FindAllReferences.ToReferenceOrRenameEntry<T>): T[] | undefined {
@@ -1859,8 +1858,7 @@ namespace ts {
18591858

18601859
function getFileReferences(fileName: string): ReferenceEntry[] {
18611860
synchronizeHostData();
1862-
const moduleSymbol = program.getSourceFile(fileName)?.symbol;
1863-
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(r => FindAllReferences.toReferenceEntry(r, moduleSymbol));
1861+
return FindAllReferences.Core.getReferencesForFileName(fileName, program, program.getSourceFiles()).map(FindAllReferences.toReferenceEntry);
18641862
}
18651863

18661864
function getNavigateToItems(searchValue: string, maxResultCount?: number, fileName?: string, excludeDtsFiles = false): NavigateToItem[] {

src/services/shims.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ namespace ts {
225225

226226
/**
227227
* Returns a JSON-encoded value of the type:
228-
* { fileName: string; highlights: { start: number; length: number, isDefinition: boolean }[] }[]
228+
* { fileName: string; highlights: { start: number; length: number }[] }[]
229229
*
230230
* @param fileToSearch A JSON encoded string[] containing the file names that should be
231231
* considered when searching.

src/services/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,6 @@ namespace ts {
886886

887887
export interface ReferenceEntry extends DocumentSpan {
888888
isWriteAccess: boolean;
889-
isDefinition: boolean;
890889
isInString?: true;
891890
}
892891

@@ -1046,7 +1045,11 @@ namespace ts {
10461045

10471046
export interface ReferencedSymbol {
10481047
definition: ReferencedSymbolDefinitionInfo;
1049-
references: ReferenceEntry[];
1048+
references: ReferencedSymbolEntry[];
1049+
}
1050+
1051+
export interface ReferencedSymbolEntry extends ReferenceEntry {
1052+
isDefinition?: boolean;
10501053
}
10511054

10521055
export enum SymbolDisplayPartKind {

src/testRunner/unittests/tsserver/declarationFileMaps.ts

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,20 @@ namespace ts.projectSystem {
1313
}
1414

1515
interface MakeReferenceEntry extends DocumentSpanFromSubstring {
16-
isDefinition: boolean;
16+
isDefinition?: boolean;
17+
isWriteAccess?: boolean;
1718
}
18-
function makeReferenceEntry({ isDefinition, ...rest }: MakeReferenceEntry): ReferenceEntry {
19-
return {
19+
function makeReferencedSymbolEntry({ isDefinition, isWriteAccess, ...rest }: MakeReferenceEntry): ReferencedSymbolEntry {
20+
const result = {
2021
...documentSpanFromSubstring(rest),
2122
isDefinition,
22-
isWriteAccess: isDefinition,
23+
isWriteAccess: !!isWriteAccess,
2324
isInString: undefined,
2425
};
26+
if (isDefinition === undefined) {
27+
delete result.isDefinition;
28+
}
29+
return result;
2530
}
2631

2732
function checkDeclarationFiles(file: File, session: TestSession, expectedFiles: readonly File[]): void {
@@ -373,17 +378,18 @@ namespace ts.projectSystem {
373378
]);
374379
});
375380

376-
const referenceATs = (aTs: File): protocol.ReferencesResponseItem => makeReferenceItem({
381+
const referenceATs = (aTs: File, isDefinition: true | undefined): protocol.ReferencesResponseItem => makeReferenceItem({
377382
file: aTs,
378-
isDefinition: true,
383+
isDefinition,
384+
isWriteAccess: true,
379385
text: "fnA",
380386
contextText: "export function fnA() {}",
381387
lineText: "export function fnA() {}"
382388
});
383-
const referencesUserTs = (userTs: File): readonly protocol.ReferencesResponseItem[] => [
389+
const referencesUserTs = (userTs: File, isDefinition: false | undefined): readonly protocol.ReferencesResponseItem[] => [
384390
makeReferenceItem({
385391
file: userTs,
386-
isDefinition: false,
392+
isDefinition,
387393
text: "fnA",
388394
lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
389395
}),
@@ -394,7 +400,7 @@ namespace ts.projectSystem {
394400

395401
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(userTs, "fnA()"));
396402
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
397-
refs: [...referencesUserTs(userTs), referenceATs(aTs)],
403+
refs: [...referencesUserTs(userTs, /*isDefinition*/ undefined), referenceATs(aTs, /*isDefinition*/ true)], // Presently inconsistent across projects
398404
symbolName: "fnA",
399405
symbolStartOffset: protocolLocationFromSubstring(userTs.content, "fnA()").offset,
400406
symbolDisplayString: "function fnA(): void",
@@ -408,7 +414,7 @@ namespace ts.projectSystem {
408414
openFilesForSession([aTs], session); // If it's not opened, the reference isn't found.
409415
const response = executeSessionRequest<protocol.ReferencesRequest, protocol.ReferencesResponse>(session, protocol.CommandTypes.References, protocolFileLocationFromSubstring(aTs, "fnA"));
410416
assert.deepEqual<protocol.ReferencesResponseBody | undefined>(response, {
411-
refs: [referenceATs(aTs), ...referencesUserTs(userTs)],
417+
refs: [referenceATs(aTs, /*isDefinition*/ true), ...referencesUserTs(userTs, /*isDefinition*/ false)],
412418
symbolName: "fnA",
413419
symbolStartOffset: protocolLocationFromSubstring(aTs.content, "fnA").offset,
414420
symbolDisplayString: "function fnA(): void",
@@ -448,8 +454,8 @@ namespace ts.projectSystem {
448454
],
449455
},
450456
references: [
451-
makeReferenceEntry({ file: userTs, /*isDefinition*/ isDefinition: false, text: "fnA" }),
452-
makeReferenceEntry({ file: aTs, /*isDefinition*/ isDefinition: true, text: "fnA", contextText: "export function fnA() {}" }),
457+
makeReferencedSymbolEntry({ file: userTs, text: "fnA" }),
458+
makeReferencedSymbolEntry({ file: aTs, text: "fnA", isDefinition: true, isWriteAccess: true, contextText: "export function fnA() {}" }),
453459
],
454460
},
455461
]);
@@ -502,16 +508,15 @@ namespace ts.projectSystem {
502508
name: "function f(): void",
503509
},
504510
references: [
505-
makeReferenceEntry({
511+
makeReferencedSymbolEntry({
506512
file: aTs,
507513
text: "f",
508514
options: { index: 1 },
509515
contextText: "function f() {}",
510-
isDefinition: true
516+
isWriteAccess: true,
511517
}),
512518
{
513519
fileName: bTs.path,
514-
isDefinition: false,
515520
isInString: undefined,
516521
isWriteAccess: false,
517522
textSpan: { start: 0, length: 1 },
@@ -529,14 +534,13 @@ namespace ts.projectSystem {
529534
refs: [
530535
makeReferenceItem({
531536
file: bDts,
532-
isDefinition: true,
537+
isWriteAccess: true,
533538
text: "fnB",
534539
contextText: "export declare function fnB(): void;",
535540
lineText: "export declare function fnB(): void;"
536541
}),
537542
makeReferenceItem({
538543
file: userTs,
539-
isDefinition: false,
540544
text: "fnB",
541545
lineText: "export function fnUser() { a.fnA(); b.fnB(); a.instanceA; }"
542546
}),

src/testRunner/unittests/tsserver/getFileReferences.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ namespace ts.projectSystem {
4444

4545
const expectResponse: protocol.FileReferencesResponseBody = {
4646
refs: [
47-
makeReferenceItem({ file: bTs, text: "./a", lineText: importA, contextText: importA, isDefinition: false, isWriteAccess: false }),
48-
makeReferenceItem({ file: cTs, text: "./a", lineText: importCurlyFromA, contextText: importCurlyFromA, isDefinition: false, isWriteAccess: false }),
49-
makeReferenceItem({ file: dTs, text: "/project/a", lineText: importAFromA, contextText: importAFromA, isDefinition: false, isWriteAccess: false }),
50-
makeReferenceItem({ file: dTs, text: "./a", lineText: typeofImportA, contextText: typeofImportA, isDefinition: false, isWriteAccess: false }),
47+
makeReferenceItem({ file: bTs, text: "./a", lineText: importA, contextText: importA, isWriteAccess: false }),
48+
makeReferenceItem({ file: cTs, text: "./a", lineText: importCurlyFromA, contextText: importCurlyFromA, isWriteAccess: false }),
49+
makeReferenceItem({ file: dTs, text: "/project/a", lineText: importAFromA, contextText: importAFromA, isWriteAccess: false }),
50+
makeReferenceItem({ file: dTs, text: "./a", lineText: typeofImportA, contextText: typeofImportA, isWriteAccess: false }),
5151
],
5252
symbolName: `"${aTs.path}"`,
5353
};

src/testRunner/unittests/tsserver/helpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ namespace ts.projectSystem {
713713
}
714714

715715
export interface MakeReferenceItem extends DocumentSpanFromSubstring {
716-
isDefinition: boolean;
716+
isDefinition?: boolean;
717717
isWriteAccess?: boolean;
718718
lineText: string;
719719
}
@@ -722,7 +722,7 @@ namespace ts.projectSystem {
722722
return {
723723
...protocolFileSpanWithContextFromSubstring(rest),
724724
isDefinition,
725-
isWriteAccess: isWriteAccess === undefined ? isDefinition : isWriteAccess,
725+
isWriteAccess: isWriteAccess === undefined ? !!isDefinition : isWriteAccess,
726726
lineText,
727727
};
728728
}

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6209,7 +6209,6 @@ declare namespace ts {
62096209
}
62106210
interface ReferenceEntry extends DocumentSpan {
62116211
isWriteAccess: boolean;
6212-
isDefinition: boolean;
62136212
isInString?: true;
62146213
}
62156214
interface ImplementationLocation extends DocumentSpan {
@@ -6323,7 +6322,10 @@ declare namespace ts {
63236322
}
63246323
interface ReferencedSymbol {
63256324
definition: ReferencedSymbolDefinitionInfo;
6326-
references: ReferenceEntry[];
6325+
references: ReferencedSymbolEntry[];
6326+
}
6327+
interface ReferencedSymbolEntry extends ReferenceEntry {
6328+
isDefinition?: boolean;
63276329
}
63286330
enum SymbolDisplayPartKind {
63296331
aliasName = 0,
@@ -7855,9 +7857,12 @@ declare namespace ts.server.protocol {
78557857
*/
78567858
isWriteAccess: boolean;
78577859
/**
7858-
* True if reference is a definition, false otherwise.
7860+
* Present only if the search was triggered from a declaration.
7861+
* True indicates that the references refers to the same symbol
7862+
* (i.e. has the same meaning) as the declaration that began the
7863+
* search.
78597864
*/
7860-
isDefinition: boolean;
7865+
isDefinition?: boolean;
78617866
}
78627867
/**
78637868
* The body of a "references" response message.

tests/baselines/reference/api/typescript.d.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6209,7 +6209,6 @@ declare namespace ts {
62096209
}
62106210
interface ReferenceEntry extends DocumentSpan {
62116211
isWriteAccess: boolean;
6212-
isDefinition: boolean;
62136212
isInString?: true;
62146213
}
62156214
interface ImplementationLocation extends DocumentSpan {
@@ -6323,7 +6322,10 @@ declare namespace ts {
63236322
}
63246323
interface ReferencedSymbol {
63256324
definition: ReferencedSymbolDefinitionInfo;
6326-
references: ReferenceEntry[];
6325+
references: ReferencedSymbolEntry[];
6326+
}
6327+
interface ReferencedSymbolEntry extends ReferenceEntry {
6328+
isDefinition?: boolean;
63276329
}
63286330
enum SymbolDisplayPartKind {
63296331
aliasName = 0,

tests/baselines/reference/autoImportProvider_referencesCrash.baseline.jsonc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@
4040
"length": 1
4141
},
4242
"fileName": "/b/b.ts",
43-
"isWriteAccess": false,
44-
"isDefinition": false
43+
"isWriteAccess": false
4544
}
4645
]
4746
}

tests/baselines/reference/esModuleInteropFindAllReferences.baseline.jsonc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,17 +142,15 @@ undefined
142142
"start": 25,
143143
"length": 23
144144
},
145-
"isWriteAccess": true,
146-
"isDefinition": true
145+
"isWriteAccess": true
147146
},
148147
{
149148
"textSpan": {
150149
"start": 21,
151150
"length": 1
152151
},
153152
"fileName": "/b.ts",
154-
"isWriteAccess": false,
155-
"isDefinition": false
153+
"isWriteAccess": false
156154
}
157155
]
158156
}

0 commit comments

Comments
 (0)