diff --git a/src/server/session.ts b/src/server/session.ts index 86d87ad023fda..dc5cc9a9628ec 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -412,6 +412,7 @@ namespace ts.server { let progress = false; perProjectResults.forEach((referencedSymbols, project) => { if (updatedProjects.has(project)) return; + if (!referencedSymbols) return; const updated = project.getLanguageService().updateIsDefinitionOfReferencedSymbols(referencedSymbols, knownSymbolSpans); if (updated) { updatedProjects.add(project); @@ -423,6 +424,7 @@ namespace ts.server { perProjectResults.forEach((referencedSymbols, project) => { if (updatedProjects.has(project)) return; + if (!referencedSymbols) return; for (const referencedSymbol of referencedSymbols) { for (const ref of referencedSymbol.references) { ref.isDefinition = false; @@ -441,27 +443,29 @@ namespace ts.server { // Otherwise, it just ends up attached to the first corresponding def we happen to process. The others may or may not be // dropped later when we check for defs with ref-count 0. perProjectResults.forEach((projectResults, project) => { - for (const referencedSymbol of projectResults) { - const mappedDefinitionFile = getMappedLocationForProject(documentSpanLocation(referencedSymbol.definition), project); - const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? - referencedSymbol.definition : - { - ...referencedSymbol.definition, - textSpan: createTextSpan(mappedDefinitionFile.pos, referencedSymbol.definition.textSpan.length), // Why would the length be the same in the original? - fileName: mappedDefinitionFile.fileName, - contextSpan: getMappedContextSpanForProject(referencedSymbol.definition, project) - }; + if (projectResults) { + for (const referencedSymbol of projectResults) { + const mappedDefinitionFile = getMappedLocationForProject(documentSpanLocation(referencedSymbol.definition), project); + const definition: ReferencedSymbolDefinitionInfo = mappedDefinitionFile === undefined ? + referencedSymbol.definition : + { + ...referencedSymbol.definition, + textSpan: createTextSpan(mappedDefinitionFile.pos, referencedSymbol.definition.textSpan.length), // Why would the length be the same in the original? + fileName: mappedDefinitionFile.fileName, + contextSpan: getMappedContextSpanForProject(referencedSymbol.definition, project) + }; - let symbolToAddTo = find(results, o => documentSpansEqual(o.definition, definition)); - if (!symbolToAddTo) { - symbolToAddTo = { definition, references: [] }; - results.push(symbolToAddTo); - } + let symbolToAddTo = find(results, o => documentSpansEqual(o.definition, definition)); + if (!symbolToAddTo) { + symbolToAddTo = { definition, references: [] }; + results.push(symbolToAddTo); + } - for (const ref of referencedSymbol.references) { - if (!seenRefs.has(ref) && !getMappedLocationForProject(documentSpanLocation(ref), project)) { - seenRefs.add(ref); - symbolToAddTo.references.push(ref); + for (const ref of referencedSymbol.references) { + if (!seenRefs.has(ref) && !getMappedLocationForProject(documentSpanLocation(ref), project)) { + seenRefs.add(ref); + symbolToAddTo.references.push(ref); + } } } } @@ -504,9 +508,9 @@ namespace ts.server { isForRename: boolean, getResultsForPosition: (project: Project, location: DocumentPosition) => readonly TResult[] | undefined, forPositionInResult: (result: TResult, cb: (location: DocumentPosition) => void) => void, - ): readonly TResult[] | ESMap { + ): readonly TResult[] | ESMap { // If `getResultsForPosition` returns results for a project, they go in here - const resultsMap = new Map(); + const resultsMap = new Map(); const queue: ProjectAndLocation[] = []; @@ -588,7 +592,8 @@ namespace ts.server { // it easier for the caller to skip post-processing. if (resultsMap.size === 1) { const it = resultsMap.values().next(); - return it.done ? emptyArray : it.value; // There may not be any results at all + Debug.assert(!it.done); + return it.value ?? emptyArray; } return resultsMap;