Получить тип "var" с Roslyn?
У меня есть файл .cs с именем test.cs, который выглядит примерно так:
namespace test
{
public class TestClass
{
public void Hello()
{
var x = 1;
}
}
}
Я пытаюсь разобрать это с Roslyn и получить тип x, который должен быть "int", но я могу только узнать, что он набирает "var", я не могу получить фактический базовый тип.
Вот в основном, что мой код сейчас
var location = "test.cs";
var sourceTree = CSharpSyntaxTree.ParseFile(location);
var root = (CompilationUnitSyntax)sourceTree.GetRoot();
foreach (var member in root.Members)
{
//...get to a method
var method = (MethodDeclarationSyntax())member;
foreach (var child in method.Body.ChildNodes())
{
if (child is LocalDeclarationStatementSyntax)
{
//var x = 1;
child.Type.RealType()?
}
}
}
Как я могу получить реальный тип ребенка? Я видел некоторые вещи, говоря, что я должен использовать SemanticModel или Solution или Workspace, но я не могу понять, как загрузить мое тестовое решение с Roslyn, а затем получить тип "x".
Кроме того, я не смог найти действительно хорошую документацию Roslyn, все это, похоже, распространено среди множества разных версий и ничего для новичков, как я. Кто-нибудь знает о "вступлении к Roslyn" или подобном быстром старте, о котором я мог прочитать?
Ответы
Ответ 1
Чтобы получить фактический тип для переменной, объявленной с помощью var
, вызовите GetSymbolInfo()
на SemanticModel
. Вы можете открыть существующее решение с помощью MSBuildWorkspace
, затем перечислить его проекты и их документы. Используйте документ, чтобы получить его SyntaxRoot
и SemanticModel
, затем найдите VariableDeclarations
и извлеките символы для Type
объявленной переменной следующим образом:
var workspace = MSBuildWorkspace.Create();
var solution = workspace.OpenSolutionAsync("c:\\path\\to\\solution.sln").Result;
foreach (var document in solution.Projects.SelectMany(project => project.Documents))
{
var rootNode = document.GetSyntaxRootAsync().Result;
var semanticModel = document.GetSemanticModelAsync().Result;
var variableDeclarations = rootNode
.DescendantNodes()
.OfType<LocalDeclarationStatementSyntax>();
foreach (var variableDeclaration in variableDeclarations)
{
var symbolInfo = semanticModel.GetSymbolInfo(variableDeclaration.Declaration.Type);
var typeSymbol = symbolInfo.Symbol; // the type symbol for the variable..
}
}
Ответ 2
См. unit test, называемый TestGetDeclaredSymbolFromLocalDeclarator в дереве источников Roslyn.