提交 b45ceeaf 编写于 作者: C Cyrus Najmabadi

Have goto def go to implemented interface members if on an implementation already

上级 3b7504db
......@@ -938,4 +938,7 @@ Do you want to proceed?</value>
<data name="Removal_of_document_not_supported" xml:space="preserve">
<value>Removal of document not supported</value>
</data>
</root>
<data name="_0_implemented_members" xml:space="preserve">
<value>'{0}' implemented members</value>
</data>
</root>
\ No newline at end of file
......@@ -4,9 +4,11 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.FindUsages;
using Microsoft.CodeAnalysis.Editor.Host;
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Navigation;
......@@ -52,9 +54,11 @@ public bool TryGoToDefinition(Document document, int position, CancellationToken
var symbolService = document.GetLanguageService<IGoToDefinitionSymbolService>();
var (symbol, _) = symbolService.GetSymbolAndBoundSpanAsync(document, position, includeType: true, cancellationToken).WaitAndGetResult(cancellationToken);
if (symbol is null)
{
return false;
}
var remapped = TryRemapIfAlreadyOnDefinition(document, position, symbol, cancellationToken);
if (remapped)
return true;
var isThirdPartyNavigationAllowed = IsThirdPartyNavigationAllowed(symbol, position, document, cancellationToken);
......@@ -62,10 +66,47 @@ public bool TryGoToDefinition(Document document, int position, CancellationToken
document.Project,
_streamingPresenter.Value,
thirdPartyNavigationAllowed: isThirdPartyNavigationAllowed,
throwOnHiddenDefinition: true,
cancellationToken: cancellationToken);
}
private bool TryRemapIfAlreadyOnDefinition(
Document document, int position,
ISymbol symbol, CancellationToken cancellationToken)
{
var project = document.Project;
var solution = project.Solution;
// if the symbol only has a single source location, and we're already on it,
// try to see if there's a better symbol we could navigate to.
var sourceLocations = symbol.Locations.WhereAsArray(loc => loc.IsInSource);
if (sourceLocations.Length != 1)
return false;
var definitionLocation = sourceLocations[0];
if (!definitionLocation.SourceSpan.IntersectsWith(position))
return false;
var definitionTree = definitionLocation.SourceTree;
var definitionDocument = solution.GetDocument(definitionTree);
if (definitionDocument != document)
return false;
// Ok, found a match. Look for better symbols we could show results for instead.
var interfaceImpls = symbol.ExplicitOrImplicitInterfaceImplementations();
if (interfaceImpls.Length == 0)
return false;
var definitions = interfaceImpls.SelectMany(
i => GoToDefinitionHelpers.GetDefinitions(
i, project, thirdPartyNavigationAllowed: false, cancellationToken)).ToImmutableArray();
var title = string.Format(EditorFeaturesResources._0_implemented_members,
FindUsagesHelpers.GetDisplayName(symbol));
return _streamingPresenter.Value.TryNavigateToOrPresentItemsAsync(
solution.Workspace, title, definitions).WaitAndGetResult(cancellationToken);
}
private static bool IsThirdPartyNavigationAllowed(ISymbol symbolToNavigateTo, int caretPosition, Document document, CancellationToken cancellationToken)
{
var syntaxRoot = document.GetSyntaxRootSynchronously(cancellationToken);
......
......@@ -99,8 +99,7 @@ internal static class GoToDefinitionHelpers
Project project,
IStreamingFindUsagesPresenter streamingPresenter,
CancellationToken cancellationToken,
bool thirdPartyNavigationAllowed = true,
bool throwOnHiddenDefinition = false)
bool thirdPartyNavigationAllowed = true)
{
var definitions = GetDefinitions(symbol, project, thirdPartyNavigationAllowed, cancellationToken);
......
......@@ -402,6 +402,11 @@
<target state="translated">Vyřeší se tento počet konfliktů: {0}.</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">Počet nevyřešených konfliktů: {0}</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">{0} Konflikt(e) werden gelöst</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} nicht lösbare Konflikt(s)</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">Se va(n) a resolver {0} conflicto(s)</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} conflicto(s) sin solución</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">{0} conflit(s) seront résolus</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} conflit(s) ne pouvant pas être résolu(s)</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">Verranno risolti {0} conflitti</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} conflitti non risolti</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">{0} 個の競合が解決されます</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">未解決の競合 {0}</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">충돌 {0}개가 해결됩니다.</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">해결할 수 없는 충돌 {0}개</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">Następująca liczba konfliktów zostanie rozwiązana: {0}</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">Liczba nierozwiązanych konfliktów: {0}</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">{0} conflito(s) será(ão) resolvido(s)</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} conflito(s) não solucionável(is)</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">Конфликтов будет разрешено: {0}</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} неразрешимые конфликты</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">{0} çakışmaları çözümlenecek</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} çözümlenemeyen çakışma</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">将解决 {0} 个冲突</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">{0} 个无法解决的冲突</target>
......
......@@ -402,6 +402,11 @@
<target state="translated">將解決 {0} 項衝突</target>
<note />
</trans-unit>
<trans-unit id="_0_implemented_members">
<source>'{0}' implemented members</source>
<target state="new">'{0}' implemented members</target>
<note />
</trans-unit>
<trans-unit id="_0_unresolvable_conflict_s">
<source>{0} unresolvable conflict(s)</source>
<target state="translated">有 {0} 個未解決的衝突</target>
......
......@@ -962,6 +962,75 @@ class C
Test(workspace)
End Sub
<WorkItem(41870, "https://github.com/dotnet/roslyn/issues/41870")>
<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestCSharpGoToImplementedInterfaceMemberFromImpl1()
Dim workspace =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
interface IFoo1 { void [|Bar|](); }
class Foo : IFoo1
{
public void $$Bar()
{
}
}
</Document>
</Project>
</Workspace>
Test(workspace)
End Sub
<WorkItem(41870, "https://github.com/dotnet/roslyn/issues/41870")>
<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestCSharpGoToImplementedInterfaceMemberFromImpl2()
Dim workspace =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
interface IFoo1 { void [|Bar|](); }
class Foo : IFoo1
{
void IFoo1.$$Bar()
{
}
}
</Document>
</Project>
</Workspace>
Test(workspace)
End Sub
<WorkItem(41870, "https://github.com/dotnet/roslyn/issues/41870")>
<WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition)>
Public Sub TestCSharpGoToImplementedInterfaceMemberFromImpl3()
Dim workspace =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
interface IFoo1 { void [|Bar|](); }
interface IFoo2 { void [|Bar|](); }
class Foo : IFoo1, IFoo2
{
public void $$Bar()
{
}
}
</Document>
</Project>
</Workspace>
Test(workspace)
End Sub
#End Region
#Region "CSharp TupleTests"
......
......@@ -106,6 +106,9 @@ public static ImmutableArray<ISymbol> ExplicitInterfaceImplementations(this ISym
public static ImmutableArray<ISymbol> ExplicitOrImplicitInterfaceImplementations(this ISymbol symbol)
{
if (symbol.Kind != SymbolKind.Method && symbol.Kind != SymbolKind.Property && symbol.Kind != SymbolKind.Event)
return ImmutableArray<ISymbol>.Empty;
var containingType = symbol.ContainingType;
var query = from iface in containingType.AllInterfaces
from interfaceMember in iface.GetMembers()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册