Optimize namespace comparisons (#17119)

Fixes: #16922

Improves the performance significantly by avoiding allocations for the
purpose of comparing the namespace.
This commit is contained in:
Ryan Nowak 2019-11-15 14:41:33 -08:00 committed by GitHub
parent 7cbe8aa5e3
commit 2ff8f45193
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 5 deletions

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using Microsoft.AspNetCore.Components.Analyzers;
using Microsoft.CodeAnalysis;
@ -15,6 +16,8 @@ namespace Microsoft.Extensions.Internal
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ComponentInternalUsageDiagnosticAnalyzer : DiagnosticAnalyzer
{
private static readonly string[] NamespaceParts = new[] { "RenderTree", "Components", "AspNetCore", "Microsoft", };
private readonly InternalUsageAnalyzer _inner;
public ComponentInternalUsageDiagnosticAnalyzer()
@ -27,17 +30,25 @@ namespace Microsoft.Extensions.Internal
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
_inner.Register(context);
}
private static bool IsInInternalNamespace(ISymbol symbol)
{
if (symbol?.ContainingNamespace?.ToDisplayString() is string ns)
var @namespace = symbol?.ContainingNamespace;
for (var i = 0; i < NamespaceParts.Length; i++)
{
return string.Equals(ns, "Microsoft.AspNetCore.Components.RenderTree");
if (@namespace == null || !string.Equals(NamespaceParts[i], @namespace.Name, StringComparison.Ordinal))
{
return false;
}
@namespace = @namespace.ContainingNamespace;
}
return false;
return @namespace.IsGlobalNamespace;
}
}
}

View File

@ -40,6 +40,7 @@ namespace Microsoft.Extensions.Internal
context.RegisterOperationAction(
AnalyzeOperation,
OperationKind.ObjectCreation,
OperationKind.Invocation,
OperationKind.FieldReference,
OperationKind.MethodReference,
OperationKind.PropertyReference,

View File

@ -42,6 +42,11 @@ namespace Microsoft.AspNetCore.Components.Analyzers
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MMField"], diagnostic.Location);
},
diagnostic =>
{
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MMInvocation"], diagnostic.Location);
},
diagnostic =>
{
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MMProperty"], diagnostic.Location);
@ -84,6 +89,16 @@ namespace Microsoft.AspNetCore.Components.Analyzers
{
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MMProperty"], diagnostic.Location);
},
diagnostic =>
{
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MMNewObject2"], diagnostic.Location);
},
diagnostic =>
{
Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.MarkerLocations["MMInvocation"], diagnostic.Location);
});
}
}

View File

@ -12,7 +12,9 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInt
var frame = /*MMNewObject*/new RenderTreeFrame();
GC.KeepAlive(/*MMProperty*/frame.Component);
}
var range = /*MMNewObject2*/new ArrayRange<string>(null, 0);
/*MMInvocation*/range.Clone();
}
}
}

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInt
private Renderer /*MMField*/_field = null;
public UsesRendererTypesInDeclarations()
: base(null, null)
/*MMInvocation*/: base(null, null)
{
}