使用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
方法。
答案 0 :(得分:3)
您需要语义模型,它来自authorization_endpoint
(带参考和配置)。
然后,您可以在该节点上调用Compilation
并转换为GetTypeSymbol()
。
答案 1 :(得分:2)
您应该查找ReturnStatementSyntax
和TypeOfExpressionSyntax
。其中包含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;
}