简体   繁体   English

C# 源代码生成器:通过命令行属性或预处理器定义常量有条件地生成代码

[英]C# Source Generators: conditionally generate code via command line properties or pre-processor define constants

I am writing a source generator using the incremental generator approach.我正在使用增量生成器方法编写源代码生成器。

I want to allow the developers to be able to conditionally generate some extra code (eg extra comments, debug printouts, pedantic validations in the generated code, etc.) and I would like this to be controlled by either:我想让开发人员能够有条件地生成一些额外的代码(例如,额外的注释、调试打印输出、生成的代码中的迂腐验证等),我希望这可以通过以下任一方式来控制:

  • DefineConstants by adding the following to the .csproj file of the project using my source generator:通过使用我的源生成器将以下内容添加到项目的DefineConstants文件来.csproj
<PropertyGroup>
  <DefineConstants>$(DefineConstants);MY_PROJECT_EXTRA</DefineConstants>
</PropertyGroup>
  • or via the -p: option on the do.net build command line:或者通过do.net build命令行上的-p:选项:
dotnet build ProjectUsingMySourceGeneratorCode.csproj -p:MyProjectExtra=true

I checked the following types I have access to: IncrementalGeneratorInitializationContext , SourceProductionContext , Compilation but could not find anything.我检查了我有权访问的以下类型: IncrementalGeneratorInitializationContextSourceProductionContextCompilation但找不到任何内容。

As workaround I could add a custom attribute that developers can use to decorate the syntax elements they want to control, but this might require developers to add the attribute many classes/methods manually.作为解决方法,我可以添加一个自定义属性,开发人员可以使用该属性来装饰他们想要控制的语法元素,但这可能需要开发人员手动添加许多类/方法的属性。

Is there a way I can access either (or both) DefineConstants or command line -p: properties (or any other compile-time settings) inside the IncrementalGenerator workflow?有没有一种方法可以访问IncrementalGenerator工作流中的一个(或两个) DefineConstants或命令行-p: properties(或任何其他编译时设置)?

Thanks to comment from @caton7 I was able to find a way an initial solution using .editorconfig .感谢 @caton7 的评论,我能够找到一种使用.editorconfig的初始解决方案。 I think incremental generators might work slightly different than original source generators so I ended up doing something similar to https://github.com/do.net/roslyn/blob/main/docs/features/source-generators.cookbook.md#access-analyzer-config-properties .我认为增量生成器的工作方式可能与原始源生成器略有不同,所以我最终做了类似于https://github.com/do.net/roslyn/blob/main/docs/features/source-generators.cookbook.md#的操作访问分析器配置属性

My solution我的解决方案

.editorconfig .editorconfig

myvalue = foo

SourceGenerator.cs源代码生成器.cs

public class SourceGenerator : IIncrementalGenerator {
   public void Initialize(IncrementalGeneratorInitializationContext context)
   {
       // Step 1. Identify the classes.
       var classDeclarations = context.SyntaxProvider.CreateSyntaxProvider(
                static (node, ct) => true /* Update with your code */,
                static (context, ct) => context.Node as ClassDeclarationSyntax /* Update with your code*/)
            .Where(CommonExtensions.IsNotNull);

       // Step 2. Combine analyser, compilation and class declaration
       var analizerConfigOptionsCompilationAndClasses = context
            .AnalyzerConfigOptionsProvider
            .Combine(context
                .CompilationProvider
                .Combine(classDeclarations.Collect()));

       // Step 3. Register the source output to generate the code.
       context.RegisterSourceOutput(
            analizerConfigOptionsCompilationAndClasses,
            static (context, settings) => Execute(context, settings.Left, settings.Right.Left, settings.Right.Right));
    }

   private static Execute(SourceProductionContext context, AnalyzerConfigOptionsProvider analyzerConfigOptionsProvider, Compilation compilation, ImmutableArray<ClassDeclarationSyntax?> classDeclarationSyntaxes))
   {
      // NOTE: Unsure why by analyzerConfigOptionsProvider.TryGetValue("myvalue", out var x) would never return the values I would be expecting.

      foreach (var classDeclarationSyntax in classDeclarationSyntaxes)
      {
         if (classDeclarationSyntax is null)
         {
            continue;
         }

         var options = analyzerConfigOptionsProvider.GetOptions(classDeclarationSyntax.SyntaxTree);
         options.TryGetValue("myvalue", out string? myvalue);
         /* myvalue should now be equal to the string foo as defined in .editorconfig */
      }
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 c#预处理器指令范围 - c# Pre-processor directive scope 快速问题:C#中的此预处理程序指令出了什么问题 - Quick Question: Whats wrong with this pre-processor directive in C# 在一个项目中定义预处理器标志,并在另一个项目中使用它 - Define pre-processor flag in one project and use it in another C#中#if DEBUG预处理器指令的用法是什么? 什么时候必须使用它? - What is the usage of #if DEBUG pre-processor directive in C#? When must we use this? 预处理程序指令是否可以保护客户端的服务器代码? - Do pre-processor directives protect server code from the client? 从 C# 调用 C 预处理器时,UTF-8 输入文件(作为参数提供)的某些字符已损坏 - While calling C pre-processor from C#, some characters of a UTF-8 input file (supplied as argument) are corrupted 在C#/ Visual Studio 2010中构建标签。在AssemblyInfo.cs中创建可由预处理器/编译器使用的常量 - Build labelling in C# / Visual Studio 2010. Create a constant that can be used by pre-processor / compiler in AssemblyInfo.cs C# 源代码生成器:如何调试生成代码中的编译器错误? - C# source generators: How to debug compiler errors in the generated code? 消除预处理器命令的方法 - Way to eliminate pre-processor commands C# 源码生成器在 vscode 中调试 - C# Source Generators debug in vscode
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM