Roslyn analyzer pre .NET solution
original bol blogpost publikovaný tu
Použili ste už niekedy roslyn analyzátory v solution? Ak si myslíte že nie, tak ste na omyle. Všetky refaktoringy ktoré vám Visual Studio poskytuje sú postavené nad statickou analýzou kódu pomocou Roslynu.
Roslyn je v skratke .NET kompilátor, ktorý je napísaný v C#. Roslyn analyzátor je staticky anlyzátor, ktorý môže byť distribuovaný pomocou nuget balíčku alebo pomocou Visual Studia extensions.
Dnes si ma zavolal kolega ktorý potreboval pomôcť so setupom globálneho Roslyn analyzátora, ktorý mu bude vyhadzovať build error ak niekto zabudne dať do asynchronnej metódy suffix Async
. V msbuild systéme existuje koncept Directory.Build.props
and Directory.Build.targets
. Tieto dva "čarovné" súbory fungujú tak, že ak pri builde nájde msbuild tieto súbor, tak aplikuje ich obsah pri kompilácii projektu (určeného csproj
súborom). Directory.Build.props
sa aplikuje pred csproj
(takže csproj môže ovveridnuť hodnoty a premenné z Directory.Build.props
) a po aplikkovaní csproj
sa aplikuje Directory.Build.targets
. (dokumentácia).
Takýto scenár nie je úplne bežná rutina .NET developera a tým pádom Vám pred týmto experimentom radím zavrite Visual Studio. Dôvpd je taký, že Visual Studio s obľubom lockuje všetky súbory naokolo (hlavne nacachované), klasicky samo sebe 🤯, na boj proti nemu odporúčam lockhunter)
Takže si vytvoríme súbor Directory.Build.props
pri .sln
súbore (best practice). Treba si uvedomiť že sln
súbor je iba najvyšší "projektový" súbor a s msbuildom nemá nič spoločné. Msbuild si z sln
súboru zoberie iba cesty k csproj
projektom (prípadne obdobným pre F#, VB.NET, etc.).
Tak ako bude vyzerať náš príklad?
Demo si môžete stiahnuť z https://github.com/PadreSVK/dotnet-solution-analyzers-sample. Obsahuje dve branche, master
a fixed-code
kde v master branchi si môžete overiť funkčnosť solution analyzers.
Štruktúra solution:
C:.
│ Directory.Build.props // Build props for projects (ClassLibrary1, ConsoleApp1, ConsoleApp2)
│ Solution.ruleset // Rulessetom môžeme modifikovať ako má msbuild jednotlivé analyzátory vyhodnocovať = error, warning, message
│ SolutionAnalyzersCore.sln
│
├───ClassLibrary1
│ Class1.cs
│ ClassLibrary1.csproj
│
├───ConsoleApp1
│ ConsoleApp1.csproj
│ Program.cs
│
└───ConsoleApp2
ConsoleApp2.csproj
Program.cs
Štruktúra Directory.Build.props
:
<Project>
<PropertyGroup>
<LangVersion>preview</LangVersion> <!--Set C# version for every projects-->
<Nullable>enable</Nullable> <!--Enable nullable for projects-->
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)Solution.ruleset</CodeAnalysisRuleSet> <!--Path to Solution.ruleset config for analyzers-->
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.5.132" /> <!--some analyzer from nuget https://www.nuget.org/packages/Microsoft.VisualStudio.Threading.Analyzers/ -->
</ItemGroup>
</Project>
Z príkladu si môžete všimnúť že štruktúra je rovnaká ako pri csproj
a môžeme teda využiť aj "sdk" style referencie na nuget balíčky (analyzátory).
Použili sme analyzátor Microsoft.VisualStudio.Threading.Analyzers
, čiže sme pridali <PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="16.5.132" />
.
Po tomto kruku nám stačí zavolať dotnet CLI dotnet build
na úrovni sln
ktorý prevolá msbuild a stiahne potrebné balíčky.
Po tomto ktroku môžete spustiť Visual Studio a užiť si plnohodnotnú buzeráciu Roslyn Analyzátorov 😁
Tu sa nachádza zoznam analyzátorov Microsoft.VisualStudio.Threading.Analyzers.
Na záver už iba posledná vec. Ak chcete používať async Task Main
metódu, je treba bypasnuť analyzátor pomocou pragma warning
direktívy ako je zobrazená na codesnippete nižšie.
internal class Program
{
#pragma warning disable VSTHRD200
private static async Task Main(string[] args)
{
await Task.CompletedTask;
Console.WriteLine("Hello World!");
}
#pragma warning restore VSTHRD200
}