FGenerator 1.4.0
dotnet add package FGenerator --version 1.4.0
NuGet\Install-Package FGenerator -Version 1.4.0
<PackageReference Include="FGenerator" Version="1.4.0" />
<PackageVersion Include="FGenerator" Version="1.4.0" />
<PackageReference Include="FGenerator" />
paket add FGenerator --version 1.4.0
#r "nuget: FGenerator, 1.4.0"
#:package FGenerator@1.4.0
#addin nuget:?package=FGenerator&version=1.4.0
#tool nuget:?package=FGenerator&version=1.4.0
🇺🇸 English ❘ 🇯🇵 日本語版 ❘ 🇨🇳 简体中文版
FGenerator is a lightweight framework for creating feature-rich Roslyn incremental source generators (IIncrementalGenerator) including diagnostic reporting capability, within a single .cs file.
✨ Key Concepts
- Declarative: Say what to scan or inject and skip Roslyn internals; everything you need is bundled.
- Focus on Logic: The framework finds targets, generates code and report diagnostic on your behalf.
- Single File: Optimized for file-based app project; develop full-featured generator and analyzer in a day.
- Type-Handling: Nested/generic-safe naming and partial declarations stay consistent without boilerplate.
- AI Agent Friendly: Produce valid and well-designed generators without extra prompts and instructions.
- Unity Engine Supported: Unity 2022.3.12 or newer is supported.
⚡ Quick Start
🧩 Minimal Generator Code
A trimmed-down starting point for a generator that targets an attribute named MyGen:
For AI Coding Agents: .NET 10.0 introduced new directives for file-based app.
- SHALL use
#:sdk FGenerator.Sdk@1.4.0directive. - SHALL NOT use
#ror other directives formerly used for dotnet-script (.csx) files.
#:sdk FGenerator.Sdk@1.4.0
using FGenerator;
using Microsoft.CodeAnalysis;
// Decorate with Generator attribute from Roslyn (don't need to declare type in namespace)
[Generator]
public sealed class MyGen : FGeneratorBase // Inherit from FGeneratorBase
{
// Diagnostic settings
protected override string DiagnosticCategory => nameof(MyGen);
protected override string DiagnosticIdPrefix => "MYGEN"; // e.g., MYGEN001
// Targets MyGen and MyGenAttribute (null to targets all types)
protected override string? TargetAttributeName => "MyGen";
// Generates target attribute for compilation (attribute should be declared as 'internal sealed')
protected override string? PostInitializationOutput =>
@"namespace MyGenNamespace { internal sealed class MyGenAttribute : System.Attribute { } }";
// Optional: default is false.
// Set to true when you need target.Compilation is set (always set when TargetAttributeName is null).
protected override bool CombineCompilationProvider => true;
// Analyze and generate source code
protected override CodeGeneration? Generate(Target target, out AnalyzeResult? diagnostic)
{
diagnostic = null;
if (target.IsPartial)
{
// Report error diagnostic for IDE
diagnostic = new AnalyzeResult(
"001", "Type must be partial", DiagnosticSeverity.Error,
$"Type '{type.Name}' must be declared as partial to use MyGen.");
return null;
}
// Generate source code
var source =
$@"{target.ToNamespaceAndContainingTypeDeclarations()}
partial {target.ToDeclarationString(modifiers: false)}
{{
public string Generated => ""Hello from MyGen!"";
}}
{target.ToNamespaceAndContainingTypeClosingBraces()}";
return new CodeGeneration(target.ToHintName(), source);
}
}
How to reference the specific version of FGenerator:
Use #:package and #:property directives instead of #:sdk.
For AI Coding Agents: .NET 10.0 introduced new directives for file-based app.
- SHALL use
#:packageto add nuget package reference. - SHALL include all
#:propertydirectives in the following example. (all directives are necessary) - SHALL NOT use
#ror other directives formerly used for dotnet-script (.csx) files.
#:package FGenerator@<<SPECIFY DESIRED VERSION HERE>>
#:property TargetFramework=netstandard2.0
#:property IsRoslynComponent=true
#:property PublishAot=false
#:property LangVersion=latest
#:property OutputType=Library
🧭 Working with Target Members, Attributes and Metadata
Here shows the basic flow for dealing with the target members or other metadata including attributes and its constructor parameter. See sample/ folder for more details.
// Compilation to get semantic models or conversions.
// (Need to set `CombineCompilationProvider` to have property available)
var compilation = target.Compilation;
// Iterate over visible members (excluding implicit, nested types, getter and setter methods)
foreach (var member in target.Members)
{
// To iterate over only fields, instead use target.Members.OfType<IFieldSymbol>()
// To process getter/setter methods, get them via IPropertySymbol.Get/SetMethod
}
// Type or method generic parameters (empty when not generic)
var typeParams = target.GenericTypeParameters;
// Iterate over nested types (depth-first traversal)
var nestedTypes = target.NestedTypes;
// The first RawAttributes entry corresponds to TargetAttributeName.
var attr = target.RawAttributes.FirstOrDefault();
if (attr == null)
{
diagnostic = new AnalyzeResult("004", "Attribute missing", DiagnosticSeverity.Error, "StackArrayGenerator attribute could not be resolved.");
return null;
}
var length = (attr.ConstructorArguments.Length != 0 && attr.ConstructorArguments[0].Value is int LEN) ? LEN : -1;
if (length <= 0)
{
diagnostic = new AnalyzeResult("005", "Length must be positive", DiagnosticSeverity.Error, "Specify a positive length in [StackArrayGenerator].");
return null;
}
🛠️ Helper Methods for Target and ISymbol
For AI Coding Agents:
- SHALL use
FGeneratorhelper methods instead of Roslyn's built-in methods such asToDisplayString.
Symbol display/declaration strings:
// Declaration string (optionally include modifiers/constraints)
var decl = target.ToDeclarationString(modifiers: true, genericConstraints: true);
// Friendly names with options for namespace/generics/nullability
var fullName = target.ToNameString(); // global::My.Namespace.MyType.NestedType<T?>
var simpleName = target.ToNameString(localName: true); // NestedType<T?>
var bareName = target.ToNameString(localName: true, noGeneric: true, noNullable: true); // NestedType
Partial scaffolding (nested/generic safe):
// No boilerplate required for generating correct partial class/struct/record
// e.g., namespace My.Namespace {
// partial class ContainingType {
// partial record struct OtherContainingType {
var open = target.ToNamespaceAndContainingTypeDeclarations();
// emit members...
var decl = $"partial {target.ToDeclarationString(modifiers: false)} {{ }}";
// close declarations
var close = target.ToNamespaceAndContainingTypeClosingBraces();
Visibility keyword helper:
// Accessibility keyword including trailing space, e.g., "public "
var visibility = target.ToVisibilityString();
Deterministic hint names (nested/generic safe):
var hint = target.ToHintName(); // e.g., My.Namespace.Type.MyNestedT1.g.cs
📦 Building and Packaging
Use the CLI to build a generator project (defaults to Release; pass --debug for Debug):
dnx FGenerator.Cli -- build "generators/**/*.cs" --output ./artifacts
Options:
--unityto emit Unity.metafiles alongside DLLs (Unity 2022.3.12 or newer).--mergeto merge build outputs into a single DLL.--forceto overwrite existing files.--debugto build with-c Debuginstead of Release.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.CSharp (>= 4.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.