« Code analysis » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
(Page créée avec « Category:.NET Core = [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8 Code analysis] = * [https://editorconfig.org/ editorconfig] == Code quality analysis == Those [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enabled-rules rules] are enabled by default.<br> Here is how to enabled [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enable-a... »)
 
(21 versions intermédiaires par le même utilisateur non affichées)
Ligne 1 : Ligne 1 :
[[Category:.NET Core]]
[[Category:.NET Core]]
= [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8 Code analysis] =
= Links =
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8 .NET source code analysis]
* [https://editorconfig.org/ editorconfig]
* [https://editorconfig.org/ editorconfig]


== Code quality analysis ==
= [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8#enable-additional-rules Enable additional rules] =
Those [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enabled-rules rules] are enabled by default.<br>
Those [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-8#enabled-rules rules] are enabled by default.<br>
Here is how to enabled [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview?tabs=net-7#enable-additional-rules additional rules]:
Edit the project file to enable additional rules:
<filebox fn='MyProject.csproj' lang='xml'>
<filebox fn='MyProject.csproj' lang='xml'>
<PropertyGroup>
<PropertyGroup>
Ligne 13 : Ligne 14 :
</filebox>
</filebox>


* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ Code quality rules CAxxxx]
= Editorconfig =
 
== Core options ==
{{info | Prefer the use of {{boxx|editorconfig}} to {{boxx|globalconfig}}}}
<filebox fn='.editorconfig' lang='ini'>
<filebox fn='.globalconfig' lang='ini' collapsed>
# Top level entry required to mark this as a global AnalyzerConfig file
is_global = true
 
# NOTE: No section headers for configuration entries
 
#### .NET Coding Conventions ####
 
# this. and Me. preferences
dotnet_style_qualification_for_method = true:warning
 
#### Diagnostic configuration ####
 
# CA2007: Do not directly await a Task
dotnet_diagnostic.CA2007.severity = none
</filebox>
 
== Code style analysis ==
<kode lang='bash'>
# verify that all code is correctly formatted
dotnet format --verify-no-changes
 
# format all code
dotnet format
</kode>
 
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files#global-analyzerconfig Configuration files for code analysis rules]
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options#example-editorconfig-file An example of .editorconfig file with the default options]
* [https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules Code-style rules IDExxxx]
* [[Encodage_de_caractères#Convertion|Change encoding]]
 
<filebox fn='.editorconfig' lang='ini' collapsed>
###############################
# Core EditorConfig Options  #
###############################
root = true
root = true


Ligne 71 : Ligne 37 :
indent_size              = 4
indent_size              = 4
trim_trailing_whitespace = true
trim_trailing_whitespace = true
</filebox>


###############################
== Analyzer configuration ==
# Analyzer configuration     #
<filebox fn='.editorconfig' lang='ini'>
###############################
 
# set the rules severity to warning
# set the rules severity to warning
dotnet_analyzer_diagnostic.severity = warning
dotnet_analyzer_diagnostic.severity = warning
# speller
</filebox>
dotnet_diagnostic.VSSpell001.severity = suggestion
dotnet_diagnostic.VSSpell002.severity = suggestion


###############################
== Miscellaneous configuration ==
# .NET Coding Conventions    #
<filebox fn='.editorconfig' lang='ini'>
###############################
# Sort using and Import directives with System.* appearing first
[*.cs]
# Organize usings
dotnet_sort_system_directives_first = true
dotnet_sort_system_directives_first = true
</filebox>


###############################
== Style configuration ==
# Code Quality configuration #
<filebox fn='.editorconfig' lang='ini'>
###############################
# IDE0160 / IDE0161: Namespace declaration preferences
# CA1826: Use property instead of Linq Enumerable method
csharp_style_namespace_declarations = file_scoped : error
# Exclude FirstOrDefault and LastOrDefault methods
dotnet_code_quality.CA1826.exclude_ordefault_methods = true
 
###############################
# Style configuration        #
###############################
# IDE0003 / IDE0009: this and Me preferences
dotnet_style_qualification_for_field = true


# IDE0007 / IDE0008: 'var' preferences
# IDE0007 / IDE0008: 'var' preferences
csharp_style_var_for_built_in_types    = true
csharp_style_var_for_built_in_types    = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere            = true : silent
csharp_style_var_elsewhere            = false : suggestion
</filebox>


# IDE0011: Add braces
== Disable rules ==
csharp_prefer_braces = when_multiline
<filebox fn='.editorconfig' lang='ini'>
 
# lower speller rule severity to suggestion
# IDE0022: Use expression body for methods
dotnet_diagnostic.VSSpell001.severity = suggestion
csharp_style_expression_bodied_methods = when_on_single_line
dotnet_diagnostic.VSSpell002.severity = suggestion
 
# IDE0160 / IDE0161: Namespace declaration preferences
csharp_style_namespace_declarations = file_scoped : error
 
###############################
# Disabled rules              #
###############################
# IDE0046: Use conditional expression for return
dotnet_diagnostic.IDE0046.severity = suggestion
 
# IDE0058: Remove unnecessary expression value
dotnet_diagnostic.IDE0058.severity = none
 
# CA1305: Specify IFormatProvider
dotnet_diagnostic.CA1305.severity = none
 
# CA1310: Specify StringComparison for correctness
dotnet_diagnostic.CA1310.severity = none


# Specify CultureInfo
# Specify CultureInfo
Ligne 135 : Ligne 72 :
# Specify a culture
# Specify a culture
dotnet_diagnostic.CA1311.severity = suggestion
dotnet_diagnostic.CA1311.severity = suggestion
</filebox>


###############################
== Custom naming convention rules ==
# Naming Conventions          #
<filebox fn='.editorconfig' lang='ini'>
###############################
# Style Definitions
# Style Definitions
dotnet_naming_style.upper_case_style.capitalization = all_upper
dotnet_naming_style.upper_case_style.capitalization     = all_upper
dotnet_naming_style.camel_case_style.capitalization = camel_case
dotnet_naming_style.camel_case_style.capitalization     = camel_case
dotnet_naming_style.end_with_async_style.required_suffix = Async
dotnet_naming_style.end_with_async_style.capitalization  = pascal_case


# Use UpperCase for constant fields
# Use UPPER_CASE for constant fields
dotnet_naming_symbols.constant_fields.applicable_kinds           = field
dotnet_naming_symbols.constant_field_symbol.applicable_kinds     = field
dotnet_naming_symbols.constant_fields.required_modifiers         = const
dotnet_naming_symbols.constant_field_symbol.required_modifiers   = const
dotnet_naming_rule.constant_fields_should_be_upper_case.symbols  = constant_fields
dotnet_naming_rule.constant_fields_should_be_upper_case.symbols  = constant_field_symbol
dotnet_naming_rule.constant_fields_should_be_upper_case.style    = upper_case_style
dotnet_naming_rule.constant_fields_should_be_upper_case.style    = upper_case_style
dotnet_naming_rule.constant_fields_should_be_upper_case.severity = warning
dotnet_naming_rule.constant_fields_should_be_upper_case.severity = warning


# Use camelCase for variables
# Use camelCase for local variables, parameters, instance fields
dotnet_naming_symbols.local_symbol.applicable_kinds       = local
dotnet_naming_symbols.local_parameter_field_symbol.applicable_kinds = local, parameter, field
dotnet_naming_rule.variables_should_be_camel_case.symbols  = local_symbol
dotnet_naming_rule.should_be_camel_case.symbols                     = local_parameter_field_symbol
dotnet_naming_rule.variables_should_be_camel_case.style    = camel_case_style
dotnet_naming_rule.should_be_camel_case.style                       = camel_case_style
dotnet_naming_rule.variables_should_be_camel_case.severity = warning
dotnet_naming_rule.should_be_camel_case.severity                   = warning
 
# Use camelCase for parameters
dotnet_naming_symbols.parameter_symbol.applicable_kinds      = parameter
dotnet_naming_rule.parameters_should_be_camel_case.symbols   = parameter_symbol
dotnet_naming_rule.parameters_should_be_camel_case.style     = camel_case_style
dotnet_naming_rule.parameters_should_be_camel_case.severity   = warning


# Async methods should have "Async" suffix
# Async methods should have "Async" suffix
dotnet_naming_rule.async_methods_end_in_async.symbols  = any_async_methods
dotnet_naming_symbols.async_method_symbol.applicable_kinds   = method
dotnet_naming_rule.async_methods_end_in_async.style    = end_in_async
dotnet_naming_symbols.async_method_symbol.required_modifiers = async
dotnet_naming_rule.async_methods_end_in_async.severity = suggestion
dotnet_naming_rule.should_end_with_async.symbols            = async_method_symbol
dotnet_naming_symbols.any_async_methods.applicable_kinds           = method
dotnet_naming_rule.should_end_with_async.style              = end_with_async_style
dotnet_naming_symbols.any_async_methods.applicable_accessibilities = *
dotnet_naming_rule.should_end_with_async.severity            = warning
dotnet_naming_symbols.any_async_methods.required_modifiers         = async
dotnet_naming_style.end_in_async.required_prefix =  
dotnet_naming_style.end_in_async.required_suffix = Async
dotnet_naming_style.end_in_async.capitalization  = pascal_case
dotnet_naming_style.end_in_async.word_separator  =  
</filebox>
</filebox>


== Visual Studio Code integration ==
= [https://docs.sonarsource.com/sonarlint/visual-studio Sonar Lint] =
<filebox fn='settings.json'>
* [https://rules.sonarsource.com/csharp/ C# rules]
"omnisharp.enableRoslynAnalyzers": true,
<filebox fn='.editorconfig' lang='ini'>
"omnisharp.enableEditorConfigSupport": true,
# S1135: Track uses of "TODO" tags
dotnet_diagnostic.S1135.severity = none
</filebox>
</filebox>


== Visual Studio ==
== Installation ==
=== [https://learn.microsoft.com/en-us/visualstudio/code-quality/configure-live-code-analysis-scope-managed-code?view=vs-2022#custom-analysis-scope Set the scope of live code analysis] ===
* Installation the extension for Visual Studio or VS Code
 
= Visual Studio =
== Change Code Style rules and generate a .editorconfig file ==
Tools → Options → Text Editor → C# → Code Style → General
 
== [https://learn.microsoft.com/en-us/visualstudio/code-quality/configure-live-code-analysis-scope-managed-code?view=vs-2022#custom-analysis-scope Set the scope of live code analysis] ==
# Tools → Options
# Tools → Options
# Text Editor → C# → Advanced
# Text Editor → C# → Advanced
Ligne 188 : Ligne 123 :
## Show compiler errors and warnings for: Open documents
## Show compiler errors and warnings for: Open documents


== [https://github.com/josefpihrt/roslynator Roslynator] ==
== [https://learn.microsoft.com/en-us/visualstudio/ide/code-styles-and-code-cleanup?view=vs-2022#apply-code-styles Code Cleanup] ==
# Install the Roslynator extension in Visual Studio or Visual Studio Code
Right click on the solution → Analyze and Code Cleanup:
# Configure Roslynator on a user-wide basis
* Run Code Cleanup (Profile X)
## vscode → Ctrl + Shift + P → enter roslynator → select Roslynator: Open Default Configuration File (.roslynatorconfig)
* Configure Code Cleanup (configure the profiles)
* [https://github.com/JosefPihrt/Roslynator/tree/main/docs/analyzers Analyzers RCSxxxx]
* Set Analysis scope → Entire solution


<filebox fn='~/.local/share/JosefPihrt/Roslynator/.roslynatorconfig' lang='ini' collapsed>
{| class="wikitable wtp"
is_global = true
! Fixer
 
! Description
# enable all analyzers by default and set the severity to warning
|-
roslynator_analyzers.enabled_by_default = true
| Apply conditional expression preferences || apply ternary conditional expression {{boxx|? :}}
dotnet_analyzer_diagnostic.category-roslynator.severity = warning
|}
 
# enable all refactorings
roslynator_refactorings.enabled = true
 
# enable all compiler diagnostic fixes
roslynator_compiler_diagnostic_fixes.enabled = true
 
# Options
roslynator_accessibility_modifiers = explicit
roslynator_accessor_braces_style = single_line_when_expression_is_on_single_line
roslynator_array_creation_type_style = implicit_when_type_is_obvious
roslynator_arrow_token_new_line = before
roslynator_binary_operator_new_line = before
roslynator_blank_line_after_file_scoped_namespace_declaration = true
roslynator_blank_line_between_closing_brace_and_switch_section = false
roslynator_blank_line_between_single_line_accessors = false
roslynator_blank_line_between_using_directives = never
roslynator_block_braces_style = single_line_when_empty
#roslynator_body_style = block|expression
roslynator_conditional_operator_condition_parentheses_style = omit
roslynator_conditional_operator_new_line = beforeroslynator_configure_await = false
roslynator_doc_comment_summary_style = multi_line
roslynator_empty_string_style = field
roslynator_enum_flag_value_style = decimal_number
roslynator_enum_has_flag_style = method
roslynator_equals_token_new_line = before
roslynator_infinite_loop_style = while
roslynator_max_line_length = 140
roslynator_new_line_at_end_of_file = false
roslynator_new_line_before_while_in_do_statement = false
roslynator_null_conditional_operator_new_line = before
roslynator_null_check_style = pattern_matching
roslynator_object_creation_parentheses_style = omit
roslynator_object_creation_type_style = implicit_when_type_is_obvious
roslynator_prefix_field_identifier_with_underscore = false
roslynator_suppress_unity_script_methods = true
roslynator_use_anonymous_function_or_method_group = method_group
roslynator_use_block_body_when_declaration_spans_over_multiple_lines = true
roslynator_use_block_body_when_expression_spans_over_multiple_lines = true
roslynator_use_var_instead_of_implicit_object_creation = true
 
# Analyzers
# Add blank line between single-line declarations
dotnet_diagnostic.rcs0012.severity = none
# Remove braces from if-else
dotnet_diagnostic.rcs1004.severity = none
# Use explicit type instead of 'var' (when the type is not obvious)
dotnet_diagnostic.rcs1008.severity = none
# Use explicit type instead of 'var' (foreach variable)
dotnet_diagnostic.rcs1009.severity = none
# Use explicit type instead of 'var' (when the type is obvious)
dotnet_diagnostic.rcs1012.severity = none
# Avoid unnecessary boxing of value type
dotnet_diagnostic.rcs1198.severity = none
# Mark publicly visible type with DebuggerDisplay attribute
dotnet_diagnostic.rcs1223.severity = none
</filebox>
 
=== [https://github.com/JosefPihrt/Roslynator/blob/main/docs/cli/README.md Roslynator CLI] ===
<kode lang='bash'>
# install
dotnet tool install -g roslynator.dotnet.cli
 
roslynator analyze \
  --analyzer-assemblies \
  ~/.vscode/extensions/josefpihrt-vscode.roslynator-4.3.0/roslyn/common \
  ~/.vscode/extensions/josefpihrt-vscode.roslynator-4.3.0/roslyn/analyzers
</kode>
{{info | 1=To fix the error:<br>
Could not load file or assembly 'System.Composition.AttributedModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.<br>
The system cannot find the file specified.<br>
<kode lang='bash'>
cd ~/.dotnet/tools/.store/roslynator.dotnet.cli/0.6.0/roslynator.dotnet.cli/0.6.0/tools/net7.0/any/
# backup the provided System.Composition.AttributedModel.dll which is in version 6.0
mv System.Composition.AttributedModel.dll System.Composition.AttributedModel-6.0.dll
# replace it by its version 7.0
cp /usr/share/dotnet/sdk/7.0.105/DotnetTools/dotnet-format/System.Composition.AttributedModel.dll .
</kode>
}}
 
== Code coverage ==
* [https://reportgenerator.io/ ReportGenerator]
<kode lang='bash'>
# add the XunitXML.TestLogger nuget package to the unit test project
dotnet add package XunitXML.TestLogger
# run unit tests with Coverlet data collector and log the results
dotnet test MySolution.sln --collect="XPlat Code Coverage" --logger:"xunit;LogFilePath=TestResults.xml"
# creates a TestResults.xml report and a TestResults/[guid]/coverage.cobertura.xml report
 
# extract the line coverage:
xmllint --xpath "string(/coverage/@line-rate)" TestResults/[guid]/coverage.cobertura.xml
sed -n -r 's/<coverage line-rate="([0-9.]+)".*/\1/p' TestResults/[guid]/coverage.cobertura.xml
 
# install the ReportGenerator tool
dotnet tool install -g dotnet-reportgenerator-globaltool
# get a text summary report from all the cobertura reports
reportgenerator -reports:"*/TestResults/*/coverage.cobertura.xml" -targetdir:CoverageReport -reporttypes:TextSummary
# creates CoverageReport/TextSummary.txt
# extract the line coverage:
sed -n -r 's/Line coverage: ([0-9.]+)%/\1/p' CoverageReport/Summary.txt
</kode>
 
== Ignore generated code ==
Create an {{boxx|.editorconfig}} file in a folder to not run code analysis on the files of this folder.
<filebox fn='MyWebapi/DataAccess/.editorconfig' lang='ini'>
[*]
generated_code = true
dotnet_analyzer_diagnostic.severity = silent
</filebox>

Version du 24 avril 2024 à 14:21

Links

Enable additional rules

Those rules are enabled by default.
Edit the project file to enable additional rules:

MyProject.csproj
<PropertyGroup>
  <!-- ... -->
  <AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>

Editorconfig

Core options

.editorconfig
root = true

# All files
[*]
indent_style         = space
insert_final_newline = true
charset              = utf-8

# XML project files
[*.csproj]
indent_size = 2

# JSON config files
[*.json]
indent_size = 2

# C# code files
[*.cs]
indent_size              = 4
trim_trailing_whitespace = true

Analyzer configuration

.editorconfig
# set the rules severity to warning
dotnet_analyzer_diagnostic.severity = warning

Miscellaneous configuration

.editorconfig
# Sort using and Import directives with System.* appearing first
dotnet_sort_system_directives_first = true

Style configuration

.editorconfig
# IDE0160 / IDE0161: Namespace declaration preferences
csharp_style_namespace_declarations = file_scoped : error

# IDE0007 / IDE0008: 'var' preferences
csharp_style_var_for_built_in_types    = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere             = false : suggestion

Disable rules

.editorconfig
# lower speller rule severity to suggestion
dotnet_diagnostic.VSSpell001.severity = suggestion
dotnet_diagnostic.VSSpell002.severity = suggestion

# Specify CultureInfo
dotnet_diagnostic.CA1304.severity = suggestion
# Specify a culture
dotnet_diagnostic.CA1311.severity = suggestion

Custom naming convention rules

.editorconfig
# Style Definitions
dotnet_naming_style.upper_case_style.capitalization      = all_upper
dotnet_naming_style.camel_case_style.capitalization      = camel_case
dotnet_naming_style.end_with_async_style.required_suffix = Async
dotnet_naming_style.end_with_async_style.capitalization  = pascal_case

# Use UPPER_CASE for constant fields
dotnet_naming_symbols.constant_field_symbol.applicable_kinds     = field
dotnet_naming_symbols.constant_field_symbol.required_modifiers   = const
dotnet_naming_rule.constant_fields_should_be_upper_case.symbols  = constant_field_symbol
dotnet_naming_rule.constant_fields_should_be_upper_case.style    = upper_case_style
dotnet_naming_rule.constant_fields_should_be_upper_case.severity = warning

# Use camelCase for local variables, parameters, instance fields
dotnet_naming_symbols.local_parameter_field_symbol.applicable_kinds = local, parameter, field
dotnet_naming_rule.should_be_camel_case.symbols                     = local_parameter_field_symbol
dotnet_naming_rule.should_be_camel_case.style                       = camel_case_style
dotnet_naming_rule.should_be_camel_case.severity                    = warning

# Async methods should have "Async" suffix
dotnet_naming_symbols.async_method_symbol.applicable_kinds   = method
dotnet_naming_symbols.async_method_symbol.required_modifiers = async
dotnet_naming_rule.should_end_with_async.symbols             = async_method_symbol
dotnet_naming_rule.should_end_with_async.style               = end_with_async_style
dotnet_naming_rule.should_end_with_async.severity            = warning

Sonar Lint

.editorconfig
# S1135: Track uses of "TODO" tags
dotnet_diagnostic.S1135.severity = none

Installation

  • Installation the extension for Visual Studio or VS Code

Visual Studio

Change Code Style rules and generate a .editorconfig file

Tools → Options → Text Editor → C# → Code Style → General

Set the scope of live code analysis

  1. Tools → Options
  2. Text Editor → C# → Advanced
    1. Run background code analysis for: Current document
    2. Show compiler errors and warnings for: Open documents

Code Cleanup

Right click on the solution → Analyze and Code Cleanup:

  • Run Code Cleanup (Profile X)
  • Configure Code Cleanup (configure the profiles)
  • Set Analysis scope → Entire solution
Fixer Description
Apply conditional expression preferences apply ternary conditional expression ? :