| File: TrimAnalysis\FeatureCheckReturnValuePattern.cs | Web Access |
| Project: src\runtime\src\tools\illink\src\ILLink.RoslynAnalyzer\ILLink.RoslynAnalyzer.csproj (ILLink.RoslynAnalyzer) |
// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; using System.Collections.Generic; using ILLink.RoslynAnalyzer.DataFlow; using ILLink.Shared; using ILLink.Shared.DataFlow; using ILLink.Shared.TrimAnalysis; using Microsoft.CodeAnalysis; namespace ILLink.RoslynAnalyzer.TrimAnalysis { internal readonly record struct FeatureCheckReturnValuePattern { public FeatureChecksValue ReturnValue { get; init; } public ValueSet<string> FeatureCheckAnnotations { get; init; } public IOperation Operation { get; init; } public IPropertySymbol OwningSymbol { get; init; } public FeatureCheckReturnValuePattern( FeatureChecksValue returnValue, ValueSet<string> featureCheckAnnotations, IOperation operation, IPropertySymbol owningSymbol) { ReturnValue = returnValue.DeepCopy(); FeatureCheckAnnotations = featureCheckAnnotations.DeepCopy(); Operation = operation; OwningSymbol = owningSymbol; } public void ReportDiagnostics(DataFlowAnalyzerContext context, Action<Diagnostic> reportDiagnostic) { var diagnosticContext = new DiagnosticContext(Operation.Syntax.GetLocation(), reportDiagnostic); // For now, feature check validation is enabled only when trim analysis is enabled. if (context.TrimAnalyzer is null) return; if (!OwningSymbol.IsStatic || OwningSymbol.Type.SpecialType != SpecialType.System_Boolean || OwningSymbol.SetMethod != null) { // Warn about invalid feature checks (non-static or non-bool properties or properties with setter) diagnosticContext.AddDiagnostic( DiagnosticId.InvalidFeatureGuard); return; } if (ReturnValue == FeatureChecksValue.All) return; ValueSet<string> returnValueFeatures = ReturnValue.EnabledFeatures; // For any analyzer-supported feature that this property is declared to guard, // the abstract return value must include that feature // (indicating it is known to be enabled when the return value is true). foreach (string feature in FeatureCheckAnnotations.GetKnownValues()) { foreach (var analyzer in context.EnabledRequiresAnalyzers) { if (feature != analyzer.RequiresAttributeFullyQualifiedName) continue; if (!returnValueFeatures.Contains(feature)) { diagnosticContext.AddDiagnostic( DiagnosticId.ReturnValueDoesNotMatchFeatureGuards, OwningSymbol.GetDisplayName(), feature); } } } } } }