Создайте граф управления потоком для кода C # с помощью компилятора .Net Roslyn - PullRequest
0 голосов
/ 31 января 2019

Я не могу найти способ построить граф потока управления для кода c #, используя Roslyn.

Я знаю, что в компиляторе 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

пожалуйста, если кто-нибудь знает, как использовать это пространство имен для построения графа потока управления, или если есть пример для использования.спасибо

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

В зависимости от ответа и комментария Карела, как создать график потока управления без ошибок:

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);
0 голосов
/ 06 февраля 2019

Мне удалось создать 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 ...

Карел

...