public void AnalyzeProgram_FlagMethodWhenBaseClassIsFlagged()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public class CriticalBaseClass {
                }

                public class CriticalBaseClassEx : CriticalBaseClass {
                }

                public class CriticalClass : CriticalBaseClassEx {
                    public string CreateString() {
                        return null;
                    }
                }

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public void PerfCritical(CriticalClass c) {
                    string str = c.CreateString();
                }";

            var analyser = new MethodCallAnalyzer();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));
            Assert.AreEqual(0, info.Allocations.Count);
        }
        public void AnalyzeProgram_MethodShouldOnlyBeAllowedToCallNonAllocatingMethodsOnNonAllocatingInterface()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                interface IFoo
                {
                    [HotPathAllocationAnalyzer.Support.NoAllocation]
                    int StringLength(string str);
                }

                public class Foo : IFoo
                {
                     public int StringLength(string str)
                     {
                        return 0;
                     }
                }

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public void PerfCritical(Foo foo, string str)
                {
                    int l = foo.StringLength(str);
                }";

            var analyser = new MethodCallAnalyzer();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));
            Assert.AreEqual(0, info.Allocations.Count);
        }
示例#3
0
        public void AnalyzeProgram_AllowCallingFlaggedPropertyGetter_Interface()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer;
                
                public interface IFoo 
                {                
                    string Name { [HotPathAllocationAnalyzer.Support.NoAllocation] get; }
                }            
                    
                public class Foo : IFoo
                {                
                    public string Name { get; }
                }
                
                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public string PerfCritical(Foo f) {
                    return f.Name;
                }";

            var analyser = new MethodCallAnalyzer();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));

            Assert.AreEqual(0, info.Allocations.Count);
        }
示例#4
0
        public void AnalyzeProgram_ConsiderAutoPropertyAndFieldsAsSafe()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;
                
                public abstract class FooBase
                {
                    public string FullName;
                    public string Name { get; } = ""Hello"";
                    public int[] Data { get; } = new int[10];
                }
                
                public class Foo : FooBase
                {
                    public int[] Data { get; } = new int[10];
                }
                
                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public int PerfCritical(Foo f) 
                {
                    return f.Name.Length + + f.FullName.Length + f.Data.Length;
                }";

            var analyser = new MethodCallAnalyzer();

            analyser.AddToWhiteList("string.Length");
            analyser.AddToWhiteList("System.Array.Length");

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));

            Assert.AreEqual(0, info.Allocations.Count);
        }
        public void AnalyzeProgram_NotAllowCallingExternalMethod()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public string PerfCritical(string str) {
                    return string.Copy(str);
                }";

            var analyser = new MethodCallAnalyzer();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));
            Assert.AreEqual(1, info.Allocations.Count);
        }
示例#6
0
        public void AnalyzeProgram()
        {
            if (!System.Diagnostics.Debugger.IsAttached)
            {
                return;
            }

            var csProjPath = @"C:\Dev\dotnet\src\Abc.Trading.Strategies\Abc.Trading.Services.Common\Abc.Trading.Services.Common.csproj";

            var testAnalyser = new MethodCallAnalyzer();


            var manager = new AnalyzerManager();

            var analyzer = manager.GetProject(csProjPath);

            analyzer.SetGlobalProperty("IsRunningHotPathAllocationAnalyzerConfiguration", "true");
            analyzer.IgnoreFaultyImports = true;

            var workspace = new AdhocWorkspace();
            var project   = analyzer.AddToWorkspace(workspace)
                            .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, metadataImportOptions: MetadataImportOptions.Public))
                            .WithAnalyzerReferences(new AnalyzerReference[0]);

            var trees = project.Documents.Select(x => x.GetSyntaxTreeAsync().Result)
                        .ToArray();

            // Run the code tree through the analyzer and record the allocations it reports
            var compilation = CSharpCompilation.Create(project.AssemblyName, trees, project.MetadataReferences, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, metadataImportOptions: MetadataImportOptions.Public));

            var diagnostics = compilation.GetDiagnostics();

            if (diagnostics.Count(d => d.Severity == DiagnosticSeverity.Error) > 0)
            {
                var msg = "There were Errors in the sample code\n";
                Console.WriteLine(msg);
                foreach (var info in diagnostics)
                {
                    Console.WriteLine(info);
                }
            }

            var compilationWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create((DiagnosticAnalyzer)testAnalyser));
            var allocations = compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().GetAwaiter().GetResult().Distinct(DiagnosticEqualityComparer.Instance).ToList();
        }
        public void AnalyzeProgram_NotAllowCallingExternalMethod_UnlessItIsWhitelisted_ByConventionProject()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public bool PerfCritical(string str) {
                    return str.IsNormalized();
                }";

            var analyser = new MethodCallAnalyzer();
            var currentFilePath = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression), filePath: currentFilePath);
            Assert.AreEqual(0, info.Allocations.Count);
        }
        public void AnalyzeProgram_NotAllowCallingExternalMethod_UnlessItIsWhitelisted()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public bool PerfCritical(string str) {
                    return str.Contains(""zig"");
                }";

            var analyser = new MethodCallAnalyzer();

            analyser.AddToWhiteList("string.IsNormalized()");
            analyser.AddToWhiteList("string.Contains(string)");

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression, SyntaxKind.ClassDeclaration));
            Assert.AreEqual(0, info.Allocations.Count);
        }
        public void AnalyzeProgram_NotAllowCallingExternalMethod_UnlessItIsInSafeScope3()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public bool PerfCritical(string str)
                {
                    var result = str.IsNormalized();
                    using var safeScope = new AllocationFreeScope();
                    return result;
                }";

            var analyser = new MethodCallAnalyzer();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));
            Assert.AreEqual(1, info.Allocations.Count);
        }
        public void AnalyzeProgram_NotAllowCallingOwnedUnFlaggedMethod()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer.Support;

                public string CreateString() {
                    return new string('a', 5);
                }

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public void PerfCritical() {
                    string str = CreateString();
                }";

            var analyser = new MethodCallAnalyzer();

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));
            Assert.AreEqual(1, info.Allocations.Count);
        }
        public void AnalyzeProgram_NotAllowCallingNonGenericWhitelistedMethods()
        {
            //language=cs
            const string sample =
                @"
                    using System;
                    using System.Collections.Generic;
                    using HotPathAllocationAnalyzer.Support;

                    [HotPathAllocationAnalyzer.Support.NoAllocation]
                    public int PerfCritical<T>(List<T> l, T val) {
                        return l.IndexOf(val);
                    }
                ";

            var analyser = new MethodCallAnalyzer();
            analyser.AddToWhiteList("System.Collections.Generic.List<double>.IndexOf(double)");

            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));
            Assert.AreEqual(1, info.Allocations.Count);
        }
示例#12
0
        public void AnalyzeProgram_AllowCallingGenericWhitelistedProperty()
        {
            //language=cs
            const string sample =
                @"using System;
                using HotPathAllocationAnalyzer;

                public class DateProvider
                {
                    public DateTime? Date { [HotPathAllocationAnalyzer.Support.NoAllocation] get; }
                }

                [HotPathAllocationAnalyzer.Support.NoAllocation]
                public DateTime PerfCritical(DateProvider dp) {
                    return dp.Date.Value;
                }";

            var analyser = new MethodCallAnalyzer();

            analyser.AddToWhiteList("System.Nullable<T>.Value");
            var info = ProcessCode(analyser, sample, ImmutableArray.Create(SyntaxKind.InvocationExpression));

            Assert.AreEqual(0, info.Allocations.Count);
        }