我找不到使用Roslyn为c#代码构造控制流程图的方法。
我知道Roslyn编译器中有一个名为“ Microsoft.CodeAnalysis.FlowAnalysis”的命名空间,其中包含一些用于创建控制流图的类,但是我不知道如何使用它。
https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.flowanalysis?view=roslyn-dotnet
有一个名为ControlFlowGraph.cs的类,但是问题是我无法从此类创建对象或子类。 https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.flowanalysis.controlflowgraph?view=roslyn-dotnet
请问是否有人知道如何使用此命名空间来构造控制流程图,或者是否有使用示例。 谢谢
答案 0 :(得分:2)
我设法从方法节点创建CFG:
CSharpParseOptions options = CSharpParseOptions.Default
.WithFeatures(new[] { new KeyValuePair<string, string>("flow-analysis", "")
});
MSBuildWorkspace workspace = MSBuildWorkspace.Create();
Solution solution = workspace.OpenSolutionAsync(solutionUrl).Result; // path to your SLN file
ProjectDependencyGraph projectGraph = solution.GetProjectDependencyGraph();
Dictionary<string, Stream> assemblies = new Dictionary<string, Stream>();
var projects = projectGraph.GetTopologicallySortedProjects().ToDictionary(
p => p,
p => solution.GetProject(p).Name);
var bllProjectId = projects.First(p => p.Value == "<your project name>").Key; // choose project for analysis
var projectId = bllProjectId;
solution = solution.WithProjectParseOptions(projectId, options);
Compilation compilation = solution.GetProject(projectId).GetCompilationAsync().Result;
if (compilation != null && !string.IsNullOrEmpty(compilation.AssemblyName))
{
var syntaxTree = compilation.SyntaxTrees.First();
// get syntax nodes for methods
var methodNodes = from methodDeclaration in syntaxTree.GetRoot().DescendantNodes()
.Where(x => x is MethodDeclarationSyntax)
select methodDeclaration;
foreach (MethodDeclarationSyntax node in methodNodes)
{
var model = compilation.GetSemanticModel(node.SyntaxTree);
node.Identifier.ToString().Dump();
if (node.SyntaxTree.Options.Features.Any())
{
var graph = ControlFlowGraph.Create(node, model); // CFG is here
}
else
{
// "No features".Dump();
}
}
}
下一步将是分析CFG ...
Karel
答案 1 :(得分:0)
根据卡雷尔的回答和评论,这是如何创建没有错误的控制流图:
var source = @"
class C
{
int M(int x)
{
x = 0;
int y = x * 3;
return y;
}
}";
CSharpParseOptions options = CSharpParseOptions.Default
.WithFeatures(new[] { new KeyValuePair<string, string>("flow-analysis", "")});
var tree = CSharpSyntaxTree.ParseText(source, options);
var compilation = CSharpCompilation.Create("c", new[] { tree });
var model = compilation.GetSemanticModel(tree, ignoreAccessibility: true);
var methodBodySyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType<BaseMethodDeclarationSyntax>().Last();
var cfgFromSyntax = ControlFlowGraph.Create(methodBodySyntax, model);