From 510037941717301fed4c52c6797ebd337c3b6cc4 Mon Sep 17 00:00:00 2001 From: n0099 Date: Mon, 25 Mar 2024 01:56:31 +0800 Subject: [PATCH] * replace `#pragma warning (disable|restore)` directives with `[SuppressMessage]` scoped attribute + four NuGet packages of Roslyn analyzer and disable some of rules in GlobalSuppressions.cs @ tbm.Shared.csproj @ c# --- c#/GlobalSuppressions.cs | 28 ++++++++++++++++++- c#/crawler/packages.lock.json | 26 ++++++++++++++++- c#/crawler/src/Db/CrawlerDbContext.cs | 3 +- c#/crawler/src/EntryPoint.cs | 4 +-- .../src/Tieba/Crawl/Parser/ReplyParser.cs | 2 +- c#/imagePipeline/packages.lock.json | 26 ++++++++++++++++- c#/imagePipeline/src/EntryPoint.cs | 4 +-- c#/shared/packages.lock.json | 24 ++++++++++++++++ c#/shared/src/ErrorableWorker.cs | 2 ++ c#/shared/src/TbmDbContext.cs | 14 ++++++---- c#/shared/tbm.Shared.csproj | 18 ++++++++---- 11 files changed, 129 insertions(+), 22 deletions(-) diff --git a/c#/GlobalSuppressions.cs b/c#/GlobalSuppressions.cs index 93b44952..ce490629 100644 --- a/c#/GlobalSuppressions.cs +++ b/c#/GlobalSuppressions.cs @@ -3,12 +3,38 @@ [assembly: SuppressMessage("Major Code Smell", "S125:Sections of code should not be commented out")] [assembly: SuppressMessage("Minor Code Smell", "S3604:Member initializer values should not be redundant")] +[assembly: SuppressMessage("Critical Bug", "S6674:Log message template should be syntactically correct")] [assembly: SuppressMessage("Roslynator", "RCS1001:Add braces (when expression spans over multiple lines).")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.")] [assembly: SuppressMessage("Roslynator", "RCS1156:Use string.Length instead of comparison with empty string.")] [assembly: SuppressMessage("Style", "VSTHRD200:Use \"Async\" suffix for async methods")] -[assembly: SuppressMessage("Critical Bug", "S6674:Log message template should be syntactically correct")] +[assembly: SuppressMessage("Style", "CC0061:Asynchronous method can be terminated with the 'Async' keyword.")] +[assembly: SuppressMessage("Naming", "AV1755:Name of async method should end with Async or TaskAsync")] +[assembly: SuppressMessage("Naming", "AV1706:Identifier contains an abbreviation or is too short")] +[assembly: SuppressMessage("Maintainability", "AV1580:Method argument calls a nested method")] +[assembly: SuppressMessage("Maintainability", "AV1500:Member or local function contains too many statements")] +[assembly: SuppressMessage("Miscellaneous Design", "AV1210:Catch a specific exception instead of Exception, SystemException or ApplicationException")] +[assembly: SuppressMessage("Design", "CC0031:Check for null before calling a delegate")] +[assembly: SuppressMessage("Maintainability", "AV1561:Signature contains too many parameters")] +[assembly: SuppressMessage("Design", "MA0051:Method is too long")] +[assembly: SuppressMessage("Usage", "MA0004:Use Task.ConfigureAwait")] +[assembly: SuppressMessage("Design", "CC0120:Your Switch maybe include default clause")] +[assembly: SuppressMessage("Correctness", "SS019:Switch should have default label.")] +[assembly: SuppressMessage("Maintainability", "AV1555:Avoid using non-(nullable-)boolean named arguments")] +[assembly: SuppressMessage("Maintainability", "AV1535:Missing block in case or default clause of switch statement")] +[assembly: SuppressMessage("Maintainability", "CC0097:You have missing/unexistent parameters in Xml Docs")] +[assembly: SuppressMessage("Design", "MA0048:File name must match type name")] +[assembly: SuppressMessage("Maintainability", "AV1507:File contains multiple types")] +[assembly: SuppressMessage("Style", "MA0007:Add a comma after the last value")] +[assembly: SuppressMessage("Style", "MA0003:Add parameter name to improve readability")] +[assembly: SuppressMessage("Design", "CC0021:Use nameof")] +[assembly: SuppressMessage("Naming", "AV1704:Identifier contains one or more digits in its name")] +[assembly: SuppressMessage("Usage", "MA0006:Use String.Equals instead of equality operator")] +[assembly: SuppressMessage("Maintainability", "AV1537:If-else-if construct should end with an unconditional else clause")] +[assembly: SuppressMessage("Maintainability", "AV1554:Method contains optional parameter in type hierarchy")] +[assembly: SuppressMessage("Maintainability", "AV1564:Parameter in public or internal member is of type bool or bool?")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements should be documented")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1602:Enumeration items should be documented")] diff --git a/c#/crawler/packages.lock.json b/c#/crawler/packages.lock.json index a58c6f2f..4694af30 100644 --- a/c#/crawler/packages.lock.json +++ b/c#/crawler/packages.lock.json @@ -108,11 +108,21 @@ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, + "codecracker.CSharp": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "s5KSzc65WjT+912x+OLGrW0jA/R8e67GRymQeVUfIJsBx+UJVnPShvaqM48G7oGYUTqVnpJElYjGX313yeSuIA==" + }, "CommunityToolkit.Diagnostics": { "type": "Transitive", "resolved": "8.2.2", "contentHash": "iILVyo7VvzTlQT7b2qOs1ZDcneKsmuy2mTuxCCaBWEfg3tjw35B/ImO9Xw6It7xi2ie8/2PWfXhFn+Prztg03w==" }, + "CSharpGuidelinesAnalyzer": { + "type": "Transitive", + "resolved": "3.8.4", + "contentHash": "yfpcYXiPeyTRcifpYsk8Ez7GqhzBHF+cFxfo8fjH4jctQqr+shTfpOeE+4kj6+SNvJBZsBzYJ/3pi5aj+1q9Wg==" + }, "EFCore.NamingConventions": { "type": "Transitive", "resolved": "8.0.3", @@ -148,6 +158,11 @@ "resolved": "1.2.5", "contentHash": "+5UKyagtVX33TSeOGorYzDXus/ypAISfM7HFfrix4BEmuuGF+nhSjf8P9csejLQ79ny5ms33M5/lQ2SkwC0Jxw==" }, + "Meziantou.Analyzer": { + "type": "Transitive", + "resolved": "2.0.146", + "contentHash": "pJ3k+3UjD2WwPsZR7fkgVYviXP3PCQM0hjwN1TuM4C0u1TuGKC9WdZCo0RAPZ+azhRPmYGSUjkjsN2fkQByghQ==" + }, "Microsoft.CodeAnalysis.NetAnalyzers": { "type": "Transitive", "resolved": "8.0.0", @@ -527,6 +542,11 @@ "resolved": "4.12.0", "contentHash": "0n7hlgpD57vKCC39iz6lLg6RIgPF6B2S0z7HzcRSkeu35svFKSGqKJhh2MfCsoHrrPMugnlMZI9NZwrkFPTqYA==" }, + "SharpSource": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "W3FnCahaLO22Wm/1WVnWi19hhrTW9Q1Jav5aSXzF2WtBJixHmDs2H8vcNx7Fm2P1mYRUs9k7cNZLm2z5sOHKzQ==" + }, "SonarAnalyzer.CSharp": { "type": "Transitive", "resolved": "9.22.0.87781", @@ -581,9 +601,11 @@ "dependencies": { "Autofac": "[8.0.0, )", "Autofac.Extensions.DependencyInjection": "[9.0.0, )", + "CSharpGuidelinesAnalyzer": "[3.8.4, )", "CommunityToolkit.Diagnostics": "[8.2.2, )", "EFCore.NamingConventions": "[8.0.3, )", "IDisposableAnalyzers": "[4.0.7, )", + "Meziantou.Analyzer": "[2.0.146, )", "Microsoft.CodeAnalysis.NetAnalyzers": "[8.0.0, )", "Microsoft.EntityFrameworkCore": "[8.0.3, )", "Microsoft.Extensions.Hosting": "[8.0.0, )", @@ -591,9 +613,11 @@ "NLog.Extensions.Logging": "[5.3.8, )", "Pomelo.EntityFrameworkCore.MySql": "[8.0.2, )", "Roslynator.Analyzers": "[4.12.0, )", + "SharpSource": "[1.24.0, )", "SonarAnalyzer.CSharp": "[9.22.0.87781, )", "StyleCop.Analyzers.Unstable": "[1.2.0.556, )", - "SuperLinq": "[5.4.0, )" + "SuperLinq": "[5.4.0, )", + "codecracker.CSharp": "[1.1.0, )" } } } diff --git a/c#/crawler/src/Db/CrawlerDbContext.cs b/c#/crawler/src/Db/CrawlerDbContext.cs index 05d23311..973bdffe 100644 --- a/c#/crawler/src/Db/CrawlerDbContext.cs +++ b/c#/crawler/src/Db/CrawlerDbContext.cs @@ -60,7 +60,7 @@ public void TimestampingEntities() => } }); -#pragma warning disable IDE0058 // Expression value is never used + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void OnModelCreating(ModelBuilder b) { base.OnModelCreating(b); @@ -101,7 +101,6 @@ protected override void OnModelCreating(ModelBuilder b) .HasKey(e => new {e.Fid, e.Portrait, e.DiscoveredAt, e.ModeratorTypes}); b.Entity().ToTable("tbm_forum"); } -#pragma warning restore IDE0058 // Expression value is never used public class ModelCacheKeyFactory : IModelCacheKeyFactory { // https://stackoverflow.com/questions/51864015/entity-framework-map-model-class-to-table-at-run-time/51899590#51899590 diff --git a/c#/crawler/src/EntryPoint.cs b/c#/crawler/src/EntryPoint.cs index 3e8d6170..24b02827 100644 --- a/c#/crawler/src/EntryPoint.cs +++ b/c#/crawler/src/EntryPoint.cs @@ -3,12 +3,11 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Http; -#pragma warning disable IDE0058 // Expression value is never used - namespace tbm.Crawler; public class EntryPoint : BaseEntryPoint { + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void ConfigureServices(HostBuilderContext context, IServiceCollection service) { service.AddHostedService(); @@ -32,6 +31,7 @@ protected override void ConfigureServices(HostBuilderContext context, IServiceCo service.RemoveAll(); } + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void ConfigureContainer(HostBuilderContext context, ContainerBuilder builder) { var baseClassOfClassesToBeRegistered = new[] diff --git a/c#/crawler/src/Tieba/Crawl/Parser/ReplyParser.cs b/c#/crawler/src/Tieba/Crawl/Parser/ReplyParser.cs index a786b015..76fd8d60 100644 --- a/c#/crawler/src/Tieba/Crawl/Parser/ReplyParser.cs +++ b/c#/crawler/src/Tieba/Crawl/Parser/ReplyParser.cs @@ -38,7 +38,7 @@ protected override ReplyPost Convert(Reply inPost) { c.OriginSrc = urlFilename; } - else if (uri.Host is not "tb2.bdstatic.com") // http://tb2.bdstatic.com/tb/cms/commonsub/editor/images/qw_cat_small/qw_cat_0001.gif + else if (uri.Host != "tb2.bdstatic.com") // http://tb2.bdstatic.com/tb/cms/commonsub/editor/images/qw_cat_small/qw_cat_0001.gif { logger.LogInformation("Detected an image in the content of reply with pid {} references to {}" + " instead of common domains of tieba image hosting service, content={}", diff --git a/c#/imagePipeline/packages.lock.json b/c#/imagePipeline/packages.lock.json index 4ea0786c..3bbdb034 100644 --- a/c#/imagePipeline/packages.lock.json +++ b/c#/imagePipeline/packages.lock.json @@ -133,11 +133,21 @@ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, + "codecracker.CSharp": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "s5KSzc65WjT+912x+OLGrW0jA/R8e67GRymQeVUfIJsBx+UJVnPShvaqM48G7oGYUTqVnpJElYjGX313yeSuIA==" + }, "CommunityToolkit.Diagnostics": { "type": "Transitive", "resolved": "8.2.2", "contentHash": "iILVyo7VvzTlQT7b2qOs1ZDcneKsmuy2mTuxCCaBWEfg3tjw35B/ImO9Xw6It7xi2ie8/2PWfXhFn+Prztg03w==" }, + "CSharpGuidelinesAnalyzer": { + "type": "Transitive", + "resolved": "3.8.4", + "contentHash": "yfpcYXiPeyTRcifpYsk8Ez7GqhzBHF+cFxfo8fjH4jctQqr+shTfpOeE+4kj6+SNvJBZsBzYJ/3pi5aj+1q9Wg==" + }, "EFCore.NamingConventions": { "type": "Transitive", "resolved": "8.0.3", @@ -153,6 +163,11 @@ "resolved": "4.0.7", "contentHash": "Xrn/VABG/JhulJOmHOeOAY4/qafbEyRj3Z6gMeSABT1XCqMe8HnqOvid8gEVJt47VUZ6eD7XpTFLZ1KLyTZgdw==" }, + "Meziantou.Analyzer": { + "type": "Transitive", + "resolved": "2.0.146", + "contentHash": "pJ3k+3UjD2WwPsZR7fkgVYviXP3PCQM0hjwN1TuM4C0u1TuGKC9WdZCo0RAPZ+azhRPmYGSUjkjsN2fkQByghQ==" + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "7.0.0", @@ -616,6 +631,11 @@ "resolved": "0.33.0", "contentHash": "FlHfpTAADzaSlVCBF33iKJk9UhOr3Xj+r5LXbW2GzqYr0SrhiOf6shLX2LC2fqs7g7d+YlwKbBXqWFtb+e7icw==" }, + "SharpSource": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "W3FnCahaLO22Wm/1WVnWi19hhrTW9Q1Jav5aSXzF2WtBJixHmDs2H8vcNx7Fm2P1mYRUs9k7cNZLm2z5sOHKzQ==" + }, "SonarAnalyzer.CSharp": { "type": "Transitive", "resolved": "9.22.0.87781", @@ -914,9 +934,11 @@ "dependencies": { "Autofac": "[8.0.0, )", "Autofac.Extensions.DependencyInjection": "[9.0.0, )", + "CSharpGuidelinesAnalyzer": "[3.8.4, )", "CommunityToolkit.Diagnostics": "[8.2.2, )", "EFCore.NamingConventions": "[8.0.3, )", "IDisposableAnalyzers": "[4.0.7, )", + "Meziantou.Analyzer": "[2.0.146, )", "Microsoft.CodeAnalysis.NetAnalyzers": "[8.0.0, )", "Microsoft.EntityFrameworkCore": "[8.0.3, )", "Microsoft.Extensions.Hosting": "[8.0.0, )", @@ -924,9 +946,11 @@ "NLog.Extensions.Logging": "[5.3.8, )", "Pomelo.EntityFrameworkCore.MySql": "[8.0.2, )", "Roslynator.Analyzers": "[4.12.0, )", + "SharpSource": "[1.24.0, )", "SonarAnalyzer.CSharp": "[9.22.0.87781, )", "StyleCop.Analyzers.Unstable": "[1.2.0.556, )", - "SuperLinq": "[5.4.0, )" + "SuperLinq": "[5.4.0, )", + "codecracker.CSharp": "[1.1.0, )" } } } diff --git a/c#/imagePipeline/src/EntryPoint.cs b/c#/imagePipeline/src/EntryPoint.cs index eaaf027b..2188bc02 100644 --- a/c#/imagePipeline/src/EntryPoint.cs +++ b/c#/imagePipeline/src/EntryPoint.cs @@ -3,12 +3,11 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Http; -#pragma warning disable IDE0058 // Expression value is never used - namespace tbm.ImagePipeline; public partial class EntryPoint : BaseEntryPoint { + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void ConfigureServices(HostBuilderContext context, IServiceCollection service) { service.AddHostedService(); @@ -51,6 +50,7 @@ protected override void ConfigureServices(HostBuilderContext context, IServiceCo service.RemoveAll(); } + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void ConfigureContainer(HostBuilderContext context, ContainerBuilder builder) { builder.RegisterType(); diff --git a/c#/shared/packages.lock.json b/c#/shared/packages.lock.json index 798fda41..0bc18640 100644 --- a/c#/shared/packages.lock.json +++ b/c#/shared/packages.lock.json @@ -21,12 +21,24 @@ "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" } }, + "codecracker.CSharp": { + "type": "Direct", + "requested": "[1.1.0, )", + "resolved": "1.1.0", + "contentHash": "s5KSzc65WjT+912x+OLGrW0jA/R8e67GRymQeVUfIJsBx+UJVnPShvaqM48G7oGYUTqVnpJElYjGX313yeSuIA==" + }, "CommunityToolkit.Diagnostics": { "type": "Direct", "requested": "[8.2.2, )", "resolved": "8.2.2", "contentHash": "iILVyo7VvzTlQT7b2qOs1ZDcneKsmuy2mTuxCCaBWEfg3tjw35B/ImO9Xw6It7xi2ie8/2PWfXhFn+Prztg03w==" }, + "CSharpGuidelinesAnalyzer": { + "type": "Direct", + "requested": "[3.8.4, )", + "resolved": "3.8.4", + "contentHash": "yfpcYXiPeyTRcifpYsk8Ez7GqhzBHF+cFxfo8fjH4jctQqr+shTfpOeE+4kj6+SNvJBZsBzYJ/3pi5aj+1q9Wg==" + }, "EFCore.NamingConventions": { "type": "Direct", "requested": "[8.0.3, )", @@ -44,6 +56,12 @@ "resolved": "4.0.7", "contentHash": "Xrn/VABG/JhulJOmHOeOAY4/qafbEyRj3Z6gMeSABT1XCqMe8HnqOvid8gEVJt47VUZ6eD7XpTFLZ1KLyTZgdw==" }, + "Meziantou.Analyzer": { + "type": "Direct", + "requested": "[2.0.146, )", + "resolved": "2.0.146", + "contentHash": "pJ3k+3UjD2WwPsZR7fkgVYviXP3PCQM0hjwN1TuM4C0u1TuGKC9WdZCo0RAPZ+azhRPmYGSUjkjsN2fkQByghQ==" + }, "Microsoft.CodeAnalysis.NetAnalyzers": { "type": "Direct", "requested": "[8.0.0, )", @@ -125,6 +143,12 @@ "resolved": "4.12.0", "contentHash": "0n7hlgpD57vKCC39iz6lLg6RIgPF6B2S0z7HzcRSkeu35svFKSGqKJhh2MfCsoHrrPMugnlMZI9NZwrkFPTqYA==" }, + "SharpSource": { + "type": "Direct", + "requested": "[1.24.0, )", + "resolved": "1.24.0", + "contentHash": "W3FnCahaLO22Wm/1WVnWi19hhrTW9Q1Jav5aSXzF2WtBJixHmDs2H8vcNx7Fm2P1mYRUs9k7cNZLm2z5sOHKzQ==" + }, "SonarAnalyzer.CSharp": { "type": "Direct", "requested": "[9.22.0.87781, )", diff --git a/c#/shared/src/ErrorableWorker.cs b/c#/shared/src/ErrorableWorker.cs index 8f4d8855..82ace6cf 100644 --- a/c#/shared/src/ErrorableWorker.cs +++ b/c#/shared/src/ErrorableWorker.cs @@ -3,7 +3,9 @@ namespace tbm.Shared; +#pragma warning disable AV1564 // Parameter in public or internal member is of type bool or bool? public abstract class ErrorableWorker(bool shouldExitOnException = false, bool shouldExitOnFinish = false) +#pragma warning restore AV1564 // Parameter in public or internal member is of type bool or bool? : BackgroundService { // ReSharper disable UnusedAutoPropertyAccessor.Global diff --git a/c#/shared/src/TbmDbContext.cs b/c#/shared/src/TbmDbContext.cs index 6336fe76..7f700ca1 100644 --- a/c#/shared/src/TbmDbContext.cs +++ b/c#/shared/src/TbmDbContext.cs @@ -1,5 +1,6 @@ using System.Data; using System.Data.Common; +using System.Diagnostics.CodeAnalysis; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -14,6 +15,7 @@ public abstract class TbmDbContext : DbContext { protected static readonly SelectForUpdateCommandInterceptor SelectForUpdateCommandInterceptorInstance = new(); + [SuppressMessage("Style", "CC0072:Remove Async termination when method is not asynchronous.", Justification = "https://github.com/code-cracker/code-cracker/issues/1086")] protected sealed class SelectForUpdateCommandInterceptor : DbCommandInterceptor { // https://stackoverflow.com/questions/37984312/how-to-implement-select-for-update-in-ef-core/75086260#75086260 public override InterceptionResult ScalarExecuting @@ -65,12 +67,12 @@ public class TbmDbContext : TbmDbContext public DbSet ImageInReplies => Set(); public DbSet ReplyContentImages => Set(); -#pragma warning disable IDE0058 // Expression value is never used -#pragma warning disable S927 // Parameter names should match base declaration and other partial definitions + [SuppressMessage("Critical Code Smell", "S927:Parameter names should match base declaration and other partial definitions")] + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void OnConfiguring(DbContextOptionsBuilder options) { - var connectionStr = Config.GetConnectionString("Main"); - options.UseMySql(connectionStr!, ServerVersion.AutoDetect(connectionStr), OnConfiguringMysql) + var connectionString = Config.GetConnectionString("Main"); + options.UseMySql(connectionString!, ServerVersion.AutoDetect(connectionString), OnConfiguringMysql) .ReplaceService() .AddInterceptors(SelectForUpdateCommandInterceptorInstance) .UseCamelCaseNamingConvention(); @@ -86,6 +88,8 @@ protected override void OnConfiguring(DbContextOptionsBuilder options) if (dbSettings.GetValue("EnableSensitiveDataLogging", false)) options.EnableSensitiveDataLogging(); } + [SuppressMessage("Critical Code Smell", "S927:Parameter names should match base declaration and other partial definitions")] + [SuppressMessage("Style", "IDE0058:Expression value is never used")] protected override void OnModelCreating(ModelBuilder b) { b.Entity().ToTable("tbmi_imageInReply"); @@ -95,8 +99,6 @@ protected override void OnModelCreating(ModelBuilder b) protected void OnModelCreatingWithFid(ModelBuilder b, uint fid) => b.Entity().ToTable($"tbmc_f{fid}_reply_content_image"); -#pragma warning restore S927 // Parameter names should match base declaration and other partial definitions -#pragma warning restore IDE0058 // Expression value is never used protected virtual void OnConfiguringMysql(MySqlDbContextOptionsBuilder builder) { } } diff --git a/c#/shared/tbm.Shared.csproj b/c#/shared/tbm.Shared.csproj index 1aca0e20..64574bae 100644 --- a/c#/shared/tbm.Shared.csproj +++ b/c#/shared/tbm.Shared.csproj @@ -13,12 +13,18 @@ - - - - - - + + + + + + + + + + + +