diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 7c5922035ea..268af57e5a3 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -424,7 +424,8 @@ namespace ts.FindAllReferences.Core { readonly text: string; readonly escapedText: __String; /** Only set if `options.implementations` is true. These are the symbols checked to get the implementations of a property access. */ - readonly parents: Symbol[] | undefined; + readonly parents: ReadonlyArray | undefined; + readonly allSearchSymbols: ReadonlyArray; /** * Whether a symbol is in the search set. @@ -500,14 +501,11 @@ namespace ts.FindAllReferences.Core { // here appears to be intentional). const { text = stripQuotes(unescapeLeadingUnderscores((getLocalSymbolForExportDefault(symbol) || symbol).escapedName)), - allSearchSymbols, + allSearchSymbols = [symbol], } = searchOptions; const escapedText = escapeLeadingUnderscores(text); const parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker); - return { - symbol, comingFrom, text, escapedText, parents, - includes: referenceSymbol => allSearchSymbols ? contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol, - }; + return { symbol, comingFrom, text, escapedText, parents, allSearchSymbols, includes: sym => contains(allSearchSymbols, sym) }; } private readonly symbolIdToReferences: Entry[][] = []; @@ -534,13 +532,17 @@ namespace ts.FindAllReferences.Core { } // Source file ID → symbol ID → Whether the symbol has been searched for in the source file. - private readonly sourceFileToSeenSymbols: true[][] = []; + private readonly sourceFileToSeenSymbols: Map[] = []; /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */ - markSearchedSymbol(sourceFile: SourceFile, symbol: Symbol): boolean { + markSearchedSymbols(sourceFile: SourceFile, symbols: ReadonlyArray): boolean { const sourceId = getNodeId(sourceFile); - const symbolId = getSymbolId(symbol); - const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = []); - return !seenSymbols[symbolId] && (seenSymbols[symbolId] = true); + const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = createMap()); + + let anyNewSymbols = false; + for (const sym of symbols) { + anyNewSymbols = addToSeen(seenSymbols, getSymbolId(sym)) || anyNewSymbols; + } + return anyNewSymbols; } } @@ -804,7 +806,7 @@ namespace ts.FindAllReferences.Core { * searchLocation: a node where the search value */ function getReferencesInContainer(container: Node, sourceFile: SourceFile, search: Search, state: State, addReferencesHere: boolean): void { - if (!state.markSearchedSymbol(sourceFile, search.symbol)) { + if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) { return; } diff --git a/tests/cases/fourslash/findAllReferencesDynamicImport3.ts b/tests/cases/fourslash/findAllReferencesDynamicImport3.ts index 21d2e1097db..636e640ceb3 100644 --- a/tests/cases/fourslash/findAllReferencesDynamicImport3.ts +++ b/tests/cases/fourslash/findAllReferencesDynamicImport3.ts @@ -1,13 +1,13 @@ /// // @Filename: foo.ts -//// export function [|bar|]() { return "bar"; } - -//// import('./foo').then(({ [|bar|] }) => undefined); +////export function [|{| "isWriteAccess": true, "isDefinition": true |}bar|]() { return "bar"; } +////import('./foo').then(({ [|{| "isWriteAccess": true, "isDefinition": true |}bar|] }) => undefined); const [r0, r1] = test.ranges(); -// This is because bindingElement at r1 are both name and value -verify.referencesOf(r0, [r1, r0, r1, r0]); -verify.referencesOf(r1, [r0, r1, r1, r0]); -verify.renameLocations(r0, [r0, r1]); -verify.renameLocations(r1, [r1, r0, r0, r1]); \ No newline at end of file +verify.referenceGroups(r0, [{ definition: "function bar(): string", ranges: [r0, r1] }]); +verify.referenceGroups(r1, [ + { definition: "function bar(): string", ranges: [r0] }, + { definition: "var bar: () => string", ranges: [r1] }, +]); +verify.rangesAreRenameLocations();