| File: Analyzers\ValidatableTypeInGeneratedCodeDiagnosticAnalyzer.cs | Web Access |
| Project: src\aspnetcore\src\Validation\gen\Microsoft.Extensions.Validation.ValidationsGenerator.csproj (Microsoft.Extensions.Validation.ValidationsGenerator) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.Extensions.Validation; [DiagnosticAnalyzer(LanguageNames.CSharp)] internal sealed class ValidatableTypeInGeneratedCodeDiagnosticAnalyzer : DiagnosticAnalyzer { private const string Usage = "Usage"; internal static readonly DiagnosticDescriptor ValidatableTypeCantBeUsedInGeneratedCode = new( "ASP0037", "[ValidatableType] cannot be used in generated code", "'[ValidatableType]' on type '{0}' has no effect because the type is declared in generated code (for example, in a .razor file). Source generators cannot inspect each other's output. Declare the type in a regular .cs file instead.", Usage, DiagnosticSeverity.Warning, isEnabledByDefault: true, description: null, helpLinkUri: "https://learn.microsoft.com/aspnet/core/diagnostics/asp0037"); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = [ ValidatableTypeCantBeUsedInGeneratedCode, ]; public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.EnableConcurrentExecution(); context.RegisterCompilationStartAction(context => { var validatableTypeAttribute = context.Compilation.GetTypeByMetadataName("Microsoft.Extensions.Validation.ValidatableTypeAttribute"); if (validatableTypeAttribute is null) { return; } context.RegisterOperationAction(context => { if (!context.IsGeneratedCode) { return; } var attributeOperation = (IAttributeOperation)context.Operation; if (context.ContainingSymbol is INamedTypeSymbol attributedType && attributeOperation.Operation is IObjectCreationOperation attributeObjectCreationOperation && validatableTypeAttribute.Equals(attributeObjectCreationOperation.Constructor?.ContainingType, SymbolEqualityComparer.Default)) { context.ReportDiagnostic(Diagnostic.Create( ValidatableTypeCantBeUsedInGeneratedCode, attributedType.Locations.FirstOrDefault(), attributedType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat))); } }, OperationKind.Attribute); }); } }