From 6cd95d1cb4f0655fab5a05f5a3777c87a3630b1c Mon Sep 17 00:00:00 2001 From: Giacomo Stelluti Scala Date: Thu, 9 Jan 2020 08:40:47 +0100 Subject: [PATCH] Upgraded RailwaySharp from Version 1.1.0 --- src/CommandLine/CommandLine.csproj | 2 +- src/CommandLine/Core/InstanceBuilder.cs | 6 +- src/CommandLine/Core/Tokenizer.cs | 2 +- .../Infrastructure/ErrorHandling.cs | 257 +++++++++--------- .../Infrastructure/ResultExtensions.cs | 33 --- .../Unit/Core/TokenizerTests.cs | 2 +- 6 files changed, 133 insertions(+), 169 deletions(-) delete mode 100644 src/CommandLine/Infrastructure/ResultExtensions.cs diff --git a/src/CommandLine/CommandLine.csproj b/src/CommandLine/CommandLine.csproj index b05cbb04..22c4ef51 100644 --- a/src/CommandLine/CommandLine.csproj +++ b/src/CommandLine/CommandLine.csproj @@ -4,7 +4,7 @@ CommandLine Library netstandard2.0;net40;net45;net461 - $(DefineConstants);CSX_EITHER_INTERNAL;CSX_REM_EITHER_BEYOND_2;CSX_ENUM_INTERNAL;ERRH_INTERNAL;ERRH_DISABLE_INLINE_METHODS;CSX_MAYBE_INTERNAL;CSX_REM_EITHER_FUNC;CSX_REM_CRYPTORAND + $(DefineConstants);CSX_EITHER_INTERNAL;CSX_REM_EITHER_BEYOND_2;CSX_ENUM_INTERNAL;ERRH_INTERNAL;CSX_MAYBE_INTERNAL;CSX_REM_EITHER_FUNC;CSX_REM_CRYPTORAND;ERRH_ADD_MAYBE_METHODS $(DefineConstants);SKIP_FSHARP true ..\..\CommandLine.snk diff --git a/src/CommandLine/Core/InstanceBuilder.cs b/src/CommandLine/Core/InstanceBuilder.cs index 4aff4080..0ae564b5 100644 --- a/src/CommandLine/Core/InstanceBuilder.cs +++ b/src/CommandLine/Core/InstanceBuilder.cs @@ -98,10 +98,10 @@ public static ParserResult Build( var validationErrors = specPropsWithValue.Validate(SpecificationPropertyRules.Lookup(tokens)); var allErrors = - tokenizerResult.SuccessfulMessages() + tokenizerResult.SuccessMessages() .Concat(missingValueErrors) - .Concat(optionSpecPropsResult.SuccessfulMessages()) - .Concat(valueSpecPropsResult.SuccessfulMessages()) + .Concat(optionSpecPropsResult.SuccessMessages()) + .Concat(valueSpecPropsResult.SuccessMessages()) .Concat(validationErrors) .Concat(setPropertyErrors) .Memoize(); diff --git a/src/CommandLine/Core/Tokenizer.cs b/src/CommandLine/Core/Tokenizer.cs index 9fd8863c..ba6f1ef5 100644 --- a/src/CommandLine/Core/Tokenizer.cs +++ b/src/CommandLine/Core/Tokenizer.cs @@ -74,7 +74,7 @@ public static Result, Error> ExplodeOptionList( var flattened = exploded.SelectMany(x => x); - return Result.Succeed(flattened, tokenizerResult.SuccessfulMessages()); + return Result.Succeed(flattened, tokenizerResult.SuccessMessages()); } public static IEnumerable Normalize( diff --git a/src/CommandLine/Infrastructure/ErrorHandling.cs b/src/CommandLine/Infrastructure/ErrorHandling.cs index 142e1461..8aee4bac 100644 --- a/src/CommandLine/Infrastructure/ErrorHandling.cs +++ b/src/CommandLine/Infrastructure/ErrorHandling.cs @@ -1,62 +1,17 @@ //Use project level define(s) when referencing with Paket. -//#define ERRH_INTERNAL // Uncomment this to set visibility to internal. -//#define ERRH_DISABLE_INLINE_METHODS // Uncomment this to enable method inlining when compiling for >= NET 4.5. -//#define ERRH_BUILTIN_TYPES // Uncomment this to use built-in Unit type, instead of extenral identical CSharpx.Unit. +//#define ERRH_INTERNAL // Uncomment or define at build time to set accessibility to internal. +//#define ERRH_ENABLE_INLINE_METHODS // Uncomment or define at build time to enable method inlining when compiling for >= NET 4.5. +//#define ERRH_ADD_MAYBE_METHODS // Uncomment or define at build time to add methods that use Maybe type using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; -#if !ERRH_BUILTIN_TYPES +#if ERRH_ADD_MAYBE_METHODS using CSharpx; #endif namespace RailwaySharp.ErrorHandling { - #region Unit Type -#if ERRH_BUILTIN_TYPES -#if !ERRH_INTERNAL - public -#endif - struct Unit : IEquatable - { - private static readonly Unit @default = new Unit(); - - public bool Equals(Unit other) - { - return true; - } - - public override bool Equals(object obj) - { - return obj is Unit; - } - - public override int GetHashCode() - { - return 0; - } - - public override string ToString() - { - return "()"; - } - - public static bool operator ==(Unit first, Unit second) - { - return true; - } - - public static bool operator !=(Unit first, Unit second) - { - return false; - } - - public static Unit Default { get { return @default; } } - } -#endif - #endregion - #if !ERRH_INTERNAL public #endif @@ -76,29 +31,28 @@ enum ResultType #endif abstract class Result { - private readonly ResultType tag; + private readonly ResultType _tag; protected Result(ResultType tag) { - this.tag = tag; + _tag = tag; } public ResultType Tag { - get { return tag; } + get { return _tag; } } public override string ToString() { - switch (Tag) - { - case ResultType.Ok: + switch (Tag) { + default: var ok = (Ok)this; return string.Format( "OK: {0} - {1}", ok.Success, string.Join(Environment.NewLine, ok.Messages.Select(v => v.ToString()))); - default: + case ResultType.Bad: var bad = (Bad)this; return string.Format( "Error: {0}", @@ -117,22 +71,24 @@ public override string ToString() #endif sealed class Ok : Result { - private readonly Tuple> value; + private readonly Tuple> _value; public Ok(TSuccess success, IEnumerable messages) : base(ResultType.Ok) { - this.value = Tuple.Create(success, messages); + if (messages == null) throw new ArgumentNullException(nameof(messages)); + + _value = Tuple.Create(success, messages); } public TSuccess Success { - get { return value.Item1; } + get { return _value.Item1; } } public IEnumerable Messages { - get { return value.Item2; } + get { return _value.Item2; } } } @@ -146,17 +102,19 @@ public IEnumerable Messages #endif sealed class Bad : Result { - private readonly IEnumerable messages; + private readonly IEnumerable _messages; public Bad(IEnumerable messages) : base(ResultType.Bad) { - this.messages = messages; + if (messages == null) throw new ArgumentException(nameof(messages)); + + _messages = messages; } public IEnumerable Messages { - get { return messages; } + get { return _messages; } } } @@ -170,6 +128,8 @@ static class Result /// public static Result FailWith(IEnumerable messages) { + if (messages == null) throw new ArgumentException(nameof(messages)); + return new Bad(messages); } @@ -178,6 +138,8 @@ public static Result FailWith(IEnumerabl /// public static Result FailWith(TMessage message) { + if (message == null) throw new ArgumentException(nameof(message)); + return new Bad(new[] { message }); } @@ -194,6 +156,8 @@ public static Result Succeed(TSuccess va /// public static Result Succeed(TSuccess value, TMessage message) { + if (message == null) throw new ArgumentException(nameof(message)); + return new Ok(value, new[] { message }); } @@ -202,6 +166,8 @@ public static Result Succeed(TSuccess va /// public static Result Succeed(TSuccess value, IEnumerable messages) { + if (messages == null) throw new ArgumentException(nameof(messages)); + return new Ok(value, messages); } @@ -210,13 +176,13 @@ public static Result Succeed(TSuccess va /// public static Result Try(Func func) { - try - { + if (func == null) throw new ArgumentException(nameof(func)); + + try { return new Ok( func(), Enumerable.Empty()); } - catch (Exception ex) - { + catch (Exception ex) { return new Bad( new[] { ex }); } @@ -231,7 +197,7 @@ static class Trial /// /// Wraps a value in a Success. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Ok(TSuccess value) @@ -242,7 +208,7 @@ public static Result Ok(TSuccess value) /// /// Wraps a value in a Success. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Pass(TSuccess value) @@ -253,29 +219,33 @@ public static Result Pass(TSuccess value /// /// Wraps a value in a Success and adds a message. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Warn(TMessage message, TSuccess value) { + if (message == null) throw new ArgumentException(nameof(message)); + return new Ok(value, new[] { message }); } /// /// Wraps a message in a Failure. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Fail(TMessage message) { + if (message == null) throw new ArgumentException(nameof(message)); + return new Bad(new[] { message }); } /// /// Returns true if the result was not successful. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool Failed(Result result) @@ -286,7 +256,7 @@ public static bool Failed(Result result) /// /// Takes a Result and maps it with successFunc if it is a Success otherwise it maps it with failureFunc. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static TResult Either( @@ -294,9 +264,11 @@ public static TResult Either( Func, TResult> failureFunc, Result trialResult) { + if (successFunc == null) throw new ArgumentException(nameof(successFunc)); + if (failureFunc == null) throw new ArgumentException(nameof(failureFunc)); + var ok = trialResult as Ok; - if (ok != null) - { + if (ok != null) { return successFunc(ok.Success, ok.Messages); } var bad = (Bad)trialResult; @@ -307,7 +279,7 @@ public static TResult Either( /// If the given result is a Success the wrapped value will be returned. /// Otherwise the function throws an exception with Failure message of the result. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static TSuccess ReturnOrFail(Result result) @@ -325,13 +297,15 @@ public static TSuccess ReturnOrFail(Result /// Appends the given messages with the messages in the given result. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result MergeMessages( IEnumerable messages, Result result) { + if (messages == null) throw new ArgumentException(nameof(messages)); + Func, Result> successFunc = (succ, msgs) => new Ok( @@ -347,13 +321,15 @@ public static Result MergeMessages( /// If the result is a Success it executes the given function on the value. /// Otherwise the exisiting failure is propagated. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Bind( Func> func, Result result) { + if (func == null) throw new ArgumentException(nameof(func)); + Func, Result> successFunc = (succ, msgs) => MergeMessages(msgs, func(succ)); @@ -366,7 +342,7 @@ public static Result Bind( /// /// Flattens a nested result given the Failure types are equal. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Flatten( @@ -374,46 +350,44 @@ public static Result Flatten( { return Bind(x => x, result); } - + /// /// If the wrapped function is a success and the given result is a success the function is applied on the value. /// Otherwise the exisiting error messages are propagated. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Apply( Result, TMessage> wrappedFunction, Result result) { - if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Ok) - { + if (wrappedFunction == null) throw new ArgumentException(nameof(wrappedFunction)); + + if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Ok) { var ok1 = (Ok, TMessage>)wrappedFunction; var ok2 = (Ok)result; return new Ok( ok1.Success(ok2.Success), ok1.Messages.Concat(ok2.Messages)); } - if (wrappedFunction.Tag == ResultType.Bad && result.Tag == ResultType.Ok) - { + if (wrappedFunction.Tag == ResultType.Bad && result.Tag == ResultType.Ok) { return new Bad(((Bad)result).Messages); } - if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Bad) - { + if (wrappedFunction.Tag == ResultType.Ok && result.Tag == ResultType.Bad) { return new Bad( ((Bad)result).Messages); } var bad1 = (Bad, TMessage>)wrappedFunction; var bad2 = (Bad)result; - return new Bad(bad1.Messages.Concat(bad2.Messages)); } /// /// Lifts a function into a Result container and applies it on the given result. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Lift( @@ -426,22 +400,22 @@ public static Result Lift( /// /// Promote a function to a monad/applicative, scanning the monadic/applicative arguments from left to right. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Lift2( Func> func, - Result a, - Result b) + Result first, + Result second) { - return Apply(Lift(func, a), b); + return Apply(Lift(func, first), second); } /// /// Collects a sequence of Results and accumulates their values. /// If the sequence contains an error the error will be propagated. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result, TMessage> Collect( @@ -449,21 +423,18 @@ public static Result, TMessage> Collect, Result, TMessage>, Result, TMessage>>( - null, - (result, next) => - { - if (result.Tag == ResultType.Ok && next.Tag == ResultType.Ok) - { + null, + (result, next) => { + if (result.Tag == ResultType.Ok && next.Tag == ResultType.Ok) { var ok1 = (Ok, TMessage>)result; var ok2 = (Ok)next; return new Ok, TMessage>( - Enumerable.Empty().Concat(new[] { ok2.Success }).Concat(ok1.Success), + Enumerable.Empty().Concat(new [] { ok2.Success }).Concat(ok1.Success), ok1.Messages.Concat(ok2.Messages)); } if ((result.Tag == ResultType.Ok && next.Tag == ResultType.Bad) - || (result.Tag == ResultType.Bad && next.Tag == ResultType.Ok)) - { + || (result.Tag == ResultType.Bad && next.Tag == ResultType.Ok)) { var m1 = result.Tag == ResultType.Ok ? ((Ok, TMessage>)result).Messages : ((Bad)next).Messages; @@ -472,8 +443,9 @@ public static Result, TMessage> Collect)next).Messages; return new Bad, TMessage>(m1.Concat(m2)); } + var bad1 = (Bad, TMessage>)result; - var bad2 = (Bad)next; + var bad2 = (Bad)next; return new Bad, TMessage>(bad1.Messages.Concat(bad2.Messages)); }, x => x)); } @@ -490,19 +462,22 @@ static class ResultExtensions /// /// Allows pattern matching on Results. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static void Match(this Result result, Action> ifSuccess, Action> ifFailure) { + if (ifSuccess == null) throw new ArgumentException(nameof(ifSuccess)); + if (ifFailure == null) throw new ArgumentException(nameof(ifFailure)); + var ok = result as Ok; - if (ok != null) - { + if (ok != null) { ifSuccess(ok.Success, ok.Messages); return; } + var bad = (Bad)result; ifFailure(bad.Messages); } @@ -510,26 +485,20 @@ public static void Match(this Result res /// /// Allows pattern matching on Results. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static TResult Either(this Result result, Func, TResult> ifSuccess, Func, TResult> ifFailure) { - var ok = result as Ok; - if (ok != null) - { - return ifSuccess(ok.Success, ok.Messages); - } - var bad = (Bad)result; - return ifFailure(bad.Messages); + return Trial.Either(ifSuccess, ifFailure, result); } /// /// Lifts a Func into a Result and applies it on the given result. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Map(this Result result, @@ -542,7 +511,7 @@ public static Result Map(this Re /// Collects a sequence of Results and accumulates their values. /// If the sequence contains an error the error will be propagated. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result, TMessage> Collect( @@ -555,18 +524,16 @@ public static Result, TMessage> Collect -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result, TMessage> Flatten(this Result>, TMessage> result) { - if (result.Tag == ResultType.Ok) - { + if (result.Tag == ResultType.Ok) { var ok = (Ok>, TMessage>)result; var values = ok.Success; var result1 = Collect(values); - if (result1.Tag == ResultType.Ok) - { + if (result1.Tag == ResultType.Ok) { var ok1 = (Ok, TMessage>)result1; return new Ok, TMessage>(ok1.Success, ok1.Messages); } @@ -581,7 +548,7 @@ public static Result, TMessage> Flatten -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result SelectMany(this Result result, @@ -595,7 +562,7 @@ public static Result SelectMany( /// If the result of the Func is a Success it maps it using the given Func. /// Otherwise the exisiting failure is propagated. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result SelectMany( @@ -603,6 +570,9 @@ public static Result SelectMany> func, Func mapperFunc) { + if (func == null) throw new ArgumentException(nameof(func)); + if (mapperFunc == null) throw new ArgumentException(nameof(mapperFunc)); + Func> curriedMapper = suc => val => mapperFunc(suc, val); Func< Result, @@ -616,7 +586,7 @@ public static Result SelectMany /// Lifts a Func into a Result and applies it on the given result. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static Result Select(this Result result, @@ -628,13 +598,12 @@ public static Result Select(this /// /// Returns the error messages or fails if the result was a success. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static IEnumerable FailedWith(this Result result) { - if (result.Tag == ResultType.Ok) - { + if (result.Tag == ResultType.Ok) { var ok = (Ok)result; throw new Exception( string.Format("Result was a success: {0} - {1}", @@ -648,13 +617,12 @@ public static IEnumerable FailedWith(this Result /// Returns the result or fails if the result was an error. /// -#if !ERRH_DISABLE_INLINE_METHODS +#if ERRH_ENABLE_INLINE_METHODS [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static TSuccess SucceededWith(this Result result) { - if (result.Tag == ResultType.Ok) - { + if (result.Tag == ResultType.Ok) { var ok = (Ok)result; return ok.Success; } @@ -663,5 +631,34 @@ public static TSuccess SucceededWith(this Result m.ToString())))); } + + /// + /// Returns messages in case of success, otherwise an empty sequence. + /// + public static IEnumerable SuccessMessages(this Result result) + { + if (result.Tag == ResultType.Ok) { + var ok = (Ok)result; + return ok.Messages; + } + return Enumerable.Empty(); + } + +#if ERRH_ADD_MAYBE_METHODS +#if ERRH_ENABLE_INLINE_METHODS + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + /// + /// Builds a Maybe type instance from a Result one. + /// + public static Maybe ToMaybe(this Result result) + { + if (result.Tag == ResultType.Ok) { + var ok = (Ok)result; + return Maybe.Just(ok.Success); + } + return Maybe.Nothing(); + } +#endif } } \ No newline at end of file diff --git a/src/CommandLine/Infrastructure/ResultExtensions.cs b/src/CommandLine/Infrastructure/ResultExtensions.cs deleted file mode 100644 index bdc2a480..00000000 --- a/src/CommandLine/Infrastructure/ResultExtensions.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. - -using System.Collections.Generic; -using System.Linq; - -using CSharpx; -using RailwaySharp.ErrorHandling; - -namespace CommandLine.Infrastructure -{ - static class ResultExtensions - { - public static IEnumerable SuccessfulMessages(this Result result) - { - if (result.Tag == ResultType.Ok) - { - var ok = (Ok)result; - return ok.Messages; - } - return Enumerable.Empty(); - } - - public static Maybe ToMaybe(this Result result) - { - if (result.Tag == ResultType.Ok) - { - var ok = (Ok)result; - return Maybe.Just(ok.Success); - } - return Maybe.Nothing(); - } - } -} \ No newline at end of file diff --git a/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs b/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs index 3bd95891..e2803a8f 100644 --- a/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/TokenizerTests.cs @@ -121,7 +121,7 @@ public void Should_return_error_if_option_format_with_equals_is_not_correct() var result = Tokenizer.Tokenize(args, name => NameLookupResult.OtherOptionFound, token => token); - var tokens = result.SuccessfulMessages(); + var tokens = result.SuccessMessages(); Assert.NotNull(tokens); Assert.Equal(2, tokens.Count());