Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use c# 12 primary constructors #812

Merged
merged 2 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 25 additions & 33 deletions src/NSubstitute/Compatibility/DiagnosticsNullabilityAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,64 +22,56 @@ internal sealed class MaybeNullAttribute : Attribute { }
internal sealed class NotNullAttribute : Attribute { }

/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter may be null even if the corresponding type disallows it.</summary>
/// <remarks>Initializes the attribute with the specified return value condition.</remarks>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter may be null.
/// </param>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class MaybeNullWhenAttribute : Attribute
internal sealed class MaybeNullWhenAttribute(bool returnValue) : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter may be null.
/// </param>
public MaybeNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;

/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
public bool ReturnValue { get; } = returnValue;
}

/// <summary>Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.</summary>
/// <remarks>Initializes the attribute with the specified return value condition.</remarks>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
internal sealed class NotNullWhenAttribute(bool returnValue) : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;

/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
public bool ReturnValue { get; } = returnValue;
}

/// <summary>Specifies that the output will be non-null if the named parameter is non-null.</summary>
/// <remarks>Initializes the attribute with the associated parameter name.</remarks>
/// <param name="parameterName">
/// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.
/// </param>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
internal sealed class NotNullIfNotNullAttribute : Attribute
internal sealed class NotNullIfNotNullAttribute(string parameterName) : Attribute
{
/// <summary>Initializes the attribute with the associated parameter name.</summary>
/// <param name="parameterName">
/// The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.
/// </param>
public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;

/// <summary>Gets the associated parameter name.</summary>
public string ParameterName { get; }
public string ParameterName { get; } = parameterName;
}

/// <summary>Applied to a method that will never return under any circumstance.</summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class DoesNotReturnAttribute : Attribute { }

/// <summary>Specifies that the method will not return if the associated Boolean parameter is passed the specified value.</summary>
/// <remarks>Initializes the attribute with the specified parameter value.</remarks>
/// <param name="parameterValue">
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to
/// the associated parameter matches this value.
/// </param>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class DoesNotReturnIfAttribute : Attribute
internal sealed class DoesNotReturnIfAttribute(bool parameterValue) : Attribute
{
/// <summary>Initializes the attribute with the specified parameter value.</summary>
/// <param name="parameterValue">
/// The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to
/// the associated parameter matches this value.
/// </param>
public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;

/// <summary>Gets the condition parameter value.</summary>
public bool ParameterValue { get; }
public bool ParameterValue { get; } = parameterValue;
}

/// <summary>Specifies that the method or property will ensure that the listed field and property members have not-null values.</summary>
Expand Down
11 changes: 2 additions & 9 deletions src/NSubstitute/Core/ArgumentSpecificationDequeue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@

namespace NSubstitute.Core;

