查找所有类声明而不是从Roslyn继承另一个类声明

时间:2015-01-30 10:40:20

标签: c# roslyn

我有一个包含CSharpCompilation数组的SyntaxTree实例,我正在尝试查找从类继承的所有类声明

e.g

// Not in syntax tree but referenced in project
public class Base{}

// In syntax tree, how to find all such classes?
public class MyClass : Base {}

我尝试了一些事情,但对所有选项感到困惑,似乎无法找到正确的方法。

我试图获取符号,但这对继承的类型不起作用

SyntaxTree[] trees = context.CSharpCompilation.SyntaxTrees;
IEnumerable<ISymbol> symbols = context.CSharpCompilation.GetSymbolsWithName(x => x == typeof(Base).Name, SymbolFilter.Type);

罗斯林的新手,非常感谢任何有关如何实现这一目标的建议或指示。

3 个答案:

答案 0 :(得分:7)

首先,你需要获得Base的符号。如果这是您事先知道的特定类型,则可以使用Compilation.GetTypeByMetadataName。该链接还将向您显示该方法的100多个示例。

从那里,这取决于你想要做什么。如果您是从分析器内部执行此操作(我怀疑来自&34; context.CSharpCompilation&#34;在您的代码中),并且您正在尝试识别然后检查这些派生的某些属性类型,你可以使用RegisterSymbolAction作为SymbolKind.NamedType,然后检查每个类型BaseType(可能递归,取决于你想要完成的内容),看看你是否找到上面的GetTypeByMetadataName发现的类型。

如果您在分析器的上下文之外进行解决方案范围的分析,那么Roslyn代码库中有helper for this,但它是内部的。existing request。有一个{{3}}可以公开ITypeSymbolExtensions,所以我在该请求中提到了这个帖子并建议将其扩展为包含INamedTypeSymbolExtensions。

答案 1 :(得分:2)

所以我提出了以下内容,它将以递归方式检查所有类的继承类型

public class BaseClassRewriter : CSharpSyntaxRewriter
{
    private readonly SemanticModel _model;

    public BaseClassRewriter(SemanticModel model)
    {
        _model = model;
    }

    public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        var symbol = _model.GetDeclaredSymbol(node);
        if (InheritsFrom<BaseClass>(symbol))
        {
            // hit!
        }
    }

    private bool InheritsFrom<T>(INamedTypeSymbol symbol)
    {
        while (true)
        {
            if (symbol.ToString() == typeof(T).FullName)
            {
                return true;
            }
            if (symbol.BaseType != null)
            {
                symbol = symbol.BaseType;
                continue;
            }
            break;
        }
        return false;
    }
}

答案 2 :(得分:1)

var classDecSynList = classDecSynList.Where(x=>
       (((IdentifierNameSyntax(x.BaseList.Types.FirstOrDefault()))
              .Identifier.ValueText=="Base"));

假设您拥有所有类声明语法列表;