Skip to content

Commit

Permalink
Update code for analyzers and squigglecop baseline
Browse files Browse the repository at this point in the history
  • Loading branch information
rjmurillo committed Aug 26, 2024
1 parent e18ee47 commit af7ebf3
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 22 deletions.
53 changes: 53 additions & 0 deletions src/Moq.Analyzers/Common/ArrayExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using ArgumentOutOfRangeException = System.ArgumentOutOfRangeException;

Check failure on line 1 in src/Moq.Analyzers/Common/ArrayExtensions.cs

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/Moq.Analyzers/Common/ArrayExtensions.cs#L1

Provide an 'AssemblyVersion' attribute for assembly 'srcassembly.dll'.

namespace Moq.Analyzers.Common;

internal static class ArrayExtensions
{
/// <summary>
/// Returns an array with the element at the specified position removed.
/// </summary>
/// <typeparam name="T">The array type.</typeparam>
/// <param name="array">The array.</param>
/// <param name="index">The 0-based index into the array for the element to omit from the returned array.</param>
/// <returns>The new array.</returns>
internal static T[] RemoveAt<T>(this T[] array, int index)
{
return RemoveRange(array, index, 1);
}

/// <summary>
/// Returns an array with the elements at the specified position removed.
/// </summary>
/// <typeparam name="T">The array type.</typeparam>
/// <param name="array">The array.</param>
/// <param name="index">The 0-based index into the array for the element to omit from the returned array.</param>
/// <param name="length">The number of elements to remove.</param>
/// <returns>The new array.</returns>
private static T[] RemoveRange<T>(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;
}
}
24 changes: 11 additions & 13 deletions src/Moq.Analyzers/ConstructorArgumentsShouldMatchAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ private static void AnalyzeNewObject(SyntaxNodeAnalysisContext context)
/// <remarks>Handles <see langword="params" /> and optional parameters.</remarks>
[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<IMethodSymbol> constructors,
IMethodSymbol[] constructors,
ArgumentSyntax[] arguments,
SyntaxNodeAnalysisContext context)
{
Expand All @@ -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
Expand Down Expand Up @@ -403,7 +403,7 @@ private static bool AnyConstructorsFound(
}

private static (bool IsEmpty, Location Location) ConstructorIsEmpty(
ImmutableArray<IMethodSymbol> constructors,
IMethodSymbol[] constructors,
ArgumentListSyntax? argumentList,
SyntaxNodeAnalysisContext context)
{
Expand All @@ -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(
Expand All @@ -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)
Expand Down Expand Up @@ -469,11 +467,11 @@ private static void VerifyClassMockAttempt(
ArgumentListSyntax? argumentList,
ArgumentSyntax[] arguments)
{
ImmutableArray<IMethodSymbol> constructors = mockedClass
IMethodSymbol[] constructors = mockedClass
.GetMembers()
.OfType<IMethodSymbol>()
.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);
Expand Down
2 changes: 1 addition & 1 deletion src/Moq.Analyzers/SquiggleCop.Baseline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
16 changes: 8 additions & 8 deletions src/tools/PerfDiff/SquiggleCop.Baseline.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down

0 comments on commit af7ebf3

Please sign in to comment.