Skip to content

Commit

Permalink
[dotnet#23030] Disable literal Ctrl+Click navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
isc30 committed Feb 17, 2018
1 parent 467c216 commit fc50bd7
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public async Task<IEnumerable<INavigableItem>> FindDefinitionsAsync(
Document document, int position, CancellationToken cancellationToken)
{
var symbolService = document.GetLanguageService<IGoToDefinitionSymbolService>();
var (symbol, span) = await symbolService.GetSymbolAndBoundSpanAsync(document, position, cancellationToken).ConfigureAwait(false);
var (symbol, span) = await symbolService.GetSymbolAndBoundSpanAsync(document, position, includeLiterals: true, cancellationToken).ConfigureAwait(false);

// Try to compute source definitions from symbol.
var items = symbol != null
Expand All @@ -43,7 +43,7 @@ public bool TryGoToDefinition(Document document, int position, CancellationToken
{
// Try to compute the referenced symbol and attempt to go to definition for the symbol.
var symbolService = document.GetLanguageService<IGoToDefinitionSymbolService>();
var (symbol, _) = symbolService.GetSymbolAndBoundSpanAsync(document, position, cancellationToken).WaitAndGetResult(cancellationToken);
var (symbol, _) = symbolService.GetSymbolAndBoundSpanAsync(document, position, includeLiterals: true, cancellationToken).WaitAndGetResult(cancellationToken);
if (symbol is null)
{
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Editor.GoToDefinition
Expand All @@ -12,23 +13,36 @@ internal abstract class AbstractGoToDefinitionSymbolService : IGoToDefinitionSym
{
protected abstract ISymbol FindRelatedExplicitlyDeclaredSymbol(ISymbol symbol, Compilation compilation);

public async Task<(ISymbol, TextSpan)> GetSymbolAndBoundSpanAsync(Document document, int position, CancellationToken cancellationToken)
public async Task<(ISymbol, TextSpan)> GetSymbolAndBoundSpanAsync(Document document, int position, bool includeLiterals, CancellationToken cancellationToken)
{
var workspace = document.Project.Solution.Workspace;

var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var semanticInfo = await SymbolFinder.GetSemanticInfoAtPositionAsync(semanticModel, position, workspace, cancellationToken).ConfigureAwait(false);
var symbol = GetSymbol(semanticInfo, includeLiterals);

// prefer references to declarations. It's more likely that the user is attempting to
// go to a definition at some other location, rather than the definition they're on.
if (symbol is null)
{
return (null, semanticInfo.Span);
}

return (FindRelatedExplicitlyDeclaredSymbol(symbol, semanticModel.Compilation), semanticInfo.Span);
}

private ISymbol GetSymbol(TokenSemanticInfo semanticInfo, bool includeLiterals)
{
// Prefer references to declarations. It's more likely that the user is attempting to
// go to a definition at some other location, rather than the definition they're on.
// This can happen when a token is at a location that is both a reference and a definition.
// For example, on an anonymous type member declaration.
var symbol = semanticInfo.AliasSymbol ??
semanticInfo.ReferencedSymbols.FirstOrDefault() ??
semanticInfo.DeclaredSymbol ??
semanticInfo.Type;

return (FindRelatedExplicitlyDeclaredSymbol(symbol, semanticModel.Compilation), semanticInfo.Span);
var symbol = semanticInfo.AliasSymbol
?? semanticInfo.ReferencedSymbols.FirstOrDefault()
?? semanticInfo.DeclaredSymbol;

return includeLiterals
? (symbol ?? semanticInfo.Type)
: symbol;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public async Task GetSymbolsAsync(GoToSymbolContext context)
var cancellationToken = context.CancellationToken;

var service = document.GetLanguageService<IGoToDefinitionSymbolService>();
var (symbol, span) = await service.GetSymbolAndBoundSpanAsync(document, position, cancellationToken).ConfigureAwait(false);
var (symbol, span) = await service.GetSymbolAndBoundSpanAsync(document, position, includeLiterals: false, cancellationToken).ConfigureAwait(false);

if (symbol == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ namespace Microsoft.CodeAnalysis.Editor.GoToDefinition
{
internal interface IGoToDefinitionSymbolService : ILanguageService
{
Task<(ISymbol, TextSpan)> GetSymbolAndBoundSpanAsync(Document document, int position, CancellationToken cancellationToken);
Task<(ISymbol, TextSpan)> GetSymbolAndBoundSpanAsync(Document document, int position, bool includeLiterals, CancellationToken cancellationToken);
}
}
56 changes: 56 additions & 0 deletions src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,34 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.GoToDefinition
Test(workspace)
End Sub

<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestCSharpLiteralGoToDefinition()
Dim workspace =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
int x = 1$$23;
</Document>
</Project>
</Workspace>

Test(workspace)
End Sub

<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestCSharpStringLiteralGoToDefinition()
Dim workspace =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
string x = "wo$$ow";
</Document>
</Project>
</Workspace>

Test(workspace)
End Sub

<WorkItem(3589, "https://github.com/dotnet/roslyn/issues/3589")>
<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestCSharpGoToDefinitionOnAnonymousMember()
Expand Down Expand Up @@ -1457,6 +1485,34 @@ class D
Test(workspace)
End Sub

<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestVisualBasicLiteralGoToDefinition()
Dim workspace =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Dim x as Integer = 12$$3
</Document>
</Project>
</Workspace>

Test(workspace)
End Sub

<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestVisualBasicStringLiteralGoToDefinition()
Dim workspace =
<Workspace>
<Project Language="Visual Basic" CommonReferences="true">
<Document>
Dim x as String = "wo$$ow"
</Document>
</Project>
</Workspace>

Test(workspace)
End Sub

<WorkItem(541105, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541105")>
<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestVisualBasicPropertyBackingField()
Expand Down
66 changes: 64 additions & 2 deletions src/EditorFeatures/Test2/NavigableSymbols/NavigableSymbolsTest.vb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Imports Microsoft.VisualStudio.Composition
Imports Microsoft.VisualStudio.Text
Imports Roslyn.Test.Utilities
Imports Xunit
Imports Microsoft.VisualStudio.Language.Intellisense

Namespace Microsoft.CodeAnalysis.Editor.UnitTests.NavigableSymbols

Expand Down Expand Up @@ -45,6 +46,32 @@ class {|target:C|}
End Using
End Function

<WpfFact, Trait(Traits.Feature, Traits.Features.NavigableSymbols)>
Public Async Function TestCharpLiteral() As Task
Dim markup = "var x = {|literal:1$$23|};"
Dim text As String = Nothing
Dim position As Integer? = Nothing
Dim spans As IDictionary(Of String, ImmutableArray(Of TextSpan)) = Nothing
MarkupTestFile.GetPositionAndSpans(markup, text, position, spans)

Using workspace = TestWorkspace.CreateCSharp(text, exportProvider:=s_exportProvider)
Await TestNotNavigated(workspace, position.Value, spans)
End Using
End Function

<WpfFact, Trait(Traits.Feature, Traits.Features.NavigableSymbols)>
Public Async Function TestCharpStringLiteral() As Task
Dim markup = "var x = ""{|literal:w$$ow|}"";"
Dim text As String = Nothing
Dim position As Integer? = Nothing
Dim spans As IDictionary(Of String, ImmutableArray(Of TextSpan)) = Nothing
MarkupTestFile.GetPositionAndSpans(markup, text, position, spans)

Using workspace = TestWorkspace.CreateCSharp(text, exportProvider:=s_exportProvider)
Await TestNotNavigated(workspace, position.Value, spans)
End Using
End Function

<WpfFact, Trait(Traits.Feature, Traits.Features.NavigableSymbols)>
Public Async Function TestVB() As Task
Dim markup = "
Expand All @@ -61,14 +88,44 @@ End Class"
End Using
End Function

Private Async Function TestNavigated(workspace As TestWorkspace, position As Integer, spans As IDictionary(Of String, ImmutableArray(Of TextSpan))) As Task
<WpfFact, Trait(Traits.Feature, Traits.Features.NavigableSymbols)>
Public Async Function TestVBLiteral() As Task
Dim markup = "Dim x as Integer = {|literal:1$$23|}"
Dim text As String = Nothing
Dim position As Integer? = Nothing
Dim spans As IDictionary(Of String, ImmutableArray(Of TextSpan)) = Nothing
MarkupTestFile.GetPositionAndSpans(markup, text, position, spans)

Using workspace = TestWorkspace.CreateVisualBasic(text, exportProvider:=s_exportProvider)
Await TestNotNavigated(workspace, position.Value, spans)
End Using
End Function

<WpfFact, Trait(Traits.Feature, Traits.Features.NavigableSymbols)>
Public Async Function TestVBStringLiteral() As Task
Dim markup = "Dim x as String = ""{|literal:w$$ow|}"""
Dim text As String = Nothing
Dim position As Integer? = Nothing
Dim spans As IDictionary(Of String, ImmutableArray(Of TextSpan)) = Nothing
MarkupTestFile.GetPositionAndSpans(markup, text, position, spans)

Using workspace = TestWorkspace.CreateVisualBasic(text, exportProvider:=s_exportProvider)
Await TestNotNavigated(workspace, position.Value, spans)
End Using
End Function

Private Function ExtractSymbol(workspace As TestWorkspace, position As Integer, spans As IDictionary(Of String, ImmutableArray(Of TextSpan))) As Task(Of INavigableSymbol)
Dim presenter = {New Lazy(Of IStreamingFindUsagesPresenter)(Function() New MockStreamingFindUsagesPresenter(Sub() Return))}
Dim service = New NavigableSymbolService(TestWaitIndicator.Default, presenter)
Dim view = workspace.Documents.First().GetTextView()
Dim buffer = workspace.Documents.First().GetTextBuffer()
Dim triggerSpan = New SnapshotSpan(buffer.CurrentSnapshot, New Span(position, 0))
Dim source = service.TryCreateNavigableSymbolSource(view, buffer)
Dim symbol = Await source.GetNavigableSymbolAsync(triggerSpan, CancellationToken.None)
Return source.GetNavigableSymbolAsync(triggerSpan, CancellationToken.None)
End Function

Private Async Function TestNavigated(workspace As TestWorkspace, position As Integer, spans As IDictionary(Of String, ImmutableArray(Of TextSpan))) As Task
Dim symbol = Await ExtractSymbol(workspace, position, spans)

Dim highlightedSpan = spans("highlighted").First()
Dim navigationTarget = spans("target").First()
Expand All @@ -84,5 +141,10 @@ End Class"
Assert.Equal(True, navigationService.TryNavigateToSpanReturnValue)
Assert.Equal(navigationTarget, navigationService.ProvidedTextSpan)
End Function

Private Async Function TestNotNavigated(workspace As TestWorkspace, position As Integer, spans As IDictionary(Of String, ImmutableArray(Of TextSpan))) As Task
Dim symbol = Await ExtractSymbol(workspace, position, spans)
Assert.Null(symbol)
End Function
End Class
End Namespace

0 comments on commit fc50bd7

Please sign in to comment.