Skip to main content
Any Framework

Source helpers for Roslyn analyzers and source generators

Published
Sep 5, 2026
1mo ago
Total Downloads
7.2K
7,214

Install

dotnet add package Meziantou.Framework.Roslyn --version 1.0.10

No framework information available.

README

Meziantou.Framework.Roslyn

Meziantou.Framework.Roslyn provides source helpers for Roslyn analyzers and source generators. The package does not ship a library assembly; helper code is compiled into the consuming project.

Usage

Install the package in an analyzer or source generator project that already references Roslyn packages:

<ItemGroup>
  <PackageReference Include="Meziantou.Framework.Roslyn" Version="x.y.z" PrivateAssets="all" />
  <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.6.0" PrivateAssets="all" />
</ItemGroup>

Then import the helper namespace:

using Meziantou.Framework.Roslyn;

Helpers

  • Compilation.GetBestTypeByMetadataName
  • Compilation.IsNet9OrGreater
  • ContextExtensions.ReportDiagnostic
  • DiagnosticReporter
  • DiagnosticReporter.CanReportDiagnostic
  • ExpressionSyntax.Parenthesize
  • GeneratedCodeExtensions.IsGeneratedCodeFile
  • IOperation.UnwrapImplicitConversions
  • LanguageVersionExtensions
  • LocalDataFlowAnalysis
  • LocationExtensions
  • MethodSymbolExtensions
  • NamespaceSymbolExtensions
  • SuppressorHelpers
  • SymbolAttributeExtensions
  • SyntaxNode.HasAutoGeneratedComment
  • SyntaxNode.Parenthesize
  • SyntaxTree.IsGeneratedCode
  • ISymbol.GetFirstSourceLocation
  • ISymbol.IsVisibleOutsideOfAssembly
  • ITypeSymbol.GetUnderlyingNullableTypeOrSelf
  • TypeSymbolExtensions

The package also defines Roslyn and C# feature constants before compilation based on the referenced Microsoft.CodeAnalysis.* package version, such as ROSLYN_4_8_OR_GREATER and CSHARP12_OR_GREATER.

ROSLYN_WORKSPACES is defined when the project references a Roslyn workspaces package (Microsoft.CodeAnalysis.Workspaces.Common, Microsoft.CodeAnalysis.CSharp.Workspaces, Microsoft.CodeAnalysis.VisualBasic.Workspaces or Microsoft.CodeAnalysis.Workspaces.MSBuild). The helpers use it to light up the features that need a workspace, such as annotating the nodes they create with Simplifier.Annotation.

Type relationships

InheritsFrom, Implements and ImplementsGenericInterface are strict: a type never derives from or implements itself. When the queried symbol is a type parameter, its constraints are inspected and a constraint that is the queried type is a match, so T in where T : Base derives from Base and T in where T : ISample implements ISample.

Use IsOrInheritsFrom and IsOrImplements to ask whether a type is assignable to another one; they include the type itself, so they don't depend on that distinction:

// true when the type is Base or derives from it
if (type.IsOrInheritsFrom(baseType))
{
}

Diagnostic filtering

DiagnosticReporter.CanReportDiagnostic is a global filter evaluated before a diagnostic is reported. It defaults to null, so no filtering occurs. When it is set, every diagnostic reported through a DiagnosticReporter or through the ReportDiagnostic extension methods of the analysis contexts is evaluated, and returning false drops it:

DiagnosticReporter.CanReportDiagnostic = (diagnostic, options, cancellationToken)
    => diagnostic.Location.SourceTree?.IsGeneratedCode(options, cancellationToken) is not true;

The delegate gets the Diagnostic about to be reported, so the descriptor is available with diagnostic.Descriptor and the syntax tree with diagnostic.Location.SourceTree. The AnalyzerOptions and the CancellationToken are the ones of the context the diagnostic is reported from.

The filter is meant to be set once, when the analyzer is initialized. As all types of this package are embedded, it only applies to the assembly that consumes the package. Diagnostics reported directly on a Roslyn context, such as SymbolAnalysisContext.ReportDiagnostic(Diagnostic), don't go through the reporter and are not filtered.

Type embedding

All types are decorated with [Microsoft.CodeAnalysis.Embedded], so the compiler hides them from other assemblies. This means the helpers don't conflict when an assembly that uses this package exposes its internals with [InternalsVisibleTo] to another assembly that also uses it (warning CS0436).

The package declares Microsoft.CodeAnalysis.EmbeddedAttribute as an internal sealed partial class without any attribute on it, so it can be merged with the declarations emitted by other source generators or packages.

Define the MEZIANTOU_FRAMEWORK_ROSLYN_DISABLE_EMBEDDEDATTRIBUTE constant to opt out of both the attribute usages and the attribute declaration:

<PropertyGroup>
  <DefineConstants>$(DefineConstants);MEZIANTOU_FRAMEWORK_ROSLYN_DISABLE_EMBEDDEDATTRIBUTE</DefineConstants>
</PropertyGroup>

If the attribute is already declared in the project in a way that conflicts with this declaration, define MEZIANTOU_FRAMEWORK_ROSLYN_DISABLE_EMBEDDEDATTRIBUTE_DECLARATION instead. The types are still marked as embedded, but the attribute must be provided by the project:

<PropertyGroup>
  <DefineConstants>$(DefineConstants);MEZIANTOU_FRAMEWORK_ROSLYN_DISABLE_EMBEDDEDATTRIBUTE_DECLARATION</DefineConstants>
</PropertyGroup>

Compiler warnings

The helper files suppress all compiler warnings so they don't pollute the consuming project's build. Define the MEZIANTOU_FRAMEWORK_ROSLYN_ENABLE_WARNINGS constant to report them:

<PropertyGroup>
  <DefineConstants>$(DefineConstants);MEZIANTOU_FRAMEWORK_ROSLYN_ENABLE_WARNINGS</DefineConstants>
</PropertyGroup>

Changes from Previous Version

No structural changes between v1.0.9 and v1.0.10.

Adoption Assessment

A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.

No target framework metadata is available. Confirm compatibility in a representative project before standardising on this package.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.