Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve find implementations #1935

Merged
merged 4 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,25 @@ public async Task<QuickFixResponse> Handle(FindImplementationsRequest request)
var quickFixes = new List<QuickFix>();
var symbol = await SymbolFinder.FindSymbolAtPositionAsync(semanticModel, position, _workspace);

// SymbolFinder.FindImplementationsAsync will not include the method overrides
var implementations = await SymbolFinder.FindImplementationsAsync(symbol, _workspace.CurrentSolution);
foreach (var implementation in implementations)
if (symbol.IsInterfaceType() || symbol.IsImplementableMember())
{
quickFixes.Add(implementation, _workspace);

if (implementation.IsOverridable())
// SymbolFinder.FindImplementationsAsync will not include the method overrides
var implementations = await SymbolFinder.FindImplementationsAsync(symbol, _workspace.CurrentSolution);
foreach (var implementation in implementations)
{
var overrides = await SymbolFinder.FindOverridesAsync(implementation, _workspace.CurrentSolution);
quickFixes.AddRange(overrides, _workspace);
quickFixes.Add(implementation, _workspace);

if (implementation.IsOverridable())
{
var overrides = await SymbolFinder.FindOverridesAsync(implementation, _workspace.CurrentSolution);
quickFixes.AddRange(overrides, _workspace);
}
}
}

// for types also include derived classes
// for other symbols, find overrides and include those
if (symbol is INamedTypeSymbol namedTypeSymbol)
else if (symbol is INamedTypeSymbol namedTypeSymbol)
{
// for types also include derived classes
// for other symbols, find overrides and include those
var derivedTypes = await SymbolFinder.FindDerivedClassesAsync(namedTypeSymbol, _workspace.CurrentSolution);
quickFixes.AddRange(derivedTypes, _workspace);
}
Expand Down
33 changes: 33 additions & 0 deletions src/OmniSharp.Roslyn/Extensions/SymbolExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -297,5 +297,38 @@ internal static string GetFilePathForExternalSymbol(this ISymbol symbol, Project
}

private static string Folderize(string path) => string.Join("/", path.Split('.'));

public static bool IsInterfaceType(this ISymbol symbol) => (symbol as ITypeSymbol)?.IsInterfaceType() == true;

public static bool IsInterfaceType(this ITypeSymbol symbol) => symbol?.TypeKind == TypeKind.Interface;

public static bool IsImplementableMember(this ISymbol symbol)
{
if (symbol?.ContainingType?.TypeKind == TypeKind.Interface)
{
filipw marked this conversation as resolved.
Show resolved Hide resolved
if (symbol.Kind == SymbolKind.Event)
{
return true;
}

if (symbol.Kind == SymbolKind.Property)
{
return true;
}

if (symbol.Kind == SymbolKind.Method)
{
var methodSymbol = (IMethodSymbol)symbol;
if (methodSymbol.MethodKind == MethodKind.Ordinary ||
methodSymbol.MethodKind == MethodKind.PropertyGet ||
methodSymbol.MethodKind == MethodKind.PropertySet)
{
return true;
}
}
}

return false;
}
}
}