Skip to content

Commit

Permalink
Merge pull request #587 from Sergio0694/dev/generated-marshaller-attr…
Browse files Browse the repository at this point in the history
…ibute

Add [D2DGeneratedPixelShaderDescriptor] attribute and use FAWMN
  • Loading branch information
Sergio0694 authored Oct 3, 2023
2 parents 4ab55e8 + 112a4af commit 57ecb78
Show file tree
Hide file tree
Showing 75 changed files with 1,080 additions and 124 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ jobs:
- name: Run ComputeSharp.D2D1.Tests.AssemblyLevelAttributes
run: dotnet test tests\ComputeSharp.D2D1.Tests.AssemblyLevelAttributes\ComputeSharp.D2D1.Tests.AssemblyLevelAttributes.csproj -c Release -f ${{matrix.framework}} -v n -l "console;verbosity=detailed"

# Run the D2D1 source generators tests as well (only on .NET 6, like for the DX12 ones)
- if: matrix.framework == 'net6.0'
name: Run ComputeSharp.D2D1.Tests.SourceGenerators
run: dotnet test tests\ComputeSharp.D2D1.Tests.SourceGenerators\ComputeSharp.D2D1.Tests.SourceGenerators.csproj -v n -l "console;verbosity=detailed"

# Run all unit tests using D3D12MA
run-tests-d3d12ma:
needs: [build-solution]
Expand Down
23 changes: 22 additions & 1 deletion ComputeSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D2D1.Uwp.Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D2D1.WinUI.Tests", "tests\ComputeSharp.D2D1.WinUI.Tests\ComputeSharp.D2D1.WinUI.Tests.csproj", "{73C32D0F-64DB-4674-84E9-8FCC41228474}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D3D12MemoryAllocator", "src\ComputeSharp.D3D12MemoryAllocator\ComputeSharp.D3D12MemoryAllocator.csproj", "{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D3D12MemoryAllocator", "src\ComputeSharp.D3D12MemoryAllocator\ComputeSharp.D3D12MemoryAllocator.csproj", "{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeSharp.D2D1.CodeFixers", "src\ComputeSharp.D2D1.CodeFixers\ComputeSharp.D2D1.CodeFixers.csproj", "{54654960-54B5-4E19-B3ED-993591CA39E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComputeSharp.D2D1.Tests.SourceGenerators", "tests\ComputeSharp.D2D1.Tests.SourceGenerators\ComputeSharp.D2D1.Tests.SourceGenerators.csproj", "{59A17380-24A0-4BD7-9012-B105A9E7D46F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -454,6 +458,22 @@ Global
{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}.Release|ARM64.Build.0 = Release|Any CPU
{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}.Release|x64.ActiveCfg = Release|Any CPU
{E017B3B6-C7D3-4E53-A7F6-1036178E98C3}.Release|x64.Build.0 = Release|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|ARM64.Build.0 = Debug|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|x64.ActiveCfg = Debug|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Debug|x64.Build.0 = Debug|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Release|ARM64.ActiveCfg = Release|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Release|ARM64.Build.0 = Release|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Release|x64.ActiveCfg = Release|Any CPU
{54654960-54B5-4E19-B3ED-993591CA39E5}.Release|x64.Build.0 = Release|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|ARM64.Build.0 = Debug|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|x64.ActiveCfg = Debug|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Debug|x64.Build.0 = Debug|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|ARM64.ActiveCfg = Release|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|ARM64.Build.0 = Release|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|x64.ActiveCfg = Release|Any CPU
{59A17380-24A0-4BD7-9012-B105A9E7D46F}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -494,6 +514,7 @@ Global
{346AEB10-A4EA-427E-8578-F60915DB3053} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7}
{4D4BB2F6-5653-4DB5-A8DD-90D58D8FE4D3} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7}
{73C32D0F-64DB-4674-84E9-8FCC41228474} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7}
{59A17380-24A0-4BD7-9012-B105A9E7D46F} = {F8EFBB27-4EE2-4463-A75B-7EFDFB55D0F7}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4664C5E3-0340-4E22-BCFD-98AAEDF5F2DC}
Expand Down
6 changes: 5 additions & 1 deletion build/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,12 @@
<IsPublishedProject>$(ProjectDirectoryPathFromSourceRoot.StartsWith('src\'))</IsPublishedProject>
<IsSourceGeneratorProject>false</IsSourceGeneratorProject>
<IsSourceGeneratorProject Condition="$(IsPublishedProject) AND $(MSBuildProjectName.EndsWith('.SourceGenerators'))">true</IsSourceGeneratorProject>
<IsCodeFixersProject>false</IsCodeFixersProject>
<IsCodeFixersProject Condition="$(IsPublishedProject) AND $(MSBuildProjectName.EndsWith('.CodeFixers'))">true</IsCodeFixersProject>
<IsAnalyzersProject>false</IsAnalyzersProject>
<IsAnalyzersProject Condition="$(IsSourceGeneratorProject) OR $(IsCodeFixersProject)">true</IsAnalyzersProject>
<IsPackagedProject>false</IsPackagedProject>
<IsPackagedProject Condition="$(IsPublishedProject) AND !$(IsSourceGeneratorProject)">true</IsPackagedProject>
<IsPackagedProject Condition="$(IsPublishedProject) AND !$(IsAnalyzersProject)">true</IsPackagedProject>
<IsTestProject>$(ProjectDirectoryPathFromSourceRoot.StartsWith('tests\'))</IsTestProject>
<IsInternalsTestProject>false</IsInternalsTestProject>
<IsInternalsTestProject Condition="$(IsTestProject) AND $(MSBuildProjectName.EndsWith('.Internals'))">true</IsInternalsTestProject>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct ColorfulInfinity : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct ContouredLayers : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct FractalTiling : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct HelloWorld : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct MengerJourney : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct Octagrams : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct ProteanClouds : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct PyramidPattern : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct TerracedHills : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct TriangleGridContouring : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace ComputeSharp.SwapChain.Shaders.D2D1;
[D2DInputCount(0)]
[D2DRequiresScenePosition]
[D2DShaderProfile(D2D1ShaderProfile.PixelShader50)]
[D2DGeneratedPixelShaderDescriptor]
[AutoConstructor]
internal readonly partial struct TwoTiledTruchet : ID2D1PixelShader
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.6.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ComputeSharp.D2D1.SourceGenerators\ComputeSharp.D2D1.SourceGenerators.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using ComputeSharp.SourceGeneration.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Text;
using static ComputeSharp.SourceGeneration.Diagnostics.DiagnosticDescriptors;

namespace ComputeSharp.D2D1.CodeFixers;

/// <summary>
/// A code fixer that adds the <c>[D2DGeneratedPixelShaderDescriptor]</c> to D2D1 shader types with no descriptor.
/// </summary>
[ExportCodeFixProvider(LanguageNames.CSharp)]
[Shared]
public sealed class MissingPixelShaderDescriptorOnPixelShaderCodeFixer : CodeFixProvider
{
/// <summary>
/// The set of type names for all D2D attributes that can be over shader types.
/// </summary>
private static readonly ImmutableArray<string> D2DAttributeTypeNames = ImmutableArray.Create(
"ComputeSharp.D2D1.D2DCompileOptionsAttribute",
"ComputeSharp.D2D1.D2DEffectAuthorAttribute",
"ComputeSharp.D2D1.D2DEffectCategoryAttribute",
"ComputeSharp.D2D1.D2DEffectDescriptionAttribute",
"ComputeSharp.D2D1.D2DEffectDisplayNameAttribute",
"ComputeSharp.D2D1.D2DEffectIdAttribute",
"ComputeSharp.D2D1.D2DInputComplexAttribute",
"ComputeSharp.D2D1.D2DInputCountAttribute",
"ComputeSharp.D2D1.D2DInputDescriptionAttribute",
"ComputeSharp.D2D1.D2DInputSimpleAttribute",
"ComputeSharp.D2D1.D2DOutputBufferAttribute",
"ComputeSharp.D2D1.D2DPixelOptionsAttribute",
"ComputeSharp.D2D1.D2DRequiresScenePositionAttribute",
"ComputeSharp.D2D1.D2DShaderProfileAttribute");

/// <inheritdoc/>
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(MissingPixelShaderDescriptorOnPixelShaderTypeId);

/// <inheritdoc/>
public override Microsoft.CodeAnalysis.CodeFixes.FixAllProvider? GetFixAllProvider()
{
return new FixAllProvider();
}

/// <inheritdoc/>
public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
Diagnostic diagnostic = context.Diagnostics[0];
TextSpan diagnosticSpan = context.Span;

SyntaxNode? root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

// Get the struct declaration from the target diagnostic
if (root?.FindNode(diagnosticSpan) is StructDeclarationSyntax structDeclaration)
{
// Register the code fix to update the return type to be Task instead
context.RegisterCodeFix(
CodeAction.Create(
title: "Add [D2DGeneratedPixelShaderDescriptor] attribute",
createChangedDocument: token => AddMissingD2DGeneratedPixelShaderDescriptorAttribute(context.Document, root, structDeclaration, token),
equivalenceKey: "Add [D2DGeneratedPixelShaderDescriptor] attribute"),
diagnostic);
}
}

/// <summary>
/// Applies the code fix to add the [D2DGeneratedPixelShaderDescriptor] attribute to a target type.
/// </summary>
/// <param name="document">The original document being fixed.</param>
/// <param name="root">The original tree root belonging to the current document.</param>
/// <param name="structDeclaration">The <see cref="StructDeclarationSyntax"/> to update.</param>
/// <param name="cancellationToken">The cancellation token for the operation.</param>
/// <returns>An updated document with the applied code fix, and the return type of the method being <see cref="Task"/>.</returns>
private static async Task<Document> AddMissingD2DGeneratedPixelShaderDescriptorAttribute(
Document document,
SyntaxNode root,
StructDeclarationSyntax structDeclaration,
CancellationToken cancellationToken)
{
// Get the new struct declaration
SyntaxNode updatedStructDeclaration = await AddMissingD2DGeneratedPixelShaderDescriptorAttribute(
document,
structDeclaration,
cancellationToken);

// Replace the node in the document tree
return document.WithSyntaxRoot(root.ReplaceNode(structDeclaration, updatedStructDeclaration));
}

/// <summary>
/// Applies the code fix to add the [D2DGeneratedPixelShaderDescriptor] attribute to a target type.
/// </summary>
/// <param name="document">The original document being fixed.</param>
/// <param name="structDeclaration">The <see cref="StructDeclarationSyntax"/> to update.</param>
/// <param name="cancellationToken">The cancellation token for the operation.</param>
/// <returns>An updated document with the applied code fix, and the return type of the method being <see cref="Task"/>.</returns>
private static async Task<SyntaxNode> AddMissingD2DGeneratedPixelShaderDescriptorAttribute(
Document document,
StructDeclarationSyntax structDeclaration,
CancellationToken cancellationToken)
{
// Get the semantic model (bail if it's not available)
if (await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false) is not SemanticModel semanticModel)
{
return structDeclaration;
}

// Build the map of D2D attributes to look for
if (!semanticModel.Compilation.TryBuildNamedTypeSymbolSet(D2DAttributeTypeNames, out ImmutableHashSet<INamedTypeSymbol>? d2DAttributeTypeSymbols))
{
return structDeclaration;
}

// Also bail if we can't resolve the [D2DGeneratedPixelShaderDescriptor] attribute symbol (this should really never happen)
if (semanticModel.Compilation.GetTypeByMetadataName("ComputeSharp.D2D1.D2DGeneratedPixelShaderDescriptorAttribute") is not INamedTypeSymbol attributeSymbol)
{
return structDeclaration;
}

int index = 0;

// Find the index to use to insert the attribute. We want to make it so that if the struct declaration
// has a bunch of D2D attributes, the new one will be inserted right after that. This way the final list
// will be nicely sorted, instead of having D2D attributes interleaving other unrelated attributes, if any.
foreach (AttributeListSyntax attributeList in structDeclaration.AttributeLists)
{
// Make sure we have an attribute to check
if (attributeList.Attributes is not [AttributeSyntax attribute, ..])
{
continue;
}

// Resolve the symbol for the attribute (stop here if this failed for whatever reason)
if (!semanticModel.GetSymbolInfo(attribute, cancellationToken).TryGetAttributeTypeSymbol(out INamedTypeSymbol? attributeTypeSymbol))
{
break;
}

// If the attribute is D2D one, increment the index and continue
if (d2DAttributeTypeSymbols.Contains(attributeTypeSymbol))
{
index++;
}
else
{
// Otherwise, stop here, we reached the end of the sequence
break;
}
}

SyntaxGenerator syntaxGenerator = SyntaxGenerator.GetGenerator(document);

// Create the attribute syntax for the new attribute. Also annotate it
// to automatically add using directives to the document, if needed.
// Then create the attribute syntax and insert it at the right position.
SyntaxNode attributeTypeSyntax = syntaxGenerator.TypeExpression(attributeSymbol).WithAdditionalAnnotations(Simplifier.AddImportsAnnotation);
SyntaxNode attributeSyntax = syntaxGenerator.Attribute(attributeTypeSyntax);
SyntaxNode updatedStructDeclarationSyntax = syntaxGenerator.InsertAttributes(structDeclaration, index, attributeSyntax);

// Replace the node in the syntax tree
return updatedStructDeclarationSyntax;
}

/// <summary>
/// A custom <see cref="FixAllProvider"/> with the logic from <see cref="MissingPixelShaderDescriptorOnPixelShaderCodeFixer"/>.
/// </summary>
private sealed class FixAllProvider : DocumentBasedFixAllProvider
{
/// <inheritdoc/>
protected override async Task<Document?> FixAllAsync(FixAllContext fixAllContext, Document document, ImmutableArray<Diagnostic> diagnostics)
{
// Get the document root (this should always succeed)
if (await document.GetSyntaxRootAsync(fixAllContext.CancellationToken).ConfigureAwait(false) is not SyntaxNode root)
{
return document;
}

SyntaxEditor syntaxEditor = new(root, fixAllContext.Solution.Services);

foreach (Diagnostic diagnostic in diagnostics)
{
// Get the current struct declaration for the diagnostic
if (root.FindNode(diagnostic.Location.SourceSpan) is not StructDeclarationSyntax structDeclaration)
{
continue;
}

// Get the syntax node with the updated declaration
SyntaxNode updatedStructDeclaration = await AddMissingD2DGeneratedPixelShaderDescriptorAttribute(
document,
structDeclaration,
fixAllContext.CancellationToken);

// Replace the node via the editor
syntaxEditor.ReplaceNode(structDeclaration, updatedStructDeclaration);
}

return document.WithSyntaxRoot(syntaxEditor.GetChangedRoot());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,5 @@ CMPSD2D0061 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github
CMPSD2D0062 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp)
CMPSD2D0063 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp)
CMPSD2D0064 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp)
CMPSD2D0065 | ComputeSharp.D2D1.Shaders | Warning | [Documentation](https://github.com/Sergio0694/ComputeSharp)
CMPSD2D0066 | ComputeSharp.D2D1.Shaders | Error | [Documentation](https://github.com/Sergio0694/ComputeSharp)
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,9 @@

<!-- Shared project with .NET Standard 2.0 polyfills -->
<Import Project="..\ComputeSharp.NetStandard\ComputeSharp.NetStandard.projitems" Label="Shared" />

<!-- Give access to the code fixers project for the exported diagnostic ids and properties -->
<ItemGroup>
<InternalsVisibleTo Include="ComputeSharp.D2D1.CodeFixers, PublicKey=$(AssemblySignPublicKey)" />
</ItemGroup>
</Project>
Loading

0 comments on commit 57ecb78

Please sign in to comment.