[英]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>
-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.我检查了我有权访问的以下类型:
IncrementalGeneratorInitializationContext
、 SourceProductionContext
、 Compilation
但找不到任何内容。
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.