Skip to content

Commit 598ca48

Browse files
authored
Merge pull request #10542 from Microsoft/far_display_parts
Adding display parts to definition items to support FindAllReferences
2 parents e62f118 + d72ed3c commit 598ca48

File tree

4 files changed

+86
-27
lines changed

4 files changed

+86
-27
lines changed

src/harness/fourslash.ts

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,24 @@ namespace FourSlash {
206206

207207
private inputFiles = ts.createMap<string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
208208

209+
private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) {
210+
let result = "";
211+
ts.forEach(displayParts, part => {
212+
if (result) {
213+
result += ",\n ";
214+
}
215+
else {
216+
result = "[\n ";
217+
}
218+
result += JSON.stringify(part);
219+
});
220+
if (result) {
221+
result += "\n]";
222+
}
223+
224+
return result;
225+
}
226+
209227
// Add input file which has matched file name with the given reference-file path.
210228
// This is necessary when resolveReference flag is specified
211229
private addMatchedInputFile(referenceFilePath: string, extensions: string[]) {
@@ -777,6 +795,20 @@ namespace FourSlash {
777795
ts.forEachProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
778796
}
779797

798+
public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) {
799+
const referencedSymbols = this.findReferencesAtCaret();
800+
801+
if (referencedSymbols.length === 0) {
802+
this.raiseError("No referenced symbols found at current caret position");
803+
}
804+
else if (referencedSymbols.length > 1) {
805+
this.raiseError("More than one referenced symbol found");
806+
}
807+
808+
assert.equal(TestState.getDisplayPartsJson(referencedSymbols[0].definition.displayParts),
809+
TestState.getDisplayPartsJson(expected), this.messageAtLastKnownMarker("referenced symbol definition display parts"));
810+
}
811+
780812
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {
781813
for (let i = 0; i < references.length; i++) {
782814
const reference = references[i];
@@ -811,6 +843,10 @@ namespace FourSlash {
811843
return this.languageService.getReferencesAtPosition(this.activeFile.fileName, this.currentCaretPosition);
812844
}
813845

846+
private findReferencesAtCaret() {
847+
return this.languageService.findReferences(this.activeFile.fileName, this.currentCaretPosition);
848+
}
849+
814850
public getSyntacticDiagnostics(expected: string) {
815851
const diagnostics = this.languageService.getSyntacticDiagnostics(this.activeFile.fileName);
816852
this.testDiagnostics(expected, diagnostics);
@@ -856,30 +892,12 @@ namespace FourSlash {
856892
displayParts: ts.SymbolDisplayPart[],
857893
documentation: ts.SymbolDisplayPart[]) {
858894

859-
function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) {
860-
let result = "";
861-
ts.forEach(displayParts, part => {
862-
if (result) {
863-
result += ",\n ";
864-
}
865-
else {
866-
result = "[\n ";
867-
}
868-
result += JSON.stringify(part);
869-
});
870-
if (result) {
871-
result += "\n]";
872-
}
873-
874-
return result;
875-
}
876-
877895
const actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition);
878896
assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind"));
879897
assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers"));
880898
assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan"));
881-
assert.equal(getDisplayPartsJson(actualQuickInfo.displayParts), getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts"));
882-
assert.equal(getDisplayPartsJson(actualQuickInfo.documentation), getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation"));
899+
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.displayParts), TestState.getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts"));
900+
assert.equal(TestState.getDisplayPartsJson(actualQuickInfo.documentation), TestState.getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation"));
883901
}
884902

885903
public verifyRenameLocations(findInStrings: boolean, findInComments: boolean, ranges?: Range[]) {
@@ -2947,6 +2965,10 @@ namespace FourSlashInterface {
29472965
this.state.verifyRangesReferenceEachOther(ranges);
29482966
}
29492967

2968+
public findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]) {
2969+
this.state.verifyDisplayPartsOfReferencedSymbol(expected);
2970+
}
2971+
29502972
public rangesWithSameTextReferenceEachOther() {
29512973
this.state.verifyRangesWithSameTextReferenceEachOther();
29522974
}

src/services/services.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,8 +1373,12 @@ namespace ts {
13731373
containerName: string;
13741374
}
13751375

1376+
export interface ReferencedSymbolDefinitionInfo extends DefinitionInfo {
1377+
displayParts: SymbolDisplayPart[];
1378+
}
1379+
13761380
export interface ReferencedSymbol {
1377-
definition: DefinitionInfo;
1381+
definition: ReferencedSymbolDefinitionInfo;
13781382
references: ReferenceEntry[];
13791383
}
13801384

@@ -6107,7 +6111,7 @@ namespace ts {
61076111

61086112
return result;
61096113

6110-
function getDefinition(symbol: Symbol): DefinitionInfo {
6114+
function getDefinition(symbol: Symbol): ReferencedSymbolDefinitionInfo {
61116115
const info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), node);
61126116
const name = map(info.displayParts, p => p.text).join("");
61136117
const declarations = symbol.declarations;
@@ -6121,7 +6125,8 @@ namespace ts {
61216125
name,
61226126
kind: info.symbolKind,
61236127
fileName: declarations[0].getSourceFile().fileName,
6124-
textSpan: createTextSpan(declarations[0].getStart(), 0)
6128+
textSpan: createTextSpan(declarations[0].getStart(), 0),
6129+
displayParts: info.displayParts
61256130
};
61266131
}
61276132

@@ -6316,13 +6321,14 @@ namespace ts {
63166321
}
63176322
});
63186323

