Skip to content

Commit

Permalink
Merge pull request #639 from zvirja/consume-latest-language-features
Browse files Browse the repository at this point in the history
Slightly refactor code to make it look fresh
  • Loading branch information
zvirja authored Dec 29, 2020
2 parents 46d4e06 + 10101d6 commit a4e2e6d
Show file tree
Hide file tree
Showing 93 changed files with 903 additions and 975 deletions.
5 changes: 5 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion

# ReSharper properties
resharper_int_align_switch_expressions = true
resharper_keep_existing_invocation_parens_arrangement = false
resharper_space_within_single_line_array_initializer_braces = true
6 changes: 3 additions & 3 deletions src/NSubstitute/Callback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public static Callback AlwaysThrow<TException>(Func<CallInfo, TException> throwT
/// <returns></returns>
public static Callback AlwaysThrow<TException>(TException exception) where TException : Exception
{
return AlwaysThrow(info => exception);
return AlwaysThrow(_ => exception);
}

protected static Action<CallInfo> ToCallback<TException>(Func<CallInfo, TException> throwThis)
Expand All @@ -93,12 +93,12 @@ protected void AddCallback(Action<CallInfo> doThis)

protected void SetAlwaysDo(Action<CallInfo> always)
{
alwaysDo = always == null ? x => { } : always;
alwaysDo = always ?? (_ => { });
}

protected void SetKeepDoing(Action<CallInfo> keep)
{
keepDoing = keep == null ? x => { } : keep;
keepDoing = keep ?? (_ => { });
}

public void Call(CallInfo callInfo)
Expand Down
31 changes: 6 additions & 25 deletions src/NSubstitute/Callbacks/ConfiguredCallback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ internal ConfiguredCallback() { }
/// <summary>
/// Perform this action once in chain of called callbacks.
/// </summary>
/// <param name="doThis"></param>
/// <returns></returns>
public ConfiguredCallback Then(Action<CallInfo> doThis)
{
AddCallback(doThis);
Expand All @@ -24,8 +22,6 @@ public ConfiguredCallback Then(Action<CallInfo> doThis)
/// <summary>
/// Keep doing this action after the other callbacks have run.
/// </summary>
/// <param name="doThis"></param>
/// <returns></returns>
public EndCallbackChain ThenKeepDoing(Action<CallInfo> doThis)
{
SetKeepDoing(doThis);
Expand All @@ -35,31 +31,20 @@ public EndCallbackChain ThenKeepDoing(Action<CallInfo> doThis)
/// <summary>
/// Keep throwing this exception after the other callbacks have run.
/// </summary>
/// <typeparam name="TException"></typeparam>
/// <param name="throwThis"></param>
/// <returns></returns>
public EndCallbackChain ThenKeepThrowing<TException>(Func<CallInfo, TException> throwThis) where TException : Exception
{
return ThenKeepDoing(ToCallback(throwThis));
}
public EndCallbackChain ThenKeepThrowing<TException>(Func<CallInfo, TException> throwThis) where TException : Exception =>
ThenKeepDoing(ToCallback(throwThis));

/// <summary>
/// Keep throwing this exception after the other callbacks have run.
/// </summary>
/// <typeparam name="TException"></typeparam>
/// <param name="throwThis"></param>
/// <returns></returns>
public EndCallbackChain ThenKeepThrowing<TException>(TException throwThis) where TException : Exception
{
return ThenKeepThrowing(info => throwThis);
}
public EndCallbackChain ThenKeepThrowing<TException>(TException throwThis) where TException : Exception =>
ThenKeepThrowing(info => throwThis);

/// <summary>
/// Throw exception returned by function once when called in a chain of callbacks.
/// </summary>
/// <typeparam name="TException">The type of the exception</typeparam>
/// <param name="throwThis">Produce the exception to throw for a CallInfo</param>
/// <returns></returns>
public ConfiguredCallback ThenThrow<TException>(Func<CallInfo, TException> throwThis) where TException : Exception
{
AddCallback(ToCallback(throwThis));
Expand All @@ -71,11 +56,8 @@ public ConfiguredCallback ThenThrow<TException>(Func<CallInfo, TException> throw
/// </summary>
/// <typeparam name="TException">The type of the exception</typeparam>
/// <param name="exception">The exception to throw</param>
/// <returns></returns>
public ConfiguredCallback ThenThrow<TException>(TException exception) where TException : Exception
{
return ThenThrow(ci => exception);
}
public ConfiguredCallback ThenThrow<TException>(TException exception) where TException : Exception =>
ThenThrow(_ => exception);
}

public class EndCallbackChain : Callback
Expand All @@ -86,7 +68,6 @@ internal EndCallbackChain() { }
/// Perform the given action for every call.
/// </summary>
/// <param name="doThis">The action to perform for every call</param>
/// <returns></returns>
public Callback AndAlways(Action<CallInfo> doThis)
{
SetAlwaysDo(doThis);
Expand Down
26 changes: 9 additions & 17 deletions src/NSubstitute/Core/Argument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public Argument(Type declaredType, Func<object?> getValue, Action<object?> setVa

public Argument(ICall call, int argIndex)
{
_call = call ?? throw new ArgumentNullException(nameof(call));
_call = call;
_argIndex = argIndex;
}

Expand All @@ -48,24 +48,16 @@ public object? Value

public Type ActualType => Value == null ? DeclaredType : Value.GetType();

public bool IsDeclaredTypeEqualToOrByRefVersionOf(Type type)
{
return AsNonByRefType(DeclaredType) == type;
}
public bool IsDeclaredTypeEqualToOrByRefVersionOf(Type type) =>
AsNonByRefType(DeclaredType) == type;

public bool IsValueAssignableTo(Type type)
{
return type.IsAssignableFrom(AsNonByRefType(ActualType));
}
public bool IsValueAssignableTo(Type type) =>
type.IsAssignableFrom(AsNonByRefType(ActualType));

public bool CanSetValueWithInstanceOf(Type type)
{
return AsNonByRefType(DeclaredType).IsAssignableFrom(type);
}
public bool CanSetValueWithInstanceOf(Type type) =>
AsNonByRefType(DeclaredType).IsAssignableFrom(type);

private static Type AsNonByRefType(Type type)
{
return type.IsByRef ? type.GetElementType()! : type;
}
private static Type AsNonByRefType(Type type) =>
type.IsByRef ? type.GetElementType()! : type;
}
}
23 changes: 9 additions & 14 deletions src/NSubstitute/Core/Arguments/ArgumentFormatter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Globalization;
using System.Reflection;

namespace NSubstitute.Core.Arguments
Expand All @@ -16,20 +15,16 @@ public string Format(object? argument, bool highlight)

private string Format(object? arg)
{
switch (arg)
return arg switch
{
case null:
return "<null>";
null => "<null>",
string str => $"\"{str}\"",
{ } obj when HasDefaultToString(obj) => arg.GetType().GetNonMangledTypeName(),
_ => arg.ToString() ?? string.Empty
};

case string str:
return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", str);

case object obj when obj.GetType().GetMethod(nameof(ToString), Type.EmptyTypes)!.DeclaringType == typeof(object):
return arg.GetType().GetNonMangledTypeName();

default:
return arg.ToString() ?? string.Empty;
}
}
static bool HasDefaultToString(object obj)
=> obj.GetType().GetMethod(nameof(ToString), Type.EmptyTypes)!.DeclaringType == typeof(object);
}
}
}
4 changes: 2 additions & 2 deletions src/NSubstitute/Core/Arguments/ArgumentMatchInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ public ArgumentMatchInfo(int index, object? argument, IArgumentSpecification spe

private readonly object? _argument;
private readonly IArgumentSpecification _specification;
public int Index { get; private set; }
public int Index { get; }

public bool IsMatch { get { return _specification.IsSatisfiedBy(_argument); } }
public bool IsMatch => _specification.IsSatisfiedBy(_argument);

public string DescribeNonMatch()
{
Expand Down
29 changes: 11 additions & 18 deletions src/NSubstitute/Core/Arguments/ArgumentMatcher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using NSubstitute.Exceptions;

namespace NSubstitute.Core.Arguments
{
Expand All @@ -13,28 +14,20 @@ public static class ArgumentMatcher
{
if (argumentMatcher == null) throw new ArgumentNullException(nameof(argumentMatcher));

IArgumentMatcher nonGenericMatcher;
if (argumentMatcher is IDescribeNonMatches)
IArgumentMatcher nonGenericMatcher = argumentMatcher switch
{
nonGenericMatcher = new GenericToNonGenericMatcherProxyWithDescribe<T>(argumentMatcher);
}
else
{
nonGenericMatcher = new GenericToNonGenericMatcherProxy<T>(argumentMatcher);
}
IDescribeNonMatches => new GenericToNonGenericMatcherProxyWithDescribe<T>(argumentMatcher),
_ => new GenericToNonGenericMatcherProxy<T>(argumentMatcher)
};

return ref EnqueueArgSpecification<T>(new ArgumentSpecification(typeof(T), nonGenericMatcher));
}

internal static ref T? Enqueue<T>(IArgumentMatcher argumentMatcher)
{
return ref EnqueueArgSpecification<T>(new ArgumentSpecification(typeof(T), argumentMatcher));
}
internal static ref T? Enqueue<T>(IArgumentMatcher argumentMatcher) =>
ref EnqueueArgSpecification<T>(new ArgumentSpecification(typeof(T), argumentMatcher));

internal static ref T? Enqueue<T>(IArgumentMatcher argumentMatcher, Action<object?> action)
{
return ref EnqueueArgSpecification<T>(new ArgumentSpecification(typeof(T), argumentMatcher, action));
}
internal static ref T? Enqueue<T>(IArgumentMatcher argumentMatcher, Action<object?> action) =>
ref EnqueueArgSpecification<T>(new ArgumentSpecification(typeof(T), argumentMatcher, action));

private static ref T? EnqueueArgSpecification<T>(IArgumentSpecification specification)
{
Expand All @@ -51,14 +44,14 @@ public GenericToNonGenericMatcherProxy(IArgumentMatcher<T> matcher)
_matcher = matcher;
}

public bool IsSatisfiedBy(object? argument) => _matcher.IsSatisfiedBy((T) argument!);
public bool IsSatisfiedBy(object? argument) => _matcher.IsSatisfiedBy((T?) argument!);
}

private class GenericToNonGenericMatcherProxyWithDescribe<T> : GenericToNonGenericMatcherProxy<T>, IDescribeNonMatches
{
public GenericToNonGenericMatcherProxyWithDescribe(IArgumentMatcher<T> matcher) : base(matcher)
{
if (matcher as IDescribeNonMatches == null) throw new ArgumentException("Should implement IDescribeNonMatches type.");
if (matcher is not IDescribeNonMatches) throw new SubstituteInternalException("Should implement IDescribeNonMatches type.");
}

public string DescribeFor(object? argument) => ((IDescribeNonMatches) _matcher).DescribeFor(argument);
Expand Down
51 changes: 32 additions & 19 deletions src/NSubstitute/Core/Arguments/ArgumentSpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace NSubstitute.Core.Arguments
{
public class ArgumentSpecification : IArgumentSpecification
{
private static readonly Action<object?> NoOpAction = x => { };
private static readonly Action<object?> NoOpAction = _ => { };

private readonly IArgumentMatcher _matcher;
private readonly Action<object?> _action;
public Type ForType { get; }
Expand All @@ -22,26 +22,40 @@ public ArgumentSpecification(Type forType, IArgumentMatcher matcher, Action<obje

public bool IsSatisfiedBy(object? argument)
{
if (!IsCompatibleWith(argument)) return false;
try { return _matcher.IsSatisfiedBy(argument); }
catch { return false; }
if (!IsCompatibleWith(argument))
{
return false;
}

try
{
return _matcher.IsSatisfiedBy(argument);
}
catch
{
return false;
}
}

public string DescribeNonMatch(object? argument)
{
var describable = _matcher as IDescribeNonMatches;
if (describable == null) return string.Empty;
if (!IsCompatibleWith(argument))
{
return GetIncompatibleTypeMessage(argument);
}

return IsCompatibleWith(argument) ? describable.DescribeFor(argument) : GetIncompatibleTypeMessage(argument);
return _matcher is IDescribeNonMatches describe
? describe.DescribeFor(argument)
: string.Empty;
}

public string FormatArgument(object? argument)
{
var isSatisfiedByArg = IsSatisfiedBy(argument);
var matcherFormatter = _matcher as IArgumentFormatter;
return matcherFormatter == null
? ArgumentFormatter.Default.Format(argument, !isSatisfiedByArg)
: matcherFormatter.Format(argument, isSatisfiedByArg);

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

public override string ToString() => _matcher.ToString() ?? string.Empty;
Expand All @@ -63,19 +77,18 @@ public void RunAction(object? argument)

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

private bool IsCompatibleWith(object? argument)
{
return argument.IsCompatibleWith(ForType);
}
private bool IsCompatibleWith(object? argument) => argument.IsCompatibleWith(ForType);

private string GetIncompatibleTypeMessage(object? argument)
{
var argumentType = argument == null ? typeof(object) : argument.GetType();
return string.Format("Expected an argument compatible with type {0}. Actual type was {1}.", ForType, argumentType);
return $"Expected an argument compatible with type '{ForType}'. Actual type was '{argumentType}'.";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ArgumentSpecificationCompatibilityTester : IArgumentSpecificationCo

public ArgumentSpecificationCompatibilityTester(IDefaultChecker defaultChecker)
{
_defaultChecker = defaultChecker ?? throw new ArgumentNullException(nameof(defaultChecker));
_defaultChecker = defaultChecker;
}

public bool IsSpecificationCompatible(IArgumentSpecification specification, object? argumentValue, Type argumentType)
Expand Down
14 changes: 6 additions & 8 deletions src/NSubstitute/Core/Arguments/ArrayContentsArgumentMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,18 @@ public bool IsSatisfiedBy(object? argument)
if (argument != null)
{
var argumentArray = ((IEnumerable) argument).Cast<object>().ToArray();
if (argumentArray.Length == _argumentSpecifications.Count())
if (argumentArray.Length == _argumentSpecifications.Length)
{
return
_argumentSpecifications.Select(
(value, index) => value.IsSatisfiedBy(argumentArray[index])).All(x => x);
return _argumentSpecifications
.Select((spec, index) => spec.IsSatisfiedBy(argumentArray[index]))
.All(x => x);
}
}

return false;
}

public override string ToString()
{
return string.Join(", ", _argumentSpecifications.Select(x => x.ToString()));
}
public override string ToString() => string.Join(", ", _argumentSpecifications.Select(x => x.ToString()));

public string Format(object? argument, bool highlight)
{
Expand Down
Loading

0 comments on commit a4e2e6d

Please sign in to comment.