Skip to content

Commit 3722bb7

Browse files
Merge pull request #19873 from CyrusNajmabadi/docHighlightsCrash
Fix crash in DocHighlights when delegating to a different language.
2 parents 237f04c + 02b5332 commit 3722bb7

File tree

3 files changed

+65
-10
lines changed

3 files changed

+65
-10
lines changed

src/EditorFeatures/Test2/EditorServicesTest2.vbproj

+1
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@
249249
<Compile Include="IntelliSense\CompletionRulesTests.vb" />
250250
<Compile Include="LanguageServices\SyntaxFactsServiceTests.vb" />
251251
<Compile Include="NamingStyles\NamingStylesTests.vb" />
252+
<Compile Include="ReferenceHighlighting\DocumentHighlightsServiceTests.vb" />
252253
<Compile Include="Simplification\BlockSimplificationTests.vb" />
253254
<Compile Include="Simplification\SimplifierAPITests.vb" />
254255
<Compile Include="CodeFixes\CodeFixServiceTests.vb" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
Imports System.Collections.Immutable
2+
Imports System.Threading
3+
Imports System.Threading.Tasks
4+
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
5+
6+
Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting
7+
Public Class DocumentHighlightsServiceTests
8+
9+
<WorkItem(441151, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/441151")>
10+
<Fact, Trait(Traits.Feature, Traits.Features.ReferenceHighlighting)>
11+
Public Async Function TestMultipleLanguagesPassedToAPI() As Task
12+
Dim workspaceElement =
13+
<Workspace>
14+
<Project Language="C#" CommonReferences="true">
15+
<Document>
16+
class C
17+
{
18+
$$string Blah()
19+
{
20+
return null;
21+
}
22+
}
23+
</Document>
24+
</Project>
25+
<Project Language="Visual Basic">
26+
<Document>
27+
Class VBClass
28+
End Class
29+
</Document>
30+
</Project>
31+
</Workspace>
32+
Using workspace = TestWorkspace.Create(workspaceElement)
33+
Dim position = workspace.DocumentWithCursor.CursorPosition.Value
34+
35+
Dim solution = workspace.CurrentSolution
36+
Dim csharpDocument = solution.Projects.Single(Function(p) p.Language = LanguageNames.CSharp).Documents.Single()
37+
Dim vbDocument = solution.Projects.Single(Function(p) p.Language = LanguageNames.VisualBasic).Documents.Single()
38+
39+
Dim service = csharpDocument.GetLanguageService(Of Microsoft.CodeAnalysis.DocumentHighlighting.IDocumentHighlightsService)
40+
Await service.GetDocumentHighlightsAsync(
41+
csharpDocument, position, ImmutableHashSet.Create(csharpDocument, vbDocument), CancellationToken.None)
42+
End Using
43+
End Function
44+
End Class
45+
End Namespace

src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs

+19-10
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ private async Task<ImmutableArray<DocumentHighlights>> GetDocumentHighlightsInCu
7676

7777
// Get unique tags for referenced symbols
7878
return await GetTagsForReferencedSymbolAsync(
79-
new SymbolAndProjectId(symbol, document.Project.Id), documentsToSearch,
80-
solution, cancellationToken).ConfigureAwait(false);
79+
new SymbolAndProjectId(symbol, document.Project.Id),
80+
document, documentsToSearch, cancellationToken).ConfigureAwait(false);
8181
}
8282

8383
private static async Task<ISymbol> GetSymbolToSearchAsync(Document document, int position, SemanticModel semanticModel, ISymbol symbol, CancellationToken cancellationToken)
@@ -95,8 +95,8 @@ private static async Task<ISymbol> GetSymbolToSearchAsync(Document document, int
9595

9696
private async Task<ImmutableArray<DocumentHighlights>> GetTagsForReferencedSymbolAsync(
9797
SymbolAndProjectId symbolAndProjectId,
98+
Document document,
9899
IImmutableSet<Document> documentsToSearch,
99-
Solution solution,
100100
CancellationToken cancellationToken)
101101
{
102102
var symbol = symbolAndProjectId.Symbol;
@@ -106,11 +106,11 @@ private async Task<ImmutableArray<DocumentHighlights>> GetTagsForReferencedSymbo
106106
var progress = new StreamingProgressCollector(
107107
StreamingFindReferencesProgress.Instance);
108108
await SymbolFinder.FindReferencesAsync(
109-
symbolAndProjectId, solution, progress,
109+
symbolAndProjectId, document.Project.Solution, progress,
110110
documentsToSearch, cancellationToken).ConfigureAwait(false);
111111

112112
return await FilterAndCreateSpansAsync(
113-
progress.GetReferencedSymbols(), solution, documentsToSearch,
113+
progress.GetReferencedSymbols(), document, documentsToSearch,
114114
symbol, cancellationToken).ConfigureAwait(false);
115115
}
116116

@@ -142,10 +142,12 @@ private static bool ShouldConsiderSymbol(ISymbol symbol)
142142
}
143143

144144
private async Task<ImmutableArray<DocumentHighlights>> FilterAndCreateSpansAsync(
145-
IEnumerable<ReferencedSymbol> references, Solution solution,
146-
IImmutableSet<Document> documentsToSearch, ISymbol symbol,
145+
IEnumerable<ReferencedSymbol> references, Document startingDocument,
146+
IImmutableSet<Document> documentsToSearch, ISymbol symbol,
147147
CancellationToken cancellationToken)
148148
{
149+
var solution = startingDocument.Project.Solution;
150+
149151
references = references.FilterToItemsToShow();
150152
references = references.FilterNonMatchingMethodNames(solution, symbol);
151153
references = references.FilterToAliasMatches(symbol as IAliasSymbol);
@@ -157,13 +159,20 @@ private async Task<ImmutableArray<DocumentHighlights>> FilterAndCreateSpansAsync
157159

158160
var additionalReferences = new List<Location>();
159161

160-
foreach (var document in documentsToSearch)
162+
foreach (var currentDocument in documentsToSearch)
161163
{
162-
additionalReferences.AddRange(await GetAdditionalReferencesAsync(document, symbol, cancellationToken).ConfigureAwait(false));
164+
// 'documentsToSearch' may contain documents from languages other than our own
165+
// (for example cshtml files when we're searching the cs document). Since we're
166+
// delegating to a virtual method for this language type, we have to make sure
167+
// we only process the document if it's also our language.
168+
if (currentDocument.Project.Language == startingDocument.Project.Language)
169+
{
170+
additionalReferences.AddRange(await GetAdditionalReferencesAsync(currentDocument, symbol, cancellationToken).ConfigureAwait(false));
171+
}
163172
}
164173

165174
return await CreateSpansAsync(
166-
solution, symbol, references, additionalReferences,
175+
solution, symbol, references, additionalReferences,
167176
documentsToSearch, cancellationToken).ConfigureAwait(false);
168177
}
169178

0 commit comments

Comments
 (0)