public class ArgumentSpecificationDequeue : IArgumentSpecificationDequeue
public class ArgumentSpecificationDequeue(Func<IList<IArgumentSpecification>> dequeueAllQueuedArgSpecs) : IArgumentSpecificationDequeue
{
private static readonly IArgumentSpecification[] EmptySpecifications = [];

private readonly Func<IList<IArgumentSpecification>> _dequeueAllQueuedArgSpecs;

public ArgumentSpecificationDequeue(Func<IList<IArgumentSpecification>> dequeueAllQueuedArgSpecs)
{
_dequeueAllQueuedArgSpecs = dequeueAllQueuedArgSpecs;
}

public IList<IArgumentSpecification> DequeueAllArgumentSpecificationsForMethod(int parametersCount)
{
if (parametersCount == 0)
Expand All @@ -24,7 +17,7 @@ public IList<IArgumentSpecification> DequeueAllArgumentSpecificationsForMethod(i
return EmptySpecifications;
}

var queuedArgSpecifications = _dequeueAllQueuedArgSpecs.Invoke();
var queuedArgSpecifications = dequeueAllQueuedArgSpecs.Invoke();
return queuedArgSpecifications;
}

Expand Down
13 changes: 3 additions & 10 deletions src/NSubstitute/Core/Arguments/AnyArgumentMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
namespace NSubstitute.Core.Arguments;

public class AnyArgumentMatcher : IArgumentMatcher
public class AnyArgumentMatcher(Type typeArgMustBeCompatibleWith) : IArgumentMatcher
{
private readonly Type _typeArgMustBeCompatibleWith;
public override string ToString() => "any " + typeArgMustBeCompatibleWith.GetNonMangledTypeName();

public AnyArgumentMatcher(Type typeArgMustBeCompatibleWith)
{
_typeArgMustBeCompatibleWith = typeArgMustBeCompatibleWith;
}

public override string ToString() => "any " + _typeArgMustBeCompatibleWith.GetNonMangledTypeName();

public bool IsSatisfiedBy(object? argument) => argument.IsCompatibleWith(_typeArgMustBeCompatibleWith);
public bool IsSatisfiedBy(object? argument) => argument.IsCompatibleWith(typeArgMustBeCompatibleWith);
}
15 changes: 4 additions & 11 deletions src/NSubstitute/Core/Arguments/ArgumentMatchInfo.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
namespace NSubstitute.Core.Arguments;

public class ArgumentMatchInfo
public class ArgumentMatchInfo(int index, object? argument, IArgumentSpecification specification)
{
public ArgumentMatchInfo(int index, object? argument, IArgumentSpecification specification)
{
Index = index;
_argument = argument;
_specification = specification;
}

private readonly object? _argument;
private readonly IArgumentSpecification _specification;
public int Index { get; }
private readonly object? _argument = argument;
private readonly IArgumentSpecification _specification = specification;
public int Index { get; } = index;

public bool IsMatch => _specification.IsSatisfiedBy(_argument);

Expand Down
9 changes: 2 additions & 7 deletions src/NSubstitute/Core/Arguments/ArgumentMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,9 @@ public static class ArgumentMatcher
return ref new DefaultValueContainer<T>().Value;
}

private class GenericToNonGenericMatcherProxy<T> : IArgumentMatcher
private class GenericToNonGenericMatcherProxy<T>(IArgumentMatcher<T> matcher) : IArgumentMatcher
{
protected readonly IArgumentMatcher<T> _matcher;

public GenericToNonGenericMatcherProxy(IArgumentMatcher<T> matcher)
{
_matcher = matcher;
}
protected readonly IArgumentMatcher<T> _matcher = matcher;

public bool IsSatisfiedBy(object? argument) => _matcher.IsSatisfiedBy((T?)argument!);
}
Expand Down
30 changes: 10 additions & 20 deletions src/NSubstitute/Core/Arguments/ArgumentSpecification.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,13 @@
namespace NSubstitute.Core.Arguments;

public class ArgumentSpecification : IArgumentSpecification
public class ArgumentSpecification(Type forType, IArgumentMatcher matcher, Action<object?> action) : IArgumentSpecification
{
private static readonly Action<object?> NoOpAction = _ => { };

private readonly IArgumentMatcher _matcher;
private readonly Action<object?> _action;
public Type ForType { get; }
public bool HasAction => _action != NoOpAction;
public Type ForType { get; } = forType;
public bool HasAction => action != NoOpAction;

public ArgumentSpecification(Type forType, IArgumentMatcher matcher) : this(forType, matcher, NoOpAction) { }

public ArgumentSpecification(Type forType, IArgumentMatcher matcher, Action<object?> action)
{
ForType = forType;
_matcher = matcher;
_action = action;
}

public bool IsSatisfiedBy(object? argument)
{
if (!IsCompatibleWith(argument))
Expand All @@ -27,7 +17,7 @@ public bool IsSatisfiedBy(object? argument)

try
{
return _matcher.IsSatisfiedBy(argument);
return matcher.IsSatisfiedBy(argument);
}
catch
{
Expand All @@ -42,7 +32,7 @@ public string DescribeNonMatch(object? argument)
return GetIncompatibleTypeMessage(argument);
}

return _matcher is IDescribeNonMatches describe
return matcher is IDescribeNonMatches describe
? describe.DescribeFor(argument)
: string.Empty;
}
Expand All @@ -51,12 +41,12 @@ public string FormatArgument(object? argument)
{
var isSatisfiedByArg = IsSatisfiedBy(argument);

return _matcher is IArgumentFormatter matcherFormatter
return matcher is IArgumentFormatter matcherFormatter
? matcherFormatter.Format(argument, highlight: !isSatisfiedByArg)
: ArgumentFormatter.Default.Format(argument, highlight: !isSatisfiedByArg);
}

public override string ToString() => _matcher.ToString() ?? string.Empty;
public override string ToString() => matcher.ToString() ?? string.Empty;

public IArgumentSpecification CreateCopyMatchingAnyArgOfType(Type requiredType)
{
Expand All @@ -65,19 +55,19 @@ public IArgumentSpecification CreateCopyMatchingAnyArgOfType(Type requiredType)
return new ArgumentSpecification(
requiredType,
new AnyArgumentMatcher(requiredType),
_action == NoOpAction ? NoOpAction : RunActionIfTypeIsCompatible);
action == NoOpAction ? NoOpAction : RunActionIfTypeIsCompatible);
}

public void RunAction(object? argument)
{
_action(argument);
action(argument);
}

private void RunActionIfTypeIsCompatible(object? argument)
{
if (argument.IsCompatibleWith(ForType))
{
_action(argument);
action(argument);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
namespace NSubstitute.Core.Arguments;

public class ArgumentSpecificationCompatibilityTester : IArgumentSpecificationCompatibilityTester
public class ArgumentSpecificationCompatibilityTester(IDefaultChecker defaultChecker) : IArgumentSpecificationCompatibilityTester
{
private readonly IDefaultChecker _defaultChecker;

public ArgumentSpecificationCompatibilityTester(IDefaultChecker defaultChecker)
{
_defaultChecker = defaultChecker;
}

public bool IsSpecificationCompatible(IArgumentSpecification specification, object? argumentValue, Type argumentType)
{
var typeArgSpecIsFor = specification.ForType;
Expand All @@ -18,7 +11,7 @@ public bool IsSpecificationCompatible(IArgumentSpecification specification, obje

private bool IsProvidedArgumentTheOneWeWouldGetUsingAnArgSpecForThisType(object? argument, Type typeArgSpecIsFor)
{
return _defaultChecker.IsDefault(argument, typeArgSpecIsFor);
return defaultChecker.IsDefault(argument, typeArgSpecIsFor);
}

private bool AreTypesCompatible(Type argumentType, Type typeArgSpecIsFor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,9 @@ private IEnumerable<IArgumentSpecification> UnwrapParamsArguments(IEnumerable<ob
return result;
}

private class ParameterInfoFromType : IParameterInfo
private class ParameterInfoFromType(Type parameterType) : IParameterInfo
{
public ParameterInfoFromType(Type parameterType)
{
ParameterType = parameterType;
}

public Type ParameterType { get; }
public Type ParameterType { get; } = parameterType;

public bool IsParams => false;

Expand Down
21 changes: 7 additions & 14 deletions src/NSubstitute/Core/Arguments/ArgumentSpecificationsFactory.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
using System.Reflection;
using NSubstitute.Exceptions;
using NSubstitute.Exceptions;
using System.Reflection;

namespace NSubstitute.Core.Arguments;

public class ArgumentSpecificationsFactory : IArgumentSpecificationsFactory
public class ArgumentSpecificationsFactory(
IArgumentSpecificationFactory argumentSpecificationFactory,
ISuppliedArgumentSpecificationsFactory suppliedArgumentSpecificationsFactory) : IArgumentSpecificationsFactory
{
private readonly IArgumentSpecificationFactory _argumentSpecificationFactory;
private readonly ISuppliedArgumentSpecificationsFactory _suppliedArgumentSpecificationsFactory;

public ArgumentSpecificationsFactory(IArgumentSpecificationFactory argumentSpecificationFactory, ISuppliedArgumentSpecificationsFactory suppliedArgumentSpecificationsFactory)
{
_argumentSpecificationFactory = argumentSpecificationFactory;
_suppliedArgumentSpecificationsFactory = suppliedArgumentSpecificationsFactory;
}

public IEnumerable<IArgumentSpecification> Create(IList<IArgumentSpecification> argumentSpecs, object?[] arguments, IParameterInfo[] parameterInfos, MethodInfo methodInfo, MatchArgs matchArgs)
{
var suppliedArgumentSpecifications = _suppliedArgumentSpecificationsFactory.Create(argumentSpecs);
var suppliedArgumentSpecifications = suppliedArgumentSpecificationsFactory.Create(argumentSpecs);

var result = new List<IArgumentSpecification>();
for (var i = 0; i < arguments.Length; i++)
Expand All @@ -26,7 +19,7 @@ public IEnumerable<IArgumentSpecification> Create(IList<IArgumentSpecification>

try
{
result.Add(_argumentSpecificationFactory.Create(arg, paramInfo, suppliedArgumentSpecifications));
result.Add(argumentSpecificationFactory.Create(arg, paramInfo, suppliedArgumentSpecifications));
}
catch (AmbiguousArgumentsException ex) when (ex.ContainsDefaultMessage)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@

namespace NSubstitute.Core.Arguments;

public class ArrayContentsArgumentMatcher : IArgumentMatcher, IArgumentFormatter
public class ArrayContentsArgumentMatcher(IEnumerable<IArgumentSpecification> argumentSpecifications) : IArgumentMatcher, IArgumentFormatter
{
private readonly IArgumentSpecification[] _argumentSpecifications;

public ArrayContentsArgumentMatcher(IEnumerable<IArgumentSpecification> argumentSpecifications)
{
_argumentSpecifications = argumentSpecifications.ToArray();
}
private readonly IArgumentSpecification[] _argumentSpecifications = argumentSpecifications.ToArray();

public bool IsSatisfiedBy(object? argument)
{
Expand Down
11 changes: 2 additions & 9 deletions src/NSubstitute/Core/Arguments/DefaultChecker.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
namespace NSubstitute.Core.Arguments;

public class DefaultChecker : IDefaultChecker
public class DefaultChecker(IDefaultForType defaultForType) : IDefaultChecker
{
private readonly IDefaultForType _defaultForType;

public DefaultChecker(IDefaultForType defaultForType)
{
_defaultForType = defaultForType;
}

public bool IsDefault(object? value, Type forType)
{
return EqualityComparer<object>.Default.Equals(value, _defaultForType.GetDefaultFor(forType));
return EqualityComparer<object>.Default.Equals(value, defaultForType.GetDefaultFor(forType));
}
}
13 changes: 3 additions & 10 deletions src/NSubstitute/Core/Arguments/EqualsArgumentMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
namespace NSubstitute.Core.Arguments;

public class EqualsArgumentMatcher : IArgumentMatcher
public class EqualsArgumentMatcher(object? value) : IArgumentMatcher
{
private readonly object? _value;
public override string ToString() => ArgumentFormatter.Default.Format(value, false);

public EqualsArgumentMatcher(object? value)
{
_value = value;
}

public override string ToString() => ArgumentFormatter.Default.Format(_value, false);

public bool IsSatisfiedBy(object? argument) => EqualityComparer<object>.Default.Equals(_value, argument);
public bool IsSatisfiedBy(object? argument) => EqualityComparer<object>.Default.Equals(value, argument);
}
Loading
Loading