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