AaronRobinsonMSFT / DNNE

Prototype native exports for a .NET Assembly.
MIT License
394 stars 41 forks source link

Use source generator to generate attributes #168

Closed JeremyAnsel closed 10 months ago

JeremyAnsel commented 1 year ago

Hello, I have an idea.

To use the DNNE.ExportAttribute, DNNE.C99TypeAttribute, or DNNE.C99DeclCodeAttribute attribute, you have to manually add them to your project as shown in test/ExportingAssembly/Dnne.Attributes.cs. Instead of manually add them, I suggest to include a source generator to generate the attributes.

Something like that: .csproj class library project:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <ImplicitUsings>disable</ImplicitUsings>
    <Nullable>disable</Nullable>
    <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
  </ItemGroup>

</Project>

AttributesGenerator.cs file:

using Microsoft.CodeAnalysis;

namespace DnneAttributesGenerator
{
    [Generator]
    public class AttributesGenerator : ISourceGenerator
    {
        public void Execute(GeneratorExecutionContext context)
        {
            string source =
@"
using System;

namespace DNNE
{
    internal class ExportAttribute : System.Attribute
    {
        public ExportAttribute() { }
        public string EntryPoint { get; set; }
    }

    internal class C99TypeAttribute : System.Attribute
    {
        public C99TypeAttribute(string code) { }
    }

    internal class C99DeclCodeAttribute : System.Attribute
    {
        public C99DeclCodeAttribute(string code) { }
    }
}
";

            context.AddSource(nameof(AttributesGenerator), source);
        }

        public void Initialize(GeneratorInitializationContext context)
        {
        }
    }
}

You can reference the project with:

  <ItemGroup>
    <ProjectReference Include="..\DnneAttributesGenerator\DnneAttributesGenerator.csproj"
                      OutputItemType="Analyzer"
                      ReferenceOutputAssembly="false" />
  </ItemGroup>

The documentation to add the source generator to a NuGet package is here: Package a generator as a NuGet package

AaronRobinsonMSFT commented 1 year ago

I suggest to include a source generator to generate the attributes.

I am familiar with source generators. I'm not really inclined to do that though. The biggest reason is source generators should be used to respond specifically to user edits, not just inject basic types. A source generator seems like a rather big hammer for something as small as adding a few types.

AaronRobinsonMSFT commented 1 year ago

Looks like there might be a more light weight approach to this using the incremental source generators - RegisterPostInitializationOutput. I'll try to get to this as it might be helpful for others.

AaronRobinsonMSFT commented 10 months ago

@JeremyAnsel Thanks to @Sergio0694, a source generator now exists in https://www.nuget.org/packages/DNNE/2.0.6

ThaDaVos commented 7 months ago

Funny thing - already did this with my fork too 🤣🤣