cezarypiatek / CSharpExtensions

A set of annotations and analyzers that add additional constraints to your codebase
MIT License
122 stars 12 forks source link
roslyn roslyn-analyzers

CSharpExtensions

Nuget packge: https://www.nuget.org/packages/SmartAnalyzers.CSharpExtensions.Annotations/

Articles that explain implemented concepts:

Analyzers

Rule Description Related attributes Documentation
CSE001 Required properties initialization [InitRequired], [InitRequiredForNotNull] link
CSE002 InitOnly member modification [InitOnly], [InitOnlyOptional] link
CSE003 Type should have the same fields as twin type [TwinType] link
CSE004 Member with InitOnlyOptional requires default value [InitOnlyOptional]
CSE005 Return value unused link
CSE006 Expression too complex
CSE007 Return disposable value unused Same as SE005 but tracks only IDisposable and IAsyncDisposable values
CSE008 Return async result unused Same as SE005 but tracks only IAsyncResult (Task, ValueTask) values
CSE009 Task variable not awaited Check if task stored in a variable is awaited

Configuration

Add CSharpExtensions.json file with custom configuration:

{
  "CSE005": {
    "IgnoredReturnTypes": [ 
        "Microsoft.Extensions.DependencyInjection.IServiceCollection",
        "Microsoft.Extensions.Configuration.IConfigurationBuilder",
        "Microsoft.Extensions.Logging.ILoggingBuilder"
        ] 
  } 
}

Include config file as AdditionalFile in csproj:

<ItemGroup>
    <AdditionalFiles Include="CSharpExtensions.json" />
</ItemGroup>

Migrating from Constructors to Initialization Blocks

Step 1: Configure CSharpExtensions to report CSE001 even when constructor invocation is present

{
  "CSE001": {
    "SkipWhenConstructorUsed":  false 
  } 
}

Step 2: Execute "Try to move initialization from constructor to init block" CodeFix for CSE001 occurrences.

Init-related attributes vs init keyword (C# 9+ feature)

Feature Required in init block Can be modified outside init block Application level
init keyword NO NO Property
[InitRequired] YES YES Property. Class
[InitOnly] YES NO Property. Class
[InitOnlyOptional] NO NO Property. Class
[InitRequiredForNotNull] YES for non-null references and not Nullable<T> YES assembly