从Roslyn

时间:2017-11-03 20:53:47

标签: c# roslyn

使用Roslyn我试图解释一些看起来像这样的代码:

public class Foo
{
    public override Type BarType
    {
        get { return typeof(MyBar); }
    }
}

我想要做的是获取MyBar,然后将该类型作为符号,但我不确定这是否是可能或实际可行的事情。我将有几个看起来像这样的类,并且都来自基类。

鉴于ClassDeclarationSyntax的{​​{1}},我可以这样做:

Foo

或者var prop = syntax.DescendantNodes().OfType<PropertyDeclarationSyntax>() .FirstOrDefault(p => p.Identifier.ToString() == "BarType"); INamedTypeSymbol,我可以这样做:

Foo

但我不知道从哪里去。

最终我希望能够获得var member = symbol.GetMembers("BarType").FirstOrDefault(); 的符号以进行进一步分析,因此即使获得字符串MyBar也不会有帮助,因为它并不完全合格。

有什么建议吗?

修改

我正在获得一个项目和这样的汇编:

"MyBar"

var workspace = MSBuildWorkspace.Create(); var project = workspace.OpenProjectAsync(projectPath).Result; var compilation = project.GetCompilationAsync().Result; 此处为compilation。从那里我做这样的事情:

CSharpCompilation

无论哪种方式,我都会得到foreach (var doc in project.Documents) { Console.WriteLine($"Analyzing {doc.Name}"); //var model = doc.GetSemanticModelAsync().Result; var tree = doc.GetSyntaxTreeAsync().Result; var root = tree.GetRoot(); var model = compilation.GetSemanticModel(tree); var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>(); foreach (var syntax in classes) { var symbol = model.GetDeclaredSymbol(syntax); //... need to analyze properties in the class here... } } 我最终得到的model似乎没有SyntaxTreeSemanticModel方法。

2 个答案:

答案 0 :(得分:3)

您需要语义模型,它来自authorization_endpoint(带参考和配置)。

然后,您可以在该节点上调用Compilation并转换为GetTypeSymbol()

答案 1 :(得分:2)

您应该查找ReturnStatementSyntaxTypeOfExpressionSyntax。其中包含MyBar类型。使用SemanticModel,您可以获得SymbolInfo,如下所示:

var classDeclarationSyntaxs = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach ( var classDeclarationSyntax in classDeclarationSyntaxs )
{
    var propertyDeclarationSyntaxs = classDeclarationSyntax.Members.OfType<PropertyDeclarationSyntax>();
    var barTypePropertyDeclarationSyntax = propertyDeclarationSyntaxs.FirstOrDefault( p => p.Identifier.Text == "BarType" );
    if ( barTypePropertyDeclarationSyntax != null )
    {
        var returnStatementSyntax = barTypePropertyDeclarationSyntax.DescendantNodes().OfType<ReturnStatementSyntax>().FirstOrDefault();
        if ( returnStatementSyntax != null )
        {
            var typeOfExpressionSyntax = returnStatementSyntax.ChildNodes().OfType<TypeOfExpressionSyntax>().FirstOrDefault();
            if ( typeOfExpressionSyntax != null )
            {
                var symbolInfo = semanticModel.GetSymbolInfo( typeOfExpressionSyntax.Type );
                var symbolInfoSymbol = symbolInfo.Symbol;
            }
        }
    }
}

您也可以使用SyntaxWalker

public class TypeOfSyntaxWalker : CSharpSyntaxWalker
{
    private readonly SemanticModel _semanticModel;

    public ISymbol SymbolInfoSymbol { get; private set; }

    public TypeOfSyntaxWalker( SemanticModel semanticModel )
    {
        _semanticModel = semanticModel;
    }

    public override void VisitTypeOfExpression( TypeOfExpressionSyntax typeOfExpressionSyntax )
    {
        var parent = typeOfExpressionSyntax.Parent;
        if ( parent.Kind() == SyntaxKind.ReturnStatement )
        {
            var propertyDeclarationSyntax = parent.FirstAncestorOrSelf<PropertyDeclarationSyntax>();
            if ( propertyDeclarationSyntax != null &&
                    propertyDeclarationSyntax.Identifier.ValueText == "BarType" )
            {
                var symbolInfo = _semanticModel.GetSymbolInfo( typeOfExpressionSyntax.Type );
                SymbolInfoSymbol = symbolInfo.Symbol;
            }
        }
        base.VisitTypeOfExpression( typeOfExpressionSyntax );
    }
}

用法:

var classDeclarationSyntaxs = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach ( var classDeclarationSyntax in classDeclarationSyntaxs )
{
    var typeOfSyntaxWalker = new TypeOfSyntaxWalker( semanticModel );
    typeOfSyntaxWalker.VisitClassDeclaration( classDeclarationSyntax );
    var symbolInfoSymbol = typeOfSyntaxWalker.SymbolInfoSymbol;
}