Roslyn analyzer pre .NET solution

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 teda 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:

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 😁

analyzers in action

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=a na codesnippete nižšie.