C# Language
.NET 컴파일러 플랫폼 (Roslyn)
수색…
MSBuild 프로젝트에서 작업 공간 생성
계속하기 전에 먼저 Microsoft.CodeAnalysis.CSharp.Workspaces
Nuget을 가져옵니다.
var workspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(projectFilePath);
var compilation = await project.GetCompilationAsync();
foreach (var diagnostic in compilation.GetDiagnostics()
.Where(d => d.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error))
{
Console.WriteLine(diagnostic);
}
작업 영역에 기존 코드를로드하려면 오류를 컴파일하고보고하십시오. 그 후 코드가 메모리에 저장됩니다. 여기에서 통사론과 의미 론적 측면 모두를 사용할 수 있습니다.
구문 트리
구문 트리 (Syntax Tree) 는 프로그램을 이름, 명령 및 표시의 트리로 나타내는 불변의 데이터 구조입니다 (이전에 편집기에서 구성한대로).
예를 들어 compilation
이라는 Microsoft.CodeAnalysis.Compilation
인스턴스가 구성되어 있다고 가정합니다. 로드 된 코드에서 선언 된 모든 변수의 이름을 나열하는 여러 가지 방법이 있습니다. 이렇게 순진하게하기 위해서는 모든 문서 ( DescendantNodes
메소드)의 모든 구문을 가져 와서 Linq를 사용하여 변수 선언을 설명하는 노드를 선택하십시오.
foreach (var syntaxTree in compilation.SyntaxTrees)
{
var root = await syntaxTree.GetRootAsync();
var declaredIdentifiers = root.DescendantNodes()
.Where(an => an is VariableDeclaratorSyntax)
.Cast<VariableDeclaratorSyntax>()
.Select(vd => vd.Identifier);
foreach (var di in declaredIdentifiers)
{
Console.WriteLine(di);
}
}
해당 유형을 가진 모든 유형의 C # 구문이 구문 트리에 존재합니다. 특정 유형을 빨리 찾으려면 Visual Studio의 Syntax Visualizer
창을 사용하십시오. 그러면 현재 열려있는 문서가 Roslyn 구문 트리로 해석됩니다.
시맨틱 모델
시맨틱 모델 (Semantic Model) 은 구문 트리와 비교하여 코드 해석 및 통찰력이 더 깊다. 구문 트리가 변수의 이름을 말할 수있는 곳에서 의미 론적 모델은 유형과 모든 참조를 제공합니다. 구문 트리는 메서드 호출을 인식하지만 의미 론적 모델은 메서드가 선언 된 정확한 위치에 대한 참조를 제공합니다 (오버로드 확인이 적용된 후).
var workspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var sln = await workspace.OpenSolutionAsync(solutionFilePath);
var project = sln.Projects.First();
var compilation = await project.GetCompilationAsync();
foreach (var syntaxTree in compilation.SyntaxTrees)
{
var root = await syntaxTree.GetRootAsync();
var declaredIdentifiers = root.DescendantNodes()
.Where(an => an is VariableDeclaratorSyntax)
.Cast<VariableDeclaratorSyntax>();
foreach (var di in declaredIdentifiers)
{
Console.WriteLine(di.Identifier);
// => "root"
var variableSymbol = compilation
.GetSemanticModel(syntaxTree)
.GetDeclaredSymbol(di) as ILocalSymbol;
Console.WriteLine(variableSymbol.Type);
// => "Microsoft.CodeAnalysis.SyntaxNode"
var references = await SymbolFinder.FindReferencesAsync(variableSymbol, sln);
foreach (var reference in references)
{
foreach (var loc in reference.Locations)
{
Console.WriteLine(loc.Location.SourceSpan);
// => "[1375..1379)"
}
}
}
}
구문 트리를 사용하여 로컬 변수 목록을 출력합니다. 그런 다음 의미 론적 모델을 참조하여 전체 유형 이름을 얻고 모든 변수의 모든 참조를 찾습니다.