/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/RoslynAnalyzers/PerformanceSensitiveAnalyzers/Core/AbstractAllocationAnalyzer.cs
149 строк
6 KB
Joey Robichaud
Fix file headers
15 мар 2025, 02:53
15 мар 2025, 02:53
e56be3a
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Immutable; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.CodeAnalysis.PerformanceSensitiveAnalyzers { internal abstract class AbstractAllocationAnalyzer : DiagnosticAnalyzer { protected abstract ImmutableArray<OperationKind> Operations { get; } protected abstract void AnalyzeNode(OperationAnalysisContext context, in PerformanceSensitiveInfo info); public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); // This analyzer is triggered by an attribute, even if it appears in generated code context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); if (Operations.IsEmpty) { return; } context.RegisterCompilationStartAction(compilationStartContext => { var compilation = compilationStartContext.Compilation; var attributeSymbol = compilation.GetOrCreateTypeByMetadataName(AllocationRules.PerformanceSensitiveAttributeName); // Bail if PerformanceSensitiveAttribute is not declared in the compilation. if (attributeSymbol == null) { return; } compilationStartContext.RegisterOperationBlockStartAction(blockStartContext => { var checker = new AttributeChecker(attributeSymbol); RegisterOperationAnalysis(blockStartContext, checker); }); }); } private void RegisterOperationAnalysis(OperationBlockStartAnalysisContext operationBlockStartAnalysisContext, AttributeChecker performanceSensitiveAttributeChecker) { var owningSymbol = operationBlockStartAnalysisContext.OwningSymbol; if (!performanceSensitiveAttributeChecker.TryGetContainsPerformanceSensitiveInfo(owningSymbol, out var info)) { return; } operationBlockStartAnalysisContext.RegisterOperationAction( syntaxNodeContext => { AnalyzeNode(syntaxNodeContext, in info); }, Operations); } protected sealed class AttributeChecker { private INamedTypeSymbol PerfSensitiveAttributeSymbol { get; } public AttributeChecker(INamedTypeSymbol perfSensitiveAttributeSymbol) { PerfSensitiveAttributeSymbol = perfSensitiveAttributeSymbol; } public bool TryGetContainsPerformanceSensitiveInfo(ISymbol symbol, out PerformanceSensitiveInfo info) { if (TryGet(symbol, out info)) { return true; } // The attribute might be applied to a property declaration, instead of its accessor declaration. if (symbol is IMethodSymbol methodSymbol && (methodSymbol.MethodKind == MethodKind.PropertyGet || methodSymbol.MethodKind == MethodKind.PropertySet) && TryGet(methodSymbol.AssociatedSymbol!, out info)) { return true; } info = default; return false; bool TryGet(ISymbol s, out PerformanceSensitiveInfo i) { if (s.GetAttribute(PerfSensitiveAttributeSymbol) is { } attribute) { i = CreatePerformanceSensitiveInfo(attribute); return true; } i = default; return false; } } private static PerformanceSensitiveInfo CreatePerformanceSensitiveInfo(AttributeData data) { var allowCaptures = true; var allowGenericEnumeration = true; var allowLocks = true; foreach (var namedArgument in data.NamedArguments) { switch (namedArgument.Key) { case "AllowCaptures": allowCaptures = (bool)namedArgument.Value.Value!; break; case "AllowGenericEnumeration": allowGenericEnumeration = (bool)namedArgument.Value.Value!; break; case "AllowLocks": allowLocks = (bool)namedArgument.Value.Value!; break; } } return new PerformanceSensitiveInfo(allowCaptures, allowGenericEnumeration, allowLocks); } } #pragma warning disable CA1815 // Override equals and operator equals on value types. This type is never used for comparison protected readonly struct PerformanceSensitiveInfo #pragma warning restore CA1815 { public bool AllowCaptures { get; } public bool AllowGenericEnumeration { get; } public bool AllowLocks { get; } public PerformanceSensitiveInfo( bool allowCaptures = true, bool allowGenericEnumeration = true, bool allowLocks = true) { AllowCaptures = allowCaptures; AllowGenericEnumeration = allowGenericEnumeration; AllowLocks = allowLocks; } } } }