提交 58917650 编写于 作者: C CyrusNajmabadi

Properly 'go to implementation' when there are abstract overrides in the hierarchy.

上级 75084293
......@@ -413,5 +413,31 @@ class D : C
Await TestAsync(workspace)
End Function
<WpfFact, Trait(Traits.Feature, Traits.Features.GoToImplementation)>
<WorkItem(19700, "https://github.com/dotnet/roslyn/issues/19700")>
Public Async Function TestWithIntermediateAbstractOverrides() As Task
Dim workspace =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
abstract class A {
public virtual void $$[|M|]() { }
}
abstract class B : A {
public abstract override void M();
}
sealed class C1 : B {
public override void [|M|]() { }
}
sealed class C2 : A {
public override void [|M|]() => base.M();
}
</Document>
</Project>
</Workspace>
Await TestAsync(workspace)
End Function
End Class
End Namespace
\ No newline at end of file
......@@ -32,41 +32,48 @@ public static partial class SymbolFinder
internal static async Task<ImmutableArray<SymbolAndProjectId>> FindOverridesAsync(
SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects = null, CancellationToken cancellationToken = default(CancellationToken))
{
// Method can only have overrides if its a virtual, abstract or override and is not
// sealed.
var symbol = symbolAndProjectId.Symbol;
var results = ArrayBuilder<SymbolAndProjectId>.GetInstance();
var symbol = symbolAndProjectId.Symbol?.OriginalDefinition;
if (symbol.IsOverridable())
{
// To find the overrides, we need to walk down the type hierarchy and check all
// derived types. TODO(cyrusn): This seems extremely costly. Is there any way to
// speed this up?
var containingType = symbol.ContainingType.OriginalDefinition;
// derived types.
var containingType = symbol.ContainingType;
var derivedTypes = await FindDerivedClassesAsync(
symbolAndProjectId.WithSymbol(containingType),
solution, projects, cancellationToken).ConfigureAwait(false);
var results = ArrayBuilder<SymbolAndProjectId>.GetInstance();
foreach (var type in derivedTypes)
{
foreach (var m in GetMembers(type, symbol.Name))
foreach (var m in type.Symbol.GetMembers(symbol.Name))
{
var sourceMember = await FindSourceDefinitionAsync(m, solution, cancellationToken).ConfigureAwait(false);
var bestMember = sourceMember.Symbol != null ? sourceMember : m;
var member = bestMember.Symbol;
if (member != null &&
member.IsOverride &&
member.OverriddenMember() != null &&
OriginalSymbolsMatch(member.OverriddenMember().OriginalDefinition, symbol.OriginalDefinition, solution, cancellationToken))
var bestMember = sourceMember ?? m;
if (IsOverride(solution, bestMember, symbol, cancellationToken))
{
results.Add(bestMember);
results.Add(new SymbolAndProjectId(bestMember, type.ProjectId));
}
}
}
}
return results.ToImmutableAndFree();
return results.ToImmutableAndFree();
}
private static bool IsOverride(
Solution solution, ISymbol member, ISymbol symbol, CancellationToken cancellationToken)
{
for (var current = member; current != null; current = current.OverriddenMember())
{
if (OriginalSymbolsMatch(current.OverriddenMember(), symbol.OriginalDefinition, solution, cancellationToken))
{
return true;
}
}
return ImmutableArray<SymbolAndProjectId>.Empty;
return false;
}
/// <summary>
......
......@@ -102,12 +102,11 @@ public static ImmutableArray<ISymbol> ExplicitInterfaceImplementations(this ISym
public static bool IsOverridable(this ISymbol symbol)
{
return
symbol != null &&
symbol.ContainingType != null &&
symbol.ContainingType.TypeKind == TypeKind.Class &&
(symbol.IsVirtual || symbol.IsAbstract || symbol.IsOverride) &&
!symbol.IsSealed;
// Members can only have overrides if they are virtual, abstract or override and is not
// sealed.
return symbol?.ContainingType?.TypeKind == TypeKind.Class &&
(symbol.IsVirtual || symbol.IsAbstract || symbol.IsOverride) &&
!symbol.IsSealed;
}
public static bool IsImplementableMember(this ISymbol symbol)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册