├── .config └── dotnet-tools.json ├── .editorconfig ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ ├── create-stable-release.yml │ ├── jira.yml │ ├── publish.yml │ └── semgrep.yml ├── .gitignore ├── Build.ps1 ├── CODEOWNERS ├── CONTRIBUTING.md ├── Directory.Build.props ├── GitVersion.yml ├── LICENSE ├── README.md ├── SECURITY.md ├── Workleap.DotNet.CodingStandards.nuspec ├── global.json ├── renovate.json ├── src ├── build │ ├── Workleap.DotNet.CodingStandards.props │ └── Workleap.DotNet.CodingStandards.targets ├── buildMultiTargeting │ ├── Workleap.DotNet.CodingStandards.props │ └── Workleap.DotNet.CodingStandards.targets ├── buildTransitive │ ├── Workleap.DotNet.CodingStandards.props │ └── Workleap.DotNet.CodingStandards.targets └── files │ ├── 1_FileDefaults.editorconfig │ ├── 2_CodeStyle.editorconfig │ ├── 3_ReSharperAnalyzers.editorconfig │ ├── 4_TestProjectsAnalyzers.editorconfig │ ├── BannedSymbols.txt │ └── analyzers │ ├── Analyzer.Meziantou.Analyzer.editorconfig │ ├── Analyzer.Microsoft.CodeAnalysis.BannedApiAnalyzers.editorconfig │ ├── Analyzer.Microsoft.CodeAnalysis.CSharp.CodeStyle.editorconfig │ ├── Analyzer.Microsoft.CodeAnalysis.NetAnalyzers.editorconfig │ ├── Analyzer.StyleCop.Analyzers.Unstable.editorconfig │ └── manual_rules.editorconfig ├── tests └── Workleap.DotNet.CodingStandards.Tests │ ├── CodingStandardTests.cs │ ├── Helpers │ ├── PathHelpers.cs │ ├── ProjectBuilder.cs │ ├── SarifFile.cs │ ├── SarifFileRun.cs │ ├── SarifFileRunResult.cs │ ├── SarifFileRunResultMessage.cs │ ├── SharedHttpClient.cs │ └── TemporaryDirectory.cs │ ├── PackageFixture.cs │ └── Workleap.DotNet.CodingStandards.Tests.csproj ├── tools └── ConfigurationFilesGenerator │ ├── ConfigurationFilesGenerator.csproj │ └── Program.cs └── wl-dotnet-codingstandards.sln /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "gitversion.tool": { 6 | "version": "5.12.0", 7 | "commands": [ 8 | "dotnet-gitversion" 9 | ] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # Default settings 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | # Xml project files 12 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] 13 | indent_size = 2 14 | ij_xml_space_inside_empty_tag = true 15 | 16 | # Xml files 17 | [*.{xml,stylecop,resx,ruleset}] 18 | indent_size = 2 19 | ij_xml_space_inside_empty_tag = true 20 | 21 | # Xml config files 22 | [*.{props,targets,config,nuspec,conf}] 23 | indent_size = 2 24 | ij_xml_space_inside_empty_tag = true 25 | 26 | # YAML config files 27 | [*.{yml,yaml}] 28 | indent_size = 2 29 | 30 | # Shell scripts 31 | [*.{sh,ps1}] 32 | end_of_line = lf 33 | indent_size = 2 34 | 35 | [*.{cmd,bat}] 36 | end_of_line = crlf 37 | indent_size = 2 38 | 39 | # JSON 40 | [*.{json,json5,jsonc}] 41 | indent_size = 2 42 | 43 | # CSharp 44 | [*.cs] 45 | max_line_length = off 46 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Copied from the .NET runtime repository 2 | # https://github.com/dotnet/runtime/blob/v8.0.0/.gitattributes 3 | 4 | # Set default behavior to automatically normalize line endings. 5 | * text=auto 6 | 7 | *.doc diff=astextplain 8 | *.DOC diff=astextplain 9 | *.docx diff=astextplain 10 | *.DOCX diff=astextplain 11 | *.dot diff=astextplain 12 | *.DOT diff=astextplain 13 | *.pdf diff=astextplain 14 | *.PDF diff=astextplain 15 | *.rtf diff=astextplain 16 | *.RTF diff=astextplain 17 | 18 | *.jpg binary 19 | *.png binary 20 | *.gif binary 21 | 22 | *.lss text 23 | 24 | # Force bash scripts to always use lf line endings so that if a repo is accessed 25 | # in Unix via a file share from Windows, the scripts will work. 26 | *.in text eol=lf 27 | *.sh text eol=lf 28 | 29 | # Likewise, force cmd and batch scripts to always use crlf 30 | *.cmd text eol=crlf 31 | *.bat text eol=crlf 32 | 33 | *.cs text=auto diff=csharp 34 | *.vb text=auto 35 | *.resx text=auto 36 | *.c text=auto 37 | *.cpp text=auto 38 | *.cxx text=auto 39 | *.h text=auto 40 | *.hxx text=auto 41 | *.py text=auto 42 | *.rb text=auto 43 | *.java text=auto 44 | *.html text=auto 45 | *.htm text=auto 46 | *.css text=auto 47 | *.scss text=auto 48 | *.sass text=auto 49 | *.less text=auto 50 | *.js text=auto 51 | *.lisp text=auto 52 | *.clj text=auto 53 | *.sql text=auto 54 | *.php text=auto 55 | *.lua text=auto 56 | *.m text=auto 57 | *.asm text=auto 58 | *.erl text=auto 59 | *.fs text=auto 60 | *.fsx text=auto 61 | *.hs text=auto 62 | 63 | *.csproj text=auto 64 | *.vbproj text=auto 65 | *.fsproj text=auto 66 | *.dbproj text=auto 67 | *.sln text=auto eol=crlf 68 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @workleap/internal-developer-platform 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. See error 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Environment (please complete the following information):** 26 | - OS: [e.g. Windows] 27 | - Version: [e.g. 1.2.3] 28 | - IDE: [e.g. Rider] 29 | - etc. 30 | 31 | **Additional context** 32 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description of changes 4 | 5 | 6 | ## Breaking changes 7 | 8 | 9 | ## Additional checks 10 | 11 | 12 | - [ ] Updated the documentation of the project to reflect the changes 13 | - [ ] Added new tests that cover the code changes 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | paths-ignore: ["*.md"] 7 | 8 | push: 9 | branches: 10 | - "renovate/**" 11 | 12 | # Prevent duplicate runs if Renovate falls back to creating a PR 13 | concurrency: 14 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} 15 | cancel-in-progress: true 16 | 17 | # We are using OpenID Connect to authenticate with Azure with secret. 18 | # https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-azure 19 | permissions: 20 | id-token: write 21 | contents: read 22 | 23 | jobs: 24 | main: 25 | # We need windows to use nuget 26 | runs-on: [self-hosted, idp] 27 | environment: ci 28 | steps: 29 | - uses: actions/checkout@v4 30 | with: 31 | fetch-depth: 0 32 | 33 | - name: Get gsoft-nuget-feed secret 34 | id: get_gsoft_nuget_feed_secret 35 | uses: workleap/wl-reusable-workflows/retrieve-managed-secret@main 36 | with: 37 | azure-client-id: ${{ vars.AZURE_CLIENT_ID }} 38 | azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} 39 | azure-subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} 40 | keyvault-name: ${{ vars.IDP_CICD_KEYVAULT_NAME }} 41 | secret-name: "gsoft-nuget-feed-ado-pat" 42 | 43 | - uses: actions/setup-dotnet@v4 44 | with: 45 | source-url: ${{ vars.GSOFTDEV_NUGET_SOURCE }} 46 | env: 47 | NUGET_AUTH_TOKEN: ${{ steps.get_gsoft_nuget_feed_secret.outputs.secret }} 48 | 49 | - name: Install Mono 50 | shell: bash 51 | run: | 52 | apt-get update 53 | apt-get install -y mono-complete 54 | 55 | - uses: NuGet/setup-nuget@v2 56 | 57 | - run: ./Build.ps1 58 | shell: pwsh 59 | env: 60 | NUGET_SOURCE: ${{ vars.GSOFTDEV_NUGET_SOURCE }} 61 | NUGET_API_KEY: ${{ steps.get_gsoft_nuget_feed_secret.outputs.secret }} 62 | 63 | linearb: 64 | needs: [main] 65 | uses: workleap/wl-reusable-workflows/.github/workflows/linearb-deployment.yml@main 66 | with: 67 | environment: development 68 | permissions: 69 | id-token: write 70 | contents: read 71 | -------------------------------------------------------------------------------- /.github/workflows/create-stable-release.yml: -------------------------------------------------------------------------------- 1 | name: Create stable release 2 | 3 | on: 4 | schedule: 5 | - cron: "0 3 * * 0" # At 03:00 on Sunday 6 | workflow_dispatch: 7 | 8 | jobs: 9 | create-release: 10 | permissions: 11 | contents: write 12 | id-token: write 13 | uses: workleap/wl-reusable-workflows/.github/workflows/create-stable-release.yml@main 14 | -------------------------------------------------------------------------------- /.github/workflows/jira.yml: -------------------------------------------------------------------------------- 1 | name: Jira 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | paths-ignore: ["*.md"] 7 | 8 | jobs: 9 | call-workflow-jira: 10 | uses: workleap/wl-reusable-workflows/.github/workflows/reusable-jira-workflow.yml@main 11 | with: 12 | branch_name: ${{ github.head_ref }} 13 | permissions: 14 | contents: read 15 | id-token: write 16 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | tags: ["*.*.*"] 7 | paths-ignore: ["*.md"] 8 | 9 | # We are using OpenID Connect to authenticate with Azure with secret. 10 | # https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-azure 11 | permissions: 12 | id-token: write 13 | contents: read 14 | 15 | jobs: 16 | main: 17 | # We need windows to use nuget 18 | runs-on: [self-hosted, idp] 19 | environment: ci 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | fetch-depth: 0 25 | 26 | - name: Get nuget-org-workleap-api-key 27 | id: get_nuget_org_workleap_api_key_secret 28 | uses: workleap/wl-reusable-workflows/retrieve-managed-secret@main 29 | with: 30 | azure-client-id: ${{ vars.AZURE_CLIENT_ID }} 31 | azure-tenant-id: ${{ vars.AZURE_TENANT_ID }} 32 | azure-subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }} 33 | keyvault-name: ${{ vars.IDP_CICD_KEYVAULT_NAME }} 34 | secret-name: "nuget-org-workleap-api-key" 35 | 36 | - uses: actions/setup-dotnet@v4 37 | 38 | - name: Install Mono 39 | shell: bash 40 | run: | 41 | apt-get update 42 | apt-get install -y mono-complete 43 | 44 | - uses: NuGet/setup-nuget@v2 45 | 46 | - run: ./Build.ps1 47 | shell: pwsh 48 | env: 49 | NUGET_SOURCE: ${{ vars.NUGET_SOURCE }} 50 | NUGET_API_KEY: ${{ steps.get_nuget_org_workleap_api_key_secret.outputs.secret }} 51 | 52 | linearb: 53 | needs: [main] 54 | uses: workleap/wl-reusable-workflows/.github/workflows/linearb-deployment.yml@main 55 | with: 56 | environment: 'release' 57 | permissions: 58 | id-token: write 59 | contents: read 60 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | name: Semgrep scan 2 | 3 | on: 4 | pull_request: 5 | branches: ["main"] 6 | workflow_dispatch: {} 7 | schedule: 8 | - cron: "52 2 * * 6" 9 | 10 | jobs: 11 | call-workflow-semgrep: 12 | permissions: 13 | contents: read 14 | security-events: write 15 | uses: workleap/wl-reusable-workflows/.github/workflows/reusable-semgrep-workflow.yml@main 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from `dotnet new gitignore` 5 | 6 | # dotenv files 7 | .env 8 | 9 | # User-specific files 10 | *.rsuser 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Mono auto generated files 20 | mono_crash.* 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | [Ww][Ii][Nn]32/ 30 | [Aa][Rr][Mm]/ 31 | [Aa][Rr][Mm]64/ 32 | bld/ 33 | [Bb]in/ 34 | [Oo]bj/ 35 | [Ll]og/ 36 | [Ll]ogs/ 37 | 38 | # Visual Studio 2015/2017 cache/options directory 39 | .vs/ 40 | # Uncomment if you have tasks that create the project's static files in wwwroot 41 | #wwwroot/ 42 | 43 | # Visual Studio 2017 auto generated files 44 | Generated\ Files/ 45 | 46 | # MSTest test Results 47 | [Tt]est[Rr]esult*/ 48 | [Bb]uild[Ll]og.* 49 | 50 | # NUnit 51 | *.VisualState.xml 52 | TestResult.xml 53 | nunit-*.xml 54 | 55 | # Build Results of an ATL Project 56 | [Dd]ebugPS/ 57 | [Rr]eleasePS/ 58 | dlldata.c 59 | 60 | # Benchmark Results 61 | BenchmarkDotNet.Artifacts/ 62 | 63 | # .NET 64 | project.lock.json 65 | project.fragment.lock.json 66 | artifacts/ 67 | 68 | # Tye 69 | .tye/ 70 | 71 | # ASP.NET Scaffolding 72 | ScaffoldingReadMe.txt 73 | 74 | # StyleCop 75 | StyleCopReport.xml 76 | 77 | # Files built by Visual Studio 78 | *_i.c 79 | *_p.c 80 | *_h.h 81 | *.ilk 82 | *.meta 83 | *.obj 84 | *.iobj 85 | *.pch 86 | *.pdb 87 | *.ipdb 88 | *.pgc 89 | *.pgd 90 | *.rsp 91 | *.sbr 92 | *.tlb 93 | *.tli 94 | *.tlh 95 | *.tmp 96 | *.tmp_proj 97 | *_wpftmp.csproj 98 | *.log 99 | *.tlog 100 | *.vspscc 101 | *.vssscc 102 | .builds 103 | *.pidb 104 | *.svclog 105 | *.scc 106 | 107 | # Chutzpah Test files 108 | _Chutzpah* 109 | 110 | # Visual C++ cache files 111 | ipch/ 112 | *.aps 113 | *.ncb 114 | *.opendb 115 | *.opensdf 116 | *.sdf 117 | *.cachefile 118 | *.VC.db 119 | *.VC.VC.opendb 120 | 121 | # Visual Studio profiler 122 | *.psess 123 | *.vsp 124 | *.vspx 125 | *.sap 126 | 127 | # Visual Studio Trace Files 128 | *.e2e 129 | 130 | # TFS 2012 Local Workspace 131 | $tf/ 132 | 133 | # Guidance Automation Toolkit 134 | *.gpState 135 | 136 | # ReSharper is a .NET coding add-in 137 | _ReSharper*/ 138 | *.[Rr]e[Ss]harper 139 | *.DotSettings.user 140 | 141 | # TeamCity is a build add-in 142 | _TeamCity* 143 | 144 | # DotCover is a Code Coverage Tool 145 | *.dotCover 146 | 147 | # AxoCover is a Code Coverage Tool 148 | .axoCover/* 149 | !.axoCover/settings.json 150 | 151 | # Coverlet is a free, cross platform Code Coverage Tool 152 | coverage*.json 153 | coverage*.xml 154 | coverage*.info 155 | 156 | # Visual Studio code coverage results 157 | *.coverage 158 | *.coveragexml 159 | 160 | # NCrunch 161 | _NCrunch_* 162 | .*crunch*.local.xml 163 | nCrunchTemp_* 164 | 165 | # MightyMoose 166 | *.mm.* 167 | AutoTest.Net/ 168 | 169 | # Web workbench (sass) 170 | .sass-cache/ 171 | 172 | # Installshield output folder 173 | [Ee]xpress/ 174 | 175 | # DocProject is a documentation generator add-in 176 | DocProject/buildhelp/ 177 | DocProject/Help/*.HxT 178 | DocProject/Help/*.HxC 179 | DocProject/Help/*.hhc 180 | DocProject/Help/*.hhk 181 | DocProject/Help/*.hhp 182 | DocProject/Help/Html2 183 | DocProject/Help/html 184 | 185 | # Click-Once directory 186 | publish/ 187 | 188 | # Publish Web Output 189 | *.[Pp]ublish.xml 190 | *.azurePubxml 191 | # Note: Comment the next line if you want to checkin your web deploy settings, 192 | # but database connection strings (with potential passwords) will be unencrypted 193 | *.pubxml 194 | *.publishproj 195 | 196 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 197 | # checkin your Azure Web App publish settings, but sensitive information contained 198 | # in these scripts will be unencrypted 199 | PublishScripts/ 200 | 201 | # NuGet Packages 202 | *.nupkg 203 | # NuGet Symbol Packages 204 | *.snupkg 205 | # The packages folder can be ignored because of Package Restore 206 | **/[Pp]ackages/* 207 | # except build/, which is used as an MSBuild target. 208 | !**/[Pp]ackages/build/ 209 | # Uncomment if necessary however generally it will be regenerated when needed 210 | #!**/[Pp]ackages/repositories.config 211 | # NuGet v3's project.json files produces more ignorable files 212 | *.nuget.props 213 | *.nuget.targets 214 | 215 | # Microsoft Azure Build Output 216 | csx/ 217 | *.build.csdef 218 | 219 | # Microsoft Azure Emulator 220 | ecf/ 221 | rcf/ 222 | 223 | # Windows Store app package directories and files 224 | AppPackages/ 225 | BundleArtifacts/ 226 | Package.StoreAssociation.xml 227 | _pkginfo.txt 228 | *.appx 229 | *.appxbundle 230 | *.appxupload 231 | 232 | # Visual Studio cache files 233 | # files ending in .cache can be ignored 234 | *.[Cc]ache 235 | # but keep track of directories ending in .cache 236 | !?*.[Cc]ache/ 237 | 238 | # Others 239 | ClientBin/ 240 | ~$* 241 | *~ 242 | *.dbmdl 243 | *.dbproj.schemaview 244 | *.jfm 245 | *.pfx 246 | *.publishsettings 247 | orleans.codegen.cs 248 | 249 | # Including strong name files can present a security risk 250 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 251 | #*.snk 252 | 253 | # Since there are multiple workflows, uncomment next line to ignore bower_components 254 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 255 | #bower_components/ 256 | 257 | # RIA/Silverlight projects 258 | Generated_Code/ 259 | 260 | # Backup & report files from converting an old project file 261 | # to a newer Visual Studio version. Backup files are not needed, 262 | # because we have git ;-) 263 | _UpgradeReport_Files/ 264 | Backup*/ 265 | UpgradeLog*.XML 266 | UpgradeLog*.htm 267 | ServiceFabricBackup/ 268 | *.rptproj.bak 269 | 270 | # SQL Server files 271 | *.mdf 272 | *.ldf 273 | *.ndf 274 | 275 | # Business Intelligence projects 276 | *.rdl.data 277 | *.bim.layout 278 | *.bim_*.settings 279 | *.rptproj.rsuser 280 | *- [Bb]ackup.rdl 281 | *- [Bb]ackup ([0-9]).rdl 282 | *- [Bb]ackup ([0-9][0-9]).rdl 283 | 284 | # Microsoft Fakes 285 | FakesAssemblies/ 286 | 287 | # GhostDoc plugin setting file 288 | *.GhostDoc.xml 289 | 290 | # Node.js Tools for Visual Studio 291 | .ntvs_analysis.dat 292 | node_modules/ 293 | 294 | # Visual Studio 6 build log 295 | *.plg 296 | 297 | # Visual Studio 6 workspace options file 298 | *.opt 299 | 300 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 301 | *.vbw 302 | 303 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 304 | *.vbp 305 | 306 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 307 | *.dsw 308 | *.dsp 309 | 310 | # Visual Studio 6 technical files 311 | *.ncb 312 | *.aps 313 | 314 | # Visual Studio LightSwitch build output 315 | **/*.HTMLClient/GeneratedArtifacts 316 | **/*.DesktopClient/GeneratedArtifacts 317 | **/*.DesktopClient/ModelManifest.xml 318 | **/*.Server/GeneratedArtifacts 319 | **/*.Server/ModelManifest.xml 320 | _Pvt_Extensions 321 | 322 | # Paket dependency manager 323 | .paket/paket.exe 324 | paket-files/ 325 | 326 | # FAKE - F# Make 327 | .fake/ 328 | 329 | # CodeRush personal settings 330 | .cr/personal 331 | 332 | # Python Tools for Visual Studio (PTVS) 333 | __pycache__/ 334 | *.pyc 335 | 336 | # Cake - Uncomment if you are using it 337 | # tools/** 338 | # !tools/packages.config 339 | 340 | # Tabs Studio 341 | *.tss 342 | 343 | # Telerik's JustMock configuration file 344 | *.jmconfig 345 | 346 | # BizTalk build output 347 | *.btp.cs 348 | *.btm.cs 349 | *.odx.cs 350 | *.xsd.cs 351 | 352 | # OpenCover UI analysis results 353 | OpenCover/ 354 | 355 | # Azure Stream Analytics local run output 356 | ASALocalRun/ 357 | 358 | # MSBuild Binary and Structured Log 359 | *.binlog 360 | 361 | # NVidia Nsight GPU debugger configuration file 362 | *.nvuser 363 | 364 | # MFractors (Xamarin productivity tool) working folder 365 | .mfractor/ 366 | 367 | # Local History for Visual Studio 368 | .localhistory/ 369 | 370 | # Visual Studio History (VSHistory) files 371 | .vshistory/ 372 | 373 | # BeatPulse healthcheck temp database 374 | healthchecksdb 375 | 376 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 377 | MigrationBackup/ 378 | 379 | # Ionide (cross platform F# VS Code tools) working folder 380 | .ionide/ 381 | 382 | # Fody - auto-generated XML schema 383 | FodyWeavers.xsd 384 | 385 | # VS Code files for those working on multiple tools 386 | .vscode/* 387 | !.vscode/settings.json 388 | !.vscode/tasks.json 389 | !.vscode/launch.json 390 | !.vscode/extensions.json 391 | *.code-workspace 392 | 393 | # Local History for Visual Studio Code 394 | .history/ 395 | 396 | # Windows Installer files from build outputs 397 | *.cab 398 | *.msi 399 | *.msix 400 | *.msm 401 | *.msp 402 | 403 | # JetBrains Rider 404 | *.sln.iml 405 | .idea 406 | 407 | ## 408 | ## Visual studio for Mac 409 | ## 410 | 411 | 412 | # globs 413 | Makefile.in 414 | *.userprefs 415 | *.usertasks 416 | config.make 417 | config.status 418 | aclocal.m4 419 | install-sh 420 | autom4te.cache/ 421 | *.tar.gz 422 | tarballs/ 423 | test-results/ 424 | 425 | # Mac bundle stuff 426 | *.dmg 427 | *.app 428 | 429 | # content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore 430 | # General 431 | .DS_Store 432 | .AppleDouble 433 | .LSOverride 434 | 435 | # Icon must end with two \r 436 | Icon 437 | 438 | 439 | # Thumbnails 440 | ._* 441 | 442 | # Files that might appear in the root of a volume 443 | .DocumentRevisions-V100 444 | .fseventsd 445 | .Spotlight-V100 446 | .TemporaryItems 447 | .Trashes 448 | .VolumeIcon.icns 449 | .com.apple.timemachine.donotpresent 450 | 451 | # Directories potentially created on remote AFP share 452 | .AppleDB 453 | .AppleDesktop 454 | Network Trash Folder 455 | Temporary Items 456 | .apdisk 457 | 458 | # content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore 459 | # Windows thumbnail cache files 460 | Thumbs.db 461 | ehthumbs.db 462 | ehthumbs_vista.db 463 | 464 | # Dump file 465 | *.stackdump 466 | 467 | # Folder config file 468 | [Dd]esktop.ini 469 | 470 | # Recycle Bin used on file shares 471 | $RECYCLE.BIN/ 472 | 473 | # Windows Installer files 474 | *.cab 475 | *.msi 476 | *.msix 477 | *.msm 478 | *.msp 479 | 480 | # Windows shortcuts 481 | *.lnk 482 | 483 | # Vim temporary swap files 484 | *.swp 485 | 486 | # Build output 487 | .output/ 488 | -------------------------------------------------------------------------------- /Build.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 5.0 2 | 3 | Begin { 4 | $ErrorActionPreference = "stop" 5 | } 6 | 7 | Process { 8 | function Exec([scriptblock]$Command) { 9 | & $Command 10 | if ($LASTEXITCODE -ne 0) { 11 | throw ("An error occurred while executing command: {0}" -f $Command) 12 | } 13 | } 14 | 15 | $workingDir = $PSScriptRoot 16 | $outputDir = Join-Path $PSScriptRoot ".output" 17 | $nupkgsPath = Join-Path $outputDir "*.nupkg" 18 | 19 | try { 20 | Push-Location $workingDir 21 | Remove-Item $outputDir -Force -Recurse -ErrorAction SilentlyContinue 22 | 23 | # Install GitVersion which is specified in the .config/dotnet-tools.json 24 | # https://learn.microsoft.com/en-us/dotnet/core/tools/local-tools-how-to-use 25 | Exec { & dotnet tool restore } 26 | 27 | # Let GitVersion compute the NuGet package version 28 | $version = Exec { & dotnet dotnet-gitversion /output json /showvariable SemVer } 29 | 30 | # Generate .editorconfig files for analyzers 31 | Exec { & dotnet run --project=tools/ConfigurationFilesGenerator/ConfigurationFilesGenerator.csproj --configuration Release } 32 | 33 | # Pack using NuGet.exe 34 | Exec { & nuget pack Workleap.DotNet.CodingStandards.nuspec -OutputDirectory $outputDir -Version $version -ForceEnglishOutput } 35 | 36 | # Run tests 37 | Exec { & dotnet test --configuration Release --logger "console;verbosity=detailed" } 38 | 39 | # Push to a NuGet feed if the environment variables are set 40 | if (($null -ne $env:NUGET_SOURCE) -and ($null -ne $env:NUGET_API_KEY)) { 41 | Exec { & dotnet nuget push "$nupkgsPath" -s $env:NUGET_SOURCE -k $env:NUGET_API_KEY --skip-duplicate } 42 | } 43 | } 44 | finally { 45 | Pop-Location 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @workleap/internal-developer-platform 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We do not accept external pull requests yet. -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | enable 4 | enable 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: MajorMinorPatch 2 | assembly-file-versioning-scheme: MajorMinorPatch 3 | assembly-informational-format: "{NugetVersion}" 4 | mode: ContinuousDelivery 5 | increment: Inherit 6 | continuous-delivery-fallback-tag: ci 7 | tag-prefix: "[vV]" 8 | major-version-bump-message: '\+semver:\s?(breaking|major)' 9 | minor-version-bump-message: '\+semver:\s?(feature|minor)' 10 | patch-version-bump-message: '\+semver:\s?(fix|patch)' 11 | no-bump-message: '\+semver:\s?(none|skip)' 12 | legacy-semver-padding: 4 13 | build-metadata-padding: 4 14 | commits-since-version-source-padding: 4 15 | tag-pre-release-weight: 60000 16 | commit-message-incrementing: Enabled 17 | update-build-number: true 18 | 19 | branches: 20 | main: 21 | regex: ^(master|main)$ 22 | mode: ContinuousDeployment 23 | tag: preview 24 | increment: Patch 25 | prevent-increment-of-merged-branch-version: true 26 | track-merge-target: false 27 | source-branches: ["develop", "release"] 28 | tracks-release-branches: false 29 | is-release-branch: false 30 | is-mainline: true 31 | pre-release-weight: 55000 32 | develop: 33 | regex: ^dev(elop)?(ment)?$ 34 | mode: ContinuousDeployment 35 | tag: alpha 36 | increment: Minor 37 | prevent-increment-of-merged-branch-version: false 38 | track-merge-target: true 39 | source-branches: [] 40 | tracks-release-branches: true 41 | is-release-branch: false 42 | is-mainline: false 43 | pre-release-weight: 0 44 | release: 45 | regex: ^releases?[/-] 46 | mode: ContinuousDelivery 47 | tag: beta 48 | increment: None 49 | prevent-increment-of-merged-branch-version: true 50 | track-merge-target: false 51 | source-branches: ["develop", "main", "support", "release"] 52 | tracks-release-branches: false 53 | is-release-branch: true 54 | is-mainline: false 55 | pre-release-weight: 30000 56 | feature: 57 | regex: ^features?[/-] 58 | mode: ContinuousDelivery 59 | tag: useBranchName 60 | increment: Inherit 61 | prevent-increment-of-merged-branch-version: false 62 | track-merge-target: false 63 | source-branches: 64 | ["develop", "main", "release", "feature", "support", "hotfix"] 65 | tracks-release-branches: false 66 | is-release-branch: false 67 | is-mainline: false 68 | pre-release-weight: 30000 69 | pull-request: 70 | regex: ^(pull|pull\-requests|pr)[/-] 71 | mode: ContinuousDelivery 72 | tag: PullRequest 73 | increment: Inherit 74 | prevent-increment-of-merged-branch-version: false 75 | tag-number-pattern: '[/-](?\d+)[-/]' 76 | track-merge-target: false 77 | source-branches: 78 | ["develop", "main", "release", "feature", "support", "hotfix"] 79 | tracks-release-branches: false 80 | is-release-branch: false 81 | is-mainline: false 82 | pre-release-weight: 30000 83 | hotfix: 84 | regex: ^hotfix(es)?[/-] 85 | mode: ContinuousDelivery 86 | tag: beta 87 | increment: Patch 88 | prevent-increment-of-merged-branch-version: false 89 | track-merge-target: false 90 | source-branches: ["develop", "main", "support"] 91 | tracks-release-branches: false 92 | is-release-branch: false 93 | is-mainline: false 94 | pre-release-weight: 30000 95 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Workleap.DotNet.CodingStandards 2 | 3 | [![nuget](https://img.shields.io/nuget/v/Workleap.DotNet.CodingStandards.svg?logo=nuget)](https://www.nuget.org/packages/Workleap.DotNet.CodingStandards/) 4 | [![build](https://img.shields.io/github/actions/workflow/status/workleap/wl-dotnet-codingstandards/publish.yml?logo=github&branch=main)](https://github.com/workleap/wl-dotnet-codingstandards/actions/workflows/publish.yml) 5 | 6 | This package provides a set of **programming standards for .NET projects**, including rules for **style**, **quality**, **security**, and **performance**. It relies on [built-in .NET analyzers](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) that are shipped with the .NET SDK. 7 | 8 | During development, the package will provide warnings :warning: when standards are not met. For a production build (`Release` configuration), these warnings will be treated as errors :x: and will make the build fail. 9 | 10 | > [!WARNING] 11 | > This package only works with [SDK-style projects](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview). Older ASP.NET projects (non-Core) are not supported. The same applies to older desktop applications unless they have migrated to the new `Microsoft.NET.Sdk.WindowsDesktop` SDK. 12 | 13 | ## Usage 14 | 15 | Install the NuGet package in your project: 16 | 17 | ``` 18 | dotnet add package Workleap.DotNet.CodingStandards 19 | ``` 20 | 21 | If you are using [StyleCop.Analyzers](https://www.nuget.org/packages/StyleCop.Analyzers), you can safely remove it from your project. You can also remove the relevant parts of your `.editorconfig` files which contain analysis rules configuration. 22 | 23 | If you also have a `Directory.Build.props` file in your solution, you can remove properties that are [already set by this package](src/buildTransitive/Workleap.DotNet.CodingStandards.props). 24 | 25 | ## What's included 26 | 27 | - Code style and formatting options, including indentation, line wrapping, encoding, new lines preferences, and more. 28 | - .NET and C# coding conventions, including naming, preferences for types, modifiers, code blocks, expressions, pattern matching, using directives, parentheses, and much more. 29 | - Project properties, including deterministic build, strict mode, continuous integration build detection, [faster package restoration](https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#restoring-with-msbuild-static-graph-evaluation), and [faster builds on Visual Studio](https://devblogs.microsoft.com/visualstudio/vs-toolbox-accelerate-your-builds-of-sdk-style-net-projects/), and more. 30 | - .NET analysis rules configuration, including style rules (`IDExxxx`) and code analysis rules (`CAxxxx`). These rules have been manually configured to provide a good balance between quality, performance, security, and build time. 31 | - Banned APIs, such as `DateTime.Now` and `DateTimeOffset.Now` (use their UTC counterparts instead). 32 | 33 | ## What's NOT included 34 | 35 | - Enabling a specific or latest C# language version. 36 | - Enabling nullable reference types by default. 37 | - Enabling implicit using directives by default. 38 | - Enforcing a specific target framework. 39 | - Code styles for files that are not C# source files (e.g. `.csproj`, `.json`, etc.). 40 | 41 | We believe that most of these settings should be set on a per-project basis, and decided by the project's maintainers. 42 | 43 | For files other than C# source files, it is technically impossible for this package to enforce code styles, so you will have to configure their style using your own `.editorconfig` files. 44 | 45 | ## How it works 46 | 47 | This package comes with a set of `.props` and `.targets` files that are automatically imported into your project when you install the package. These files contain MSBuild properties and targets that configure the build process and the code analysis rules. 48 | 49 | It also includes multiple `.editorconfig` files that are automatically imported by Roslyn during the build process. 50 | 51 | ## Facilitating package adoption 52 | 53 | From experience, installing the package will result in numerous warnings, the majority of which are related to code formatting. We recommend addressing these in several steps to minimize the impact on code review, using the [dotnet format](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format) utility, which is included in the .NET SDK. 54 | 55 | Firstly, warnings related to code formatting **can be automatically corrected**. This includes: indentation, unnecessary spaces, empty lines, braces, file-scoped namespaces, unnecessary using directives, etc. Here is the command to execute: 56 | 57 | ``` 58 | dotnet format --diagnostics IDE0001 IDE0004 IDE0005 IDE0007 IDE0009 IDE0011 IDE0055 IDE0161 IDE2000 IDE2001 IDE2002 IDE2003 IDE2004 IDE2005 IDE2006 --verbosity diagnostic 59 | ``` 60 | 61 | Once the pull request is merged, one can then attempt to automatically correct the remaining warnings. Without the noise of formatting warnings, it will be easier to focus on them: 62 | 63 | ``` 64 | dotnet format --severity warn --verbosity diagnostic 65 | ``` 66 | 67 | You can also modify the command to specify the IDs of the analysis rules you wish to automatically correct (if a fix is available). In this way, you avoid manual work, and breaking the correction into several pull requests will increase developers' confidence in the process of adopting new standards. 68 | 69 | All rules included in this package **can be disabled or modified** in an `.editorconfig` file that you can add to your project. You can also **disable a rule for a specific line or block of code** using `#pragma` directives or `[SuppressMessage]` attributes. Learn more about [configuring code analysis rules](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/suppress-warnings). Remember to always justify why a rule is disabled or modified. Here're some examples: 70 | 71 | - Disable specific diagnostics in the code 72 | 73 | ````c# 74 | #pragma warning disable CA2200 // Rethrow to preserve stack details 75 | throw e; 76 | #pragma warning restore CA2200 77 | ```` 78 | 79 | - Disable specific diagnostics for a method 80 | 81 | ````c# 82 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2200:Rethrow to preserve stack details", Justification = "Not production code.")] 83 | void Sample() 84 | { 85 | } 86 | ```` 87 | 88 | - Disable a rule using an .editorconfig 89 | 90 | ````editorconfig 91 | # Disable CA2200 globally 92 | [*.cs] 93 | dotnet_diagnostic.CA2200.severity = none 94 | 95 | # Disable CA2200 for specific files 96 | [tests/**/*.cs] 97 | dotnet_diagnostic.CA2200.severity = none 98 | ```` 99 | 100 | - Disable [NuGet auditing](https://learn.microsoft.com/en-us/nuget/concepts/auditing-packages?WT.mc_id=DT-MVP-5003978) for a specific package 101 | 102 | ````xml 103 | 104 | ```` 105 | 106 | > [!WARNING] 107 | > Remember that this should be a temporary solution to help adopting the package 108 | 109 | Finally, the warnings breaks the CI because they are treated as errors when building the `Release` configuration. You can disable this behavior by setting the following MSBuild property in the `.csproj` file or in the `Directory.Build.props` file 110 | 111 | ````xml 112 | 113 | 114 | false 115 | false 116 | 117 | 118 | ```` 119 | 120 | ## References 121 | 122 | - [Configuration files for code analysis rules: Global analyzer options](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files#global-analyzerconfig) (Microsoft documentation). 123 | - [Sharing coding style and Roslyn analyzers across projects](https://www.meziantou.net/sharing-coding-style-and-roslyn-analyzers-across-projects.htm) (blog post written by [Gérald Barré](https://github.com/meziantou)). 124 | - [Microsoft.CodeAnalysis.NetAnalyzers package content](https://nuget.info/packages/Microsoft.CodeAnalysis.NetAnalyzers/8.0.0) (NuGet.info). 125 | 126 | ## Build and release process 127 | 128 | This project uses [GitVersion](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) as a .NET tool during the build process to automatically compute the version number for preview packages that are automatically published on the main branch and pull requests. 129 | 130 | To publish a new public (non-preview) version, simply create a new release on GitHub with a `x.y.z` tag. 131 | 132 | ## License 133 | 134 | Copyright © 2024, Workleap. This code is licensed under the Apache License, Version 2.0. You may obtain a copy of this license at https://github.com/workleap/gsoft-license/blob/master/LICENSE. 135 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | If you'd like to report a vulnerability, please open a GitHub issue. 4 | -------------------------------------------------------------------------------- /Workleap.DotNet.CodingStandards.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Workleap.DotNet.CodingStandards 5 | $version$ 6 | Workleap 7 | Workleap 8 | true 9 | Apache-2.0 10 | README.md 11 | https://github.com/workleap/wl-dotnet-codingstandards 12 | Workleap recommended coding standards for .NET. 13 | Copyright © Workleap 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "9.0.300", 4 | "rollForward": "latestMinor", 5 | "allowPrerelease": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "github>workleap/renovate-config", 5 | "github>workleap/renovate-config:all-automerge.json" 6 | ] 7 | } -------------------------------------------------------------------------------- /src/build/Workleap.DotNet.CodingStandards.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | strict 5 | true 6 | true 7 | latest-all 8 | true 9 | 10 | true 11 | embedded 12 | 13 | 14 | <_SkipUpgradeNetAnalyzersNuGetWarning>true 15 | 16 | 17 | true 18 | 19 | 20 | true 21 | true 22 | true 23 | true 24 | true 25 | 26 | 27 | true 28 | true 29 | 30 | 31 | true 32 | 33 | 34 | true 35 | 36 | 37 | 38 | 39 | 40 | true 41 | 42 | 43 | all 44 | 45 | 46 | low 47 | 48 | true 49 | 50 | 51 | 52 | (WarningsAsErrors);NU1900;NU1901;NU1902;NU1903;NU1904 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/build/Workleap.DotNet.CodingStandards.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | true 24 | 25 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/buildMultiTargeting/Workleap.DotNet.CodingStandards.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/buildMultiTargeting/Workleap.DotNet.CodingStandards.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/buildTransitive/Workleap.DotNet.CodingStandards.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/buildTransitive/Workleap.DotNet.CodingStandards.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/files/1_FileDefaults.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | global_level = -1 3 | 4 | # Default settings for C# and Visual Basic 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = false 9 | trim_trailing_whitespace = true 10 | max_line_length = off 11 | -------------------------------------------------------------------------------- /src/files/2_CodeStyle.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | global_level = -1 3 | 4 | #### BEGIN GENERATED CONTENT FROM VISUAL STUDIO CODE STYLE EDITOR #### 5 | 6 | # These options were hand-picked in VS Options > Text Editor > C# > Code Style 7 | # then exported to .editorconfig using the "Generate .editorconfig file from settings" feature 8 | 9 | #### .NET Coding Conventions #### 10 | 11 | # Organize usings 12 | dotnet_separate_import_directive_groups = false 13 | dotnet_sort_system_directives_first = true 14 | file_header_template = unset 15 | 16 | # this. and Me. preferences 17 | dotnet_style_qualification_for_event = true 18 | dotnet_style_qualification_for_field = true 19 | dotnet_style_qualification_for_method = true 20 | dotnet_style_qualification_for_property = true 21 | 22 | # Language keywords vs BCL types preferences 23 | dotnet_style_predefined_type_for_locals_parameters_members = true 24 | dotnet_style_predefined_type_for_member_access = true 25 | 26 | # Parentheses preferences 27 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity 28 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity 29 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary 30 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity 31 | 32 | # Modifier preferences 33 | dotnet_style_require_accessibility_modifiers = for_non_interface_members 34 | 35 | # Expression-level preferences 36 | dotnet_style_coalesce_expression = true 37 | dotnet_style_collection_initializer = true 38 | dotnet_style_explicit_tuple_names = true 39 | dotnet_style_namespace_match_folder = true 40 | dotnet_style_null_propagation = true 41 | dotnet_style_object_initializer = true 42 | dotnet_style_operator_placement_when_wrapping = beginning_of_line 43 | dotnet_style_prefer_auto_properties = true 44 | dotnet_style_prefer_collection_expression = true 45 | dotnet_style_prefer_compound_assignment = true 46 | dotnet_style_prefer_conditional_expression_over_assignment = true 47 | dotnet_style_prefer_conditional_expression_over_return = true 48 | dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed 49 | dotnet_style_prefer_inferred_anonymous_type_member_names = true 50 | dotnet_style_prefer_inferred_tuple_names = true 51 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true 52 | dotnet_style_prefer_simplified_boolean_expressions = true 53 | dotnet_style_prefer_simplified_interpolation = true 54 | 55 | # Field preferences 56 | dotnet_style_readonly_field = true 57 | 58 | # Parameter preferences 59 | dotnet_code_quality_unused_parameters = all 60 | 61 | # Suppression preferences 62 | dotnet_remove_unnecessary_suppression_exclusions = none 63 | 64 | # New line preferences 65 | dotnet_style_allow_multiple_blank_lines_experimental = false 66 | dotnet_style_allow_statement_immediately_after_block_experimental = false 67 | 68 | #### C# Coding Conventions #### 69 | 70 | # var preferences 71 | csharp_style_var_elsewhere = true 72 | csharp_style_var_for_built_in_types = true 73 | csharp_style_var_when_type_is_apparent = true 74 | 75 | # Expression-bodied members 76 | csharp_style_expression_bodied_accessors = true 77 | csharp_style_expression_bodied_constructors = false 78 | csharp_style_expression_bodied_indexers = true 79 | csharp_style_expression_bodied_lambdas = true 80 | csharp_style_expression_bodied_local_functions = false 81 | csharp_style_expression_bodied_methods = false 82 | csharp_style_expression_bodied_operators = false 83 | csharp_style_expression_bodied_properties = true 84 | 85 | # Pattern matching preferences 86 | csharp_style_pattern_matching_over_as_with_null_check = true 87 | csharp_style_pattern_matching_over_is_with_cast_check = true 88 | csharp_style_prefer_extended_property_pattern = true 89 | csharp_style_prefer_not_pattern = true 90 | csharp_style_prefer_pattern_matching = true 91 | csharp_style_prefer_switch_expression = true 92 | 93 | # Null-checking preferences 94 | csharp_style_conditional_delegate_call = true 95 | 96 | # Modifier preferences 97 | csharp_prefer_static_local_function = true 98 | csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async 99 | csharp_style_prefer_readonly_struct = true 100 | csharp_style_prefer_readonly_struct_member = true 101 | 102 | # Code-block preferences 103 | csharp_prefer_braces = true 104 | csharp_prefer_simple_using_statement = true 105 | csharp_style_namespace_declarations = file_scoped 106 | csharp_style_prefer_method_group_conversion = true 107 | csharp_style_prefer_primary_constructors = true 108 | csharp_style_prefer_top_level_statements = true 109 | 110 | # Expression-level preferences 111 | csharp_prefer_simple_default_expression = true 112 | csharp_style_deconstructed_variable_declaration = true 113 | csharp_style_implicit_object_creation_when_type_is_apparent = true 114 | csharp_style_inlined_variable_declaration = true 115 | csharp_style_prefer_index_operator = true 116 | csharp_style_prefer_local_over_anonymous_function = true 117 | csharp_style_prefer_null_check_over_type_check = true 118 | csharp_style_prefer_range_operator = true 119 | csharp_style_prefer_tuple_swap = true 120 | csharp_style_prefer_utf8_string_literals = true 121 | csharp_style_throw_expression = true 122 | csharp_style_unused_value_assignment_preference = discard_variable 123 | csharp_style_unused_value_expression_statement_preference = discard_variable 124 | 125 | # 'using' directive preferences 126 | csharp_using_directive_placement = outside_namespace 127 | 128 | # New line preferences 129 | csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false 130 | csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true 131 | csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false 132 | csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false 133 | csharp_style_allow_embedded_statements_on_same_line_experimental = false 134 | 135 | #### C# Formatting Rules #### 136 | 137 | # New line preferences 138 | csharp_new_line_before_catch = true 139 | csharp_new_line_before_else = true 140 | csharp_new_line_before_finally = true 141 | csharp_new_line_before_members_in_anonymous_types = true 142 | csharp_new_line_before_members_in_object_initializers = true 143 | csharp_new_line_before_open_brace = all 144 | csharp_new_line_between_query_expression_clauses = true 145 | 146 | # Indentation preferences 147 | csharp_indent_block_contents = true 148 | csharp_indent_braces = false 149 | csharp_indent_case_contents = true 150 | csharp_indent_case_contents_when_block = false 151 | csharp_indent_labels = one_less_than_current 152 | csharp_indent_switch_labels = true 153 | 154 | # Space preferences 155 | csharp_space_after_cast = false 156 | csharp_space_after_colon_in_inheritance_clause = true 157 | csharp_space_after_comma = true 158 | csharp_space_after_dot = false 159 | csharp_space_after_keywords_in_control_flow_statements = true 160 | csharp_space_after_semicolon_in_for_statement = true 161 | csharp_space_around_binary_operators = before_and_after 162 | csharp_space_around_declaration_statements = false 163 | csharp_space_before_colon_in_inheritance_clause = true 164 | csharp_space_before_comma = false 165 | csharp_space_before_dot = false 166 | csharp_space_before_open_square_brackets = false 167 | csharp_space_before_semicolon_in_for_statement = false 168 | csharp_space_between_empty_square_brackets = false 169 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 170 | csharp_space_between_method_call_name_and_opening_parenthesis = false 171 | csharp_space_between_method_call_parameter_list_parentheses = false 172 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 173 | csharp_space_between_method_declaration_name_and_open_parenthesis = false 174 | csharp_space_between_method_declaration_parameter_list_parentheses = false 175 | csharp_space_between_parentheses = false 176 | csharp_space_between_square_brackets = false 177 | 178 | # Wrapping preferences 179 | csharp_preserve_single_line_blocks = true 180 | csharp_preserve_single_line_statements = false 181 | 182 | #### Naming styles #### 183 | 184 | # Naming rules 185 | 186 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion 187 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface 188 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i 189 | 190 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion 191 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types 192 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case 193 | 194 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion 195 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members 196 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case 197 | 198 | dotnet_naming_rule.private_fields_should_be_camel_case_underscore_prefix.severity = suggestion 199 | dotnet_naming_rule.private_fields_should_be_camel_case_underscore_prefix.symbols = private_fields 200 | dotnet_naming_rule.private_fields_should_be_camel_case_underscore_prefix.style = camel_case_underscore_prefix 201 | 202 | dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.severity = suggestion 203 | dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.symbols = static_readonly_fields 204 | dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.style = pascal_case 205 | 206 | dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion 207 | dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields 208 | dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case 209 | 210 | dotnet_naming_rule.local_variables_should_be_camel_case.severity = suggestion 211 | dotnet_naming_rule.local_variables_should_be_camel_case.symbols = local_variables 212 | dotnet_naming_rule.local_variables_should_be_camel_case.style = camel_case 213 | 214 | # Symbol specifications 215 | 216 | dotnet_naming_symbols.interface.applicable_kinds = interface 217 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 218 | dotnet_naming_symbols.interface.required_modifiers = 219 | 220 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum 221 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 222 | dotnet_naming_symbols.types.required_modifiers = 223 | 224 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method 225 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 226 | dotnet_naming_symbols.non_field_members.required_modifiers = 227 | 228 | dotnet_naming_symbols.private_fields.applicable_kinds = field 229 | dotnet_naming_symbols.private_fields.applicable_accessibilities = private, private_protected 230 | dotnet_naming_symbols.private_fields.required_modifiers = 231 | 232 | dotnet_naming_symbols.static_readonly_fields.applicable_kinds = field 233 | dotnet_naming_symbols.static_readonly_fields.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 234 | dotnet_naming_symbols.static_readonly_fields.required_modifiers = static, readonly 235 | 236 | dotnet_naming_symbols.constant_fields.applicable_kinds = field 237 | dotnet_naming_symbols.constant_fields.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected 238 | dotnet_naming_symbols.constant_fields.required_modifiers = const 239 | 240 | dotnet_naming_symbols.local_variables.applicable_kinds = parameter, local 241 | dotnet_naming_symbols.local_variables.applicable_accessibilities = local 242 | dotnet_naming_symbols.local_variables.required_modifiers = 243 | 244 | # Naming styles 245 | 246 | dotnet_naming_style.pascal_case.required_prefix = 247 | dotnet_naming_style.pascal_case.required_suffix = 248 | dotnet_naming_style.pascal_case.word_separator = 249 | dotnet_naming_style.pascal_case.capitalization = pascal_case 250 | 251 | dotnet_naming_style.camel_case.required_prefix = 252 | dotnet_naming_style.camel_case.required_suffix = 253 | dotnet_naming_style.camel_case.word_separator = 254 | dotnet_naming_style.camel_case.capitalization = camel_case 255 | 256 | dotnet_naming_style.begins_with_i.required_prefix = I 257 | dotnet_naming_style.begins_with_i.required_suffix = 258 | dotnet_naming_style.begins_with_i.word_separator = 259 | dotnet_naming_style.begins_with_i.capitalization = pascal_case 260 | 261 | dotnet_naming_style.camel_case_underscore_prefix.required_prefix = _ 262 | dotnet_naming_style.camel_case_underscore_prefix.required_suffix = 263 | dotnet_naming_style.camel_case_underscore_prefix.word_separator = 264 | dotnet_naming_style.camel_case_underscore_prefix.capitalization = camel_case 265 | -------------------------------------------------------------------------------- /src/files/3_ReSharperAnalyzers.editorconfig: -------------------------------------------------------------------------------- 1 | is_global = true 2 | global_level = -1 3 | 4 | # Disable some ReSharper / Rider inspections already covered by .NET analyzers 5 | 6 | # Already covered by IDE0130 7 | resharper_check_namespace_highlighting = none 8 | 9 | # Already covered by file defaults "insert_final_newline" 10 | csharp_insert_final_newline = false 11 | 12 | # Fix to address https://youtrack.jetbrains.com/issue/RSRP-486359 13 | # where csharp_new_line_before_members_in_object_initializers would still inline object initializers 14 | resharper_wrap_object_and_collection_initializer_style = chop_always -------------------------------------------------------------------------------- /src/files/4_TestProjectsAnalyzers.editorconfig: -------------------------------------------------------------------------------- 1 | # global_level must be higher than the .NET Analyzer files 2 | is_global = true 3 | global_level = 0 4 | 5 | # GMNG01: Add 'IndexBy' or 'NoIndexNeeded' attributes on the containing type 6 | # Disabled because specifying MongoDB indexes is only required for production code, not for test projects 7 | dotnet_diagnostic.GMNG01.severity = none 8 | 9 | # GMDTR12: Use method ending with 'Async' instead 10 | # Disabled because our MediatR static extension method that ends with "Async" cannot be mocked in unit tests so developers have to use the "Send" method instead 11 | dotnet_diagnostic.GMDTR12.severity = none 12 | -------------------------------------------------------------------------------- /src/files/BannedSymbols.txt: -------------------------------------------------------------------------------- 1 | P:System.DateTime.Now;Use System.DateTime.UtcNow instead. 2 | P:System.DateTimeOffset.Now;Use System.DateTimeOffset.UtcNow instead. 3 | P:System.DateTimeOffset.DateTime;Use System.DateTimeOffset.UtcDateTime instead. 4 | 5 | F:System.StringComparison.InvariantCulture;InvariantCulture performs a linguistic comparison. Most of the time Ordinal is the correct one. 6 | F:System.StringComparison.InvariantCultureIgnoreCase;InvariantCultureIgnoreCase performs a linguistic comparison. Most of the time OrdinalIgnoreCase is the correct one. 7 | P:System.StringComparer.InvariantCulture;InvariantCulture performs a linguistic comparison. Most of the time Ordinal is the correct one. 8 | P:System.StringComparer.InvariantCultureIgnoreCase;InvariantCultureIgnoreCase performs a linguistic comparison. Most of the time OrdinalIgnoreCase is the correct one. 9 | -------------------------------------------------------------------------------- /src/files/analyzers/Analyzer.Meziantou.Analyzer.editorconfig: -------------------------------------------------------------------------------- 1 | # global_level must be higher than the NET Analyzer files 2 | is_global = true 3 | global_level = 0 4 | 5 | # MA0001: StringComparison is missing 6 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0001.md 7 | # Enabled: True, Severity: suggestion 8 | dotnet_diagnostic.MA0001.severity = none 9 | 10 | # MA0002: IEqualityComparer or IComparer is missing 11 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0002.md 12 | # Enabled: True, Severity: warning 13 | dotnet_diagnostic.MA0002.severity = none 14 | 15 | # MA0003: Add parameter name to improve readability 16 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0003.md 17 | # Enabled: True, Severity: suggestion 18 | dotnet_diagnostic.MA0003.severity = none 19 | 20 | # MA0004: Use Task.ConfigureAwait 21 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0004.md 22 | # Enabled: True, Severity: warning 23 | dotnet_diagnostic.MA0004.severity = none 24 | 25 | # MA0005: Use Array.Empty() 26 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0005.md 27 | # Enabled: True, Severity: warning 28 | dotnet_diagnostic.MA0005.severity = none 29 | 30 | # MA0006: Use String.Equals instead of equality operator 31 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0006.md 32 | # Enabled: True, Severity: warning 33 | dotnet_diagnostic.MA0006.severity = none 34 | 35 | # MA0007: Add a comma after the last value 36 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0007.md 37 | # Enabled: True, Severity: suggestion 38 | dotnet_diagnostic.MA0007.severity = none 39 | 40 | # MA0008: Add StructLayoutAttribute 41 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0008.md 42 | # Enabled: True, Severity: warning 43 | dotnet_diagnostic.MA0008.severity = none 44 | 45 | # MA0009: Add regex evaluation timeout 46 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0009.md 47 | # Enabled: True, Severity: warning 48 | dotnet_diagnostic.MA0009.severity = none 49 | 50 | # MA0010: Mark attributes with AttributeUsageAttribute 51 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0010.md 52 | # Enabled: True, Severity: warning 53 | dotnet_diagnostic.MA0010.severity = none 54 | 55 | # MA0011: IFormatProvider is missing 56 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0011.md 57 | # Enabled: True, Severity: warning 58 | dotnet_diagnostic.MA0011.severity = none 59 | 60 | # MA0012: Do not raise reserved exception type 61 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0012.md 62 | # Enabled: True, Severity: warning 63 | dotnet_diagnostic.MA0012.severity = none 64 | 65 | # MA0013: Types should not extend System.ApplicationException 66 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0013.md 67 | # Enabled: True, Severity: warning 68 | dotnet_diagnostic.MA0013.severity = none 69 | 70 | # MA0014: Do not raise System.ApplicationException type 71 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0014.md 72 | # Enabled: True, Severity: warning 73 | dotnet_diagnostic.MA0014.severity = none 74 | 75 | # MA0015: Specify the parameter name in ArgumentException 76 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0015.md 77 | # Enabled: True, Severity: warning 78 | dotnet_diagnostic.MA0015.severity = suggestion 79 | 80 | # MA0016: Prefer using collection abstraction instead of implementation 81 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0016.md 82 | # Enabled: True, Severity: warning 83 | dotnet_diagnostic.MA0016.severity = none 84 | 85 | # MA0017: Abstract types should not have public or internal constructors 86 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0017.md 87 | # Enabled: True, Severity: warning 88 | dotnet_diagnostic.MA0017.severity = suggestion 89 | 90 | # MA0018: Do not declare static members on generic types (deprecated; use CA1000 instead) 91 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0018.md 92 | # Enabled: True, Severity: suggestion 93 | dotnet_diagnostic.MA0018.severity = none 94 | 95 | # MA0019: Use EventArgs.Empty 96 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0019.md 97 | # Enabled: True, Severity: warning 98 | dotnet_diagnostic.MA0019.severity = suggestion 99 | 100 | # MA0020: Use direct methods instead of LINQ methods 101 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0020.md 102 | # Enabled: True, Severity: suggestion 103 | dotnet_diagnostic.MA0020.severity = none 104 | 105 | # MA0021: Use StringComparer.GetHashCode instead of string.GetHashCode 106 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0021.md 107 | # Enabled: True, Severity: warning 108 | dotnet_diagnostic.MA0021.severity = none 109 | 110 | # MA0022: Return Task.FromResult instead of returning null 111 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0022.md 112 | # Enabled: True, Severity: warning 113 | dotnet_diagnostic.MA0022.severity = warning 114 | 115 | # MA0023: Add RegexOptions.ExplicitCapture 116 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0023.md 117 | # Enabled: True, Severity: warning 118 | dotnet_diagnostic.MA0023.severity = suggestion 119 | 120 | # MA0024: Use an explicit StringComparer when possible 121 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0024.md 122 | # Enabled: True, Severity: warning 123 | dotnet_diagnostic.MA0024.severity = none 124 | 125 | # MA0025: Implement the functionality instead of throwing NotImplementedException 126 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0025.md 127 | # Enabled: True, Severity: warning 128 | dotnet_diagnostic.MA0025.severity = none 129 | 130 | # MA0026: Fix TODO comment 131 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0026.md 132 | # Enabled: True, Severity: warning 133 | dotnet_diagnostic.MA0026.severity = none 134 | 135 | # MA0027: Prefer rethrowing an exception implicitly 136 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0027.md 137 | # Enabled: True, Severity: warning 138 | dotnet_diagnostic.MA0027.severity = warning 139 | 140 | # MA0028: Optimize StringBuilder usage 141 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0028.md 142 | # Enabled: True, Severity: suggestion 143 | dotnet_diagnostic.MA0028.severity = none 144 | 145 | # MA0029: Combine LINQ methods 146 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0029.md 147 | # Enabled: True, Severity: suggestion 148 | dotnet_diagnostic.MA0029.severity = suggestion 149 | 150 | # MA0030: Remove useless OrderBy call 151 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0030.md 152 | # Enabled: True, Severity: warning 153 | dotnet_diagnostic.MA0030.severity = suggestion 154 | 155 | # MA0031: Optimize Enumerable.Count() usage 156 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0031.md 157 | # Enabled: True, Severity: suggestion 158 | dotnet_diagnostic.MA0031.severity = none 159 | 160 | # MA0032: Use an overload with a CancellationToken argument 161 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0032.md 162 | # Enabled: False, Severity: suggestion 163 | dotnet_diagnostic.MA0032.severity = none 164 | 165 | # MA0033: Do not tag instance fields with ThreadStaticAttribute 166 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0033.md 167 | # Enabled: True, Severity: warning 168 | dotnet_diagnostic.MA0033.severity = none 169 | 170 | # MA0035: Do not use dangerous threading methods 171 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0035.md 172 | # Enabled: True, Severity: warning 173 | dotnet_diagnostic.MA0035.severity = warning 174 | 175 | # MA0036: Make class static 176 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0036.md 177 | # Enabled: True, Severity: suggestion 178 | dotnet_diagnostic.MA0036.severity = none 179 | 180 | # MA0037: Remove empty statement 181 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0037.md 182 | # Enabled: True, Severity: error 183 | dotnet_diagnostic.MA0037.severity = warning 184 | 185 | # MA0038: Make method static (deprecated, use CA1822 instead) 186 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0038.md 187 | # Enabled: True, Severity: suggestion 188 | dotnet_diagnostic.MA0038.severity = none 189 | 190 | # MA0039: Do not write your own certificate validation method 191 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0039.md 192 | # Enabled: True, Severity: error 193 | dotnet_diagnostic.MA0039.severity = none 194 | 195 | # MA0040: Forward the CancellationToken parameter to methods that take one 196 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0040.md 197 | # Enabled: True, Severity: suggestion 198 | dotnet_diagnostic.MA0040.severity = suggestion 199 | 200 | # MA0041: Make property static (deprecated, use CA1822 instead) 201 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0041.md 202 | # Enabled: True, Severity: suggestion 203 | dotnet_diagnostic.MA0041.severity = none 204 | 205 | # MA0042: Do not use blocking calls in an async method 206 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0042.md 207 | # Enabled: True, Severity: suggestion 208 | dotnet_diagnostic.MA0042.severity = suggestion 209 | 210 | # MA0043: Use nameof operator in ArgumentException 211 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0043.md 212 | # Enabled: True, Severity: suggestion 213 | dotnet_diagnostic.MA0043.severity = none 214 | 215 | # MA0044: Remove useless ToString call 216 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0044.md 217 | # Enabled: True, Severity: suggestion 218 | dotnet_diagnostic.MA0044.severity = suggestion 219 | 220 | # MA0045: Do not use blocking calls in a sync method (need to make calling method async) 221 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0045.md 222 | # Enabled: False, Severity: suggestion 223 | dotnet_diagnostic.MA0045.severity = none 224 | 225 | # MA0046: Use EventHandler to declare events 226 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0046.md 227 | # Enabled: True, Severity: warning 228 | dotnet_diagnostic.MA0046.severity = none 229 | 230 | # MA0047: Declare types in namespaces 231 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0047.md 232 | # Enabled: True, Severity: warning 233 | dotnet_diagnostic.MA0047.severity = none 234 | 235 | # MA0048: File name must match type name 236 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0048.md 237 | # Enabled: True, Severity: warning 238 | dotnet_diagnostic.MA0048.severity = none 239 | 240 | # MA0049: Type name should not match containing namespace 241 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0049.md 242 | # Enabled: True, Severity: error 243 | dotnet_diagnostic.MA0049.severity = none 244 | 245 | # MA0050: Validate arguments correctly in iterator methods 246 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0050.md 247 | # Enabled: True, Severity: suggestion 248 | dotnet_diagnostic.MA0050.severity = none 249 | 250 | # MA0051: Method is too long 251 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0051.md 252 | # Enabled: True, Severity: warning 253 | dotnet_diagnostic.MA0051.severity = none 254 | 255 | # MA0052: Replace constant Enum.ToString with nameof 256 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0052.md 257 | # Enabled: True, Severity: suggestion 258 | dotnet_diagnostic.MA0052.severity = suggestion 259 | 260 | # MA0053: Make class sealed 261 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0053.md 262 | # Enabled: True, Severity: suggestion 263 | dotnet_diagnostic.MA0053.severity = none 264 | 265 | # MA0054: Embed the caught exception as innerException 266 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0054.md 267 | # Enabled: True, Severity: warning 268 | dotnet_diagnostic.MA0054.severity = warning 269 | 270 | # MA0055: Do not use finalizer 271 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0055.md 272 | # Enabled: True, Severity: warning 273 | dotnet_diagnostic.MA0055.severity = warning 274 | 275 | # MA0056: Do not call overridable members in constructor 276 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0056.md 277 | # Enabled: True, Severity: warning 278 | dotnet_diagnostic.MA0056.severity = suggestion 279 | 280 | # MA0057: Class name should end with 'Attribute' 281 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0057.md 282 | # Enabled: True, Severity: suggestion 283 | dotnet_diagnostic.MA0057.severity = none 284 | 285 | # MA0058: Class name should end with 'Exception' 286 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0058.md 287 | # Enabled: True, Severity: suggestion 288 | dotnet_diagnostic.MA0058.severity = none 289 | 290 | # MA0059: Class name should end with 'EventArgs' 291 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0059.md 292 | # Enabled: True, Severity: suggestion 293 | dotnet_diagnostic.MA0059.severity = none 294 | 295 | # MA0060: The value returned by Stream.Read/Stream.ReadAsync is not used 296 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0060.md 297 | # Enabled: True, Severity: warning 298 | dotnet_diagnostic.MA0060.severity = warning 299 | 300 | # MA0061: Method overrides should not change default values 301 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0061.md 302 | # Enabled: True, Severity: warning 303 | dotnet_diagnostic.MA0061.severity = none 304 | 305 | # MA0062: Non-flags enums should not be marked with "FlagsAttribute" 306 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0062.md 307 | # Enabled: True, Severity: warning 308 | dotnet_diagnostic.MA0062.severity = none 309 | 310 | # MA0063: Use Where before OrderBy 311 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0063.md 312 | # Enabled: True, Severity: suggestion 313 | dotnet_diagnostic.MA0063.severity = suggestion 314 | 315 | # MA0064: Avoid locking on publicly accessible instance 316 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0064.md 317 | # Enabled: True, Severity: warning 318 | dotnet_diagnostic.MA0064.severity = none 319 | 320 | # MA0065: Default ValueType.Equals or HashCode is used for struct equality 321 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0065.md 322 | # Enabled: True, Severity: warning 323 | dotnet_diagnostic.MA0065.severity = none 324 | 325 | # MA0066: Hash table unfriendly type is used in a hash table 326 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0066.md 327 | # Enabled: True, Severity: warning 328 | dotnet_diagnostic.MA0066.severity = none 329 | 330 | # MA0067: Use Guid.Empty 331 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0067.md 332 | # Enabled: True, Severity: suggestion 333 | dotnet_diagnostic.MA0067.severity = suggestion 334 | 335 | # MA0068: Invalid parameter name for nullable attribute 336 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0068.md 337 | # Enabled: True, Severity: warning 338 | dotnet_diagnostic.MA0068.severity = warning 339 | 340 | # MA0069: Non-constant static fields should not be visible 341 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0069.md 342 | # Enabled: True, Severity: warning 343 | dotnet_diagnostic.MA0069.severity = none 344 | 345 | # MA0070: Obsolete attributes should include explanations 346 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0070.md 347 | # Enabled: True, Severity: warning 348 | dotnet_diagnostic.MA0070.severity = suggestion 349 | 350 | # MA0071: Avoid using redundant else 351 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0071.md 352 | # Enabled: True, Severity: suggestion 353 | dotnet_diagnostic.MA0071.severity = none 354 | 355 | # MA0072: Do not throw from a finally block 356 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0072.md 357 | # Enabled: True, Severity: warning 358 | dotnet_diagnostic.MA0072.severity = warning 359 | 360 | # MA0073: Avoid comparison with bool constant 361 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0073.md 362 | # Enabled: True, Severity: suggestion 363 | dotnet_diagnostic.MA0073.severity = suggestion 364 | 365 | # MA0074: Avoid implicit culture-sensitive methods 366 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0074.md 367 | # Enabled: True, Severity: warning 368 | dotnet_diagnostic.MA0074.severity = none 369 | 370 | # MA0075: Do not use implicit culture-sensitive ToString 371 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0075.md 372 | # Enabled: True, Severity: suggestion 373 | dotnet_diagnostic.MA0075.severity = none 374 | 375 | # MA0076: Do not use implicit culture-sensitive ToString in interpolated strings 376 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0076.md 377 | # Enabled: True, Severity: suggestion 378 | dotnet_diagnostic.MA0076.severity = none 379 | 380 | # MA0077: A class that provides Equals(T) should implement IEquatable 381 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0077.md 382 | # Enabled: True, Severity: warning 383 | dotnet_diagnostic.MA0077.severity = none 384 | 385 | # MA0078: Use 'Cast' instead of 'Select' to cast 386 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0078.md 387 | # Enabled: True, Severity: suggestion 388 | dotnet_diagnostic.MA0078.severity = none 389 | 390 | # MA0079: Forward the CancellationToken using .WithCancellation() 391 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0079.md 392 | # Enabled: True, Severity: suggestion 393 | dotnet_diagnostic.MA0079.severity = suggestion 394 | 395 | # MA0080: Use a cancellation token using .WithCancellation() 396 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0080.md 397 | # Enabled: False, Severity: suggestion 398 | dotnet_diagnostic.MA0080.severity = none 399 | 400 | # MA0081: Method overrides should not omit params keyword 401 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0081.md 402 | # Enabled: True, Severity: warning 403 | dotnet_diagnostic.MA0081.severity = none 404 | 405 | # MA0082: NaN should not be used in comparisons 406 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0082.md 407 | # Enabled: True, Severity: warning 408 | dotnet_diagnostic.MA0082.severity = warning 409 | 410 | # MA0083: ConstructorArgument parameters should exist in constructors 411 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0083.md 412 | # Enabled: True, Severity: warning 413 | dotnet_diagnostic.MA0083.severity = none 414 | 415 | # MA0084: Local variables should not hide other symbols 416 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0084.md 417 | # Enabled: True, Severity: warning 418 | dotnet_diagnostic.MA0084.severity = none 419 | 420 | # MA0085: Anonymous delegates should not be used to unsubscribe from Events 421 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0085.md 422 | # Enabled: True, Severity: warning 423 | dotnet_diagnostic.MA0085.severity = warning 424 | 425 | # MA0086: Do not throw from a finalizer 426 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0086.md 427 | # Enabled: True, Severity: warning 428 | dotnet_diagnostic.MA0086.severity = warning 429 | 430 | # MA0087: Parameters with [DefaultParameterValue] attributes should also be marked [Optional] 431 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0087.md 432 | # Enabled: True, Severity: warning 433 | dotnet_diagnostic.MA0087.severity = suggestion 434 | 435 | # MA0088: Use [DefaultParameterValue] instead of [DefaultValue] 436 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0088.md 437 | # Enabled: True, Severity: warning 438 | dotnet_diagnostic.MA0088.severity = suggestion 439 | 440 | # MA0089: Optimize string method usage 441 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0089.md 442 | # Enabled: True, Severity: suggestion 443 | dotnet_diagnostic.MA0089.severity = none 444 | 445 | # MA0090: Remove empty else/finally block 446 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0090.md 447 | # Enabled: True, Severity: suggestion 448 | dotnet_diagnostic.MA0090.severity = suggestion 449 | 450 | # MA0091: Sender should be 'this' for instance events 451 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0091.md 452 | # Enabled: True, Severity: warning 453 | dotnet_diagnostic.MA0091.severity = none 454 | 455 | # MA0092: Sender should be 'null' for static events 456 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0092.md 457 | # Enabled: True, Severity: warning 458 | dotnet_diagnostic.MA0092.severity = none 459 | 460 | # MA0093: EventArgs should not be null 461 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0093.md 462 | # Enabled: True, Severity: warning 463 | dotnet_diagnostic.MA0093.severity = suggestion 464 | 465 | # MA0094: A class that provides CompareTo(T) should implement IComparable 466 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0094.md 467 | # Enabled: True, Severity: warning 468 | dotnet_diagnostic.MA0094.severity = none 469 | 470 | # MA0095: A class that implements IEquatable should override Equals(object) 471 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0095.md 472 | # Enabled: True, Severity: warning 473 | dotnet_diagnostic.MA0095.severity = none 474 | 475 | # MA0096: A class that implements IComparable should also implement IEquatable 476 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0096.md 477 | # Enabled: True, Severity: warning 478 | dotnet_diagnostic.MA0096.severity = none 479 | 480 | # MA0097: A class that implements IComparable or IComparable should override comparison operators 481 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0097.md 482 | # Enabled: True, Severity: warning 483 | dotnet_diagnostic.MA0097.severity = none 484 | 485 | # MA0098: Use indexer instead of LINQ methods 486 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0098.md 487 | # Enabled: True, Severity: suggestion 488 | dotnet_diagnostic.MA0098.severity = none 489 | 490 | # MA0099: Use Explicit enum value instead of 0 491 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0099.md 492 | # Enabled: True, Severity: warning 493 | dotnet_diagnostic.MA0099.severity = suggestion 494 | 495 | # MA0100: Await task before disposing of resources 496 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0100.md 497 | # Enabled: True, Severity: warning 498 | dotnet_diagnostic.MA0100.severity = warning 499 | 500 | # MA0101: String contains an implicit end of line character 501 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0101.md 502 | # Enabled: True, Severity: silent 503 | dotnet_diagnostic.MA0101.severity = none 504 | 505 | # MA0102: Make member readonly 506 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0102.md 507 | # Enabled: True, Severity: suggestion 508 | dotnet_diagnostic.MA0102.severity = none 509 | 510 | # MA0103: Use SequenceEqual instead of equality operator 511 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0103.md 512 | # Enabled: True, Severity: warning 513 | dotnet_diagnostic.MA0103.severity = suggestion 514 | 515 | # MA0104: Do not create a type with a name from the BCL 516 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0104.md 517 | # Enabled: False, Severity: warning 518 | dotnet_diagnostic.MA0104.severity = none 519 | 520 | # MA0105: Use the lambda parameters instead of using a closure 521 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0105.md 522 | # Enabled: True, Severity: suggestion 523 | dotnet_diagnostic.MA0105.severity = none 524 | 525 | # MA0106: Avoid closure by using an overload with the 'factoryArgument' parameter 526 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0106.md 527 | # Enabled: True, Severity: suggestion 528 | dotnet_diagnostic.MA0106.severity = none 529 | 530 | # MA0107: Do not use culture-sensitive object.ToString 531 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0107.md 532 | # Enabled: False, Severity: suggestion 533 | dotnet_diagnostic.MA0107.severity = none 534 | 535 | # MA0108: Remove redundant argument value 536 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0108.md 537 | # Enabled: True, Severity: suggestion 538 | dotnet_diagnostic.MA0108.severity = suggestion 539 | 540 | # MA0109: Consider adding an overload with a Span or Memory 541 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0109.md 542 | # Enabled: False, Severity: suggestion 543 | dotnet_diagnostic.MA0109.severity = none 544 | 545 | # MA0110: Use the Regex source generator 546 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0110.md 547 | # Enabled: True, Severity: suggestion 548 | dotnet_diagnostic.MA0110.severity = none 549 | 550 | # MA0111: Use string.Create instead of FormattableString 551 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0111.md 552 | # Enabled: True, Severity: suggestion 553 | dotnet_diagnostic.MA0111.severity = none 554 | 555 | # MA0112: Use 'Count > 0' instead of 'Any()' 556 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0112.md 557 | # Enabled: False, Severity: suggestion 558 | dotnet_diagnostic.MA0112.severity = none 559 | 560 | # MA0113: Use DateTime.UnixEpoch 561 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0113.md 562 | # Enabled: True, Severity: suggestion 563 | dotnet_diagnostic.MA0113.severity = suggestion 564 | 565 | # MA0114: Use DateTimeOffset.UnixEpoch 566 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0114.md 567 | # Enabled: True, Severity: suggestion 568 | dotnet_diagnostic.MA0114.severity = suggestion 569 | 570 | # MA0115: Unknown component parameter 571 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0115.md 572 | # Enabled: True, Severity: warning 573 | dotnet_diagnostic.MA0115.severity = none 574 | 575 | # MA0116: Parameters with [SupplyParameterFromQuery] attributes should also be marked as [Parameter] 576 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0116.md 577 | # Enabled: True, Severity: warning 578 | dotnet_diagnostic.MA0116.severity = none 579 | 580 | # MA0117: Parameters with [EditorRequired] attributes should also be marked as [Parameter] 581 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0117.md 582 | # Enabled: True, Severity: warning 583 | dotnet_diagnostic.MA0117.severity = none 584 | 585 | # MA0118: [JSInvokable] methods must be public 586 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0118.md 587 | # Enabled: True, Severity: warning 588 | dotnet_diagnostic.MA0118.severity = none 589 | 590 | # MA0119: JSRuntime must not be used in OnInitialized or OnInitializedAsync 591 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0119.md 592 | # Enabled: True, Severity: warning 593 | dotnet_diagnostic.MA0119.severity = none 594 | 595 | # MA0120: Use InvokeVoidAsync when the returned value is not used 596 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0120.md 597 | # Enabled: True, Severity: suggestion 598 | dotnet_diagnostic.MA0120.severity = none 599 | 600 | # MA0121: Do not overwrite parameter value 601 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0121.md 602 | # Enabled: False, Severity: suggestion 603 | dotnet_diagnostic.MA0121.severity = none 604 | 605 | # MA0122: Parameters with [SupplyParameterFromQuery] attributes are only valid in routable components (@page) 606 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0122.md 607 | # Enabled: True, Severity: suggestion 608 | dotnet_diagnostic.MA0122.severity = none 609 | 610 | # MA0123: Sequence number must be a constant 611 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0123.md 612 | # Enabled: True, Severity: warning 613 | dotnet_diagnostic.MA0123.severity = none 614 | 615 | # MA0124: Log parameter type is not valid 616 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0124.md 617 | # Enabled: True, Severity: warning 618 | dotnet_diagnostic.MA0124.severity = none 619 | 620 | # MA0125: The list of log parameter types contains an invalid type 621 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0125.md 622 | # Enabled: True, Severity: warning 623 | dotnet_diagnostic.MA0125.severity = none 624 | 625 | # MA0126: The list of log parameter types contains a duplicate 626 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0126.md 627 | # Enabled: True, Severity: warning 628 | dotnet_diagnostic.MA0126.severity = none 629 | 630 | # MA0127: Use String.Equals instead of is pattern 631 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0127.md 632 | # Enabled: False, Severity: warning 633 | dotnet_diagnostic.MA0127.severity = none 634 | 635 | # MA0128: Use 'is' operator instead of SequenceEqual 636 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0128.md 637 | # Enabled: True, Severity: suggestion 638 | dotnet_diagnostic.MA0128.severity = suggestion 639 | 640 | # MA0129: Await task in using statement 641 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0129.md 642 | # Enabled: True, Severity: warning 643 | dotnet_diagnostic.MA0129.severity = warning 644 | 645 | # MA0130: GetType() should not be used on System.Type instances 646 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0130.md 647 | # Enabled: True, Severity: warning 648 | dotnet_diagnostic.MA0130.severity = warning 649 | 650 | # MA0131: ArgumentNullException.ThrowIfNull should not be used with non-nullable types 651 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0131.md 652 | # Enabled: True, Severity: warning 653 | dotnet_diagnostic.MA0131.severity = none 654 | 655 | # MA0132: Do not convert implicitly to DateTimeOffset 656 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0132.md 657 | # Enabled: True, Severity: warning 658 | dotnet_diagnostic.MA0132.severity = none 659 | 660 | # MA0133: Use DateTimeOffset instead of relying on the implicit conversion 661 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0133.md 662 | # Enabled: True, Severity: suggestion 663 | dotnet_diagnostic.MA0133.severity = none 664 | 665 | # MA0134: Observe result of async calls 666 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0134.md 667 | # Enabled: True, Severity: warning 668 | dotnet_diagnostic.MA0134.severity = warning 669 | 670 | # MA0135: The log parameter has no configured type 671 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0135.md 672 | # Enabled: False, Severity: warning 673 | dotnet_diagnostic.MA0135.severity = none 674 | 675 | # MA0136: Raw String contains an implicit end of line character 676 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0136.md 677 | # Enabled: True, Severity: silent 678 | dotnet_diagnostic.MA0136.severity = none 679 | 680 | # MA0137: Use 'Async' suffix when a method returns an awaitable type 681 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0137.md 682 | # Enabled: False, Severity: warning 683 | dotnet_diagnostic.MA0137.severity = none 684 | 685 | # MA0138: Do not use 'Async' suffix when a method does not return an awaitable type 686 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0138.md 687 | # Enabled: False, Severity: warning 688 | dotnet_diagnostic.MA0138.severity = none 689 | 690 | # MA0139: Log parameter type is not valid 691 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0139.md 692 | # Enabled: True, Severity: warning 693 | dotnet_diagnostic.MA0139.severity = none 694 | 695 | # MA0140: Both if and else branch have identical code 696 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0140.md 697 | # Enabled: True, Severity: warning 698 | dotnet_diagnostic.MA0140.severity = warning 699 | 700 | # MA0141: Use pattern matching instead of inequality operators for null check 701 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0141.md 702 | # Enabled: False, Severity: suggestion 703 | dotnet_diagnostic.MA0141.severity = none 704 | 705 | # MA0142: Use pattern matching instead of equality operators for null check 706 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0142.md 707 | # Enabled: False, Severity: suggestion 708 | dotnet_diagnostic.MA0142.severity = none 709 | 710 | # MA0143: Primary constructor parameters should be readonly 711 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0143.md 712 | # Enabled: True, Severity: warning 713 | dotnet_diagnostic.MA0143.severity = suggestion 714 | 715 | # MA0144: Use System.OperatingSystem to check the current OS 716 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0144.md 717 | # Enabled: True, Severity: warning 718 | dotnet_diagnostic.MA0144.severity = suggestion 719 | 720 | # MA0145: Signature for [UnsafeAccessorAttribute] method is not valid 721 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0145.md 722 | # Enabled: True, Severity: warning 723 | dotnet_diagnostic.MA0145.severity = warning 724 | 725 | # MA0146: Name must be set explicitly on local functions 726 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0146.md 727 | # Enabled: True, Severity: warning 728 | dotnet_diagnostic.MA0146.severity = warning 729 | 730 | # MA0147: Avoid async void method for delegate 731 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0147.md 732 | # Enabled: True, Severity: warning 733 | dotnet_diagnostic.MA0147.severity = none 734 | 735 | # MA0148: Use pattern matching instead of equality operators for discrete value 736 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0148.md 737 | # Enabled: False, Severity: suggestion 738 | dotnet_diagnostic.MA0148.severity = none 739 | 740 | # MA0149: Use pattern matching instead of inequality operators for discrete value 741 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0149.md 742 | # Enabled: False, Severity: suggestion 743 | dotnet_diagnostic.MA0149.severity = none 744 | 745 | # MA0150: Do not call the default object.ToString explicitly 746 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0150.md 747 | # Enabled: True, Severity: warning 748 | dotnet_diagnostic.MA0150.severity = none 749 | 750 | # MA0151: DebuggerDisplay must contain valid members 751 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0151.md 752 | # Enabled: True, Severity: warning 753 | dotnet_diagnostic.MA0151.severity = suggestion 754 | 755 | # MA0152: Use Unwrap instead of using await twice 756 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0152.md 757 | # Enabled: True, Severity: suggestion 758 | dotnet_diagnostic.MA0152.severity = suggestion 759 | 760 | # MA0153: Do not log symbols decorated with DataClassificationAttribute directly 761 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0153.md 762 | # Enabled: True, Severity: warning 763 | dotnet_diagnostic.MA0153.severity = none 764 | 765 | # MA0154: Use langword in XML comment 766 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0154.md 767 | # Enabled: True, Severity: suggestion 768 | dotnet_diagnostic.MA0154.severity = none 769 | 770 | # MA0155: Do not use async void methods 771 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0155.md 772 | # Enabled: False, Severity: warning 773 | dotnet_diagnostic.MA0155.severity = none 774 | 775 | # MA0156: Use 'Async' suffix when a method returns IAsyncEnumerable 776 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0156.md 777 | # Enabled: False, Severity: warning 778 | dotnet_diagnostic.MA0156.severity = none 779 | 780 | # MA0157: Do not use 'Async' suffix when a method returns IAsyncEnumerable 781 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0157.md 782 | # Enabled: False, Severity: warning 783 | dotnet_diagnostic.MA0157.severity = none 784 | 785 | # MA0158: Use System.Threading.Lock 786 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0158.md 787 | # Enabled: True, Severity: warning 788 | dotnet_diagnostic.MA0158.severity = suggestion 789 | 790 | # MA0159: Use 'Order' instead of 'OrderBy' 791 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0159.md 792 | # Enabled: True, Severity: suggestion 793 | dotnet_diagnostic.MA0159.severity = suggestion 794 | 795 | # MA0160: Use ContainsKey instead of TryGetValue 796 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0160.md 797 | # Enabled: True, Severity: suggestion 798 | dotnet_diagnostic.MA0160.severity = suggestion 799 | 800 | # MA0161: UseShellExecute must be explicitly set 801 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0161.md 802 | # Enabled: False, Severity: suggestion 803 | dotnet_diagnostic.MA0161.severity = none 804 | 805 | # MA0162: Use Process.Start overload with ProcessStartInfo 806 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0162.md 807 | # Enabled: False, Severity: suggestion 808 | dotnet_diagnostic.MA0162.severity = none 809 | 810 | # MA0163: UseShellExecute must be false when redirecting standard input or output 811 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0163.md 812 | # Enabled: True, Severity: warning 813 | dotnet_diagnostic.MA0163.severity = none 814 | 815 | # MA0164: Use parentheses to make not pattern clearer 816 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0164.md 817 | # Enabled: True, Severity: warning 818 | dotnet_diagnostic.MA0164.severity = none 819 | 820 | # MA0165: Make interpolated string 821 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0165.md 822 | # Enabled: True, Severity: silent 823 | dotnet_diagnostic.MA0165.severity = none 824 | 825 | # MA0166: Forward the TimeProvider to methods that take one 826 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0166.md 827 | # Enabled: True, Severity: suggestion 828 | dotnet_diagnostic.MA0166.severity = suggestion 829 | 830 | # MA0167: Use an overload with a TimeProvider argument 831 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0167.md 832 | # Enabled: False, Severity: suggestion 833 | dotnet_diagnostic.MA0167.severity = none 834 | 835 | # MA0168: Use readonly struct for in or ref readonly parameter 836 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0168.md 837 | # Enabled: False, Severity: suggestion 838 | dotnet_diagnostic.MA0168.severity = none 839 | 840 | # MA0169: Use Equals method instead of operator 841 | # Help link: https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/Rules/MA0169.md 842 | # Enabled: True, Severity: warning 843 | dotnet_diagnostic.MA0169.severity = none 844 | 845 | -------------------------------------------------------------------------------- /src/files/analyzers/Analyzer.Microsoft.CodeAnalysis.BannedApiAnalyzers.editorconfig: -------------------------------------------------------------------------------- 1 | # global_level must be higher than the NET Analyzer files 2 | is_global = true 3 | global_level = 0 4 | 5 | # RS0030: Do not use banned APIs 6 | # Help link: https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md 7 | # Enabled: True, Severity: warning 8 | dotnet_diagnostic.RS0030.severity = warning 9 | 10 | # RS0031: The list of banned symbols contains a duplicate 11 | # Help link: https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md 12 | # Enabled: True, Severity: warning 13 | dotnet_diagnostic.RS0031.severity = warning 14 | 15 | # RS0035: External access to internal symbols outside the restricted namespace(s) is prohibited 16 | # Enabled: True, Severity: error 17 | dotnet_diagnostic.RS0035.severity = error 18 | 19 | -------------------------------------------------------------------------------- /src/files/analyzers/Analyzer.Microsoft.CodeAnalysis.CSharp.CodeStyle.editorconfig: -------------------------------------------------------------------------------- 1 | # global_level must be higher than the NET Analyzer files 2 | is_global = true 3 | global_level = 0 4 | 5 | # EnableGenerateDocumentationFile: Set MSBuild property 'GenerateDocumentationFile' to 'true' 6 | # Help link: https://github.com/dotnet/roslyn/issues/41640 7 | # Enabled: True, Severity: warning 8 | dotnet_diagnostic.EnableGenerateDocumentationFile.severity = warning 9 | 10 | # IDE0004: Remove Unnecessary Cast 11 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0004 12 | # Enabled: True, Severity: silent 13 | dotnet_diagnostic.IDE0004.severity = warning 14 | 15 | # IDE0005: Using directive is unnecessary. 16 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005 17 | # Enabled: True, Severity: silent 18 | dotnet_diagnostic.IDE0005.severity = warning 19 | 20 | # IDE0005_gen: Using directive is unnecessary. 21 | # Enabled: True, Severity: silent 22 | dotnet_diagnostic.IDE0005_gen.severity = silent 23 | 24 | # IDE0007: Use implicit type 25 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0007 26 | # Enabled: True, Severity: silent 27 | dotnet_diagnostic.IDE0007.severity = warning 28 | 29 | # IDE0008: Use explicit type 30 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0008 31 | # Enabled: True, Severity: silent 32 | dotnet_diagnostic.IDE0008.severity = silent 33 | 34 | # IDE0009: Member access should be qualified. 35 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0009 36 | # Enabled: True, Severity: silent 37 | dotnet_diagnostic.IDE0009.severity = warning 38 | 39 | # IDE0010: Add missing cases 40 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0010 41 | # Enabled: True, Severity: silent 42 | dotnet_diagnostic.IDE0010.severity = suggestion 43 | 44 | # IDE0011: Add braces 45 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0011 46 | # Enabled: True, Severity: silent 47 | dotnet_diagnostic.IDE0011.severity = warning 48 | 49 | # IDE0016: Use 'throw' expression 50 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0016 51 | # Enabled: True, Severity: silent 52 | dotnet_diagnostic.IDE0016.severity = silent 53 | 54 | # IDE0017: Simplify object initialization 55 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0017 56 | # Enabled: True, Severity: silent 57 | dotnet_diagnostic.IDE0017.severity = suggestion 58 | 59 | # IDE0018: Inline variable declaration 60 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0018 61 | # Enabled: True, Severity: silent 62 | dotnet_diagnostic.IDE0018.severity = suggestion 63 | 64 | # IDE0019: Use pattern matching 65 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0019 66 | # Enabled: True, Severity: silent 67 | dotnet_diagnostic.IDE0019.severity = suggestion 68 | 69 | # IDE0020: Use pattern matching 70 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0020 71 | # Enabled: True, Severity: silent 72 | dotnet_diagnostic.IDE0020.severity = warning 73 | 74 | # IDE0021: Use expression body for constructor 75 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0021 76 | # Enabled: True, Severity: silent 77 | dotnet_diagnostic.IDE0021.severity = silent 78 | 79 | # IDE0022: Use expression body for method 80 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0022 81 | # Enabled: True, Severity: silent 82 | dotnet_diagnostic.IDE0022.severity = silent 83 | 84 | # IDE0023: Use expression body for conversion operator 85 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0023 86 | # Enabled: True, Severity: silent 87 | dotnet_diagnostic.IDE0023.severity = silent 88 | 89 | # IDE0024: Use expression body for operator 90 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0024 91 | # Enabled: True, Severity: silent 92 | dotnet_diagnostic.IDE0024.severity = silent 93 | 94 | # IDE0025: Use expression body for property 95 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0025 96 | # Enabled: True, Severity: silent 97 | dotnet_diagnostic.IDE0025.severity = silent 98 | 99 | # IDE0026: Use expression body for indexer 100 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0026 101 | # Enabled: True, Severity: silent 102 | dotnet_diagnostic.IDE0026.severity = silent 103 | 104 | # IDE0027: Use expression body for accessor 105 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0027 106 | # Enabled: True, Severity: silent 107 | dotnet_diagnostic.IDE0027.severity = silent 108 | 109 | # IDE0028: Simplify collection initialization 110 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0028 111 | # Enabled: True, Severity: silent 112 | dotnet_diagnostic.IDE0028.severity = suggestion 113 | 114 | # IDE0029: Use coalesce expression 115 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0029 116 | # Enabled: True, Severity: silent 117 | dotnet_diagnostic.IDE0029.severity = warning 118 | 119 | # IDE0030: Use coalesce expression 120 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0030 121 | # Enabled: True, Severity: silent 122 | dotnet_diagnostic.IDE0030.severity = warning 123 | 124 | # IDE0031: Use null propagation 125 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0031 126 | # Enabled: True, Severity: silent 127 | dotnet_diagnostic.IDE0031.severity = warning 128 | 129 | # IDE0032: Use auto property 130 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0032 131 | # Enabled: True, Severity: silent 132 | dotnet_diagnostic.IDE0032.severity = silent 133 | 134 | # IDE0033: Use explicitly provided tuple name 135 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0033 136 | # Enabled: True, Severity: silent 137 | dotnet_diagnostic.IDE0033.severity = suggestion 138 | 139 | # IDE0034: Simplify 'default' expression 140 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0034 141 | # Enabled: True, Severity: silent 142 | dotnet_diagnostic.IDE0034.severity = suggestion 143 | 144 | # IDE0035: Unreachable code detected 145 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0035 146 | # Enabled: True, Severity: silent 147 | dotnet_diagnostic.IDE0035.severity = none 148 | 149 | # IDE0036: Order modifiers 150 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0036 151 | # Enabled: True, Severity: silent 152 | dotnet_diagnostic.IDE0036.severity = warning 153 | 154 | # IDE0037: Use inferred member name 155 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0037 156 | # Enabled: True, Severity: silent 157 | dotnet_diagnostic.IDE0037.severity = none 158 | 159 | # IDE0039: Use local function 160 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0039 161 | # Enabled: True, Severity: silent 162 | dotnet_diagnostic.IDE0039.severity = suggestion 163 | 164 | # IDE0040: Add accessibility modifiers 165 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0040 166 | # Enabled: True, Severity: silent 167 | dotnet_diagnostic.IDE0040.severity = warning 168 | 169 | # IDE0041: Use 'is null' check 170 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0041 171 | # Enabled: True, Severity: silent 172 | dotnet_diagnostic.IDE0041.severity = silent 173 | 174 | # IDE0042: Deconstruct variable declaration 175 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0042 176 | # Enabled: True, Severity: silent 177 | dotnet_diagnostic.IDE0042.severity = silent 178 | 179 | # IDE0043: Invalid format string 180 | # Enabled: True, Severity: suggestion 181 | dotnet_diagnostic.IDE0043.severity = warning 182 | 183 | # IDE0044: Add readonly modifier 184 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0044 185 | # Enabled: True, Severity: silent 186 | dotnet_diagnostic.IDE0044.severity = warning 187 | 188 | # IDE0045: Convert to conditional expression 189 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0045 190 | # Enabled: True, Severity: silent 191 | dotnet_diagnostic.IDE0045.severity = suggestion 192 | 193 | # IDE0046: Convert to conditional expression 194 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0046 195 | # Enabled: True, Severity: silent 196 | dotnet_diagnostic.IDE0046.severity = suggestion 197 | 198 | # IDE0047: Remove unnecessary parentheses 199 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0047 200 | # Enabled: True, Severity: silent 201 | dotnet_diagnostic.IDE0047.severity = silent 202 | 203 | # IDE0048: Add parentheses for clarity 204 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0048 205 | # Enabled: True, Severity: silent 206 | dotnet_diagnostic.IDE0048.severity = silent 207 | 208 | # IDE0051: Remove unused private members 209 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0051 210 | # Enabled: True, Severity: silent 211 | dotnet_diagnostic.IDE0051.severity = suggestion 212 | 213 | # IDE0052: Remove unread private members 214 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0052 215 | # Enabled: True, Severity: silent 216 | dotnet_diagnostic.IDE0052.severity = suggestion 217 | 218 | # IDE0053: Use block body for lambda expression 219 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0053 220 | # Enabled: True, Severity: silent 221 | dotnet_diagnostic.IDE0053.severity = silent 222 | 223 | # IDE0053: Use expression body for lambda expression 224 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0053 225 | # Enabled: True, Severity: silent 226 | dotnet_diagnostic.IDE0053.severity = silent 227 | 228 | # IDE0054: Use compound assignment 229 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0054 230 | # Enabled: True, Severity: silent 231 | dotnet_diagnostic.IDE0054.severity = warning 232 | 233 | # IDE0055: Fix formatting 234 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0055 235 | # Enabled: True, Severity: silent 236 | dotnet_diagnostic.IDE0055.severity = warning 237 | 238 | # IDE0056: Use index operator 239 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0056 240 | # Enabled: True, Severity: silent 241 | dotnet_diagnostic.IDE0056.severity = suggestion 242 | 243 | # IDE0057: Use range operator 244 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0057 245 | # Enabled: True, Severity: silent 246 | dotnet_diagnostic.IDE0057.severity = suggestion 247 | 248 | # IDE0058: Expression value is never used 249 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0058 250 | # Enabled: True, Severity: silent 251 | dotnet_diagnostic.IDE0058.severity = silent 252 | 253 | # IDE0059: Unnecessary assignment of a value 254 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0059 255 | # Enabled: True, Severity: silent 256 | dotnet_diagnostic.IDE0059.severity = warning 257 | 258 | # IDE0060: Remove unused parameter 259 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0060 260 | # Enabled: True, Severity: silent 261 | dotnet_diagnostic.IDE0060.severity = suggestion 262 | 263 | # IDE0061: Use expression body for local function 264 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0061 265 | # Enabled: True, Severity: silent 266 | dotnet_diagnostic.IDE0061.severity = silent 267 | 268 | # IDE0062: Make local function 'static' 269 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0062 270 | # Enabled: True, Severity: silent 271 | dotnet_diagnostic.IDE0062.severity = warning 272 | 273 | # IDE0063: Use simple 'using' statement 274 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0063 275 | # Enabled: True, Severity: silent 276 | dotnet_diagnostic.IDE0063.severity = silent 277 | 278 | # IDE0064: Make readonly fields writable 279 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0064 280 | # Enabled: True, Severity: suggestion 281 | dotnet_diagnostic.IDE0064.severity = suggestion 282 | 283 | # IDE0065: Misplaced using directive 284 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0065 285 | # Enabled: True, Severity: silent 286 | dotnet_diagnostic.IDE0065.severity = warning 287 | 288 | # IDE0066: Convert switch statement to expression 289 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0066 290 | # Enabled: True, Severity: silent 291 | dotnet_diagnostic.IDE0066.severity = suggestion 292 | 293 | # IDE0070: Use 'System.HashCode' 294 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0070 295 | # Enabled: True, Severity: silent 296 | dotnet_diagnostic.IDE0070.severity = suggestion 297 | 298 | # IDE0071: Simplify interpolation 299 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0071 300 | # Enabled: True, Severity: silent 301 | dotnet_diagnostic.IDE0071.severity = warning 302 | 303 | # IDE0072: Add missing cases 304 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0072 305 | # Enabled: True, Severity: silent 306 | dotnet_diagnostic.IDE0072.severity = silent 307 | 308 | # IDE0073: The file header does not match the required text 309 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0073 310 | # Enabled: True, Severity: silent 311 | dotnet_diagnostic.IDE0073.severity = silent 312 | 313 | # IDE0073: The file header is missing or not located at the top of the file 314 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0073 315 | # Enabled: True, Severity: silent 316 | dotnet_diagnostic.IDE0073.severity = silent 317 | 318 | # IDE0074: Use compound assignment 319 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0074 320 | # Enabled: True, Severity: silent 321 | dotnet_diagnostic.IDE0074.severity = warning 322 | 323 | # IDE0075: Simplify conditional expression 324 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0075 325 | # Enabled: True, Severity: silent 326 | dotnet_diagnostic.IDE0075.severity = silent 327 | 328 | # IDE0076: Invalid global 'SuppressMessageAttribute' 329 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0076 330 | # Enabled: True, Severity: suggestion 331 | dotnet_diagnostic.IDE0076.severity = warning 332 | 333 | # IDE0077: Avoid legacy format target in 'SuppressMessageAttribute' 334 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0077 335 | # Enabled: True, Severity: suggestion 336 | dotnet_diagnostic.IDE0077.severity = none 337 | 338 | # IDE0078: Use pattern matching 339 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0078 340 | # Enabled: True, Severity: silent 341 | dotnet_diagnostic.IDE0078.severity = suggestion 342 | 343 | # IDE0079: Remove unnecessary suppression 344 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0079 345 | # Enabled: True, Severity: suggestion 346 | dotnet_diagnostic.IDE0079.severity = suggestion 347 | 348 | # IDE0080: Remove unnecessary suppression operator 349 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0080 350 | # Enabled: True, Severity: silent 351 | dotnet_diagnostic.IDE0080.severity = warning 352 | 353 | # IDE0082: 'typeof' can be converted to 'nameof' 354 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0082 355 | # Enabled: True, Severity: silent 356 | dotnet_diagnostic.IDE0082.severity = warning 357 | 358 | # IDE0083: Use pattern matching 359 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0083 360 | # Enabled: True, Severity: silent 361 | dotnet_diagnostic.IDE0083.severity = suggestion 362 | 363 | # IDE0090: Use 'new(...)' 364 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0090 365 | # Enabled: True, Severity: silent 366 | dotnet_diagnostic.IDE0090.severity = silent 367 | 368 | # IDE0100: Remove redundant equality 369 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0100 370 | # Enabled: True, Severity: silent 371 | dotnet_diagnostic.IDE0100.severity = suggestion 372 | 373 | # IDE0110: Remove unnecessary discard 374 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0110 375 | # Enabled: True, Severity: silent 376 | dotnet_diagnostic.IDE0110.severity = warning 377 | 378 | # IDE0120: Simplify LINQ expression 379 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0120 380 | # Enabled: True, Severity: silent 381 | dotnet_diagnostic.IDE0120.severity = silent 382 | 383 | # IDE0121: Simplify LINQ expression 384 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0121 385 | # Enabled: True, Severity: silent 386 | dotnet_diagnostic.IDE0121.severity = silent 387 | 388 | # IDE0130: Namespace does not match folder structure 389 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0130 390 | # Enabled: True, Severity: silent 391 | dotnet_diagnostic.IDE0130.severity = warning 392 | 393 | # IDE0150: Prefer 'null' check over type check 394 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0150 395 | # Enabled: True, Severity: silent 396 | dotnet_diagnostic.IDE0150.severity = silent 397 | 398 | # IDE0160: Convert to block scoped namespace 399 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0160 400 | # Enabled: True, Severity: silent 401 | dotnet_diagnostic.IDE0160.severity = none 402 | 403 | # IDE0161: Convert to file-scoped namespace 404 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0161 405 | # Enabled: True, Severity: silent 406 | dotnet_diagnostic.IDE0161.severity = warning 407 | 408 | # IDE0170: Property pattern can be simplified 409 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0170 410 | # Enabled: True, Severity: silent 411 | dotnet_diagnostic.IDE0170.severity = warning 412 | 413 | # IDE0180: Use tuple to swap values 414 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0180 415 | # Enabled: True, Severity: silent 416 | dotnet_diagnostic.IDE0180.severity = suggestion 417 | 418 | # IDE0200: Remove unnecessary lambda expression 419 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0200 420 | # Enabled: True, Severity: silent 421 | dotnet_diagnostic.IDE0200.severity = suggestion 422 | 423 | # IDE0210: Convert to top-level statements 424 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0210 425 | # Enabled: True, Severity: silent 426 | dotnet_diagnostic.IDE0210.severity = silent 427 | 428 | # IDE0211: Convert to 'Program.Main' style program 429 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0211 430 | # Enabled: True, Severity: silent 431 | dotnet_diagnostic.IDE0211.severity = silent 432 | 433 | # IDE0220: Add explicit cast 434 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0220 435 | # Enabled: True, Severity: silent 436 | dotnet_diagnostic.IDE0220.severity = silent 437 | 438 | # IDE0230: Use UTF-8 string literal 439 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0230 440 | # Enabled: True, Severity: silent 441 | dotnet_diagnostic.IDE0230.severity = suggestion 442 | 443 | # IDE0240: Remove redundant nullable directive 444 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0240 445 | # Enabled: True, Severity: silent 446 | dotnet_diagnostic.IDE0240.severity = suggestion 447 | 448 | # IDE0241: Remove unnecessary nullable directive 449 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0241 450 | # Enabled: True, Severity: silent 451 | dotnet_diagnostic.IDE0241.severity = suggestion 452 | 453 | # IDE0250: Make struct 'readonly' 454 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0250 455 | # Enabled: True, Severity: silent 456 | dotnet_diagnostic.IDE0250.severity = suggestion 457 | 458 | # IDE0251: Make member 'readonly' 459 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0251 460 | # Enabled: True, Severity: silent 461 | dotnet_diagnostic.IDE0251.severity = silent 462 | 463 | # IDE0260: Use pattern matching 464 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0260 465 | # Enabled: True, Severity: silent 466 | dotnet_diagnostic.IDE0260.severity = suggestion 467 | 468 | # IDE0270: Use coalesce expression 469 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0270 470 | # Enabled: True, Severity: silent 471 | dotnet_diagnostic.IDE0270.severity = suggestion 472 | 473 | # IDE0280: Use 'nameof' 474 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0280 475 | # Enabled: True, Severity: silent 476 | dotnet_diagnostic.IDE0280.severity = warning 477 | 478 | # IDE0290: Use primary constructor 479 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0290 480 | # Enabled: True, Severity: silent 481 | dotnet_diagnostic.IDE0290.severity = silent 482 | 483 | # IDE0300: Simplify collection initialization 484 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0300 485 | # Enabled: True, Severity: silent 486 | dotnet_diagnostic.IDE0300.severity = suggestion 487 | 488 | # IDE0301: Simplify collection initialization 489 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0301 490 | # Enabled: True, Severity: silent 491 | dotnet_diagnostic.IDE0301.severity = suggestion 492 | 493 | # IDE0302: Simplify collection initialization 494 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0302 495 | # Enabled: True, Severity: silent 496 | dotnet_diagnostic.IDE0302.severity = suggestion 497 | 498 | # IDE0303: Simplify collection initialization 499 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0303 500 | # Enabled: True, Severity: silent 501 | dotnet_diagnostic.IDE0303.severity = suggestion 502 | 503 | # IDE0304: Simplify collection initialization 504 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0304 505 | # Enabled: True, Severity: silent 506 | dotnet_diagnostic.IDE0304.severity = suggestion 507 | 508 | # IDE0305: Simplify collection initialization 509 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0305 510 | # Enabled: True, Severity: silent 511 | dotnet_diagnostic.IDE0305.severity = suggestion 512 | 513 | # IDE0306: Simplify collection initialization 514 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0306 515 | # Enabled: True, Severity: silent 516 | dotnet_diagnostic.IDE0306.severity = silent 517 | 518 | # IDE0320: Make anonymous function static 519 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0320 520 | # Enabled: True, Severity: silent 521 | dotnet_diagnostic.IDE0320.severity = silent 522 | 523 | # IDE0330: Use 'System.Threading.Lock' 524 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0330 525 | # Enabled: True, Severity: silent 526 | dotnet_diagnostic.IDE0330.severity = suggestion 527 | 528 | # IDE0340: Use unbound generic type 529 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0340 530 | # Enabled: True, Severity: silent 531 | dotnet_diagnostic.IDE0340.severity = silent 532 | 533 | # IDE0350: Use implicitly typed lambda 534 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0350 535 | # Enabled: True, Severity: silent 536 | dotnet_diagnostic.IDE0350.severity = silent 537 | 538 | # IDE1005: Delegate invocation can be simplified. 539 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1005 540 | # Enabled: True, Severity: silent 541 | dotnet_diagnostic.IDE1005.severity = warning 542 | 543 | # IDE1006: Naming Styles 544 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide1006 545 | # Enabled: True, Severity: silent 546 | dotnet_diagnostic.IDE1006.severity = warning 547 | 548 | # IDE2000: Avoid multiple blank lines 549 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2000 550 | # Enabled: True, Severity: silent 551 | dotnet_diagnostic.IDE2000.severity = warning 552 | 553 | # IDE2001: Embedded statements must be on their own line 554 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2001 555 | # Enabled: True, Severity: silent 556 | dotnet_diagnostic.IDE2001.severity = warning 557 | 558 | # IDE2002: Consecutive braces must not have blank line between them 559 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2002 560 | # Enabled: True, Severity: silent 561 | dotnet_diagnostic.IDE2002.severity = warning 562 | 563 | # IDE2003: Blank line required between block and subsequent statement 564 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2003 565 | # Enabled: True, Severity: silent 566 | dotnet_diagnostic.IDE2003.severity = warning 567 | 568 | # IDE2004: Blank line not allowed after constructor initializer colon 569 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2004 570 | # Enabled: True, Severity: silent 571 | dotnet_diagnostic.IDE2004.severity = warning 572 | 573 | # IDE2005: Blank line not allowed after conditional expression token 574 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2005 575 | # Enabled: True, Severity: silent 576 | dotnet_diagnostic.IDE2005.severity = warning 577 | 578 | # IDE2006: Blank line not allowed after arrow expression clause token 579 | # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide2006 580 | # Enabled: True, Severity: silent 581 | dotnet_diagnostic.IDE2006.severity = warning 582 | 583 | # RemoveUnnecessaryImportsFixable: 584 | # Enabled: True, Severity: silent 585 | dotnet_diagnostic.RemoveUnnecessaryImportsFixable.severity = silent 586 | 587 | -------------------------------------------------------------------------------- /src/files/analyzers/manual_rules.editorconfig: -------------------------------------------------------------------------------- 1 | # These rules are not part of the generated rules. 2 | # The IDE rules in this file are only available in IDE, not in the build. 3 | 4 | # global_level must be higher than the NET Analyzer files 5 | is_global = true 6 | global_level = 0 7 | 8 | # CS1591: Missing XML comment for publicly visible type or member 9 | # Disabled because although XML documentation is enabled on the project, documenting everything is not always necessary 10 | dotnet_diagnostic.CS1591.severity = none 11 | 12 | # IDE0001: Simplify name (specifying a full type name is sometimes unnecessary) 13 | dotnet_diagnostic.IDE0001.severity = warning 14 | 15 | # IDE0002: Simplify member access (specifying a type name in a static invocation is sometimes unnecessary) 16 | dotnet_diagnostic.IDE0002.severity = suggestion 17 | 18 | # IDE0003: Remove this or Me qualification (enforce the use of 'this.') 19 | dotnet_diagnostic.IDE0003.severity = none 20 | 21 | # IDE0038: Use pattern matching to avoid is check followed by a cast (without variable) 22 | dotnet_diagnostic.IDE0038.severity = suggestion 23 | 24 | # IDE0049: Use language keywords instead of framework type names for type references 25 | dotnet_diagnostic.IDE0049.severity = warning 26 | 27 | # IDE0081: Remove unnecessary suppression operator 28 | dotnet_diagnostic.IDE0081.severity = none 29 | 30 | # IDE0084: Use pattern matching (IsNot operator) 31 | dotnet_diagnostic.IDE0084.severity = suggestion 32 | 33 | # IDE0140: Simplify object creation 34 | dotnet_diagnostic.IDE0140.severity = none 35 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/CodingStandardTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Compression; 2 | using System.Reflection.PortableExecutable; 3 | using Workleap.DotNet.CodingStandards.Tests.Helpers; 4 | using Xunit.Abstractions; 5 | 6 | namespace Workleap.DotNet.CodingStandards.Tests; 7 | 8 | public sealed class CodingStandardTests(PackageFixture fixture, ITestOutputHelper testOutputHelper) : IClassFixture 9 | { 10 | [Fact] 11 | public async Task BannedSymbolsAreReported() 12 | { 13 | using var project = new ProjectBuilder(fixture, testOutputHelper); 14 | project.AddCsprojFile(); 15 | project.AddFile("sample.cs", "_ = System.DateTime.Now;"); 16 | var data = await project.BuildAndGetOutput(); 17 | Assert.True(data.HasWarning("RS0030")); 18 | } 19 | 20 | [Fact] 21 | public async Task WarningsAsErrorOnGitHubActions() 22 | { 23 | using var project = new ProjectBuilder(fixture, testOutputHelper); 24 | project.AddCsprojFile(); 25 | project.AddFile("sample.cs", "_ = System.DateTime.Now;"); 26 | var data = await project.BuildAndGetOutput(["/p:GITHUB_ACTIONS=true"]); 27 | Assert.True(data.HasError("RS0030")); 28 | } 29 | 30 | [Fact] 31 | public async Task MSBuildWarningsAsErrorOnDefaultConfiguration() 32 | { 33 | using var project = new ProjectBuilder(fixture, testOutputHelper); 34 | project.AddCsprojFile(packageReferences: new Dictionary { { "Azure.Identity", "1.10.4" } }); 35 | project.AddFile("sample.cs", """ 36 | namespace sample; 37 | public static class Sample 38 | { 39 | public static void Main(string[] args) 40 | { 41 | } 42 | } 43 | """); 44 | var data = await project.BuildAndGetOutput(); 45 | Assert.True(data.HasWarning("NU1902")); 46 | } 47 | 48 | [Fact] 49 | public async Task MSBuildWarningsAsErrorOnDebugConfiguration() 50 | { 51 | using var project = new ProjectBuilder(fixture, testOutputHelper); 52 | project.AddCsprojFile(packageReferences: new Dictionary { { "Azure.Identity", "1.10.4" } }); 53 | project.AddFile("sample.cs", """ 54 | namespace sample; 55 | public static class Sample 56 | { 57 | public static void Main(string[] args) 58 | { 59 | } 60 | } 61 | """); 62 | var data = await project.BuildAndGetOutput(["--configuration", "Debug"]); 63 | Assert.True(data.HasWarning("NU1902")); 64 | } 65 | 66 | [Fact] 67 | public async Task MSBuildWarningsAsErrorOnReleaseConfiguration() 68 | { 69 | using var project = new ProjectBuilder(fixture, testOutputHelper); 70 | project.AddCsprojFile(packageReferences: new Dictionary { { "Azure.Identity", "1.10.4" } }); 71 | project.AddFile("sample.cs", """ 72 | namespace sample; 73 | public static class Sample 74 | { 75 | public static void Main(string[] args) 76 | { 77 | } 78 | } 79 | """); 80 | var data = await project.BuildAndGetOutput(["--configuration", "Release"]); 81 | Assert.True(data.HasError("NU1902")); 82 | } 83 | 84 | [Fact] 85 | public async Task NamingConvention_Invalid() 86 | { 87 | using var project = new ProjectBuilder(fixture, testOutputHelper); 88 | project.AddCsprojFile(); 89 | project.AddFile("sample.cs", """ 90 | _ = ""; 91 | 92 | class Sample 93 | { 94 | private readonly int field; 95 | 96 | public Sample(int a) => field = a; 97 | 98 | public int A() => field; 99 | } 100 | """); 101 | var data = await project.BuildAndGetOutput(["--configuration", "Release"]); 102 | Assert.True(data.HasError("IDE1006")); 103 | } 104 | 105 | [Fact] 106 | public async Task NamingConvention_Valid() 107 | { 108 | using var project = new ProjectBuilder(fixture, testOutputHelper); 109 | project.AddCsprojFile(); 110 | project.AddFile("sample.cs", """ 111 | _ = ""; 112 | 113 | class Sample 114 | { 115 | private int _field; 116 | } 117 | """); 118 | var data = await project.BuildAndGetOutput(["--configuration", "Release"]); 119 | Assert.False(data.HasError("IDE1006")); 120 | Assert.False(data.HasWarning("IDE1006")); 121 | } 122 | 123 | [Fact] 124 | public async Task ReportVulnerablePackage_Release_ShouldReportError() 125 | { 126 | using var project = new ProjectBuilder(fixture, testOutputHelper); 127 | project.AddCsprojFile(packageReferences: new Dictionary { { "System.Text.Json", "8.0.1" } }); 128 | project.AddFile("sample.cs", """ 129 | Console.WriteLine(); 130 | """); 131 | var data = await project.BuildAndGetOutput(["--configuration", "Release"]); 132 | Assert.True(data.HasError("NU1903")); 133 | } 134 | 135 | [Fact] 136 | public async Task ReportVulnerablePackage_Debug_ShouldReportWarning() 137 | { 138 | using var project = new ProjectBuilder(fixture, testOutputHelper); 139 | project.AddCsprojFile(packageReferences: new Dictionary { { "System.Text.Json", "8.0.1" } }); 140 | project.AddFile("sample.cs", """ 141 | Console.WriteLine(); 142 | """); 143 | var data = await project.BuildAndGetOutput(["--configuration", "Debug"]); 144 | Assert.False(data.HasError("NU1903")); 145 | Assert.True(data.HasWarning("NU1903")); 146 | } 147 | 148 | [Fact] 149 | public async Task ReportVulnerablePackage_DisabledWarningOnPackage() 150 | { 151 | using var project = new ProjectBuilder(fixture, testOutputHelper); 152 | project.AddFile("test.csproj", $""" 153 | 154 | 155 | exe 156 | net$(NETCoreAppMaximumVersion) 157 | enable 158 | enable 159 | {ProjectBuilder.SarifFileName},version=2.1 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | """); 168 | 169 | project.AddFile("sample.cs", """ 170 | Console.WriteLine(); 171 | """); 172 | var data = await project.BuildAndGetOutput(["--configuration", "Release"]); 173 | Assert.False(data.HasError("NU1903")); 174 | Assert.False(data.HasWarning("NU1903")); 175 | } 176 | 177 | [Fact] 178 | public async Task PdbShouldBeEmbedded_Dotnet_Build() 179 | { 180 | using var project = new ProjectBuilder(fixture, testOutputHelper); 181 | project.AddFile("test.csproj", $""" 182 | 183 | 184 | net8.0 185 | enable 186 | enable 187 | {ProjectBuilder.SarifFileName},version=2.1 188 | Foo 189 | 190 | 191 | 192 | 193 | 194 | 195 | """); 196 | 197 | project.AddFile("Sample.cs", """ 198 | namespace Foo; 199 | public static class Sample { } 200 | """); 201 | var data = await project.BuildAndGetOutput(["--configuration", "Release"]); 202 | 203 | var outputFiles = Directory.GetFiles(Path.Combine(project.RootFolder, "bin", "Release", "net8.0")); 204 | await AssertPdbIsEmbedded(outputFiles); 205 | } 206 | 207 | [Fact] 208 | public async Task PdbShouldBeEmbedded_Dotnet_Pack() 209 | { 210 | using var project = new ProjectBuilder(fixture, testOutputHelper); 211 | project.AddFile("test.csproj", $""" 212 | 213 | 214 | net8.0 215 | enable 216 | enable 217 | {ProjectBuilder.SarifFileName},version=2.1 218 | Foo 219 | 220 | 221 | 222 | 223 | 224 | 225 | """); 226 | 227 | project.AddFile("Sample.cs", """ 228 | namespace Foo; 229 | public static class Sample { } 230 | """); 231 | var data = await project.PackAndGetOutput(["--configuration", "Release"]); 232 | 233 | var extractedPath = Path.Combine(project.RootFolder, "extracted"); 234 | var files = Directory.GetFiles(Path.Combine(project.RootFolder, "bin", "Release")); 235 | Assert.Single(files); // Only the .nupkg should be generated 236 | var nupkg = files.Single(f => f.EndsWith(".nupkg", StringComparison.OrdinalIgnoreCase)); 237 | ZipFile.ExtractToDirectory(nupkg, extractedPath); 238 | 239 | var outputFiles = Directory.GetFiles(extractedPath, "*", SearchOption.AllDirectories); 240 | await AssertPdbIsEmbedded(outputFiles); 241 | } 242 | 243 | private static async Task AssertPdbIsEmbedded(string[] outputFiles) 244 | { 245 | Assert.DoesNotContain(outputFiles, f => f.EndsWith(".pdb", StringComparison.OrdinalIgnoreCase)); 246 | var dllPath = outputFiles.Single(f => f.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)); 247 | await using var stream = File.OpenRead(dllPath); 248 | var peReader = new PEReader(stream); 249 | var debug = peReader.ReadDebugDirectory(); 250 | Assert.Contains(debug, entry => entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb); 251 | } 252 | } 253 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/PathHelpers.cs: -------------------------------------------------------------------------------- 1 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 2 | 3 | internal static class PathHelpers 4 | { 5 | public static string GetRootDirectory() 6 | { 7 | var directory = Environment.CurrentDirectory; 8 | while (directory != null && !Directory.Exists(Path.Combine(directory, ".git"))) 9 | { 10 | directory = Path.GetDirectoryName(directory); 11 | } 12 | 13 | return directory ?? throw new InvalidOperationException("Cannot find the root of the git repository"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/ProjectBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using Xunit.Abstractions; 3 | using System.Text.Json; 4 | using CliWrap; 5 | using Xunit.Sdk; 6 | 7 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 8 | 9 | internal sealed class ProjectBuilder : IDisposable 10 | { 11 | public const string SarifFileName = "BuildOutput.sarif"; 12 | 13 | private readonly TemporaryDirectory _directory; 14 | private readonly ITestOutputHelper _testOutputHelper; 15 | 16 | public string RootFolder => this._directory.FullPath; 17 | 18 | public ProjectBuilder(PackageFixture fixture, ITestOutputHelper testOutputHelper) 19 | { 20 | this._testOutputHelper = testOutputHelper; 21 | 22 | this._directory = TemporaryDirectory.Create(); 23 | this._directory.CreateTextFile("NuGet.config", $""" 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | """); 43 | 44 | File.Copy(Path.Combine(PathHelpers.GetRootDirectory(), "global.json"), this._directory.GetPath("global.json")); 45 | } 46 | 47 | public void AddFile(string relativePath, string content) 48 | { 49 | File.WriteAllText(this._directory.GetPath(relativePath), content); 50 | } 51 | 52 | public void AddCsprojFile(Dictionary? properties = null, Dictionary? packageReferences = null) 53 | { 54 | var propertyElement = new XElement("PropertyGroup"); 55 | if (properties != null) 56 | { 57 | foreach (var prop in properties) 58 | { 59 | propertyElement.Add(new XElement(prop.Key), prop.Value); 60 | } 61 | } 62 | 63 | var referencesElement = new XElement("ItemGroup"); 64 | if (packageReferences != null) 65 | { 66 | foreach (var reference in packageReferences) 67 | { 68 | var packageReference = new XElement("PackageReference"); 69 | packageReference.SetAttributeValue("Include", reference.Key); 70 | packageReference.SetAttributeValue("Version", reference.Value); 71 | 72 | referencesElement.Add(packageReference); 73 | } 74 | } 75 | 76 | var content = $""" 77 | 78 | 79 | exe 80 | net$(NETCoreAppMaximumVersion) 81 | enable 82 | enable 83 | {SarifFileName},version=2.1 84 | 85 | {propertyElement} 86 | 87 | 88 | 89 | 90 | {referencesElement} 91 | 92 | """; 93 | 94 | File.WriteAllText(this._directory.GetPath("test.csproj"), content); 95 | } 96 | 97 | public Task BuildAndGetOutput(string[]? buildArguments = null) 98 | { 99 | return this.ExecuteDotnetCommandAndGetOutput("build", buildArguments); 100 | } 101 | 102 | public Task PackAndGetOutput(string[]? buildArguments = null) 103 | { 104 | return this.ExecuteDotnetCommandAndGetOutput("pack", buildArguments); 105 | } 106 | 107 | private async Task ExecuteDotnetCommandAndGetOutput(string command, string[]? buildArguments = null) 108 | { 109 | var result = await Cli.Wrap("dotnet") 110 | .WithWorkingDirectory(this._directory.FullPath) 111 | .WithArguments([command, .. (buildArguments ?? [])]) 112 | .WithEnvironmentVariables(env => env.Set("CI", null).Set("GITHUB_ACTIONS", null)) 113 | .WithStandardOutputPipe(PipeTarget.ToDelegate(this._testOutputHelper.WriteLine)) 114 | .WithStandardErrorPipe(PipeTarget.ToDelegate(this._testOutputHelper.WriteLine)) 115 | .WithValidation(CommandResultValidation.None) 116 | .ExecuteAsync(); 117 | 118 | this._testOutputHelper.WriteLine("Process exit code: " + result.ExitCode); 119 | 120 | var bytes = await File.ReadAllBytesAsync(this._directory.GetPath(SarifFileName)); 121 | var sarif = JsonSerializer.Deserialize(bytes) ?? throw new InvalidOperationException("The sarif file is invalid"); 122 | 123 | this.AppendAdditionalResult(sarif); 124 | 125 | this._testOutputHelper.WriteLine("Sarif result:\n" + string.Join("\n", sarif.AllResults().Select(r => r.ToString()))); 126 | return sarif; 127 | } 128 | 129 | public void Dispose() => this._directory.Dispose(); 130 | 131 | private void AppendAdditionalResult(SarifFile sarifFile) 132 | { 133 | if (this._testOutputHelper is not TestOutputHelper testOutputHelper || sarifFile.Runs == null) 134 | { 135 | return; 136 | } 137 | 138 | var outputLines = testOutputHelper.Output.Split(Environment.NewLine); 139 | var customRunResults = new List(); 140 | 141 | // These rules (for nuget package vulnerability) are not parsed in the sarif file automatically 142 | // See https://learn.microsoft.com/en-us/nuget/reference/errors-and-warnings/nu1901-nu1904 143 | var scannedRules = new List { "NU1901", "NU1902", "NU1903", "NU1904" } 144 | .ToDictionary(x => x, x => $"{x}:"); 145 | 146 | foreach (var outputLine in outputLines) 147 | { 148 | foreach (var scannedRule in scannedRules) 149 | { 150 | var scannedRuleIndex = outputLine.IndexOf(scannedRule.Value, StringComparison.OrdinalIgnoreCase); 151 | if (scannedRuleIndex == -1) 152 | { 153 | continue; 154 | } 155 | 156 | var previousColonIndex = outputLine.LastIndexOf(':', scannedRuleIndex); 157 | var ruleLevel = outputLine.Substring(previousColonIndex + 1, scannedRuleIndex - previousColonIndex - 1).Trim(); 158 | 159 | var message = outputLine[(scannedRuleIndex + scannedRule.Value.Length + 1)..]; 160 | customRunResults.Add(new SarifFileRunResult { Level = ruleLevel, RuleId = scannedRule.Key, Message = new SarifFileRunResultMessage { Text = message } }); 161 | } 162 | } 163 | 164 | var distinctRules = customRunResults 165 | .DistinctBy(x => new { x.RuleId, x.Level }) 166 | .ToArray(); 167 | 168 | sarifFile.Runs = sarifFile.Runs.Append(new SarifFileRun { Results = distinctRules }).ToArray(); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/SarifFile.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 4 | 5 | internal sealed class SarifFile 6 | { 7 | [JsonPropertyName("runs")] 8 | public SarifFileRun[]? Runs { get; set; } 9 | 10 | public IEnumerable AllResults() => this.Runs?.SelectMany(r => r.Results ?? []) ?? []; 11 | 12 | public bool HasError() => this.AllResults().Any(r => r.Level == "error"); 13 | public bool HasError(string ruleId) => this.AllResults().Any(r => r.Level == "error" && r.RuleId == ruleId); 14 | public bool HasWarning(string ruleId) => this.AllResults().Any(r => r.Level == "warning" && r.RuleId == ruleId); 15 | public bool HasNote(string ruleId) => this.AllResults().Any(r => r.Level == "note" && r.RuleId == ruleId); 16 | } 17 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/SarifFileRun.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 4 | 5 | internal sealed class SarifFileRun 6 | { 7 | [JsonPropertyName("results")] 8 | public SarifFileRunResult[]? Results { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/SarifFileRunResult.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 4 | 5 | internal sealed class SarifFileRunResult 6 | { 7 | [JsonPropertyName("ruleId")] 8 | public string? RuleId { get; set; } 9 | 10 | [JsonPropertyName("level")] 11 | public string? Level { get; set; } 12 | 13 | [JsonPropertyName("message")] 14 | public SarifFileRunResultMessage? Message { get; set; } 15 | 16 | public override string ToString() 17 | { 18 | return $"{this.Level}:{this.RuleId} {this.Message}"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/SarifFileRunResultMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 4 | 5 | internal sealed class SarifFileRunResultMessage 6 | { 7 | [JsonPropertyName("text")] 8 | public string? Text { get; set; } 9 | 10 | public override string ToString() 11 | { 12 | return this.Text ?? ""; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/SharedHttpClient.cs: -------------------------------------------------------------------------------- 1 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 2 | internal static class SharedHttpClient 3 | { 4 | public static HttpClient Instance { get; } = CreateHttpClient(); 5 | 6 | private static HttpClient CreateHttpClient() 7 | { 8 | var socketHandler = new SocketsHttpHandler() 9 | { 10 | PooledConnectionIdleTimeout = TimeSpan.FromMinutes(1), 11 | PooledConnectionLifetime = TimeSpan.FromMinutes(1), 12 | }; 13 | 14 | return new HttpClient(new HttpRetryMessageHandler(socketHandler), disposeHandler: true); 15 | } 16 | private sealed class HttpRetryMessageHandler(HttpMessageHandler handler) : DelegatingHandler(handler) 17 | { 18 | protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 19 | { 20 | const int maxRetries = 5; 21 | var defaultDelay = TimeSpan.FromMilliseconds(200); 22 | for (var i = 1; ; i++, defaultDelay *= 2) 23 | { 24 | TimeSpan? delayHint = null; 25 | HttpResponseMessage? result = null; 26 | 27 | try 28 | { 29 | result = await base.SendAsync(request, cancellationToken).ConfigureAwait(false); 30 | if (!IsLastAttempt(i) && ((int)result.StatusCode >= 500 || result.StatusCode is System.Net.HttpStatusCode.RequestTimeout or System.Net.HttpStatusCode.TooManyRequests)) 31 | { 32 | // Use "Retry-After" value, if available. Typically, this is sent with 33 | // either a 503 (Service Unavailable) or 429 (Too Many Requests): 34 | // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After 35 | 36 | delayHint = result.Headers.RetryAfter switch 37 | { 38 | { Date: { } date } => date - DateTimeOffset.UtcNow, 39 | { Delta: { } delta } => delta, 40 | _ => null, 41 | }; 42 | 43 | result.Dispose(); 44 | } 45 | else 46 | { 47 | return result; 48 | } 49 | } 50 | catch (HttpRequestException) 51 | { 52 | result?.Dispose(); 53 | if (IsLastAttempt(i)) 54 | { 55 | throw; 56 | } 57 | } 58 | catch (TaskCanceledException ex) when (ex.CancellationToken != cancellationToken) // catch "The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing" 59 | { 60 | result?.Dispose(); 61 | if (IsLastAttempt(i)) 62 | { 63 | throw; 64 | } 65 | } 66 | 67 | await Task.Delay(delayHint is { } someDelay && someDelay > TimeSpan.Zero ? someDelay : defaultDelay, cancellationToken).ConfigureAwait(false); 68 | 69 | static bool IsLastAttempt(int i) => i >= maxRetries; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Helpers/TemporaryDirectory.cs: -------------------------------------------------------------------------------- 1 | namespace Workleap.DotNet.CodingStandards.Tests.Helpers; 2 | 3 | internal sealed class TemporaryDirectory : IDisposable 4 | { 5 | private TemporaryDirectory(string fullPath) => this.FullPath = fullPath; 6 | 7 | public string FullPath { get; } 8 | 9 | public static TemporaryDirectory Create() 10 | { 11 | var path = Path.GetFullPath(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"))); 12 | _ = Directory.CreateDirectory(path); 13 | return new TemporaryDirectory(path); 14 | } 15 | 16 | public string GetPath(string relativePath) 17 | { 18 | return Path.Combine(this.FullPath, relativePath); 19 | } 20 | 21 | public void CreateTextFile(string relativePath, string content) 22 | { 23 | var path = this.GetPath(relativePath); 24 | _ = Directory.CreateDirectory(Path.GetDirectoryName(path)!); 25 | File.WriteAllText(path, content); 26 | } 27 | 28 | public void Dispose() 29 | { 30 | try 31 | { 32 | Directory.Delete(this.FullPath, recursive: true); 33 | } 34 | catch 35 | { 36 | // We use this code in tests, so it's not important if a folder cannot be deleted 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/PackageFixture.cs: -------------------------------------------------------------------------------- 1 | using CliWrap; 2 | using CliWrap.Buffered; 3 | using Workleap.DotNet.CodingStandards.Tests.Helpers; 4 | 5 | namespace Workleap.DotNet.CodingStandards.Tests; 6 | 7 | public sealed class PackageFixture : IAsyncLifetime 8 | { 9 | private readonly TemporaryDirectory _packageDirectory = TemporaryDirectory.Create(); 10 | 11 | public string PackageDirectory => this._packageDirectory.FullPath; 12 | 13 | public async Task InitializeAsync() 14 | { 15 | var nuspecPath = Path.Combine(PathHelpers.GetRootDirectory(), "Workleap.DotNet.CodingStandards.nuspec"); 16 | string[] args = ["pack", nuspecPath, "-ForceEnglishOutput", "-Version", "999.9.9", "-OutputDirectory", this._packageDirectory.FullPath]; 17 | 18 | if (OperatingSystem.IsWindows()) 19 | { 20 | var exe = Path.Combine(Path.GetTempPath(), $"nuget-{Guid.NewGuid()}.exe"); 21 | await DownloadFileAsync("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", exe); 22 | 23 | _ = await Cli.Wrap(exe) 24 | .WithArguments(args) 25 | .ExecuteAsync(); 26 | } 27 | else 28 | { 29 | _ = await Cli.Wrap("nuget") 30 | .WithArguments(args) 31 | .ExecuteBufferedAsync(); 32 | } 33 | } 34 | 35 | public Task DisposeAsync() 36 | { 37 | this._packageDirectory.Dispose(); 38 | return Task.CompletedTask; 39 | } 40 | 41 | private static async Task DownloadFileAsync(string url, string path) 42 | { 43 | _ = Directory.CreateDirectory(Path.GetDirectoryName(path)!); 44 | await using var nugetStream = await SharedHttpClient.Instance.GetStreamAsync(url); 45 | await using var fileStream = File.Create(path); 46 | await nugetStream.CopyToAsync(fileStream); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/Workleap.DotNet.CodingStandards.Tests/Workleap.DotNet.CodingStandards.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | false 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tools/ConfigurationFilesGenerator/ConfigurationFilesGenerator.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /tools/ConfigurationFilesGenerator/Program.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable IDE0058 // Expression value is never used 2 | #pragma warning disable SA1649 // File name should match first type name 3 | using System.Globalization; 4 | using System.Runtime.Loader; 5 | using System.Xml.Linq; 6 | using Meziantou.Framework; 7 | using Microsoft.CodeAnalysis; 8 | using Microsoft.CodeAnalysis.Diagnostics; 9 | using NuGet.Common; 10 | using NuGet.Configuration; 11 | using NuGet.Packaging.Core; 12 | using NuGet.Packaging.Signing; 13 | using NuGet.Protocol.Core.Types; 14 | using NuGet.Protocol; 15 | using NuGet.Versioning; 16 | using System.Reflection; 17 | using System.Text; 18 | using System.Text.RegularExpressions; 19 | using NuGet.Frameworks; 20 | 21 | var rootFolder = GetRootFolderPath(); 22 | 23 | var writtenFiles = 0; 24 | var packages = await GetAllReferencedNuGetPackages(); 25 | await Parallel.ForEachAsync(packages, async (item, cancellationToken) => 26 | { 27 | var (packageId, packageVersion) = item; 28 | 29 | Console.WriteLine(packageId + "@" + packageVersion); 30 | var configurationFilePath = rootFolder / "src" / "files" / "analyzers" / ("Analyzer." + packageId + ".editorconfig"); 31 | 32 | var rules = new HashSet(); 33 | foreach (var assembly in await GetAnalyzerReferences(packageId, packageVersion)) 34 | { 35 | foreach (var type in assembly.GetTypes()) 36 | { 37 | if (type.IsAbstract || type.IsInterface || !typeof(DiagnosticAnalyzer).IsAssignableFrom(type)) 38 | { 39 | continue; 40 | } 41 | 42 | var analyzer = (DiagnosticAnalyzer)Activator.CreateInstance(type)!; 43 | foreach (var diagnostic in analyzer.SupportedDiagnostics) 44 | { 45 | rules.Add(new AnalyzerRule(diagnostic.Id, diagnostic.Title.ToString(CultureInfo.InvariantCulture), diagnostic.HelpLinkUri, diagnostic.IsEnabledByDefault, diagnostic.DefaultSeverity, diagnostic.IsEnabledByDefault ? diagnostic.DefaultSeverity : null)); 46 | } 47 | } 48 | } 49 | 50 | if (rules.Count > 0) 51 | { 52 | var sb = new StringBuilder(); 53 | sb.AppendLine("# global_level must be higher than the NET Analyzer files"); 54 | sb.AppendLine("is_global = true"); 55 | sb.AppendLine("global_level = 0"); 56 | 57 | var currentConfiguration = GetConfiguration(configurationFilePath); 58 | 59 | if (currentConfiguration.Unknowns.Length > 0) 60 | { 61 | foreach (var unknown in currentConfiguration.Unknowns) 62 | { 63 | sb.AppendLine(unknown); 64 | } 65 | } 66 | else 67 | { 68 | sb.AppendLine(); 69 | } 70 | 71 | foreach (var rule in rules.OrderBy(rule => rule.Id).ThenBy(rule => rule.Title)) 72 | { 73 | var currentRuleConfiguration = currentConfiguration.Rules.FirstOrDefault(r => r.Id == rule.Id); 74 | var severity = currentRuleConfiguration != null ? currentRuleConfiguration.Severity : rule.DefaultEffectiveSeverity; 75 | 76 | sb.AppendLine($"# {rule.Id}: {rule.Title?.TrimEnd()}".TrimEnd()); 77 | if (!string.IsNullOrEmpty(rule.Url)) 78 | { 79 | sb.AppendLine($"# Help link: {rule.Url?.TrimEnd()}"); 80 | } 81 | 82 | sb.AppendLine($"# Enabled: {rule.Enabled}, Severity: {GetSeverity(rule.DefaultSeverity)}"); 83 | 84 | if (currentRuleConfiguration?.Comments.Length > 0) 85 | { 86 | foreach (var comment in currentRuleConfiguration.Comments) 87 | { 88 | sb.AppendLine(comment); 89 | } 90 | } 91 | 92 | sb.AppendLine($"dotnet_diagnostic.{rule.Id}.severity = {GetSeverity(severity)}"); 93 | sb.AppendLine(); 94 | } 95 | 96 | var text = sb.ToString().ReplaceLineEndings("\n"); 97 | 98 | if (File.Exists(configurationFilePath)) 99 | { 100 | if ((await File.ReadAllTextAsync(configurationFilePath, cancellationToken)).ReplaceLineEndings("\n") == text) 101 | { 102 | return; 103 | } 104 | } 105 | 106 | configurationFilePath.CreateParentDirectory(); 107 | await File.WriteAllTextAsync(configurationFilePath, text, cancellationToken); 108 | _ = Interlocked.Increment(ref writtenFiles); 109 | 110 | static string GetSeverity(DiagnosticSeverity? severity) 111 | { 112 | return severity switch 113 | { 114 | null => "none", 115 | DiagnosticSeverity.Hidden => "silent", 116 | DiagnosticSeverity.Info => "suggestion", 117 | DiagnosticSeverity.Warning => "warning", 118 | DiagnosticSeverity.Error => "error", 119 | _ => throw new Exception($"Severity '{severity}' is not supported"), 120 | }; 121 | } 122 | } 123 | }); 124 | 125 | if (writtenFiles > 0) 126 | { 127 | await Console.Error.WriteLineAsync("The content of the .editorconfig files is out of date. If this occurs on CI, you need to run the Build.ps1 command on your machine and commit the new .editorconfig files."); 128 | } 129 | 130 | return writtenFiles; 131 | 132 | async Task<(string Id, NuGetVersion Version)[]> GetAllReferencedNuGetPackages() 133 | { 134 | var foundPackages = new HashSet(); 135 | 136 | var cache = new SourceCacheContext(); 137 | var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json"); 138 | var resource = await repository.GetResourceAsync(); 139 | 140 | foreach (var package in GetReferencedNuGetPackages()) 141 | { 142 | // Find the latest version if no version is specified 143 | var version = package.Version is null ? null : NuGetVersion.Parse(package.Version); 144 | if (version is null) 145 | { 146 | var metadata = await resource.GetMetadataAsync(package.Id, includePrerelease: false, includeUnlisted: false, cache, NullLogger.Instance, CancellationToken.None); 147 | version = metadata.MaxBy(metadata => metadata.Identity.Version)!.Identity.Version; 148 | } 149 | 150 | var packageIdentity = new PackageIdentity(package.Id, version); 151 | await ListAllPackageDependencies(packageIdentity, [repository], NuGetFramework.AnyFramework, cache, NullLogger.Instance, foundPackages, CancellationToken.None); 152 | } 153 | 154 | return foundPackages.Select(p => (p.Id, p.Version)).ToArray(); 155 | 156 | static async Task ListAllPackageDependencies( 157 | PackageIdentity package, 158 | IEnumerable repositories, 159 | NuGetFramework framework, 160 | SourceCacheContext cache, 161 | ILogger logger, 162 | HashSet dependencies, 163 | CancellationToken cancellationToken) 164 | { 165 | if (dependencies.Contains(package)) 166 | { 167 | return; 168 | } 169 | 170 | foreach (var repository in repositories) 171 | { 172 | var dependencyInfoResource = await repository.GetResourceAsync(); 173 | var dependencyInfo = await dependencyInfoResource.ResolvePackage(package, framework, cache, logger, cancellationToken); 174 | 175 | if (dependencyInfo == null) 176 | { 177 | continue; 178 | } 179 | 180 | if (dependencies.Add(dependencyInfo)) 181 | { 182 | foreach (var dependency in dependencyInfo.Dependencies) 183 | { 184 | await ListAllPackageDependencies( 185 | new PackageIdentity(dependency.Id, dependency.VersionRange.MinVersion), 186 | repositories, 187 | framework, 188 | cache, 189 | logger, 190 | dependencies, 191 | cancellationToken); 192 | } 193 | } 194 | } 195 | } 196 | } 197 | 198 | IEnumerable<(string Id, string? Version)> GetReferencedNuGetPackages() 199 | { 200 | foreach (var nuspecPath in Directory.GetFiles(rootFolder, "*.nuspec")) 201 | { 202 | var document = XDocument.Load(nuspecPath); 203 | var ns = document.Root!.Name.Namespace; 204 | foreach (var value in document.Descendants(ns + "dependency").Select(node => (node.Attribute("id")!.Value, node.Attribute("version")!.Value))) 205 | { 206 | yield return value; 207 | } 208 | } 209 | 210 | // Add analyzers from the .NET SDK 211 | foreach (var package in new[] { "Microsoft.CodeAnalysis.NetAnalyzers", "Microsoft.CodeAnalysis.CSharp.CodeStyle" }) 212 | { 213 | yield return (package, null); 214 | } 215 | } 216 | 217 | static FullPath GetRootFolderPath() 218 | { 219 | var path = FullPath.CurrentDirectory(); 220 | while (!path.IsEmpty) 221 | { 222 | if (Directory.Exists(path / ".git")) 223 | { 224 | return path; 225 | } 226 | 227 | path = path.Parent; 228 | } 229 | 230 | return !path.IsEmpty ? path : throw new InvalidOperationException("Cannot find the root folder"); 231 | } 232 | 233 | static async Task GetAnalyzerReferences(string packageId, NuGetVersion version) 234 | { 235 | var logger = NullLogger.Instance; 236 | var cancellationToken = CancellationToken.None; 237 | 238 | var settings = Settings.LoadDefaultSettings(null); 239 | var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(settings); 240 | var source = "https://api.nuget.org/v3/index.json"; 241 | 242 | var cache = new SourceCacheContext(); 243 | var repository = Repository.Factory.GetCoreV3(source); 244 | var resource = await repository.GetResourceAsync(); 245 | 246 | // Get the package from the global cache or download it 247 | var package = GlobalPackagesFolderUtility.GetPackage(new PackageIdentity(packageId, version), globalPackagesFolder); 248 | if (package is null || package.Status is DownloadResourceResultStatus.NotFound) 249 | { 250 | // Download the package 251 | using var packageStream = new MemoryStream(); 252 | _ = await resource.CopyNupkgToStreamAsync( 253 | packageId, 254 | version, 255 | packageStream, 256 | cache, 257 | logger, 258 | cancellationToken); 259 | 260 | _ = packageStream.Seek(0, SeekOrigin.Begin); 261 | 262 | // Add it to the global package folder 263 | package = await GlobalPackagesFolderUtility.AddPackageAsync( 264 | source, 265 | new PackageIdentity(packageId, version), 266 | packageStream, 267 | globalPackagesFolder, 268 | parentId: Guid.Empty, 269 | ClientPolicyContext.GetClientPolicy(settings, logger), 270 | logger, 271 | cancellationToken); 272 | } 273 | 274 | // Load all analyzers DLLs from the NuGet packages 275 | var result = new List(); 276 | var groups = package.PackageReader.GetFiles("analyzers").GroupBy(Path.GetDirectoryName).ToArray(); 277 | foreach (var group in groups) 278 | { 279 | var context = new AssemblyLoadContext(null); 280 | foreach (var file in group) 281 | { 282 | try 283 | { 284 | using var stream = package.PackageReader.GetStream(file); 285 | result.Add(context.LoadFromStream(stream)); 286 | } 287 | catch (Exception ex) 288 | { 289 | Console.WriteLine(ex); 290 | } 291 | } 292 | } 293 | 294 | return [.. result]; 295 | } 296 | 297 | static (AnalyzerConfiguration[] Rules, string[] Unknowns) GetConfiguration(FullPath editorconfig) 298 | { 299 | var rules = new List(); 300 | var unknowns = new List(); 301 | 302 | var currentComment = new List(); 303 | try 304 | { 305 | var lines = File.ReadAllLines(editorconfig); 306 | 307 | foreach (var line in lines) 308 | { 309 | try 310 | { 311 | if (line.StartsWith('#')) 312 | { 313 | if (line.StartsWith("# Enabled: ", StringComparison.Ordinal)) 314 | { 315 | continue; 316 | } 317 | 318 | if (line.StartsWith("# Default severity: ", StringComparison.Ordinal)) 319 | { 320 | continue; 321 | } 322 | 323 | if (line.StartsWith("# Help link: ", StringComparison.Ordinal)) 324 | { 325 | continue; 326 | } 327 | 328 | currentComment.Add(line); 329 | continue; 330 | } 331 | 332 | if (line.StartsWith("is_global", StringComparison.Ordinal)) 333 | { 334 | continue; 335 | } 336 | 337 | if (line.StartsWith("global_level", StringComparison.Ordinal)) 338 | { 339 | continue; 340 | } 341 | 342 | var match = Regex.Match(line, @"^dotnet_diagnostic\.(?.+?).severity\s*=\s*(?[a-z]+)"); 343 | if (match.Success) 344 | { 345 | DiagnosticSeverity? diagnosticSeverity = null; 346 | var severityValue = match.Groups["Severity"].Value; 347 | if (severityValue == "silent") 348 | { 349 | diagnosticSeverity = DiagnosticSeverity.Hidden; 350 | } 351 | else if (severityValue == "suggestion") 352 | { 353 | diagnosticSeverity = DiagnosticSeverity.Info; 354 | } 355 | else if (Enum.TryParse(severityValue, ignoreCase: true, out var severity)) 356 | { 357 | diagnosticSeverity = severity; 358 | } 359 | 360 | rules.Add(new AnalyzerConfiguration(match.Groups["RuleId"].Value, currentComment.Skip(1).ToArray(), diagnosticSeverity)); 361 | } 362 | else 363 | { 364 | foreach (var comment in currentComment) 365 | { 366 | unknowns.Add(comment); 367 | } 368 | 369 | if (rules.Count == 0 || !string.IsNullOrEmpty(line)) 370 | { 371 | unknowns.Add(line); 372 | } 373 | } 374 | } 375 | finally 376 | { 377 | if (!line.StartsWith('#')) 378 | { 379 | currentComment.Clear(); 380 | } 381 | } 382 | } 383 | } 384 | catch 385 | { 386 | } 387 | 388 | return (rules.ToArray(), unknowns.ToArray()); 389 | } 390 | 391 | internal sealed record AnalyzerConfiguration(string Id, string[] Comments, DiagnosticSeverity? Severity); 392 | 393 | internal sealed record AnalyzerRule(string Id, string Title, string? Url, bool Enabled, DiagnosticSeverity DefaultSeverity, DiagnosticSeverity? DefaultEffectiveSeverity); 394 | -------------------------------------------------------------------------------- /wl-dotnet-codingstandards.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{C1F5A879-3A26-4621-ADB7-3B1C59CBC8B3}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Workleap.DotNet.CodingStandards.Tests", "tests\Workleap.DotNet.CodingStandards.Tests\Workleap.DotNet.CodingStandards.Tests.csproj", "{640037BA-49DF-4BBD-9858-3DC89E2739FD}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConfigurationFilesGenerator", "tools\ConfigurationFilesGenerator\ConfigurationFilesGenerator.csproj", "{2A95B554-DB07-434B-82C3-8D056819DED4}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {640037BA-49DF-4BBD-9858-3DC89E2739FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {640037BA-49DF-4BBD-9858-3DC89E2739FD}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {640037BA-49DF-4BBD-9858-3DC89E2739FD}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {640037BA-49DF-4BBD-9858-3DC89E2739FD}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {2A95B554-DB07-434B-82C3-8D056819DED4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {2A95B554-DB07-434B-82C3-8D056819DED4}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {2A95B554-DB07-434B-82C3-8D056819DED4}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {2A95B554-DB07-434B-82C3-8D056819DED4}.Release|Any CPU.Build.0 = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | GlobalSection(NestedProjects) = preSolution 31 | {640037BA-49DF-4BBD-9858-3DC89E2739FD} = {C1F5A879-3A26-4621-ADB7-3B1C59CBC8B3} 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {18E64023-58E9-4BA2-BCE7-4BD5E1A023C1} 35 | EndGlobalSection 36 | EndGlobal 37 | --------------------------------------------------------------------------------