示例#1
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));
                }
            }
        }
示例#2
0
        public void GetMethodId_Explicit_Interface_Implementations()
        {
            const string code = @"
using System;
using System.Collections.Generic;
namespace Namespace
{
    public class Bar : IBar
    {
        void IBar.Foo(string s) { }
        public void Foo(string s) { }
    }

    public interface IBar
    {
        void Foo(string s);
    }
}
";

            var(syntaxTree, semanticModel) = TestHelper.Compile(code);

            MethodId("Foo").Should().Be("Namespace.IBar.Foo(string)");
            MethodId("Foo", skip: 1).Should().Be("Namespace.Bar.Foo(string)");

            string MethodId(string methodName, int skip = 0) =>
            UniversalControlFlowGraphBuilder.GetMethodId(semanticModel.GetDeclaredSymbol(syntaxTree.GetMethod(methodName, skip)));
        }
示例#3
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))
            {
                return;
            }

            var path = Path.Combine(protobufDirectory,
                                    $"ucfg_{projectBuildId}_{Interlocked.Increment(ref protobufFileIndex)}.pb");

            using (var stream = File.Create(path))
            {
                ucfg.WriteTo(stream);
            }
        }
示例#4
0
        protected UCFG GetUcfgForMethod(string code, string methodName)
        {
            (var method, var semanticModel) = TestHelper.Compile(code, Verifier.SystemWebMvcAssembly).GetMethod(methodName);

            var builder = new UniversalControlFlowGraphBuilder();

            return(builder.Build(semanticModel, method,
                                 semanticModel.GetDeclaredSymbol(method), CSharpControlFlowGraph.Create(method.Body, semanticModel)));
        }
示例#5
0
        private static UCFG CreateUcfgForConstructor(string code, string name)
        {
            var(syntaxTree, semanticModel) = TestHelper.Compile(code, Verifier.SystemWebMvcAssembly);

            var ctor = syntaxTree.GetRoot()
                       .DescendantNodes()
                       .OfType <ConstructorDeclarationSyntax>()
                       .First(m => m.Identifier.ValueText == name);

            var builder = new UniversalControlFlowGraphBuilder();

            var ucfg = builder.Build(semanticModel, ctor,
                                     semanticModel.GetDeclaredSymbol(ctor), CSharpControlFlowGraph.Create(ctor.Body, semanticModel));

            return(ucfg);
        }
示例#6
0
        public void GetMethodId_Constructors()
        {
            const string code = @"
using System;
namespace Namespace
{
    public class Class1
    {
        public Class1() { }
        public Class1(string s) { }
    }
}
";

            var(syntaxTree, semanticModel) = TestHelper.Compile(code);

            CtorId("Class1").Should().Be("Namespace.Class1.Class1()");
            CtorId("Class1", skip: 1).Should().Be("Namespace.Class1.Class1(string)");

            string CtorId(string className, int skip = 0) =>
            UniversalControlFlowGraphBuilder.GetMethodId(semanticModel.GetDeclaredSymbol(syntaxTree.GetConstructor(className, skip)));
        }
