【问题标题】:Create control flow graph for c# code using the .Net compiler Roslyn使用 .Net 编译器 Roslyn 为 c# 代码创建控制流图
【发布时间】:2019-06-25 06:44:17
【问题描述】:

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


    【解决方案1】:

    我已经设法从方法节点创建 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 ...

    卡雷尔

    【讨论】:

    • 嘿,感谢您的回复我在这段代码中遇到了一个问题,所以我尝试遵循相同的逻辑,但没有使用工作区(MSBuildWorkspace),但条件 if(node.SyntaxTree) 仍然存在问题.Options.Features.Any()) 它总是错误的,如果我删除了这个条件,我会得到一个“invalidoperationexception”异常,说明流分析功能被禁用。请问您有什么建议或任何资源可以帮助我吗?
    • 我也为此苦苦挣扎。重要的部分是创建CSharpParseOptions options = CSharpParseOptions.Default .WithFeatures(new[] { new KeyValuePair&lt;string, string&gt;("flow-analysis", "") });,然后将它们传递给项目。我正在使用 ILSpy 工具在 GitHub 和库本身中挖掘 Roslyn 代码。我用谷歌搜索,也许这可以帮助你stackoverflow.com/questions/32769630/…
    【解决方案2】:

    根据 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);
    

    【讨论】:

      猜你喜欢
      • 2018-02-14
      • 1970-01-01
      • 2017-08-25
      • 2020-01-21
      • 2015-11-04
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多