HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Using Roslyn to find interfaces within a solution

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
roslynwithinusingfindinterfacessolution

Problem

The intent of the below code is to find all interfaces within a solution whose fully-qualified names match the given predicate. It seems to work, but as I am new to Roslyn I'm guessing there are things that could be improved. I'd appreciate any pointers.

public async Task> GetMatchingInterfacesInSolution(string solutionPath, Func predicate)
{
    var workspace = MSBuildWorkspace.Create();
    var solution = await workspace.OpenSolutionAsync(solutionPath);
    var compilations = await Task.WhenAll(solution.Projects.Select(x => x.GetCompilationAsync()));

    return compilations
        .SelectMany(x => x.SyntaxTrees.Select(y => new { Compilation = x, SyntaxTree = y }))
        .Select(x => x.Compilation.GetSemanticModel(x.SyntaxTree))
        .SelectMany(
            x => x
                .SyntaxTree
                .GetRoot()
                .DescendantNodes()
                .OfType()
                .Select(y => x.GetDeclaredSymbol(y)))
        .Where(x => predicate(x.ToDisplayString()))
        .ToImmutableList();
}


Here's another approach I tried. I couldn't really see any benefit to doing it this way. It's more verbose and difficult to follow:

```
public static async Task> GetMatchingInterfacesInSolution(string solutionPath, Func predicate)
{
var workspace = MSBuildWorkspace.Create();
var solution = await workspace.OpenSolutionAsync(solutionPath);
var compilations = await Task.WhenAll(solution.Projects.Select(x => x.GetCompilationAsync()));

return compilations
.Select(x => x.Assembly.GlobalNamespace)
.SelectMany(x => FindInterfacesRecursive(x, predicate))
.ToImmutableList();
}

private static IEnumerable FindInterfacesRecursive(INamespaceSymbol @namespace, Func predicate)
{
foreach (var member in @namespace.GetMembers())
{
var childNamespace = member as INamespaceSymbol;

if (childNamespace != null)
{
foreach (var @interface in FindInterfacesRecursive(childNamespace

Solution


  • Name captured variables as you would name local variables.



  • First SelectMany and Select can be merged into a single SelectMany.



code:

public async Task> GetMatchingInterfacesInSolution(string solutionPath, Func predicate)
{
    var workspace = MSBuildWorkspace.Create();
    var solution = await workspace.OpenSolutionAsync(solutionPath);
    var compilations = await Task.WhenAll(solution.Projects.Select(x => x.GetCompilationAsync()));

    return compilations
        .SelectMany(compilation => compilation.SyntaxTrees.Select(syntaxTree => compilation.GetSemanticModel(syntaxTree)))
        .SelectMany(
            semanticModel => semanticModel
                .SyntaxTree
                .GetRoot()
                .DescendantNodes()
                .OfType()
                .Select(interfaceDeclarationSyntax => semanticModel.GetDeclaredSymbol(interfaceDeclarationSyntax)))
        .Where(symbol => predicate(symbol.ToDisplayString()))
        .ToImmutableList();
}

Code Snippets

public async Task<IImmutableList<ISymbol>> GetMatchingInterfacesInSolution(string solutionPath, Func<string, bool> predicate)
{
    var workspace = MSBuildWorkspace.Create();
    var solution = await workspace.OpenSolutionAsync(solutionPath);
    var compilations = await Task.WhenAll(solution.Projects.Select(x => x.GetCompilationAsync()));

    return compilations
        .SelectMany(compilation => compilation.SyntaxTrees.Select(syntaxTree => compilation.GetSemanticModel(syntaxTree)))
        .SelectMany(
            semanticModel => semanticModel
                .SyntaxTree
                .GetRoot()
                .DescendantNodes()
                .OfType<InterfaceDeclarationSyntax>()
                .Select(interfaceDeclarationSyntax => semanticModel.GetDeclaredSymbol(interfaceDeclarationSyntax)))
        .Where(symbol => predicate(symbol.ToDisplayString()))
        .ToImmutableList();
}

Context

StackExchange Code Review Q#84932, answer score: 4

Revisions (0)

No revisions yet.