3

I can't find a way to construct a control flow graph for c# code using Roslyn.

I know there is a namespace in the Roslyn compiler called "Microsoft.CodeAnalysis.FlowAnalysis" that contains some classes to create a control flow graph but I don't know how to use it.

https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.flowanalysis?view=roslyn-dotnet

there is a class called ControlFlowGraph.cs but the problem i can't create an object or a subclass from this class. https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.flowanalysis.controlflowgraph?view=roslyn-dotnet

please if anyone knows how to use this namespace to construct a control flow graph or if there is an example to use. thank you

2 Answers 2

4

I have manage to create the CFG from a method node:

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();
        }
    }
}

The next step will be anaylysis of the CFG ...

Karel

Sign up to request clarification or add additional context in comments.

2 Comments

Hey, thanks for your response I encountered a problem in this code so I tried to follow the same logic but without using workspace (MSBuildWorkspace ) but I still have a problem in the condition if(node.SyntaxTree.Options.Features.Any()) it's always false and if I removed this condition I get an "invalidoperationexception" Exception that says the Flow-Analysis feature is disabled. please if you have any suggestions or any resources that will help me?
I have also struggled with this. The important part is to create CSharpParseOptions options = CSharpParseOptions.Default .WithFeatures(new[] { new KeyValuePair<string, string>("flow-analysis", "") }); and then pass them to the project. I was digging around the Roslyn code on GitHub and in the library itself using ILSpy tool. I googled around and maybe this can help you stackoverflow.com/questions/32769630/…
2

Depending on the Karel's answer and comment this is how to create a Control Flow Graph without errors:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.