Skip to content

Commit 2d7ee0d

Browse files
Update FAR and Go to Def to work on indexers (#76220)
2 parents 417f332 + 0134be4 commit 2d7ee0d

File tree

18 files changed

+146
-77
lines changed

18 files changed

+146
-77
lines changed

src/EditorFeatures/CSharp/InlineRename/CSharpEditorInlineRenameService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ await TryGetSurroundingNodeSpanAsync<MemberDeclarationSyntax>(renameDefinition.D
5353
if (symbolService is not null)
5454
{
5555
var textSpan = inlineRenameInfo.TriggerSpan;
56+
var semanticModel = await renameDefinition.Document.GetRequiredNullableDisabledSemanticModelAsync(cancellationToken).ConfigureAwait(false);
5657
var (symbol, _, _) = await symbolService.GetSymbolProjectAndBoundSpanAsync(
57-
renameDefinition.Document, textSpan.Start, cancellationToken)
58-
.ConfigureAwait(true);
58+
renameDefinition.Document, semanticModel, textSpan.Start, cancellationToken).ConfigureAwait(true);
5959
var docComment = symbol?.GetDocumentationCommentXml(expandIncludes: true, cancellationToken: cancellationToken);
6060
if (!string.IsNullOrWhiteSpace(docComment))
6161
{

src/EditorFeatures/Core/Navigation/AbstractDefinitionLocationService.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,17 @@ internal abstract partial class AbstractDefinitionLocationService(
5050

5151
async ValueTask<DefinitionLocation?> GetDefinitionLocationWorkerAsync(Document document)
5252
{
53-
return await GetControlFlowTargetLocationAsync(document).ConfigureAwait(false) ??
54-
await GetSymbolLocationAsync(document).ConfigureAwait(false);
53+
// We don't need nullable information to compute the symbol. So avoid expensive work computing this.
54+
var semanticModel = await document.GetRequiredNullableDisabledSemanticModelAsync(cancellationToken).ConfigureAwait(false);
55+
return await GetControlFlowTargetLocationAsync(document, semanticModel).ConfigureAwait(false) ??
56+
await GetSymbolLocationAsync(document, semanticModel).ConfigureAwait(false);
5557
}
5658

57-
async ValueTask<DefinitionLocation?> GetControlFlowTargetLocationAsync(Document document)
59+
async ValueTask<DefinitionLocation?> GetControlFlowTargetLocationAsync(
60+
Document document, SemanticModel semanticModel)
5861
{
5962
var (controlFlowTarget, controlFlowSpan) = await symbolService.GetTargetIfControlFlowAsync(
60-
document, position, cancellationToken).ConfigureAwait(false);
63+
document, semanticModel, position, cancellationToken).ConfigureAwait(false);
6164
if (controlFlowTarget == null)
6265
return null;
6366

@@ -66,11 +69,12 @@ internal abstract partial class AbstractDefinitionLocationService(
6669
return location is null ? null : new DefinitionLocation(location, new DocumentSpan(document, controlFlowSpan));
6770
}
6871

69-
async ValueTask<DefinitionLocation?> GetSymbolLocationAsync(Document document)
72+
async ValueTask<DefinitionLocation?> GetSymbolLocationAsync(
73+
Document document, SemanticModel semanticModel)
7074
{
7175
// Try to compute the referenced symbol and attempt to go to definition for the symbol.
7276
var (symbol, project, span) = await symbolService.GetSymbolProjectAndBoundSpanAsync(
73-
document, position, cancellationToken).ConfigureAwait(false);
77+
document, semanticModel, position, cancellationToken).ConfigureAwait(false);
7478
if (symbol is null)
7579
return null;
7680

src/EditorFeatures/Test2/FindReferences/FindReferencesTests.IndexerSymbols.vb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,32 @@ public class Test
336336
}
337337
</Document>
338338
</Project>
339+
</Workspace>
340+
Await TestAPIAndFeature(input, kind, host)
341+
End Function
342+
343+
<WpfTheory, CombinatorialData>
344+
<WorkItem("https://github.com/dotnet/roslyn/issues/31819")>
345+
Public Async Function TestCSharp_Indexer_AtReferenceLocation(kind As TestKind, host As TestHost) As Task
346+
Dim input =
347+
<Workspace>
348+
<Project Language="C#" CommonReferences="true">
349+
<Document>
350+
class C
351+
{
352+
public int {|Definition:this|}[int y] { get { } }
353+
}
354+
355+
class D
356+
{
357+
void Goo()
358+
{
359+
var q = new C();
360+
var b = q[||]$$[4];
361+
}
362+
}
363+
</Document>
364+
</Project>
339365
</Workspace>
340366
Await TestAPIAndFeature(input, kind, host)
341367
End Function

src/EditorFeatures/Test2/GoToDefinition/CSharpGoToDefinitionTests.vb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3819,6 +3819,50 @@ class Program
38193819
Await TestAsync(workspace)
38203820
End Function
38213821

3822+
<WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69916")>
3823+
Public Async Function TestCSharpGoToDefinition_OnElementAccessExpression1() As Task
3824+
Dim workspace =
3825+
<Workspace>
3826+
<Project Language="C#">
3827+
<Document>
3828+
class C
3829+
{
3830+
int [||]this[int i] => i;
3831+
3832+
void M(C c)
3833+
{
3834+
var v = c$$[0];
3835+
}
3836+
}s
3837+
</Document>
3838+
</Project>
3839+
</Workspace>
3840+
3841+
Await TestAsync(workspace)
3842+
End Function
3843+
3844+
<WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69916")>
3845+
Public Async Function TestCSharpGoToDefinition_OnElementAccessExpression2() As Task
3846+
Dim workspace =
3847+
<Workspace>
3848+
<Project Language="C#">
3849+
<Document>
3850+
class C
3851+
{
3852+
int [||]this[int i] => i;
3853+
3854+
void M(C c)
3855+
{
3856+
var v = c[0]$$;
3857+
}
3858+
}s
3859+
</Document>
3860+
</Project>
3861+
</Workspace>
3862+
3863+
Await TestAsync(workspace)
3864+
End Function
3865+
38223866
<WpfFact>
38233867
Public Async Function TestInterceptors_AttributeMissingVersion() As Task
38243868
Dim workspace =

src/EditorFeatures/Test2/ReferenceHighlighting/CSharpReferenceHighlightingTests.vb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
Imports Microsoft.CodeAnalysis.Remote.Testing
66

77
Namespace Microsoft.CodeAnalysis.Editor.UnitTests.ReferenceHighlighting
8-
Public Class CSharpReferenceHighlightingTests
8+
Public NotInheritable Class CSharpReferenceHighlightingTests
99
Inherits AbstractReferenceHighlightingTests
1010

1111
<WpfTheory, CombinatorialData>

src/Features/CSharp/Portable/QuickInfo/CSharpSemanticQuickInfoProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,9 @@ protected override NullableFlowState GetNullabilityAnalysis(SemanticModel semant
158158
}
159159

160160
var symbolService = document.GetRequiredLanguageService<IGoToDefinitionSymbolService>();
161+
var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);
161162
var (symbol, _, _) = await symbolService.GetSymbolProjectAndBoundSpanAsync(
162-
document, position, cancellationToken).ConfigureAwait(false);
163+
document, semanticModel, position, cancellationToken).ConfigureAwait(false);
163164

164165
// Don't show on-the-fly-docs for namespace symbols.
165166
if (symbol is null || symbol.IsNamespace())

src/Features/Core/Portable/FindUsages/AbstractFindUsagesService_FindReferences.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ private static async Task<bool> TryFindLiteralReferencesAsync(
179179
// bother with true/false/null as those are likely to have way too many results
180180
// to be useful.
181181
var token = await syntaxTree.GetTouchingTokenAsync(
182+
semanticModel: null,
182183
position,
183-
t => syntaxFacts.IsNumericLiteral(t) ||
184+
(_, t) => syntaxFacts.IsNumericLiteral(t) ||
184185
syntaxFacts.IsCharacterLiteral(t) ||
185186
syntaxFacts.IsStringLiteral(t),
186187
cancellationToken).ConfigureAwait(false);

src/Features/Core/Portable/GoToDefinition/AbstractGoToDefinitionSymbolService.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@ internal abstract class AbstractGoToDefinitionSymbolService : IGoToDefinitionSym
1919

2020
protected abstract int? GetTargetPositionIfControlFlow(SemanticModel semanticModel, SyntaxToken token);
2121

22-
public async Task<(ISymbol? symbol, Project project, TextSpan boundSpan)> GetSymbolProjectAndBoundSpanAsync(Document document, int position, CancellationToken cancellationToken)
22+
public async Task<(ISymbol? symbol, Project project, TextSpan boundSpan)> GetSymbolProjectAndBoundSpanAsync(
23+
Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken)
2324
{
2425
var project = document.Project;
2526
var services = document.Project.Solution.Services;
2627

27-
// We don't need nullable information to compute the symbol. So avoid expensive work computing this.
28-
var semanticModel = await document.GetRequiredNullableDisabledSemanticModelAsync(cancellationToken).ConfigureAwait(false);
2928
var semanticInfo = await SymbolFinder.GetSemanticInfoAtPositionAsync(semanticModel, position, services, cancellationToken).ConfigureAwait(false);
3029

3130
// Prefer references to declarations. It's more likely that the user is attempting to
@@ -62,18 +61,17 @@ internal abstract class AbstractGoToDefinitionSymbolService : IGoToDefinitionSym
6261
return (explicitlyDeclaredSymbol, project, semanticInfo.Span);
6362
}
6463

65-
public async Task<(int? targetPosition, TextSpan tokenSpan)> GetTargetIfControlFlowAsync(Document document, int position, CancellationToken cancellationToken)
64+
public async Task<(int? targetPosition, TextSpan tokenSpan)> GetTargetIfControlFlowAsync(
65+
Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken)
6666
{
67-
var syntaxTree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
67+
var syntaxTree = semanticModel.SyntaxTree;
6868
var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>();
69-
var token = await syntaxTree.GetTouchingTokenAsync(position, syntaxFacts.IsBindableToken, cancellationToken, findInsideTrivia: true).ConfigureAwait(false);
69+
var token = await syntaxTree.GetTouchingTokenAsync(
70+
semanticModel, position, syntaxFacts.IsBindableToken, cancellationToken, findInsideTrivia: true).ConfigureAwait(false);
7071

7172
if (token == default)
7273
return default;
7374

74-
// We don't need nullable information to compute control flow targets. So avoid expensive work computing this.
75-
var semanticModel = await document.GetRequiredNullableDisabledSemanticModelAsync(cancellationToken).ConfigureAwait(false);
76-
7775
return (GetTargetPositionIfControlFlow(semanticModel, token), token.Span);
7876
}
7977
}

src/Features/Core/Portable/GoToDefinition/IGoToDefinitionSymbolService.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ namespace Microsoft.CodeAnalysis.GoToDefinition;
1111

1212
internal interface IGoToDefinitionSymbolService : ILanguageService
1313
{
14-
Task<(ISymbol? symbol, Project project, TextSpan boundSpan)> GetSymbolProjectAndBoundSpanAsync(Document document, int position, CancellationToken cancellationToken);
14+
Task<(ISymbol? symbol, Project project, TextSpan boundSpan)> GetSymbolProjectAndBoundSpanAsync(
15+
Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken);
1516

1617
/// <summary>
1718
/// If the position is on a control flow keyword (continue, break, yield, return , etc), returns the relevant position in the corresponding control flow statement.
1819
/// Otherwise, returns null.
1920
/// </summary>
20-
Task<(int? targetPosition, TextSpan tokenSpan)> GetTargetIfControlFlowAsync(Document document, int position, CancellationToken cancellationToken);
21+
Task<(int? targetPosition, TextSpan tokenSpan)> GetTargetIfControlFlowAsync(
22+
Document document, SemanticModel semanticModel, int position, CancellationToken cancellationToken);
2123
}

src/Features/Core/Portable/Navigation/AbstractNavigableItemsService.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ await GetSymbolAsync(document.WithFrozenPartialSemantics(cancellationToken)).Con
4242

4343
async Task<(ISymbol symbol, Solution solution)?> GetSymbolAsync(Document document)
4444
{
45-
var (symbol, project, _) = await symbolService.GetSymbolProjectAndBoundSpanAsync(document, position, cancellationToken).ConfigureAwait(false);
45+
// No need for NRT analysis here as it doesn't affect navigation.
46+
var semanticModel = await document.GetRequiredNullableDisabledSemanticModelAsync(cancellationToken).ConfigureAwait(false);
47+
var (symbol, project, _) = await symbolService.GetSymbolProjectAndBoundSpanAsync(document, semanticModel, position, cancellationToken).ConfigureAwait(false);
4648

4749
var solution = project.Solution;
4850

0 commit comments

Comments
 (0)