Skip to content

Commit

Permalink
Make 'AllowsUnsafeBlocks' analyzer target attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Jun 17, 2024
1 parent ebee50d commit b6bcc1c
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class MissingAllowUnsafeBlocksCompilationOptionAnalyzer : MissingA
/// Creates a new <see cref="MissingAllowUnsafeBlocksCompilationOptionAnalyzer"/> instance.
/// </summary>
public MissingAllowUnsafeBlocksCompilationOptionAnalyzer()
: base(MissingAllowUnsafeBlocksOption)
: base(MissingAllowUnsafeBlocksOption, "ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute")
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -944,19 +944,18 @@ partial class DiagnosticDescriptors
/// <summary>
/// Gets a <see cref="DiagnosticDescriptor"/> for when the <c>AllowUnsafeBlocks</c> option is not set.
/// <para>
/// Format: <c>"Unsafe blocks must be enabled for the source generators to emit valid code (add &lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt; to your .csproj/.props file)"</c>.
/// Format: <c>"Using [D2DGeneratedPixelShaderDescriptor] requires unsafe blocks being enabled, as they needed by the source generators to emit valid code (add &lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt; to your .csproj/.props file)"</c>.
/// </para>
/// </summary>
public static readonly DiagnosticDescriptor MissingAllowUnsafeBlocksOption = new(
id: "CMPSD2D0064",
title: "Missing 'AllowUnsafeBlocks' compilation option",
messageFormat: "Unsafe blocks must be enabled for the source generators to emit valid code (add <AllowUnsafeBlocks>true</AllowUnsafeBlocks> to your .csproj/.props file)",
messageFormat: "Using [D2DGeneratedPixelShaderDescriptor] requires unsafe blocks being enabled, as they needed by the source generators to emit valid code (add <AllowUnsafeBlocks>true</AllowUnsafeBlocks> to your .csproj/.props file)",
category: "ComputeSharp.D2D1.Shaders",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: "Unsafe blocks must be enabled for the source generators to emit valid code (the <AllowUnsafeBlocks>true</AllowUnsafeBlocks> option must be set in the .csproj/.props file).",
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp",
customTags: WellKnownDiagnosticTags.CompilationEnd);
description: "Unsafe blocks must be enabled when using [D2DGeneratedPixelShaderDescriptor] for the source generators to emit valid code (the <AllowUnsafeBlocks>true</AllowUnsafeBlocks> option must be set in the .csproj/.props file).",
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp");

/// <summary>
/// Gets a <see cref="DiagnosticDescriptor"/> for when a pixel shader type doesn't have an associated descriptor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ namespace ComputeSharp.SourceGeneration.Diagnostics;
/// A diagnostic analyzer that generates an error if the <c>AllowUnsafeBlocks</c> compilation option is not set.
/// </summary>
/// <param name="diagnosticDescriptor">The <see cref="DiagnosticDescriptor"/> instance to use.</param>
public abstract class MissingAllowUnsafeBlocksCompilationOptionAnalyzerBase(DiagnosticDescriptor diagnosticDescriptor) : DiagnosticAnalyzer
/// <param name="generatedShaderDescriptorFullyQualifiedTypeName">The fully qualified type name of the target attribute.</param>
public abstract class MissingAllowUnsafeBlocksCompilationOptionAnalyzerBase(
DiagnosticDescriptor diagnosticDescriptor,
string generatedShaderDescriptorFullyQualifiedTypeName) : DiagnosticAnalyzer
{
/// <inheritdoc/>
public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = [diagnosticDescriptor];
Expand All @@ -20,13 +23,38 @@ public sealed override void Initialize(AnalysisContext context)
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
context.EnableConcurrentExecution();

context.RegisterCompilationAction(context =>
context.RegisterCompilationStartAction(context =>
{
// Check whether unsafe blocks are available, and emit an error if they are not
if (!context.Compilation.IsAllowUnsafeBlocksEnabled())
// If unsafe blocks are allowed, we'll never need to emit a diagnostic
if (context.Compilation.IsAllowUnsafeBlocksEnabled())
{
context.ReportDiagnostic(Diagnostic.Create(diagnosticDescriptor, location: null));
return;
}

// Get the symbol for the target attribute type
if (context.Compilation.GetTypeByMetadataName(generatedShaderDescriptorFullyQualifiedTypeName) is not { } generatedShaderDescriptorAttributeSymbol)
{
return;
}

// Check if any types in the compilation are using the trigger attribute
context.RegisterSymbolAction(context =>
{
// Only struct types are possible targets
if (context.Symbol is not INamedTypeSymbol { TypeKind: TypeKind.Struct } typeSymbol)
{
return;
}

// If the target type is not using the attribute, there's nothing left to do
if (!typeSymbol.TryGetAttributeWithType(generatedShaderDescriptorAttributeSymbol, out AttributeData? attribute))
{
return;
}

// Emit the error on the attribute use
context.ReportDiagnostic(Diagnostic.Create(diagnosticDescriptor, attribute.GetLocation()));
}, SymbolKind.NamedType);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class MissingAllowUnsafeBlocksCompilationOptionAnalyzer : MissingA
/// Creates a new <see cref="MissingAllowUnsafeBlocksCompilationOptionAnalyzer"/> instance.
/// </summary>
public MissingAllowUnsafeBlocksCompilationOptionAnalyzer()
: base(MissingAllowUnsafeBlocksOption)
: base(MissingAllowUnsafeBlocksOption, "ComputeSharp.GeneratedComputeShaderDescriptorAttribute")
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -720,19 +720,18 @@ partial class DiagnosticDescriptors
/// <summary>
/// Gets a <see cref="DiagnosticDescriptor"/> for when the <c>AllowUnsafeBlocks</c> option is not set.
/// <para>
/// Format: <c>"Unsafe blocks must be enabled for the source generators to emit valid code (add &lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt; to your .csproj/.props file)"</c>.
/// Format: <c>"Using [GeneratedComputeShaderDescriptor] requires unsafe blocks being enabled, as they needed by the source generators to emit valid code (add &lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt; to your .csproj/.props file)"</c>.
/// </para>
/// </summary>
public static readonly DiagnosticDescriptor MissingAllowUnsafeBlocksOption = new(
id: "CMPS0052",
title: "Missing 'AllowUnsafeBlocks' compilation option",
messageFormat: "Unsafe blocks must be enabled for the source generators to emit valid code (add <AllowUnsafeBlocks>true</AllowUnsafeBlocks> to your .csproj/.props file)",
messageFormat: "Using [GeneratedComputeShaderDescriptor] requires unsafe blocks being enabled, as they needed by the source generators to emit valid code (add <AllowUnsafeBlocks>true</AllowUnsafeBlocks> to your .csproj/.props file)",
category: "ComputeSharp.Shaders",
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true,
description: "Unsafe blocks must be enabled for the source generators to emit valid code (the <AllowUnsafeBlocks>true</AllowUnsafeBlocks> option must be set in the .csproj/.props file).",
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp",
customTags: WellKnownDiagnosticTags.CompilationEnd);
description: "Unsafe blocks must be enabled when using [GeneratedComputeShaderDescriptor] for the source generators to emit valid code (the <AllowUnsafeBlocks>true</AllowUnsafeBlocks> option must be set in the .csproj/.props file).",
helpLinkUri: "https://github.com/Sergio0694/ComputeSharp");

/// <summary>
/// Gets a <see cref="DiagnosticDescriptor"/> for when a compute shader type doesn't have an associated descriptor.
Expand Down

0 comments on commit b6bcc1c

Please sign in to comment.