more flexible error reporting for SymbolResult#2033
Conversation
|
|
||
| return null; | ||
| SymbolResultTree.ReportError(new ParseError(errorMessage, Parent is OptionResult option ? option : this)); | ||
| _conversionResult = ArgumentConversionResult.Failure(this, errorMessage, ArgumentConversionResultType.Failed); |
There was a problem hiding this comment.
at this moment we know that it's a failure
There was a problem hiding this comment.
Very nice. As long as we don't later allow clearing of the errors.
...ility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt
Outdated
Show resolved
Hide resolved
|
Was a test added to pin the expected behavior when |
* rename ReportError to AddError * test coverage improvement (multiple errors for one result)
…one (20% perf gain on simple scenarios)
…should be None improve perf: don't use .Single as it's on hot path and here we know it's only 1 (Arity has been validated)
… tests passing again
remove null checks as it's internal API and we are covered by nullable annotations
| internal ParseError? CustomError(Argument argument) | ||
| { | ||
| for (var i = 0; i < argument.Validators.Count; i++) | ||
| while (tokensToPass > 0 && nextArgumentIndex < arguments.Count) |
There was a problem hiding this comment.
previously this method was implemented in ParseResultVisitor, I've moved it here and implemented in a way it does not require an allocation of temporary list
command-line-api/src/System.CommandLine/Parsing/ParseResultVisitor.cs
Lines 251 to 295 in 6524142
| } | ||
|
|
||
| private ArgumentConversionResult Convert(Argument argument) | ||
| private ArgumentConversionResult ValidateAndConvert(bool potentialRecursion) |
There was a problem hiding this comment.
this method is now responsible for entire validation. The problem is that it can be called by not only the ParseResultVisitor but also custom parsers and validator which can do things like ArgumentResult.GetDefaultValue(). For the latter case I've added potentialRecursion argument to ensure we don't have endless recursion (validator->getvalue->validator)
There was a problem hiding this comment.
The name potentialRecursion is a little unclear to me. Is this saying whether to allow recursion?
| => argumentResult.Argument.HasDefaultValue && argumentResult.Tokens.Count == 0; | ||
|
|
||
| /// <param name="completeValidation">Only the inner most command goes through complete validation.</param> | ||
| internal void Validate(bool completeValidation) |
There was a problem hiding this comment.
I've moved this logic from the visitor and re-wrote in a way that we don't iterate over every argument more than once (previously we were setting the default values and then validating).
|
@jonsequitur the PR is ready for review. I hope that you like the refactoring I've made. The side-effects of the refactor is improved performance. For the simple use case Jan is always using it's 1-3% for cold startup time scenario (start a new process, parse the args, print and exit: jkotas/commandline-perf#2), for micro-benchmark it's 20% faster (less important, as it's warm), but the allocations has reduced nicely |
Co-authored-by: Jon Sequeira <jonsequeira@gmail.com>
|
This required changes in pretty much all of my custom parsers. They were easy to implement, though. |
I've removed
SymbolResult.ErrorMessageas it did not allow for providing multiple errors for single result and introducedSymbolResult.ReportError(name can be changed, I don't have strong preferences about it).SymbolResult.ReportErroradds a new error to the list of errors (so multiple errors per result are supported) and in case ofArgumentResultalso setsArgumentConversionResult(perf, simplicity) and encapsulates the fact thatOption.Argumentis internal and for Arguments owned by Option sets the parent toOptionResultrather thanArgumentResultI also did a lot of refactoring related to
ArgumentConversionResult, I am going to add comments explaining why.