6319-
const definition: DefinitionInfo = {
6324+
const definition: ReferencedSymbolDefinitionInfo = {
63206325
containerKind: "",
63216326
containerName: "",
63226327
fileName: targetLabel.getSourceFile().fileName,
63236328
kind: ScriptElementKind.label,
63246329
name: labelName,
6325-
textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd())
6330+
textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()),
6331+
displayParts: [displayPart(labelName, SymbolDisplayPartKind.text)]
63266332
};
63276333

63286334
return [{ definition, references }];
@@ -6562,14 +6568,20 @@ namespace ts {
65626568
getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references);
65636569
}
65646570

6571+
const thisOrSuperSymbol = typeChecker.getSymbolAtLocation(thisOrSuperKeyword);
6572+
6573+
const displayParts = thisOrSuperSymbol && getSymbolDisplayPartsDocumentationAndSymbolKind(
6574+
thisOrSuperSymbol, thisOrSuperKeyword.getSourceFile(), getContainerNode(thisOrSuperKeyword), thisOrSuperKeyword).displayParts;
6575+
65656576
return [{
65666577
definition: {
65676578
containerKind: "",
65686579
containerName: "",
65696580
fileName: node.getSourceFile().fileName,
65706581
kind: ScriptElementKind.variableElement,
65716582
name: "this",
6572-
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd())
6583+
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()),
6584+
displayParts
65736585
},
65746586
references: references
65756587
}];
@@ -6640,7 +6652,8 @@ namespace ts {
66406652
fileName: node.getSourceFile().fileName,
66416653
kind: ScriptElementKind.variableElement,
66426654
name: type.text,
6643-
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd())
6655+
textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()),
6656+
displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)]
66446657
},
66456658
references: references
66466659
}];
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
//// class Gre/*1*/eter {
4+
//// someFunction() { th/*2*/is; }
5+
//// }
6+
////
7+
//// type Options = "opt/*3*/ion 1" | "option 2";
8+
//// let myOption: Options = "option 1";
9+
////
10+
//// some/*4*/Label:
11+
//// break someLabel;
12+
13+
goTo.marker("1");
14+
verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "Greeter", kind: "className" }]);
15+
16+
goTo.marker("2");
17+
verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "this", kind: "keyword" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "this", kind: "keyword" }]);
18+
19+
goTo.marker("3");
20+
verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "\"option 1\"", kind: "stringLiteral" }]);
21+
22+
goTo.marker("4");
23+
verify.findReferencesDefinitionDisplayPartsAtCaretAre([{ text: "someLabel", kind: "text" }]);

tests/cases/fourslash/fourslash.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ declare namespace FourSlashInterface {
171171
* If `ranges` is omitted, this is `test.ranges()`.
172172
*/
173173
rangesReferenceEachOther(ranges?: Range[]): void;
174+
findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]): void;
174175
rangesWithSameTextReferenceEachOther(): void;
175176
currentParameterHelpArgumentNameIs(name: string): void;
176177
currentParameterSpanIs(parameter: string): void;

0 commit comments

Comments
 (0)