From 4b88de0738ec869170cbbd8f518d53169beb18b9 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Wed, 14 Aug 2024 13:24:21 -0700 Subject: [PATCH 1/9] Add Effective C# analyzers and update SquiggleCop baselines --- build/scripts/Set-SquiggleCopBaseline.ps1 | 3 +++ build/targets/codeanalysis/CodeAnalysis.props | 4 ++++ build/targets/codeanalysis/Packages.props | 1 + src/Moq.Analyzers/SquiggleCop.Baseline.yaml | 10 +++++++++- src/tools/PerfDiff/SquiggleCop.Baseline.yaml | 10 +++++++++- .../Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml | 10 +++++++++- tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml | 10 +++++++++- 7 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 build/scripts/Set-SquiggleCopBaseline.ps1 diff --git a/build/scripts/Set-SquiggleCopBaseline.ps1 b/build/scripts/Set-SquiggleCopBaseline.ps1 new file mode 100644 index 00000000..43ad4844 --- /dev/null +++ b/build/scripts/Set-SquiggleCopBaseline.ps1 @@ -0,0 +1,3 @@ +Get-ChildItem *.csproj -recurse -File | ForEach-Object{ + dotnet clean $_.FullName && dotnet build $_.FullName /p:PedanticMode=true /p:SquiggleCop_AutoBaseline=true +} \ No newline at end of file diff --git a/build/targets/codeanalysis/CodeAnalysis.props b/build/targets/codeanalysis/CodeAnalysis.props index e83bbdce..fdd66631 100644 --- a/build/targets/codeanalysis/CodeAnalysis.props +++ b/build/targets/codeanalysis/CodeAnalysis.props @@ -39,5 +39,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/build/targets/codeanalysis/Packages.props b/build/targets/codeanalysis/Packages.props index d7aef1b8..5169dbdf 100644 --- a/build/targets/codeanalysis/Packages.props +++ b/build/targets/codeanalysis/Packages.props @@ -8,5 +8,6 @@ + diff --git a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml index 32a531e5..99cd3ef3 100644 --- a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml +++ b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml @@ -35,7 +35,7 @@ - {Id: CA1056, Title: URI-like properties should not be strings, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1058, Title: Types should not extend certain base types, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1060, Title: Move pinvokes to native methods class, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: CA1062, Title: Validate arguments of public methods, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1063, Title: Implement IDisposable Correctly, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1064, Title: Exceptions should be public, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} @@ -298,6 +298,14 @@ - {Id: CA5403, Title: Do not hard-code certificate, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} +- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/src/tools/PerfDiff/SquiggleCop.Baseline.yaml b/src/tools/PerfDiff/SquiggleCop.Baseline.yaml index 7c8bb4a9..c4b8bf34 100644 --- a/src/tools/PerfDiff/SquiggleCop.Baseline.yaml +++ b/src/tools/PerfDiff/SquiggleCop.Baseline.yaml @@ -35,7 +35,7 @@ - {Id: CA1056, Title: URI-like properties should not be strings, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1058, Title: Types should not extend certain base types, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1060, Title: Move pinvokes to native methods class, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: CA1062, Title: Validate arguments of public methods, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1063, Title: Implement IDisposable Correctly, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1064, Title: Exceptions should be public, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} @@ -298,6 +298,14 @@ - {Id: CA5403, Title: Do not hard-code certificate, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} +- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml b/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml index b3720207..6d9f316f 100644 --- a/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml +++ b/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml @@ -35,7 +35,7 @@ - {Id: CA1056, Title: URI-like properties should not be strings, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1058, Title: Types should not extend certain base types, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1060, Title: Move pinvokes to native methods class, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: CA1062, Title: Validate arguments of public methods, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1063, Title: Implement IDisposable Correctly, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1064, Title: Exceptions should be public, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} @@ -300,6 +300,14 @@ - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CS1591, Title: Missing XML comment for publicly visible type or member, Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: false} - {Id: CS8762, Title: Parameter must have a non-null value when exiting in some condition., Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: true} +- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml b/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml index d4e3cd55..a3401ebc 100644 --- a/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml +++ b/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml @@ -35,7 +35,7 @@ - {Id: CA1056, Title: URI-like properties should not be strings, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1058, Title: Types should not extend certain base types, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1060, Title: Move pinvokes to native methods class, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: CA1061, Title: Do not hide base class methods, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: CA1062, Title: Validate arguments of public methods, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1063, Title: Implement IDisposable Correctly, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA1064, Title: Exceptions should be public, Category: Design, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} @@ -299,6 +299,14 @@ - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CS1591, Title: Missing XML comment for publicly visible type or member, Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: true} +- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} From 173b2f8cb1c418b17831c8ceda7521f05ec9d7c3 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Sun, 18 Aug 2024 14:09:11 -0700 Subject: [PATCH 2/9] Update Effective C# Analyzers --- build/targets/codeanalysis/Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/targets/codeanalysis/Packages.props b/build/targets/codeanalysis/Packages.props index 5169dbdf..b3b909c4 100644 --- a/build/targets/codeanalysis/Packages.props +++ b/build/targets/codeanalysis/Packages.props @@ -8,6 +8,6 @@ - + From 7f203bf3c3842e647a3dc312fd018f41264051b3 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Sun, 18 Aug 2024 14:18:48 -0700 Subject: [PATCH 3/9] Update SquiggleCop baseline --- src/Moq.Analyzers/SquiggleCop.Baseline.yaml | 16 ++++++++-------- src/tools/PerfDiff/SquiggleCop.Baseline.yaml | 16 ++++++++-------- .../SquiggleCop.Baseline.yaml | 16 ++++++++-------- .../Moq.Analyzers.Test/SquiggleCop.Baseline.yaml | 16 ++++++++-------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml index 99cd3ef3..b1cf4d7c 100644 --- a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml +++ b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml @@ -298,14 +298,14 @@ - {Id: CA5403, Title: Do not hard-code certificate, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/src/tools/PerfDiff/SquiggleCop.Baseline.yaml b/src/tools/PerfDiff/SquiggleCop.Baseline.yaml index c4b8bf34..90cd8b02 100644 --- a/src/tools/PerfDiff/SquiggleCop.Baseline.yaml +++ b/src/tools/PerfDiff/SquiggleCop.Baseline.yaml @@ -298,14 +298,14 @@ - {Id: CA5403, Title: Do not hard-code certificate, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml b/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml index 6d9f316f..525b4195 100644 --- a/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml +++ b/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml @@ -300,14 +300,14 @@ - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CS1591, Title: Missing XML comment for publicly visible type or member, Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: false} - {Id: CS8762, Title: Parameter must have a non-null value when exiting in some condition., Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: true} -- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml b/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml index a3401ebc..e5ecaf3f 100644 --- a/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml +++ b/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml @@ -299,14 +299,14 @@ - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CS1591, Title: Missing XML comment for publicly visible type or member, Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: true} -- {Id: ECS0001, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0002, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0004, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0005, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0006, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0007, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0008, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0009, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} From dc8369f141c791b8d651de5804a395b169c89171 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Sun, 18 Aug 2024 14:28:02 -0700 Subject: [PATCH 4/9] Update .globalconfig to set effective C# analyzer to warning --- build/targets/codeanalysis/.globalconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/build/targets/codeanalysis/.globalconfig b/build/targets/codeanalysis/.globalconfig index 0b6e8efa..2106bae7 100644 --- a/build/targets/codeanalysis/.globalconfig +++ b/build/targets/codeanalysis/.globalconfig @@ -7,3 +7,24 @@ is_global=true # AV2210 : Pass -warnaserror to the compiler or add True to your project file # This is set as part of the CI build. It is intentionally not set locally to allow for a fast inner dev loop. dotnet_diagnostic.AV2210.severity = none + +# Enable Effective C# Analyzers +dotnet_diagnostic.ECS0100.severity = warning +dotnet_diagnostic.ECS0200.severity = warning +dotnet_diagnostic.ECS0300.severity = warning +dotnet_diagnostic.ECS0400.severity = warning +dotnet_diagnostic.ECS0500.severity = warning +dotnet_diagnostic.ECS0600.severity = warning +dotnet_diagnostic.ECS0700.severity = warning +dotnet_diagnostic.ECS0800.severity = warning +dotnet_diagnostic.ECS0900.severity = warning +dotnet_diagnostic.ECS1000.severity = warning +dotnet_diagnostic.ECS1100.severity = warning +dotnet_diagnostic.ECS1200.severity = warning +dotnet_diagnostic.ECS1300.severity = warning +dotnet_diagnostic.ECS1400.severity = warning +dotnet_diagnostic.ECS1500.severity = warning +dotnet_diagnostic.ECS1600.severity = warning +dotnet_diagnostic.ECS1700.severity = warning +dotnet_diagnostic.ECS1800.severity = warning +dotnet_diagnostic.ECS1900.severity = warning From cf7d89acf74b8bde8fa266e5129b0426da2d4f3b Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Sun, 18 Aug 2024 15:03:22 -0700 Subject: [PATCH 5/9] Fix code analysis warnings --- .../AsShouldBeUsedOnlyForInterfaceAnalyzer.cs | 8 +++++-- ...ignatureShouldMatchMockedMethodAnalyzer.cs | 14 ++++------- ...SignatureShouldMatchMockedMethodCodeFix.cs | 12 +++------- .../Common/DiagnosticCategory.cs | 2 ++ .../Common/DiagnosticExtensions.cs | 8 +++---- src/Moq.Analyzers/Common/DiagnosticIds.cs | 2 ++ .../Common/MoqMethodDescriptorBase.cs | 24 +++++-------------- .../Common/WellKnownTypeNames.cs | 14 ++++++----- ...ConstructorArgumentsShouldMatchAnalyzer.cs | 20 +++++++++------- src/Moq.Analyzers/MoqSetupMethodDescriptor.cs | 2 +- .../NoMethodsInPropertySetupAnalyzer.cs | 9 ++++--- .../NoSealedClassMocksAnalyzer.cs | 9 ++++--- ...BeUsedOnlyForOverridableMembersAnalyzer.cs | 9 ++++--- ...etupShouldNotIncludeAsyncResultAnalyzer.cs | 9 ++++--- tests/Moq.Analyzers.Benchmarks/Constants.cs | 2 ++ .../Helpers/CompilationCreator.cs | 4 ++++ .../Helpers/ExportProviderExtensions.cs | 2 ++ tests/Moq.Analyzers.Test/CompositeAnalyzer.cs | 2 ++ 18 files changed, 75 insertions(+), 77 deletions(-) diff --git a/src/Moq.Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs b/src/Moq.Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs index 370d86b5..094ffb4e 100644 --- a/src/Moq.Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs +++ b/src/Moq.Analyzers/AsShouldBeUsedOnlyForInterfaceAnalyzer.cs @@ -8,8 +8,8 @@ namespace Moq.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class AsShouldBeUsedOnlyForInterfaceAnalyzer : DiagnosticAnalyzer { - private const string Title = "Moq: Invalid As type parameter"; - private const string Message = "Mock.As() should take interfaces only"; + private static readonly LocalizableString Title = "Moq: Invalid As type parameter"; + private static readonly LocalizableString Message = "Mock.As() should take interfaces only"; private static readonly DiagnosticDescriptor Rule = new( DiagnosticIds.AsShouldOnlyBeUsedForInterfacesRuleId, @@ -42,11 +42,13 @@ private void RegisterCompilationStartAction(CompilationStartAnalysisContext cont } // Look for the Mock.As() method and provide it to Analyze to avoid looking it up multiple times. +#pragma warning disable ECS0900 // Minimize boxing and unboxing ImmutableArray asMethods = mockTypes .SelectMany(mockType => mockType.GetMembers(WellKnownTypeNames.As)) .OfType() .Where(method => method.IsGenericMethod) .ToImmutableArray(); +#pragma warning restore ECS0900 // Minimize boxing and unboxing if (asMethods.IsEmpty) { @@ -66,10 +68,12 @@ private void Analyze(OperationAnalysisContext context, ImmutableArray typeArguments = targetMethod.TypeArguments; if (typeArguments.Length != 1) diff --git a/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs b/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs index 90a4d0e0..ead2b873 100644 --- a/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs +++ b/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodAnalyzer.cs @@ -6,24 +6,20 @@ namespace Moq.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class CallbackSignatureShouldMatchMockedMethodAnalyzer : DiagnosticAnalyzer { - internal const string RuleId = DiagnosticIds.BadCallbackParameters; - private const string Title = "Moq: Bad callback parameters"; - private const string Message = "Callback signature must match the signature of the mocked method"; + private static readonly LocalizableString Title = "Moq: Bad callback parameters"; + private static readonly LocalizableString Message = "Callback signature must match the signature of the mocked method"; private static readonly DiagnosticDescriptor Rule = new( - RuleId, + DiagnosticIds.BadCallbackParameters, Title, Message, DiagnosticCategory.Moq, DiagnosticSeverity.Warning, isEnabledByDefault: true, - helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{RuleId}.md"); + helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{DiagnosticIds.BadCallbackParameters}.md"); /// - public override ImmutableArray SupportedDiagnostics - { - get { return ImmutableArray.Create(Rule); } - } + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); /// public override void Initialize(AnalysisContext context) diff --git a/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodCodeFix.cs b/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodCodeFix.cs index 70a6eed7..7afedde0 100644 --- a/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodCodeFix.cs +++ b/src/Moq.Analyzers/CallbackSignatureShouldMatchMockedMethodCodeFix.cs @@ -14,16 +14,10 @@ namespace Moq.Analyzers; public class CallbackSignatureShouldMatchMockedMethodCodeFix : CodeFixProvider { /// - public sealed override ImmutableArray FixableDiagnosticIds - { - get { return ImmutableArray.Create(CallbackSignatureShouldMatchMockedMethodAnalyzer.RuleId); } - } + public sealed override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticIds.BadCallbackParameters); /// - public sealed override FixAllProvider GetFixAllProvider() - { - return WellKnownFixAllProviders.BatchFixer; - } + public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; /// public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) @@ -55,7 +49,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) } [System.Diagnostics.CodeAnalysis.SuppressMessage("Maintainability", "AV1500:Member or local function contains too many statements", Justification = "Tracked in https://github.com/rjmurillo/moq.analyzers/issues/90")] - private async Task FixCallbackSignatureAsync(SyntaxNode root, Document document, ParameterListSyntax? oldParameters, CancellationToken cancellationToken) + private static async Task FixCallbackSignatureAsync(SyntaxNode root, Document document, ParameterListSyntax? oldParameters, CancellationToken cancellationToken) { SemanticModel? semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); diff --git a/src/Moq.Analyzers/Common/DiagnosticCategory.cs b/src/Moq.Analyzers/Common/DiagnosticCategory.cs index 34f922e0..9907bdc1 100644 --- a/src/Moq.Analyzers/Common/DiagnosticCategory.cs +++ b/src/Moq.Analyzers/Common/DiagnosticCategory.cs @@ -1,5 +1,7 @@ namespace Moq.Analyzers.Common; +#pragma warning disable ECS0200 // Consider using readonly instead of const for flexibility + internal static class DiagnosticCategory { internal const string Moq = nameof(Moq); diff --git a/src/Moq.Analyzers/Common/DiagnosticExtensions.cs b/src/Moq.Analyzers/Common/DiagnosticExtensions.cs index 596d9a8e..562ac267 100644 --- a/src/Moq.Analyzers/Common/DiagnosticExtensions.cs +++ b/src/Moq.Analyzers/Common/DiagnosticExtensions.cs @@ -13,12 +13,12 @@ public static Diagnostic CreateDiagnostic( DiagnosticDescriptor rule, ImmutableDictionary? properties, params object?[]? messageArgs) - => node.CreateDiagnostic(rule, additionalLocations: ImmutableArray.Empty, properties, messageArgs); + => node.CreateDiagnostic(rule, additionalLocations: Array.Empty(), properties, messageArgs); public static Diagnostic CreateDiagnostic( this SyntaxNode node, DiagnosticDescriptor rule, - ImmutableArray additionalLocations, + IEnumerable? additionalLocations, ImmutableDictionary? properties, params object?[]? messageArgs) => node @@ -44,12 +44,12 @@ public static Diagnostic CreateDiagnostic( DiagnosticDescriptor rule, ImmutableDictionary? properties, params object?[]? messageArgs) - => location.CreateDiagnostic(rule, ImmutableArray.Empty, properties, messageArgs); + => location.CreateDiagnostic(rule, Array.Empty(), properties, messageArgs); public static Diagnostic CreateDiagnostic( this Location location, DiagnosticDescriptor rule, - ImmutableArray additionalLocations, + IEnumerable? additionalLocations, ImmutableDictionary? properties, params object?[]? messageArgs) { diff --git a/src/Moq.Analyzers/Common/DiagnosticIds.cs b/src/Moq.Analyzers/Common/DiagnosticIds.cs index 9807c038..8e143e18 100644 --- a/src/Moq.Analyzers/Common/DiagnosticIds.cs +++ b/src/Moq.Analyzers/Common/DiagnosticIds.cs @@ -1,5 +1,7 @@ namespace Moq.Analyzers.Common; +#pragma warning disable ECS0200 // Consider using readonly instead of const for flexibility + internal static class DiagnosticIds { internal const string SealedClassCannotBeMocked = "Moq1000"; diff --git a/src/Moq.Analyzers/Common/MoqMethodDescriptorBase.cs b/src/Moq.Analyzers/Common/MoqMethodDescriptorBase.cs index 7111ad57..26392264 100644 --- a/src/Moq.Analyzers/Common/MoqMethodDescriptorBase.cs +++ b/src/Moq.Analyzers/Common/MoqMethodDescriptorBase.cs @@ -11,28 +11,16 @@ /// internal abstract class MoqMethodDescriptorBase { - private const string ContainingNamespace = WellKnownTypeNames.Moq; - private const string ContainingType = WellKnownTypeNames.MockName; + private static readonly string ContainingNamespace = WellKnownTypeNames.Moq; + private static readonly string ContainingType = WellKnownTypeNames.MockName; public abstract bool IsMatch(SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccessSyntax, CancellationToken cancellationToken); - protected static bool IsFastMatch(MemberAccessExpressionSyntax memberAccessSyntax, ReadOnlySpan methodName) - { - return memberAccessSyntax.Name.Identifier.Text.AsSpan().SequenceEqual(methodName); - } + protected static bool IsFastMatch(MemberAccessExpressionSyntax memberAccessSyntax, ReadOnlySpan methodName) => memberAccessSyntax.Name.Identifier.Text.AsSpan().SequenceEqual(methodName); - protected static bool IsContainedInMockType(IMethodSymbol methodSymbol) - { - return IsInMoqNamespace(methodSymbol) && IsInMockType(methodSymbol); - } + protected static bool IsContainedInMockType(IMethodSymbol methodSymbol) => IsInMoqNamespace(methodSymbol) && IsInMockType(methodSymbol); - private static bool IsInMoqNamespace(ISymbol symbol) - { - return symbol.ContainingNamespace.Name.AsSpan().SequenceEqual(ContainingNamespace.AsSpan()); - } + private static bool IsInMoqNamespace(ISymbol symbol) => symbol.ContainingNamespace.Name.AsSpan().SequenceEqual(ContainingNamespace.AsSpan()); - private static bool IsInMockType(ISymbol symbol) - { - return symbol.ContainingType.Name.AsSpan().SequenceEqual(ContainingType.AsSpan()); - } + private static bool IsInMockType(ISymbol symbol) => symbol.ContainingType.Name.AsSpan().SequenceEqual(ContainingType.AsSpan()); } diff --git a/src/Moq.Analyzers/Common/WellKnownTypeNames.cs b/src/Moq.Analyzers/Common/WellKnownTypeNames.cs index 4ebeeb8f..e47bc65d 100644 --- a/src/Moq.Analyzers/Common/WellKnownTypeNames.cs +++ b/src/Moq.Analyzers/Common/WellKnownTypeNames.cs @@ -1,16 +1,18 @@ namespace Moq.Analyzers.Common; +#pragma warning disable ECS0200 // Consider using readonly instead of const for flexibility + internal static class WellKnownTypeNames { - internal const string Moq = "Moq"; + internal const string Moq = nameof(Moq); internal const string MockName = "Mock"; - internal const string MockBehavior = "MockBehavior"; - internal const string MockFactory = "MockFactory"; + internal const string MockBehavior = nameof(MockBehavior); + internal const string MockFactory = nameof(MockFactory); internal const string MoqMock = $"{Moq}.{MockName}"; internal const string MoqMock1 = $"{MoqMock}`1"; internal const string MoqBehavior = $"{Moq}.{MockBehavior}"; internal const string MoqRepository = $"{Moq}.MockRepository"; - internal const string As = "As"; - internal const string Create = "Create"; - internal const string Of = "Of"; + internal const string As = nameof(As); + internal const string Create = nameof(Create); + internal const string Of = nameof(Of); } diff --git a/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs b/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs index f2a1e51c..2347a967 100644 --- a/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs +++ b/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs @@ -132,7 +132,7 @@ private static bool IsFirstArgumentMockBehavior(SyntaxNodeAnalysisContext contex private static void VerifyDelegateMockAttempt( SyntaxNodeAnalysisContext context, ArgumentListSyntax? argumentList, - ImmutableArray arguments) + ArgumentSyntax[] arguments) { if (arguments.Length == 0) { @@ -149,7 +149,7 @@ private static void VerifyDelegateMockAttempt( private static void VerifyInterfaceMockAttempt( SyntaxNodeAnalysisContext context, ArgumentListSyntax? argumentList, - ImmutableArray arguments) + ArgumentSyntax[] arguments) { // Interfaces and delegates don't have ctors, so bail out early if (arguments.Length == 0) @@ -323,7 +323,7 @@ private void AnalyzeNewObject(SyntaxNodeAnalysisContext context) [SuppressMessage("Design", "MA0051:Method is too long", Justification = "This should be refactored; suppressing for now to enable TreatWarningsAsErrors in CI.")] private bool AnyConstructorsFound( ImmutableArray constructors, - ImmutableArray arguments, + ArgumentSyntax[] arguments, SyntaxNodeAnalysisContext context) { for (int constructorIndex = 0; constructorIndex < constructors.Length; constructorIndex++) @@ -331,7 +331,9 @@ private bool AnyConstructorsFound( IMethodSymbol constructor = constructors[constructorIndex]; bool hasParams = constructor.Parameters.Length > 0 && constructor.Parameters[^1].IsParams; int fixedParametersCount = hasParams ? constructor.Parameters.Length - 1 : constructor.Parameters.Length; +#pragma warning disable ECS0900 // Minimize boxing and unboxing int requiredParameters = constructor.Parameters.Count(parameterSymbol => !parameterSymbol.IsOptional); +#pragma warning restore ECS0900 // Minimize boxing and unboxing bool allParametersMatch = true; // Check if the number of arguments is valid considering params @@ -430,14 +432,16 @@ private void VerifyMockAttempt( return; } - ImmutableArray arguments = - argumentList?.Arguments.ToImmutableArray() - ?? ImmutableArray.Empty; +#pragma warning disable ECS0900 // Minimize boxing and unboxing + ArgumentSyntax[] arguments = + argumentList?.Arguments.ToArray() + ?? []; +#pragma warning restore ECS0900 // Minimize boxing and unboxing if (hasMockBehavior && arguments.Length > 0 && IsFirstArgumentMockBehavior(context, argumentList)) { // They passed a mock behavior as the first argument; ignore as Moq swallows it - arguments = arguments.RemoveAt(0); + arguments = arguments.Skip(1).ToArray(); } switch (mockedClass.TypeKind) @@ -463,7 +467,7 @@ private void VerifyClassMockAttempt( SyntaxNodeAnalysisContext context, ITypeSymbol mockedClass, ArgumentListSyntax? argumentList, - ImmutableArray arguments) + ArgumentSyntax[] arguments) { ImmutableArray constructors = mockedClass .GetMembers() diff --git a/src/Moq.Analyzers/MoqSetupMethodDescriptor.cs b/src/Moq.Analyzers/MoqSetupMethodDescriptor.cs index 9ca4f1ad..ee81d8dc 100644 --- a/src/Moq.Analyzers/MoqSetupMethodDescriptor.cs +++ b/src/Moq.Analyzers/MoqSetupMethodDescriptor.cs @@ -6,7 +6,7 @@ /// internal class MoqSetupMethodDescriptor : MoqMethodDescriptorBase { - private const string MethodName = "Setup"; + private static readonly string MethodName = "Setup"; [System.Diagnostics.CodeAnalysis.SuppressMessage("Maintainability", "AV1500:Member or local function contains too many statements", Justification = "Tracked in https://github.com/rjmurillo/moq.analyzers/issues/90")] public override bool IsMatch(SemanticModel semanticModel, MemberAccessExpressionSyntax memberAccessSyntax, CancellationToken cancellationToken) diff --git a/src/Moq.Analyzers/NoMethodsInPropertySetupAnalyzer.cs b/src/Moq.Analyzers/NoMethodsInPropertySetupAnalyzer.cs index c5d8cfbf..c5545803 100644 --- a/src/Moq.Analyzers/NoMethodsInPropertySetupAnalyzer.cs +++ b/src/Moq.Analyzers/NoMethodsInPropertySetupAnalyzer.cs @@ -6,18 +6,17 @@ namespace Moq.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class NoMethodsInPropertySetupAnalyzer : DiagnosticAnalyzer { - internal const string RuleId = DiagnosticIds.PropertySetupUsedForMethod; - private const string Title = "Moq: Property setup used for a method"; - private const string Message = "SetupGet/SetupSet should be used for properties, not for methods"; + private static readonly LocalizableString Title = "Moq: Property setup used for a method"; + private static readonly LocalizableString Message = "SetupGet/SetupSet should be used for properties, not for methods"; private static readonly DiagnosticDescriptor Rule = new( - RuleId, + DiagnosticIds.PropertySetupUsedForMethod, Title, Message, DiagnosticCategory.Moq, DiagnosticSeverity.Warning, isEnabledByDefault: true, - helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{RuleId}.md"); + helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{DiagnosticIds.PropertySetupUsedForMethod}.md"); /// public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); diff --git a/src/Moq.Analyzers/NoSealedClassMocksAnalyzer.cs b/src/Moq.Analyzers/NoSealedClassMocksAnalyzer.cs index b44d616e..63642004 100644 --- a/src/Moq.Analyzers/NoSealedClassMocksAnalyzer.cs +++ b/src/Moq.Analyzers/NoSealedClassMocksAnalyzer.cs @@ -6,18 +6,17 @@ namespace Moq.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class NoSealedClassMocksAnalyzer : DiagnosticAnalyzer { - internal const string RuleId = DiagnosticIds.SealedClassCannotBeMocked; - private const string Title = "Moq: Sealed class mocked"; - private const string Message = "Sealed classes cannot be mocked"; + private static readonly LocalizableString Title = "Moq: Sealed class mocked"; + private static readonly LocalizableString Message = "Sealed classes cannot be mocked"; private static readonly DiagnosticDescriptor Rule = new( - RuleId, + DiagnosticIds.SealedClassCannotBeMocked, Title, Message, DiagnosticCategory.Moq, DiagnosticSeverity.Warning, isEnabledByDefault: true, - helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{RuleId}.md"); + helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{DiagnosticIds.SealedClassCannotBeMocked}.md"); /// public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); diff --git a/src/Moq.Analyzers/SetupShouldBeUsedOnlyForOverridableMembersAnalyzer.cs b/src/Moq.Analyzers/SetupShouldBeUsedOnlyForOverridableMembersAnalyzer.cs index 6d851eda..9e058440 100644 --- a/src/Moq.Analyzers/SetupShouldBeUsedOnlyForOverridableMembersAnalyzer.cs +++ b/src/Moq.Analyzers/SetupShouldBeUsedOnlyForOverridableMembersAnalyzer.cs @@ -6,18 +6,17 @@ namespace Moq.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public class SetupShouldBeUsedOnlyForOverridableMembersAnalyzer : DiagnosticAnalyzer { - internal const string RuleId = DiagnosticIds.SetupOnlyUsedForOverridableMembers; - private const string Title = "Moq: Invalid setup parameter"; - private const string Message = "Setup should be used only for overridable members"; + private static readonly LocalizableString Title = "Moq: Invalid setup parameter"; + private static readonly LocalizableString Message = "Setup should be used only for overridable members"; private static readonly DiagnosticDescriptor Rule = new( - RuleId, + DiagnosticIds.SetupOnlyUsedForOverridableMembers, Title, Message, DiagnosticCategory.Moq, DiagnosticSeverity.Error, isEnabledByDefault: true, - helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{RuleId}.md"); + helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{DiagnosticIds.SetupOnlyUsedForOverridableMembers}.md"); /// public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); diff --git a/src/Moq.Analyzers/SetupShouldNotIncludeAsyncResultAnalyzer.cs b/src/Moq.Analyzers/SetupShouldNotIncludeAsyncResultAnalyzer.cs index 642bf63d..8489fabd 100644 --- a/src/Moq.Analyzers/SetupShouldNotIncludeAsyncResultAnalyzer.cs +++ b/src/Moq.Analyzers/SetupShouldNotIncludeAsyncResultAnalyzer.cs @@ -6,18 +6,17 @@ [DiagnosticAnalyzer(LanguageNames.CSharp)] public class SetupShouldNotIncludeAsyncResultAnalyzer : DiagnosticAnalyzer { - internal const string RuleId = DiagnosticIds.AsyncUsesReturnsAsyncInsteadOfResult; - private const string Title = "Moq: Invalid setup parameter"; - private const string Message = "Setup of async methods should use ReturnsAsync instead of .Result"; + private static readonly LocalizableString Title = "Moq: Invalid setup parameter"; + private static readonly LocalizableString Message = "Setup of async methods should use ReturnsAsync instead of .Result"; private static readonly DiagnosticDescriptor Rule = new( - RuleId, + DiagnosticIds.AsyncUsesReturnsAsyncInsteadOfResult, Title, Message, DiagnosticCategory.Moq, DiagnosticSeverity.Error, isEnabledByDefault: true, - helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{RuleId}.md"); + helpLinkUri: $"https://github.com/rjmurillo/moq.analyzers/blob/{ThisAssembly.GitCommitId}/docs/rules/{DiagnosticIds.AsyncUsesReturnsAsyncInsteadOfResult}.md"); /// public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); diff --git a/tests/Moq.Analyzers.Benchmarks/Constants.cs b/tests/Moq.Analyzers.Benchmarks/Constants.cs index 338f9f04..6070a45d 100644 --- a/tests/Moq.Analyzers.Benchmarks/Constants.cs +++ b/tests/Moq.Analyzers.Benchmarks/Constants.cs @@ -1,5 +1,7 @@ namespace Moq.Analyzers.Benchmarks; +#pragma warning disable ECS0200 // Consider using readonly instead of const for flexibility + internal static class Constants { public const int NumberOfCodeFiles = 1_000; diff --git a/tests/Moq.Analyzers.Benchmarks/Helpers/CompilationCreator.cs b/tests/Moq.Analyzers.Benchmarks/Helpers/CompilationCreator.cs index d3c73a03..3840df2f 100644 --- a/tests/Moq.Analyzers.Benchmarks/Helpers/CompilationCreator.cs +++ b/tests/Moq.Analyzers.Benchmarks/Helpers/CompilationCreator.cs @@ -100,7 +100,9 @@ private static async Task CreateSolutionAsync( async () => { AttributedPartDiscovery discovery = new(Resolver.DefaultInstance, isNonPublicSupported: true); +#pragma warning disable ECS0900 // Minimize boxing and unboxing DiscoveredParts parts = await discovery.CreatePartsAsync(MefHostServices.DefaultAssemblies).ConfigureAwait(false); +#pragma warning restore ECS0900 // Minimize boxing and unboxing ComposableCatalog catalog = ComposableCatalog.Create(Resolver.DefaultInstance).AddParts(parts); CompositionConfiguration configuration = CompositionConfiguration.Create(catalog); @@ -119,7 +121,9 @@ private static async Task CreateSolutionAsync( .WithProjectParseOptions(projectId, parseOptions); ImmutableArray metadataReferences = await referenceAssemblies.ResolveAsync(projectState.Language, CancellationToken.None).ConfigureAwait(false); +#pragma warning disable ECS0900 // Minimize boxing and unboxing solution = solution.AddMetadataReferences(projectId, metadataReferences); +#pragma warning restore ECS0900 // Minimize boxing and unboxing return solution; } diff --git a/tests/Moq.Analyzers.Benchmarks/Helpers/ExportProviderExtensions.cs b/tests/Moq.Analyzers.Benchmarks/Helpers/ExportProviderExtensions.cs index 57323710..216721de 100644 --- a/tests/Moq.Analyzers.Benchmarks/Helpers/ExportProviderExtensions.cs +++ b/tests/Moq.Analyzers.Benchmarks/Helpers/ExportProviderExtensions.cs @@ -27,7 +27,9 @@ public CompositionContextShim(ExportProvider exportProvider) [SuppressMessage("Maintainability", "AV1500:Member or local function contains too many statements", Justification = "Minimizing divergence from upstream")] public override bool TryGetExport(CompositionContract contract, [NotNullWhen(true)] out object? export) { +#pragma warning disable ECS0900 // Minimize boxing and unboxing bool importMany = contract.MetadataConstraints.Contains(new KeyValuePair("IsImportMany", true)); +#pragma warning restore ECS0900 // Minimize boxing and unboxing (Type contractType, Type? metadataType) = GetContractType(contract.ContractType, importMany); if (metadataType != null) diff --git a/tests/Moq.Analyzers.Test/CompositeAnalyzer.cs b/tests/Moq.Analyzers.Test/CompositeAnalyzer.cs index 56998a73..bed6ddf1 100644 --- a/tests/Moq.Analyzers.Test/CompositeAnalyzer.cs +++ b/tests/Moq.Analyzers.Test/CompositeAnalyzer.cs @@ -17,7 +17,9 @@ public class CompositeAnalyzer : DiagnosticAnalyzer public CompositeAnalyzer() { _analyzers = [.. DiagnosticAnalyzers()]; +#pragma warning disable ECS0900 // Consider using an alternative implementation to avoid boxing and unboxing _supportedDiagnostics = [.. _analyzers.SelectMany(diagnosticAnalyzer => diagnosticAnalyzer.SupportedDiagnostics)]; +#pragma warning restore ECS0900 } /// From 2937b48557cd257a3c6eb830c5eafda98e758ad0 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Sun, 18 Aug 2024 15:06:12 -0700 Subject: [PATCH 6/9] Update SquiggleCop baseline --- src/Moq.Analyzers/SquiggleCop.Baseline.yaml | 16 ++++++++-------- .../SquiggleCop.Baseline.yaml | 16 ++++++++-------- .../Moq.Analyzers.Test/SquiggleCop.Baseline.yaml | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml index b1cf4d7c..1a403116 100644 --- a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml +++ b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml @@ -298,14 +298,14 @@ - {Id: CA5403, Title: Do not hard-code certificate, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml b/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml index 525b4195..810427a3 100644 --- a/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml +++ b/tests/Moq.Analyzers.Benchmarks/SquiggleCop.Baseline.yaml @@ -300,14 +300,14 @@ - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CS1591, Title: Missing XML comment for publicly visible type or member, Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: false} - {Id: CS8762, Title: Parameter must have a non-null value when exiting in some condition., Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: true} -- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml b/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml index e5ecaf3f..2fd4fecf 100644 --- a/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml +++ b/tests/Moq.Analyzers.Test/SquiggleCop.Baseline.yaml @@ -299,14 +299,14 @@ - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CS1591, Title: Missing XML comment for publicly visible type or member, Category: Compiler, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Warning], IsEverSuppressed: true} -- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} From 968084a37ea38e2a641f3793676a9bff1cdecee0 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Mon, 19 Aug 2024 09:07:26 -0700 Subject: [PATCH 7/9] Disable ECS analyzers for tools project --- src/tools/PerfDiff/.editorconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/tools/PerfDiff/.editorconfig b/src/tools/PerfDiff/.editorconfig index 7324b7e2..2cf1d833 100644 --- a/src/tools/PerfDiff/.editorconfig +++ b/src/tools/PerfDiff/.editorconfig @@ -112,3 +112,24 @@ dotnet_diagnostic.MA0076.severity = none dotnet_diagnostic.RCS1192.severity = none # S1135: Track uses of "TODO" tags dotnet_diagnostic.S1135.severity = none + +# Enable Effective C# Analyzers +dotnet_diagnostic.ECS0100.severity = none +dotnet_diagnostic.ECS0200.severity = none +dotnet_diagnostic.ECS0300.severity = none +dotnet_diagnostic.ECS0400.severity = none +dotnet_diagnostic.ECS0500.severity = none +dotnet_diagnostic.ECS0600.severity = none +dotnet_diagnostic.ECS0700.severity = none +dotnet_diagnostic.ECS0800.severity = none +dotnet_diagnostic.ECS0900.severity = none +dotnet_diagnostic.ECS1000.severity = none +dotnet_diagnostic.ECS1100.severity = none +dotnet_diagnostic.ECS1200.severity = none +dotnet_diagnostic.ECS1300.severity = none +dotnet_diagnostic.ECS1400.severity = none +dotnet_diagnostic.ECS1500.severity = none +dotnet_diagnostic.ECS1600.severity = none +dotnet_diagnostic.ECS1700.severity = none +dotnet_diagnostic.ECS1800.severity = none +dotnet_diagnostic.ECS1900.severity = none From e18ee476e9e064ff4b4eb03ea2ea3c2fab9a38ea Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Mon, 26 Aug 2024 10:23:50 -0700 Subject: [PATCH 8/9] Update to latest Effective C# analyzers package --- build/targets/codeanalysis/Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/targets/codeanalysis/Packages.props b/build/targets/codeanalysis/Packages.props index c7e567e2..04febe30 100644 --- a/build/targets/codeanalysis/Packages.props +++ b/build/targets/codeanalysis/Packages.props @@ -8,6 +8,6 @@ - + From af7ebf3e1ac9ab7e0bb8f2beb2ad2098dc8582f7 Mon Sep 17 00:00:00 2001 From: Richard Murillo Date: Mon, 26 Aug 2024 10:29:33 -0700 Subject: [PATCH 9/9] Update code for analyzers and squigglecop baseline --- src/Moq.Analyzers/Common/ArrayExtensions.cs | 53 +++++++++++++++++++ ...ConstructorArgumentsShouldMatchAnalyzer.cs | 24 ++++----- src/Moq.Analyzers/SquiggleCop.Baseline.yaml | 2 +- src/tools/PerfDiff/SquiggleCop.Baseline.yaml | 16 +++--- 4 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 src/Moq.Analyzers/Common/ArrayExtensions.cs diff --git a/src/Moq.Analyzers/Common/ArrayExtensions.cs b/src/Moq.Analyzers/Common/ArrayExtensions.cs new file mode 100644 index 00000000..eb19cfa0 --- /dev/null +++ b/src/Moq.Analyzers/Common/ArrayExtensions.cs @@ -0,0 +1,53 @@ +using ArgumentOutOfRangeException = System.ArgumentOutOfRangeException; + +namespace Moq.Analyzers.Common; + +internal static class ArrayExtensions +{ + /// + /// Returns an array with the element at the specified position removed. + /// + /// The array type. + /// The array. + /// The 0-based index into the array for the element to omit from the returned array. + /// The new array. + internal static T[] RemoveAt(this T[] array, int index) + { + return RemoveRange(array, index, 1); + } + + /// + /// Returns an array with the elements at the specified position removed. + /// + /// The array type. + /// The array. + /// The 0-based index into the array for the element to omit from the returned array. + /// The number of elements to remove. + /// The new array. + private static T[] RemoveRange(this T[] array, int index, int length) + { + // Range check + if (index < 0 || index >= array.Length) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + if (length < 0 || index + length > array.Length) + { + throw new ArgumentOutOfRangeException(nameof(length)); + } + +#pragma warning disable S2583 // Change condition so it doesn't always evaluate to false + if (array.Length == 0) +#pragma warning restore S2583 + { + return array; + } + + T[] tmp = new T[array.Length - length]; + Array.Copy(array, tmp, index); + Array.Copy(array, index + length, tmp, index, array.Length - index - length); + + return tmp; + } +} diff --git a/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs b/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs index 3b4384b6..5b89efa5 100644 --- a/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs +++ b/src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs @@ -322,7 +322,7 @@ private static void AnalyzeNewObject(SyntaxNodeAnalysisContext context) /// Handles and optional parameters. [SuppressMessage("Design", "MA0051:Method is too long", Justification = "This should be refactored; suppressing for now to enable TreatWarningsAsErrors in CI.")] private static bool AnyConstructorsFound( - ImmutableArray constructors, + IMethodSymbol[] constructors, ArgumentSyntax[] arguments, SyntaxNodeAnalysisContext context) { @@ -331,9 +331,9 @@ private static bool AnyConstructorsFound( IMethodSymbol constructor = constructors[constructorIndex]; bool hasParams = constructor.Parameters.Length > 0 && constructor.Parameters[^1].IsParams; int fixedParametersCount = hasParams ? constructor.Parameters.Length - 1 : constructor.Parameters.Length; -#pragma warning disable ECS0900 // Minimize boxing and unboxing +#pragma warning disable ECS0900 // Consider using an alternative implementation to avoid boxing and unboxing int requiredParameters = constructor.Parameters.Count(parameterSymbol => !parameterSymbol.IsOptional); -#pragma warning restore ECS0900 // Minimize boxing and unboxing +#pragma warning restore ECS0900 // Consider using an alternative implementation to avoid boxing and unboxing bool allParametersMatch = true; // Check if the number of arguments is valid considering params @@ -403,7 +403,7 @@ private static bool AnyConstructorsFound( } private static (bool IsEmpty, Location Location) ConstructorIsEmpty( - ImmutableArray constructors, + IMethodSymbol[] constructors, ArgumentListSyntax? argumentList, SyntaxNodeAnalysisContext context) { @@ -418,7 +418,7 @@ private static (bool IsEmpty, Location Location) ConstructorIsEmpty( location = context.Node.GetLocation(); } - return (constructors.IsEmpty, location); + return (constructors.Length == 0, location); } private static void VerifyMockAttempt( @@ -432,16 +432,14 @@ private static void VerifyMockAttempt( return; } -#pragma warning disable ECS0900 // Minimize boxing and unboxing - ArgumentSyntax[] arguments = - argumentList?.Arguments.ToArray() - ?? []; -#pragma warning restore ECS0900 // Minimize boxing and unboxing +#pragma warning disable ECS0900 // Consider using an alternative implementation to avoid boxing and unboxing + ArgumentSyntax[] arguments = argumentList?.Arguments.ToArray() ?? []; +#pragma warning restore ECS0900 // Consider using an alternative implementation to avoid boxing and unboxing if (hasMockBehavior && arguments.Length > 0 && IsFirstArgumentMockBehavior(context, argumentList)) { // They passed a mock behavior as the first argument; ignore as Moq swallows it - arguments = arguments.Skip(1).ToArray(); + arguments = arguments.RemoveAt(0); } switch (mockedClass.TypeKind) @@ -469,11 +467,11 @@ private static void VerifyClassMockAttempt( ArgumentListSyntax? argumentList, ArgumentSyntax[] arguments) { - ImmutableArray constructors = mockedClass + IMethodSymbol[] constructors = mockedClass .GetMembers() .OfType() .Where(methodSymbol => methodSymbol.IsConstructor()) - .ToImmutableArray(); + .ToArray(); // Bail out early if there are no arguments on constructors or no constructors at all (bool IsEmpty, Location Location) constructorIsEmpty = ConstructorIsEmpty(constructors, argumentList, context); diff --git a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml index 8b15aa04..39400c30 100644 --- a/src/Moq.Analyzers/SquiggleCop.Baseline.yaml +++ b/src/Moq.Analyzers/SquiggleCop.Baseline.yaml @@ -1030,7 +1030,7 @@ - {Id: S2479, Title: Whitespace and control characters in string literals should be explicit, Category: Critical Code Smell, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: S2486, Title: Generic exceptions should not be ignored, Category: Minor Code Smell, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: S2551, Title: Shared resources should not be used for locking, Category: Critical Bug, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} -- {Id: S2583, Title: Conditionally executed code should be reachable, Category: Major Bug, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} +- {Id: S2583, Title: Conditionally executed code should be reachable, Category: Major Bug, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} - {Id: S2589, Title: Boolean expressions should not be gratuitous, Category: Major Code Smell, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: true} - {Id: S2612, Title: Setting loose file permissions is security-sensitive, Category: Major Security Hotspot, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: S2629, Title: Logging templates should be constant, Category: Major Code Smell, DefaultSeverity: Warning, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} diff --git a/src/tools/PerfDiff/SquiggleCop.Baseline.yaml b/src/tools/PerfDiff/SquiggleCop.Baseline.yaml index 4c237a5c..8937fe75 100644 --- a/src/tools/PerfDiff/SquiggleCop.Baseline.yaml +++ b/src/tools/PerfDiff/SquiggleCop.Baseline.yaml @@ -298,14 +298,14 @@ - {Id: CA5403, Title: Do not hard-code certificate, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5404, Title: Do not disable token validation checks, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} - {Id: CA5405, Title: Do not always skip token validation in delegates, Category: Security, DefaultSeverity: Warning, IsEnabledByDefault: false, EffectiveSeverities: [None], IsEverSuppressed: true} -- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} -- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Note], IsEverSuppressed: false} +- {Id: ECS0100, Title: Prefer implicitly typed local variables, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0200, Title: Prefer readonly over const, Category: Maintainability, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0400, Title: Replace string.Format with interpolated string, Category: Style, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0500, Title: Prefer FormattableString or string.Create for culture-specific strings, Category: Globalization, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0600, Title: Avoid stringly-typed APIs, Category: Refactoring, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0700, Title: Express callbacks with delegates, Category: Design, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0800, Title: Use the Null Conditional Operator for Event Invocations, Category: Usage, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} +- {Id: ECS0900, Title: Minimize boxing and unboxing, Category: Performance, DefaultSeverity: Note, IsEnabledByDefault: true, EffectiveSeverities: [Error, None], IsEverSuppressed: true} - {Id: EM0001, Title: Switch on Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0002, Title: Switch on Nullable Enum Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false} - {Id: EM0003, Title: Switch on Closed Type Not Exhaustive, Category: Logic, DefaultSeverity: Error, IsEnabledByDefault: true, EffectiveSeverities: [Error], IsEverSuppressed: false}