Fix find-all-references on undefined (#39591)

* Fix find-all-references on `undefined`

* Show references in input files in baseline

* Inline commentEachLine

* firstOrUndefined doesn’t take undefined
This commit is contained in:
Andrew Branch
2020-07-13 17:21:16 -07:00
committed by GitHub
parent 1e7d0891fc
commit 3c91133f97
6 changed files with 120 additions and 1 deletions

View File

@@ -1084,6 +1084,43 @@ namespace FourSlash {
}
}
public verifyBaselineFindAllReferences(markerName: string) {
const marker = this.getMarkerByName(markerName);
const references = this.languageService.findReferences(marker.fileName, marker.position);
const refsByFile = references
? ts.group(ts.sort(ts.flatMap(references, r => r.references), (a, b) => a.textSpan.start - b.textSpan.start), ref => ref.fileName)
: ts.emptyArray;
// Write input files
let baselineContent = "";
for (const group of refsByFile) {
baselineContent += getBaselineContentForFile(group[0].fileName, this.getFileContent(group[0].fileName));
baselineContent += "\n\n";
}
// Write response JSON
baselineContent += JSON.stringify(references, undefined, 2);
Harness.Baseline.runBaseline(this.getBaselineFileNameForContainingTestFile(".baseline.jsonc"), baselineContent);
function getBaselineContentForFile(fileName: string, content: string) {
let newContent = `=== ${fileName} ===\n`;
let pos = 0;
for (const { textSpan } of refsByFile.find(refs => refs[0].fileName === fileName) ?? ts.emptyArray) {
if (fileName === marker.fileName && ts.textSpanContainsPosition(textSpan, marker.position)) {
newContent += "/*FIND ALL REFS*/";
}
const end = textSpan.start + textSpan.length;
newContent += content.slice(pos, textSpan.start);
newContent += "[|";
newContent += content.slice(textSpan.start, end);
newContent += "|]";
pos = end;
}
newContent += content.slice(pos);
return newContent.split(/\r?\n/).map(l => "// " + l).join("\n");
}
}
public verifyNoReferences(markerNameOrRange?: string | Range) {
if (markerNameOrRange !== undefined) this.goToMarkerOrRange(markerNameOrRange);
const refs = this.getReferencesAtCaret();

View File

@@ -316,6 +316,10 @@ namespace FourSlashInterface {
this.state.verifyTypeOfSymbolAtLocation(range, symbol, expected);
}
public baselineFindAllReferences(markerName: string) {
this.state.verifyBaselineFindAllReferences(markerName);
}
public referenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<FourSlash.Range>, parts: ReferenceGroup[]) {
this.state.verifyReferenceGroups(starts, parts);
}

View File

@@ -304,7 +304,7 @@ namespace ts.FindAllReferences {
const { symbol } = def;
const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, checker, originalNode);
const name = displayParts.map(p => p.text).join("");
const declaration = symbol.declarations ? first(symbol.declarations) : undefined;
const declaration = symbol.declarations && firstOrUndefined(symbol.declarations);
return {
node: declaration ?
getNameOfDeclaration(declaration) || declaration :

View File

@@ -0,0 +1,66 @@
// === /a.ts ===
// /*FIND ALL REFS*/[|undefined|];
//
// void [|undefined|];
// === /b.ts ===
// [|undefined|];
[
{
"definition": {
"containerKind": "",
"containerName": "",
"fileName": "/a.ts",
"kind": "var",
"name": "var undefined",
"textSpan": {
"start": 0,
"length": 9
},
"displayParts": [
{
"text": "var",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "undefined",
"kind": "propertyName"
}
]
},
"references": [
{
"textSpan": {
"start": 0,
"length": 9
},
"fileName": "/a.ts",
"isWriteAccess": false,
"isDefinition": false
},
{
"textSpan": {
"start": 17,
"length": 9
},
"fileName": "/a.ts",
"isWriteAccess": false,
"isDefinition": false
},
{
"textSpan": {
"start": 0,
"length": 9
},
"fileName": "/b.ts",
"isWriteAccess": false,
"isDefinition": false
}
]
}
]

View File

@@ -0,0 +1,11 @@
/// <reference path="fourslash.ts" />
// @Filename: /a.ts
//// /**/undefined;
////
//// void undefined;
// @Filename: /b.ts
//// undefined;
verify.baselineFindAllReferences("");

View File

@@ -289,6 +289,7 @@ declare namespace FourSlashInterface {
goToType(startMarkerNames: ArrayOrSingle<string>, endMarkerNames: ArrayOrSingle<string>): void;
verifyGetEmitOutputForCurrentFile(expected: string): void;
verifyGetEmitOutputContentsForCurrentFile(expected: ts.OutputFile[]): void;
baselineFindAllReferences(markerName: string): void;
noReferences(markerNameOrRange?: string | Range): void;
symbolAtLocation(startRange: Range, ...declarationRanges: Range[]): void;
typeOfSymbolAtLocation(range: Range, symbol: any, expected: string): void;