public void Serialize_Some_Method()
        {
            var code = @"
class C
{
    void Foo(string a, string b)
    {
        var x = a + b;
        if (true)
        {
            Bar(a, 1);
        }
        else
        {
            Bar(b, 2);
        }
    }
    void Bar(string a, int x) { }
}
";
            var dot  = UcfgSerializer.Serialize(UcfgVerifier.GetUcfgForMethod(code, "Foo"));

            dot.Should().BeIgnoringLineEndings(@"digraph ""C.Foo(string, string)"" {
ENTRY [shape=record label=""{ENTRY|a|b}""]
ENTRY -> 0
0 [shape=record label=""{BLOCK:0|\{ \""name\"": \""%0\"" \} __concat a,b|\{ \""name\"": \""x\"" \} __id %0|TERMINATOR JUMP: 1, 2}""]
0 -> 1
0 -> 2
1 [shape=record label=""{BLOCK:1|\{ \""name\"": \""%1\"" \} C.Bar(string, int) _this_,a,\""\""\""\""|TERMINATOR JUMP: 3}""]
1 -> 3
2 [shape=record label=""{BLOCK:2|\{ \""name\"": \""%2\"" \} C.Bar(string, int) _this_,b,\""\""\""\""|TERMINATOR JUMP: 3}""]
2 -> 3
3 [shape=record label=""{BLOCK:3|TERMINATOR RET: \""\""\""\""}""]
3 -> END
END [shape=record label=""{END}""]
}
");
        }
        public void Serialize_Some_Method()
        {
            var code = @"
class C
{
    void Foo(string a, string b)
    {
        var x = a + b;
        if (true)
        {
            Bar(a, 1);
        }
        else
        {
            Bar(b, 2);
        }
    }
    void Bar(string a, int x) { }
}
";
            var dot  = UcfgSerializer.Serialize(GetUcfgForMethod(code, "Foo"));

            dot.Should().BeIgnoringLineEndings(@"digraph ""C.Foo(string, string)"" {
ENTRY [shape=record label=""{ENTRY|a|b}""]
ENTRY -> 0
0 [shape=record label=""{BLOCK|%0 __concat b,a|x __id %0}""]
0 -> 1
0 -> 2
1 [shape=record label=""{BLOCK|%0 C.Bar(string, int) a,CONST}""]
1 -> 3
2 [shape=record label=""{BLOCK|%0 C.Bar(string, int) b,CONST}""]
2 -> 3
3 [shape=record label=""{BLOCK}""]
3 -> EXIT
EXIT [shape=record label=""{EXIT}""]
}
");
        }
示例#3
0
        public void Serialize_Some_Method()
        {
            var code = @"
class C
{
    void Foo(string a, string b)
    {
        var x = a + b;
        if (true)
        {
            Bar(a, 1);
        }
        else
        {
            Bar(b, 2);
        }
    }
    void Bar(string a, int x) { }
}
";
            var dot  = UcfgSerializer.Serialize(UcfgVerifier.GetUcfgForMethod(code, "Foo"));

            dot.Should().BeIgnoringLineEndings(@"digraph ""C.Foo(string, string)"" {
ENTRY [shape=record label=""{ENTRY|a|b}""]
ENTRY -> 0
0 [shape=record label=""{BLOCK:#0|%0 := __concat [ a, b ]|x := __id [ %0 ]|TERMINATOR: JUMP: #1, #2}""]
0 -> 1
0 -> 2
1 [shape=record label=""{BLOCK:#1|%1 := C.Bar(string, int) [ this, a, CONST ]|TERMINATOR: JUMP: #3}""]
1 -> 3
2 [shape=record label=""{BLOCK:#2|%2 := C.Bar(string, int) [ this, b, CONST ]|TERMINATOR: JUMP: #3}""]
2 -> 3
3 [shape=record label=""{BLOCK:#3|TERMINATOR: RET: CONST}""]
3 -> END
END [shape=record label=""{END}""]
}
");
        }
示例#4
0
        private void WriteUCFG <TDeclarationSyntax>(SyntaxNodeAnalysisContext context, Func <TDeclarationSyntax, CSharpSyntaxNode> getBody)
            where TDeclarationSyntax : SyntaxNode
        {
            var declaration = (TDeclarationSyntax)context.Node;

            var symbol = context.SemanticModel.GetDeclaredSymbol(declaration);

            var methodSymbol = (symbol is IPropertySymbol propertySymbol)
                ? propertySymbol.GetMethod // We are in PropertyDeclarationSyntax
                : symbol as IMethodSymbol; // all other are methods

            if (methodSymbol == null ||
                methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                !CSharpControlFlowGraph.TryGet(getBody(declaration), context.SemanticModel, out var cfg))
            {
                return;
            }

            var ucfg = new UniversalControlFlowGraphBuilder()
                       .Build(context.SemanticModel, declaration, methodSymbol, cfg);

            if (IsValid(ucfg))
            {
                var fileName = $"{projectBuildId}_{Interlocked.Increment(ref protobufFileIndex)}";

                WriteProtobuf(ucfg, Path.Combine(protobufDirectory, $"ucfg_{fileName}.pb"));

                if (ShouldGenerateDot)
                {
                    WriteDot(Path.Combine(protobufDirectory, $"ucfg_{fileName}.dot"), writer => UcfgSerializer.Serialize(ucfg, writer));
                    WriteDot(Path.Combine(protobufDirectory, $"cfg_{fileName}.dot"), writer => CfgSerializer.Serialize(ucfg.MethodId, cfg, writer));
                }
            }
        }
        private void WriteUcfg <TDeclarationSyntax>(SyntaxNodeAnalysisContext context, Func <TDeclarationSyntax, CSharpSyntaxNode> getBody)
            where TDeclarationSyntax : SyntaxNode
        {
            var declaration = (TDeclarationSyntax)context.Node;

            var symbol = context.SemanticModel.GetDeclaredSymbol(declaration);

            var methodSymbol = (symbol is IPropertySymbol propertySymbol)
                ? propertySymbol.GetMethod // We are in PropertyDeclarationSyntax
                : symbol as IMethodSymbol; // all other are methods

            if (methodSymbol == null ||
                methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                !CSharpControlFlowGraph.TryGet(getBody(declaration), context.SemanticModel, out var cfg))
            {
                return;
            }

            try
            {
                var ucfg = new UcfgFactory(context.SemanticModel)
                           .Create(declaration, methodSymbol, cfg);

                if (!IsValid(ucfg))
                {
                    return;
                }

                var fileName = $"{this.projectBuildId}_{Interlocked.Increment(ref this.protobufFileIndex)}";

                WriteProtobuf(ucfg, Path.Combine(this.protobufDirectory, $"ucfg_{fileName}.pb"));

                if (ShouldGenerateDot)
                {
                    WriteDot(Path.Combine(this.protobufDirectory, $"ucfg_{fileName}.dot"), writer => UcfgSerializer.Serialize(ucfg, writer));
                    WriteDot(Path.Combine(this.protobufDirectory, $"cfg_{fileName}.dot"), writer => CfgSerializer.Serialize(ucfg.MethodId, cfg, writer));
                }
            }
            catch (UcfgException) when(!DebugHelper.IsInternalDebuggingContext())
            {
                // Ignore the exception in production
            }
        }