示例#7
0
        public void GetMethodId_Methods()
        {
            const string code = @"
using System;
using System.Collections.Generic;
namespace Namespace
{
    public class Class1
    {
        public void PrimitiveTypes1(string s) { }
        public void PrimitiveTypes2(String s) { }
        public void PrimitiveTypes3(System.String s) { }

        public void ArrayTypes1(string[] s) { }
        public void ArrayTypes2(string[,] s) { }
        public void ArrayTypes3(string[][] s) { }

        public void UserType(Class1 s) { }
        public void SystemType(Uri uri) { }
        public void GenericMethod1<T1,T2>(T1 x) { }

        public void Nullables(int? x, Nullable<int> y) { }

        public void GenericArgument(IEnumerable<string> strings) { }

        public void Overload1(string s) { }
        public void Overload1(string s, string s) { }

        public void NestedMethods()
        {
            void Foo() { } // We don't really support nested, but we should not throw
        }

        public class Class2
        {
            public void InnerClass(Class2 s) { }
        }
    }
    public class GenericClass<T1>
    {
        public void GenericMethod2(T1 x) { }
        public void GenericMethod3<T2>(T1 x, T2 y) { }
    }
    public class BaseClass<T1>
    {
        public virtual void Method1(T1 x) { }
        public virtual void Method2(T1 x) { }
    }
    public class Descendant : BaseClass<string>
    {
        public override void Method1(string x) { }
    }
    namespace Inner
    {
        public class Class2
        {
            public string InnerNamespace() { }
        }
    }
}
public class Class3
{
    public void NoNamespace(Class3 s) { }
}
public static class Extensions
{
    public static void Extension(this string s, int x) { }
}";

            var(syntaxTree, semanticModel) = TestHelper.Compile(code);

            MethodId("PrimitiveTypes1").Should().Be("Namespace.Class1.PrimitiveTypes1(string)");
            MethodId("PrimitiveTypes2").Should().Be("Namespace.Class1.PrimitiveTypes2(string)");
            MethodId("PrimitiveTypes3").Should().Be("Namespace.Class1.PrimitiveTypes3(string)");
            MethodId("ArrayTypes1").Should().Be("Namespace.Class1.ArrayTypes1(string[])");
            MethodId("ArrayTypes2").Should().Be("Namespace.Class1.ArrayTypes2(string[*,*])");
            MethodId("ArrayTypes3").Should().Be("Namespace.Class1.ArrayTypes3(string[][])");
            MethodId("UserType").Should().Be("Namespace.Class1.UserType(Namespace.Class1)");
            MethodId("SystemType").Should().Be("Namespace.Class1.SystemType(System.Uri)");
            MethodId("GenericMethod1").Should().Be("Namespace.Class1.GenericMethod1<T1, T2>(T1)");
            MethodId("Nullables").Should().Be("Namespace.Class1.Nullables(int?, int?)");
            MethodId("GenericArgument").Should().Be("Namespace.Class1.GenericArgument(System.Collections.Generic.IEnumerable<string>)");
            MethodId("Overload1").Should().Be("Namespace.Class1.Overload1(string)");
            MethodId("Overload1", skip: 1).Should().Be("Namespace.Class1.Overload1(string, string)");
            MethodId("GenericMethod2").Should().Be("Namespace.GenericClass<T1>.GenericMethod2(T1)");
            MethodId("GenericMethod3").Should().Be("Namespace.GenericClass<T1>.GenericMethod3<T2>(T1, T2)");
            MethodId("InnerClass").Should().Be("Namespace.Class1.Class2.InnerClass(Namespace.Class1.Class2)");
            MethodId("Method1").Should().Be("Namespace.BaseClass<T1>.Method1(T1)");
            MethodId("Method1", skip: 1).Should().Be("Namespace.Descendant.Method1(string)");
            MethodId("InnerNamespace").Should().Be("Namespace.Inner.Class2.InnerNamespace()");
            MethodId("NoNamespace").Should().Be("Class3.NoNamespace(Class3)");
            MethodId("Extension").Should().Be("Extensions.Extension(string, int)");

            string MethodId(string methodName, int skip = 0) =>
            UniversalControlFlowGraphBuilder.GetMethodId(semanticModel.GetDeclaredSymbol(syntaxTree.GetMethod(methodName, skip)));
        }
示例#8
0
        public void GetMethodId_Properties()
        {
            const string code = @"
using System;
namespace Namespace
{
    public class Class1
    {
        public string Property1
        {
            get { return null; }
            set { }
        }
        public string Property2 => null;
    }
    public class GenericClass<T1>
    {
        public T1 Property3 { get; set; }
    }
    public class BaseClass<T1>
    {
        public virtual T1 Property4
        {
            get { return default(T1); }
            set { }
        }
    }
    public class Descendant : BaseClass<string>
    {
        public override string Property4
        {
            get { return null; }
            set { }
        }
    }
    namespace Inner
    {
        public class Class2
        {
            public string Property5 { get; set; }
        }
    }
}
public class Class3
{
    public string Property6 { get; set; }
}";

            var(syntaxTree, semanticModel) = TestHelper.Compile(code);

            PropertyGetId("Property1").Should().Be("Namespace.Class1.Property1.get");
            PropertySetId("Property1").Should().Be("Namespace.Class1.Property1.set");

            PropertyGetId("Property2").Should().Be("Namespace.Class1.Property2.get");
            PropertySetId("Property2").Should().Be(KnownMethodId.Unknown);

            PropertyGetId("Property3").Should().Be("Namespace.GenericClass<T1>.Property3.get");
            PropertySetId("Property3").Should().Be("Namespace.GenericClass<T1>.Property3.set");

            PropertyGetId("Property4").Should().Be("Namespace.BaseClass<T1>.Property4.get");
            PropertySetId("Property4").Should().Be("Namespace.BaseClass<T1>.Property4.set");

            PropertyGetId("Property4", 1).Should().Be("Namespace.Descendant.Property4.get");
            PropertySetId("Property4", 1).Should().Be("Namespace.Descendant.Property4.set");

            PropertyGetId("Property5").Should().Be("Namespace.Inner.Class2.Property5.get");
            PropertySetId("Property5").Should().Be("Namespace.Inner.Class2.Property5.set");

            PropertyGetId("Property6").Should().Be("Class3.Property6.get");
            PropertySetId("Property6").Should().Be("Class3.Property6.set");

            string PropertyGetId(string propertyName, int skip = 0) =>
            UniversalControlFlowGraphBuilder.GetMethodId(semanticModel.GetDeclaredSymbol(syntaxTree.GetProperty(propertyName, skip)).GetMethod);

            string PropertySetId(string propertyName, int skip = 0) =>
            UniversalControlFlowGraphBuilder.GetMethodId(semanticModel.GetDeclaredSymbol(syntaxTree.GetProperty(propertyName, skip)).SetMethod);
        }