user32882
user32882

Reputation: 5877

PropertyDeclarationSyntax and MethodDeclarationSyntax have a common property but don't inherit from the same class or implement the same interface

In C# syntax analysis, the PropertyDeclarationSyntax and MethodDeclarationSyntax both have an Identifier property. However, they both inherit from CSharpSyntaxNode which does not.

I'd like to write a method that can take a CompilationUnitSyntax object, extract all PropertyDeclarationSyntax or MethodDeclarationSyntax objects from it and populate a list with their names. Here's what I have so far:

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Linq;

class Program
{

    static List<string> GrabNames(CompilationUnitSyntax root)
    {
        List<MethodDeclarationSyntax> methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>().ToList();
        List<string> methodNames = new List<string>();

        foreach (MethodDeclarationSyntax method in methods)
        {
            methodNames.Add(method.Identifier.Text);
        }

        return methodNames;
    }

    static void Main(string[] args)
    {
        string fileContainingCode = "test.cs"; // file path
        string CodeAsText = File.ReadAllText(fileContainingCode);
        SyntaxTree tree = CSharpSyntaxTree.ParseText(CodeAsText);
        CompilationUnitSyntax root = tree.GetCompilationUnitRoot();

        List<string> names = GrabNames(root);
}

I can think of one ugly solution, namely to add a string parameter called NodeTypeAsString and based on its value have two branches of an if statement do the exact same thing, but then on different types.

However, I'm thinking there has got to be a better/cleaner way. How can I achieve this without duplicating too much code?

Upvotes: 0

Views: 390

Answers (1)

Good Night Nerd Pride
Good Night Nerd Pride

Reputation: 8442

I don't think there is a clean OOP-style solution to this problem.

I suggest to use the following function:

string GetIdentifier(SyntaxNode node) => switch node {
    PropertyDeclarationSyntax p => p.Identifier,
    MethodDeclarationSyntax m => m.Identifier,
    _ => throw new NotSupportedException();
}

Use it like so:

var names = root
    .DescendantNodes()
    .Where(n => n.IsKind(SyntaxKind.PropertyDeclaration)
             || n.IsKind(SyntaxKind.MethodDeclaration))
    .Select(GetIdentifier)
    .ToArray();

Upvotes: 2

Related Questions