All analyzer projects must target netstandard2.0 due to Visual Studio not loading other runtimes in code designing stage.\n You should specify
<LangVersion>11</LangVersion>
to use latest language features
Add properties for package generation
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeBuildOutput>false</IncludeBuildOutput>
</PropertyGroup>
Add separate property group for constant NuGet package properties
<PropertyGroup>
<PackageId>SourceKit.Analyzers.MustBePartial</PackageId>
<Title>SourceKit.Analyzers.MustBePartial</Title>
<Authors>ronimizy</Authors>
</PropertyGroup>
And separate group for more volatile properties
<PropertyGroup>
<PackageReleaseNotes>Analyzers for checking whether type is partial</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Common"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" VersionOverride="4.5.0"/>
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common"/>
</ItemGroup>
You have to manually add assemblies to your analyzers NuGet package path
<ItemGroup>
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/>
<None Include="$(OutputPath)\$(AssemblyName).Annotations.dll" Pack="true" PackagePath="analyzers/dotnet/cs"
Visible="false"/>
<None Include="$(OutputPath)\SourceKit.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/>
</ItemGroup>
Choose diagnostic category, based on MS Docs listing
https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/categories
After implementing your analyzer code, include sample code, describing all use cases of your feature
into SourceKit.Sample
project
Use designated folder for it (ex: Analyzers/MustBePartial
)
You should validate your sample code using unit tests.
- Specify type alias for your verifier
using Verify = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<{AnalyzerType}>;
- Create
CSharpAnalyzerTest<{AnalyzerType}, XUnitVerifier>
instance - Add source files using
SourceFile.LoadAsync
var test = new CSharpAnalyzerTest<{AnalyzerType}, XUnitVerifier> { TestState = { Sources = { await SourceFile.LoadAsync("..."), }, }, };
- Add reference to annotations package
var test = new CSharpAnalyzerTest<{AnalyzerType}, XUnitVerifier> { TestState = { AdditionalReferences = { typeof(SomeAttribute).Assembly }, }, };
- Specify diagnostics if they are expected
var diagnostic = Verify.Diagnostic(Analyzer.Descriptor) .WithLocation(sourceFile.Name, 3, 14) .WithArguments(nameof(SomeType)); var test = new CSharpAnalyzerTest<{AnalyzerType}, XUnitVerifier> { ExpectedDiagnostics = { diagnostic }, };
- Run test
await test.RunAsync();
- Specify type alias for your verifier
using Verify = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<{AnalyzerType}>;
- Specify type alias for your code fix test
using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest< {AnalyzerType}, {CodeFixProviderType}, Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier>;
- Add source files using
SourceFile.LoadAsync
var test = new CodeFixTest { TestState = { Sources = { await SourceFile.LoadAsync("..."), }, }, };
- Add reference to annotations package
var test = new CodeFixTest { TestState = { AdditionalReferences = { typeof(SomeAttribute).Assembly }, }, };
- Specify diagnostics if they are expected
var diagnostic = Verify.Diagnostic(Analyzer.Descriptor) .WithLocation(sourceFile.Name, 3, 14) .WithArguments(nameof(SomeType)); var test = new CodeFixTest { ExpectedDiagnostics = { diagnostic }, };
- Specify fixed state
var test = new CodeFixTest { FixedState = { Sources = { fixedSource, interfaceSource }, }, };
- Run test
await test.RunAsync();