diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index ca95ff34ebb72..f33768ebb7c58 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -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(); diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index dcbd07b4dbf09..821a3c40ec570 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -316,6 +316,10 @@ namespace FourSlashInterface { this.state.verifyTypeOfSymbolAtLocation(range, symbol, expected); } + public baselineFindAllReferences(markerName: string) { + this.state.verifyBaselineFindAllReferences(markerName); + } + public referenceGroups(starts: ArrayOrSingle | ArrayOrSingle, parts: ReferenceGroup[]) { this.state.verifyReferenceGroups(starts, parts); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 1d7dbb8d66915..158b16d00c7f1 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -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 : diff --git a/tests/baselines/reference/findAllReferencesUndefined.baseline.jsonc b/tests/baselines/reference/findAllReferencesUndefined.baseline.jsonc new file mode 100644 index 0000000000000..e9aa9e9d9bb6e --- /dev/null +++ b/tests/baselines/reference/findAllReferencesUndefined.baseline.jsonc @@ -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 + } + ] + } +] \ No newline at end of file diff --git a/tests/cases/fourslash/findAllReferencesUndefined.ts b/tests/cases/fourslash/findAllReferencesUndefined.ts new file mode 100644 index 0000000000000..f129b6d499074 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesUndefined.ts @@ -0,0 +1,11 @@ +/// + +// @Filename: /a.ts +//// /**/undefined; +//// +//// void undefined; + +// @Filename: /b.ts +//// undefined; + +verify.baselineFindAllReferences(""); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index a2be4e57a2e0a..6519e27fde00e 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -289,6 +289,7 @@ declare namespace FourSlashInterface { goToType(startMarkerNames: ArrayOrSingle, endMarkerNames: ArrayOrSingle): 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;