简体   繁体   English

如何从 C# 中的 roslyn 代码分析中正确使用 ControlFlowGraph

[英]How to properly use ControlFlowGraph from roslyn code analysis in C#

I cannot understand why I am getting an error (using VS2017) for the code in below related to not finding the class ControlFlowGraph which is supposed to be part of the package Microsoft.CodeAnalysis.FlowAnalysis:我不明白为什么我在下面的代码中收到错误(使用 VS2017)与找不到类 ControlFlowGraph 相关,该类应该是 Microsoft.CodeAnalysis.FlowAnalysis 包的一部分:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.FlowAnalysis;

namespace CodeAnalysisApp3
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // Attempt to set the version of MSBuild.
            var visualStudioInstances = MSBuildLocator.QueryVisualStudioInstances().ToArray();
            var instance = visualStudioInstances[0];

            Console.WriteLine($"Using MSBuild at '{instance.MSBuildPath}' to load projects.");

            // NOTE: Be sure to register an instance with the MSBuildLocator 
            //       before calling MSBuildWorkspace.Create()
            //       otherwise, MSBuildWorkspace won't MEF compose.
            MSBuildLocator.RegisterInstance(instance);

            using (var workspace = MSBuildWorkspace.Create())
            {
                // Print message for WorkspaceFailed event to help diagnosing project load failures.
                workspace.WorkspaceFailed += (o, e) => Console.WriteLine(e.Diagnostic.Message);

                var solutionPath = args[0];
                Console.WriteLine($"Loading solution '{solutionPath}'");

                // Attach progress reporter so we print projects as they are loaded.
                var solution = await workspace.OpenSolutionAsync(solutionPath, new ConsoleProgressReporter());
                Console.WriteLine($"Finished loading solution '{solutionPath}'");

                // TODO: Do analysis on the projects in the loaded solution
                CSharpParseOptions options = CSharpParseOptions.Default
                .WithFeatures(new[] { new KeyValuePair<string, string>("flow-analysis", "") });

                var projIds = solution.ProjectIds;

                var project = solution.GetProject(projIds[0]);

                Compilation compilation = await project.GetCompilationAsync();

                if (compilation != null && !string.IsNullOrEmpty(compilation.AssemblyName))
                {
                    var mySyntaxTree = compilation.SyntaxTrees.First();

                    // get syntax nodes for methods
                    var methodNodes = from methodDeclaration in mySyntaxTree.GetRoot().DescendantNodes()
                               .Where(x => x is MethodDeclarationSyntax)
                                      select methodDeclaration;

                    foreach (MethodDeclarationSyntax node in methodNodes)
                    {
                        var model = compilation.GetSemanticModel(node.SyntaxTree);
                        node.Identifier.ToString();
                        if (node.SyntaxTree.Options.Features.Any())
                        {
                            var graph = ControlFlowGraph.Create(node, model); // CFG is here
                        }
                    }
                }
            }
        }

        private class ConsoleProgressReporter : IProgress<ProjectLoadProgress>
        {
            public void Report(ProjectLoadProgress loadProgress)
            {
                var projectDisplay = Path.GetFileName(loadProgress.FilePath);
                if (loadProgress.TargetFramework != null)
                {
                    projectDisplay += $" ({loadProgress.TargetFramework})";
                }

                Console.WriteLine($"{loadProgress.Operation,-15} {loadProgress.ElapsedTime,-15:m\\:ss\\.fffffff} {projectDisplay}");
            }
        }
    }
}

However, when I compile the above code I am getting the following error message with VS2017:但是,当我编译上面的代码时,我在 VS2017 中收到以下错误消息:

1>Program.cs(67,41,67,57): error CS0103: The name 'ControlFlowGraph' does not exist in the current context
1>Done building project "CodeAnalysisApp3.csproj" -- FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

Version used:使用的版本:

Microsoft (R) Visual C# Compiler version 4.8.3761.0
for C# 5

Based on my test, I find I can use class ControlFlowGraph.根据我的测试,我发现我可以使用 ControlFlowGraph 类。

I installed the following nugetpackage.我安装了以下 nugetpackage。

Microsoft.CodeAnalysis微软代码分析

Microsoft.Build.Locator Microsoft.Build.Locator

Then, you will see the following result.然后,您将看到以下结果。

在此处输入图片说明

Besides, I used .net framwork 4.6.1.此外,我使用了 .net 框架 4.6.1。

I was able to solve the problem when I used roslyn CodeAnalysis packages with the proper versions:当我使用正确版本的 roslyn CodeAnalysis 包时,我能够解决这个问题:

CodeAnalysis.CSharp.Workspaces (3.4.0)
CodeAnalysis.FlowAnalysis.Utilities (2.9.6)
CodeAnalysis.Workspaces.MSBuild (3.4.0)

The target framework is .NETFramework 4.7.2目标框架是.NETFramework 4.7.2

A link to a closed issue created for this question on roslyn Github repo is here在 roslyn Github repo 上为这个问题创建的已关闭问题的链接在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM