Analyzers
Analyzers
Section titled “Analyzers”The Purview.SourceGeneratorFramework package includes the
Purview.SourceGeneratorFramework.Analyzers assembly as an analyzer asset, together with the
Purview.SourceGeneratorFramework.CodeFixers code fix providers. The diagnostics are enabled
automatically when you reference Purview.SourceGeneratorFramework from a source generator project.
How the analyzers are shipped
Section titled “How the analyzers are shipped”The analyzer and code-fix assemblies are built as Roslyn components
(IsRoslynComponent = true) and packed into the Purview.SourceGeneratorFramework package under
analyzers/dotnet/cs/. Because they are not separately packable NuGet packages, they are documented
here rather than in a standalone README.
The analyzers enforce two families of rules:
- Incremental generator best practice —
PSGFR11–PSGFR33, covering pipeline design,CodeWriterusage, Roslyn component discovery, and extension-class conventions. - C# 14 extension-member conventions —
PSGFR34–PSGFR38, plus the associatedReorganizeExtensionClassCodeFixProviderandConvertToExtensionBlockCodeFixProvider.
Rule reference
Section titled “Rule reference”| Rule | Summary |
|---|---|
PSGFR11 |
Prefer SyntaxProvider.ForAttributeWithMetadataName over CreateSyntaxProvider for attribute-based detection. |
PSGFR12 |
Use IIncrementalGenerator / RegisterSourceOutput instead of ISourceGenerator. |
PSGFR14 |
Avoid RegisterImplementationSourceOutput unless implementation-only output is required. |
PSGFR15 |
Pipeline model collection members should use sequence equality (e.g. EquatableArray<T>). |
PSGFR16 |
Prefer the nullable-context Nullable()/MakeNullable() overload so annotations honour the target compilation. |
PSGFR17 |
Consume CodeWriter scope-returning methods (...Scope, IndentedScope) with using. |
PSGFR18 |
Prefer structured declaration APIs (Class, Method, Property, Field) over raw declaration text. |
PSGFR19 |
Prefer structured statement APIs (Return, MethodCall, Throw, Assignment, Using, Comment) over raw statement text. |
PSGFR20 |
Prefer the minimal CodeWriter overloads over constructing *DeclarationOptions values manually. |
PSGFR21 |
Prefer HashDefines/HashDefinesScope for #if/#endif conditional-compilation directives. |
PSGFR22 |
Prefer PragmaDisable/OpenPragmasScope for #pragma warning directives. |
PSGFR23 |
Prefer structured IfBlock/ElseIf/Else over raw if block text. |
PSGFR24 |
CodeFixProvider is not marked [ExportCodeFixProvider]; Visual Studio will never discover it. |
PSGFR25 |
DiagnosticAnalyzer is not marked [DiagnosticAnalyzer]; it will never run. |
PSGFR26 |
A generator type is not marked [Generator]; it will never run. |
PSGFR27 |
A Roslyn component type is not public; the compiler host cannot instantiate it. |
PSGFR28 |
FixableDiagnosticIds references a diagnostic ID no analyzer in the compilation produces; the fix will never be shown. |
PSGFR29 |
Do not embed a CodeWriter in a string; use XmlCommentWriter.XmlInlineCode instead. |
PSGFR30 |
Prefer static lambdas in incremental pipeline methods so the compiler never allocates a closure on the per-item hot path. |
PSGFR31 |
Prefer GeneratorAttributeSyntaxContext.TargetSymbol over SemanticModel.GetDeclaredSymbol(ctx.TargetNode). |
PSGFR32 |
Avoid NormalizeWhitespace when generating source; use an indented text writer such as CodeWriter. |
PSGFR33 |
Pipeline models must not retain Roslyn objects (ISymbol, SyntaxNode, Location, …); extract the information into value types. |
PSGFR34 |
Prefer C# 14 extension(Receiver) blocks over classic static this-parameter extension methods. |
PSGFR35 |
Extension class name must match the extended type ({Receiver}Extensions). |
PSGFR36 |
Extension classes must be placed in the extended type’s namespace under an Extensions folder. |
PSGFR37 |
One extension class per receiver type; split classes that extend multiple types. |
PSGFR38 |
Extension classes should carry [EditorBrowsable(EditorBrowsableState.Never)]. |
Type-library and attribute-model diagnostics
Section titled “Type-library and attribute-model diagnostics”The bundled generators carry their own diagnostic families, reported by the
TypeLibraryValidationAnalyzer (TLB0001–TLB0019) and the attribute-data-model validation
analyzers. These are documented on their feature pages:
Code fixes
Section titled “Code fixes”Code fix providers ship in the Purview.SourceGeneratorFramework.CodeFixers assembly and cover the
analyzer rules above, including:
AddGeneratorAttributeCodeFixProvider— adds the missing[Generator]attribute (PSGFR26).AddDiagnosticAnalyzerAttributeCodeFixProvider— adds[DiagnosticAnalyzer](PSGFR25).AddExportCodeFixProviderAttributeCodeFixProvider— adds[ExportCodeFixProvider](PSGFR24).MakeRoslynComponentPublicCodeFixProvider— makes the component type public (PSGFR27).RemoveOrphanedFixableDiagnosticIdCodeFixProvider— removes unused fixable diagnostic IDs (PSGFR28).PreferTargetSymbolCodeFixProvider— switches toTargetSymbol(PSGFR31).PreferStaticLambdaCodeFixProvider— makes pipeline lambdasstatic(PSGFR30).PreferNullableContextOverloadCodeFixProvider— adds the generation context toNullable()/MakeNullable()calls, including project-wide “Fix all” support (PSGFR16).PipelineModelReferenceEqualityCollectionCodeFixProvider— wraps collection members for sequence equality (PSGFR15).PreferStructuredCodeWriterIfBlockCodeFixProvider— rewrites rawif/else if/elseblock text to the structuredIfBlock/ElseIf/ElseAPIs (PSGFR23).CodeWriterToStringCodeFixProvider— replaces embeddedCodeWriterstring interpolation (PSGFR29).AttributeDataModelSymbolPropertyCodeFixProvider— fixes attribute-data-model symbol properties.ReorganizeExtensionClassCodeFixProvider— renames (PSGFR35), splits multi-receiver classes (PSGFR37), moves the class underExtensions/{ReceiverNamespace}/, and updates referencing files (PSGFR36).ConvertToExtensionBlockCodeFixProvider— converts classic methods to C# 14extensionblocks (PSGFR34).AddExtensionClassMetadataCodeFixProvider— adds[EditorBrowsable(EditorBrowsableState.Never)]to extension classes (PSGFR38).- Type-library fixes —
TypeLibraryMemberAccessibilityCodeFixProvider,TypeLibraryMarkerDefaultInitializerCodeFixProvider,MakeTypeLibrarySpecPartialCodeFixProvider,RenameTypeLibrarySpecCodeFixProvider, andTypeLibraryMemberTypeCodeFixProvider.
See Guide.md for the extension-class conventions the
PSGFR34–PSGFR38 rules enforce.
Roslyn component discovery
Section titled “Roslyn component discovery”The compiler host only loads a source generator, diagnostic analyzer, or code fix provider when three conditions hold. Missing any one means the component is silently ignored:
- The type is public (
PSGFR27). - The type is decorated —
[Generator](PSGFR26),[DiagnosticAnalyzer](PSGFR25), or[ExportCodeFixProvider](PSGFR24). - The assembly is loaded as an analyzer — packed under
analyzers/dotnet/cs/in a package, or referenced withOutputItemType="Analyzer"in a project reference.
A code fix provider also only appears when the diagnostic ID in FixableDiagnosticIds is actually
produced by an analyzer loaded alongside it (PSGFR28). Visual Studio MEF-composes fix providers when
the analyzer set loads, so after adding or updating a fixer assembly you must restart Visual Studio or
reload the project for the fixes to appear.
License
Section titled “License”This documentation is part of the MIT-licensed Purview.SourceGeneratorFramework project.