Using Roslyn I'm trying to interpret some code that looks something like this:
public class Foo
{
public override Type BarType
{
get { return typeof(MyBar); }
}
}
What I would like to do is get MyBar
and then get that type as a symbol, but I'm not sure if this is even something that is possible or practical to do. I'm going to have several classes that look like this and all derive from a base class.
Given the ClassDeclarationSyntax
for Foo
, I can do this:
var prop = syntax.DescendantNodes().OfType<PropertyDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ToString() == "BarType");
Or given the INamedTypeSymbol
for Foo
, I can do this:
var member = symbol.GetMembers("BarType").FirstOrDefault();
But I don't know where to go from there.
Ultimately I want to be able to get the symbol for MyBar
for further analysis, so maybe even getting the string "MyBar"
isn't going to help because it's not fully qualified.
Any suggestions?
EDIT:
I'm getting a project and a compilation like this:
var workspace = MSBuildWorkspace.Create();
var project = workspace.OpenProjectAsync(projectPath).Result;
var compilation = project.GetCompilationAsync().Result;
compilation
is a CSharpCompilation
here. From there I do something like this:
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...
}
}
Either way I get model
I end up with a SyntaxTreeSemanticModel
which doesn't seem to have a GetTypeSymbol
method.
You should look for the ReturnStatementSyntax
and TypeOfExpressionSyntax
. This contains the type MyBar
. With the SemanticModel
you can get the SymbolInfo
like this:
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;
}
}
}
}
You can also use a SyntaxWalker
for this:
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 );
}
}
Usage:
var classDeclarationSyntaxs = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach ( var classDeclarationSyntax in classDeclarationSyntaxs )
{
var typeOfSyntaxWalker = new TypeOfSyntaxWalker( semanticModel );
typeOfSyntaxWalker.VisitClassDeclaration( classDeclarationSyntax );
var symbolInfoSymbol = typeOfSyntaxWalker.SymbolInfoSymbol;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With