使用.Net编译器Roslyn为c#代码创建控制流图

问题描述 投票:2回答:2

我找不到使用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

如果有人知道如何使用这个命名空间来构建控制流图或者是否有一个例子可以使用。谢谢

c# roslyn roslyn-code-analysis control-flow-graph
2个回答
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的分析......

卡雷尔


0
投票

根据Karel的答案和注释,这是如何创建一个没有错误的控制流图:

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);
© www.soinside.com 2019 - 2024. All rights reserved.