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 😁

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á 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
}