-
Using the below source generator on this class works just fine: partial class UserClass
{
[GeneratedNamespace.GeneratedAttribute]
public partial void UserMethod();
} However if I change it to be a file-scoped class, it no longer works and I get the error file partial class UserClass
{
[GeneratedNamespace.GeneratedAttribute]
public partial void UserMethod();
} I assume this is because the way file-scoped classes work, is that they are actually a different name under the hood. Using an IL viewer I can see the class is actually called Is there any way that source generators could work for file-scoped types? Source generator codeBased on https://github.com/dotnet/roslyn/blob/main/docs/features/incremental-generators.cookbook.md [Generator]
public class Generator : IIncrementalGenerator
{
private record Model(string Namespace, string ClassName, string MethodName);
public void Initialize(IncrementalGeneratorInitializationContext context)
{
context.RegisterPostInitializationOutput(static postInitializationContext =>
{
postInitializationContext.AddSource("myGeneratedFile.cs", SourceText.From("""
using System;
namespace GeneratedNamespace
{
internal sealed class GeneratedAttribute : Attribute
{
}
}
""", Encoding.UTF8));
});
var pipeline = context.SyntaxProvider.ForAttributeWithMetadataName(
fullyQualifiedMetadataName: "GeneratedNamespace.GeneratedAttribute",
predicate: static (syntaxNode, cancellationToken) => syntaxNode is BaseMethodDeclarationSyntax,
transform: static (context, cancellationToken) =>
{
var containingClass = context.TargetSymbol.ContainingType;
return new Model(
// Note: this is a simplified example. You will also need to handle the case where the type is in a global namespace, nested, etc.
Namespace: containingClass.ContainingNamespace?.ToDisplayString(
SymbolDisplayFormat.FullyQualifiedFormat.WithGlobalNamespaceStyle(
SymbolDisplayGlobalNamespaceStyle.Omitted)),
ClassName: containingClass.Name,
MethodName: context.TargetSymbol.Name);
}
);
context.RegisterSourceOutput(pipeline, static (context, model) =>
{
var sourceText = SourceText.From($$"""
namespace {{model.Namespace}};
partial class {{model.ClassName}}
{
public partial void {{model.MethodName}}()
{
// generated code
}
}
""", Encoding.UTF8);
context.AddSource($"{model.ClassName}_{model.MethodName}.g.cs", sourceText);
});
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Source generators are generating separated files, where you can't use file scoped types by definition. |
Beta Was this translation helpful? Give feedback.
The use-case (which is: generate sources scoped for use in a single file) makes sense, but as @huoyaoyuan pointed out
, the implementation (which generate sources in separate files) doesn't support it. You can manually create a namespace which is only used by the file.