Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 288554a

Browse files
committedOct 8, 2024
Rebasing on powderhouse
1 parent 05bd9eb commit 288554a

17 files changed

+58
-127
lines changed
 

‎src/System.CommandLine.Subsystems.Tests/ErrorReportingFunctionalTests.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ public void Help_display_can_be_disabled()
5656
5757
var result = rootCommand.Parse("oops", config);
5858
59-
if (result.Action is ParseErrorAction parseError)
59+
if (result.Action is CliDiagnosticAction CliDiagnostic)
6060
{
61-
parseError.ShowHelp = false;
61+
CliDiagnostic.ShowHelp = false;
6262
}
6363
6464
result.Invoke();

‎src/System.CommandLine.Subsystems.Tests/ErrorReportingSubsystemTests.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using System.CommandLine.Parsing;
45
using FluentAssertions;
56
using Xunit;
6-
using System.CommandLine.Parsing;
77

88
namespace System.CommandLine.Subsystems.Tests;
99

@@ -12,8 +12,8 @@ public class ErrorReportingSubsystemTests
1212
[Fact]
1313
public void Report_when_single_error_writes_to_console_hack()
1414
{
15-
var error = new ParseError("a sweet error message");
16-
var errors = new List<ParseError> { error };
15+
var error = new CliDiagnostic(new("", "", "a sweet error message", CliDiagnosticSeverity.Warning, null), []);
16+
var errors = new List<CliDiagnostic> { error };
1717
var errorSubsystem = new ErrorReportingSubsystem();
1818
var consoleHack = new ConsoleHack().RedirectToBuffer(true);
1919

@@ -25,9 +25,9 @@ public void Report_when_single_error_writes_to_console_hack()
2525
[Fact]
2626
public void Report_when_multiple_error_writes_to_console_hack()
2727
{
28-
var error = new ParseError("a sweet error message");
29-
var anotherError = new ParseError("another sweet error message");
30-
var errors = new List<ParseError> { error, anotherError };
28+
var error = new CliDiagnostic(new("", "", "a sweet error message", CliDiagnosticSeverity.Warning, null), []);
29+
var anotherError = new CliDiagnostic(new("", "", "another sweet error message", CliDiagnosticSeverity.Warning, null), []);
30+
var errors = new List<CliDiagnostic> { error, anotherError };
3131
var errorSubsystem = new ErrorReportingSubsystem();
3232
var consoleHack = new ConsoleHack().RedirectToBuffer(true);
3333

@@ -39,7 +39,7 @@ public void Report_when_multiple_error_writes_to_console_hack()
3939
[Fact]
4040
public void Report_when_no_errors_writes_nothing_to_console_hack()
4141
{
42-
var errors = new List<ParseError> { };
42+
var errors = new List<CliDiagnostic> { };
4343
var errorSubsystem = new ErrorReportingSubsystem();
4444
var consoleHack = new ConsoleHack().RedirectToBuffer(true);
4545

@@ -53,7 +53,7 @@ public void Report_when_no_errors_writes_nothing_to_console_hack()
5353
[InlineData("-non_existant_option")]
5454
public void GetIsActivated_GivenInvalidInput_SubsystemIsActive(string input)
5555
{
56-
var rootCommand = new CliRootCommand {new CliOption<bool>("-v")};
56+
var rootCommand = new CliRootCommand { new CliOption<bool>("-v") };
5757
var configuration = new CliConfiguration(rootCommand);
5858
var errorSubsystem = new ErrorReportingSubsystem();
5959
IReadOnlyList<string> args = [""];

‎src/System.CommandLine.Subsystems/ErrorReportingSubsystem.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public override void Execute(PipelineResult pipelineResult)
3333
pipelineResult.SetSuccess();
3434
}
3535

36-
public void Report(ConsoleHack consoleHack, IReadOnlyList<ParseError> errors)
36+
public void Report(ConsoleHack consoleHack, IReadOnlyList<CliDiagnostic> errors)
3737
{
3838
ConsoleHelpers.ResetTerminalForegroundColor();
3939
ConsoleHelpers.SetTerminalForegroundRed();

‎src/System.CommandLine.Subsystems/PipelineResult.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation and contributors. All rights reserved.
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System.CommandLine.Parsing;
@@ -9,8 +9,8 @@ namespace System.CommandLine;
99
public class PipelineResult
1010
{
1111
// TODO: Try to build workflow so it is illegal to create this without a ParseResult
12-
private readonly List<ParseError> errors = [];
13-
private ValueProvider valueProvider { get; }
12+
private readonly List<CliDiagnostic> errors = [];
13+
private ValueProvider valueProvider { get; }
1414

1515
public PipelineResult(ParseResult parseResult, string rawInput, Pipeline? pipeline, ConsoleHack? consoleHack = null)
1616
{
@@ -44,18 +44,18 @@ public PipelineResult(ParseResult parseResult, string rawInput, Pipeline? pipeli
4444
=> ParseResult.GetValueResult(valueSymbol);
4545

4646

47-
public void AddErrors(IEnumerable<ParseError> errors)
47+
public void AddErrors(IEnumerable<CliDiagnostic> errors)
4848
{
4949
if (errors is not null)
5050
{
5151
this.errors.AddRange(errors);
5252
}
5353
}
5454

55-
public void AddError(ParseError error)
55+
public void AddError(CliDiagnostic error)
5656
=> errors.Add(error);
5757

58-
public IEnumerable<ParseError> GetErrors(bool excludeParseErrors = false)
58+
public IEnumerable<CliDiagnostic> GetErrors(bool excludeParseErrors = false)
5959
=> excludeParseErrors || ParseResult is null
6060
? errors
6161
: ParseResult.Errors.Concat(errors);

‎src/System.CommandLine.Subsystems/Validation/InclusiveGroupValidator.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ public override void Validate(CliCommandResult commandResult,
4444
// TODO: Rework to allow localization
4545
var pluralToBe = "are";
4646
var singularToBe = "is";
47-
validationContext.AddError(new ParseError( $"The members {string.Join(", ", groupMembers.Select(m => m.Name))} " +
48-
$"must all be used if one is used. {string.Join(", ", missingMembers.Select(m => m.Name))} " +
49-
$"{(missingMembers.Skip(1).Any() ? pluralToBe : singularToBe)} missing."));
47+
validationContext.AddError(new CliDiagnostic(new("", "", $"The members {string.Join(", ", groupMembers.Select(m => m.Name))} " +
48+
$"must all be used if one is used. {string.Join(", ", missingMembers.Select(m => m.Name))} " +
49+
$"{(missingMembers.Skip(1).Any() ? pluralToBe : singularToBe)} missing.", severity: CliDiagnosticSeverity.Error, null), []));
5050
}
5151
}
5252
}

‎src/System.CommandLine.Subsystems/Validation/RangeValidator.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ public override void Validate(object? value, CliValueSymbol valueSymbol,
2424
}
2525
if (valueCondition.MustHaveValidator)
2626
{
27-
validationContext.AddError(new ParseError($"Range validator missing for {valueSymbol.Name}"));
27+
validationContext.AddError(new CliDiagnostic(new("", "", $"Range validator missing for {valueSymbol.Name}", severity: CliDiagnosticSeverity.Error, null), [], cliSymbolResult: valueResult));
2828
}
2929
}
30-
31-
3230
}

‎src/System.CommandLine.Subsystems/Validation/ValidationContext.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System.CommandLine.Parsing;
55
using System.CommandLine.ValueSources;
6-
using static System.Runtime.InteropServices.JavaScript.JSType;
76

87
namespace System.CommandLine.Validation;
98

@@ -24,7 +23,7 @@ internal ValidationContext(PipelineResult pipelineResult, ValidationSubsystem va
2423
/// Adds an error to the PipelineContext.
2524
/// </summary>
2625
/// <param name="error">The <see cref="ParseError"/> to add</param>
27-
public void AddError(ParseError error)
26+
public void AddError(CliDiagnostic error)
2827
=> pipelineResult.AddError(error);
2928

3029
/// <summary>

‎src/System.CommandLine.Subsystems/Validation/Validator.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ internal Validator(string name, Type valueConditionType, params Type[] moreValue
3131
/// <remarks>
3232
/// This method needs to be evolved as we replace ParseError with CliError
3333
/// </remarks>
34-
protected static List<ParseError> AddValidationError(ref List<ParseError>? parseErrors, string message, IEnumerable<object?> errorValues)
34+
protected static List<CliDiagnostic> AddValidationError(ref List<CliDiagnostic>? parseErrors, string message, IEnumerable<object?> errorValues)
3535
{
3636
// TODO: Review the handling of errors. They are currently transient and returned by the Validate method, and to avoid allocating in the case of no errors (the common case) this method is used. This adds complexity to creating a new validator.
37-
parseErrors ??= new List<ParseError>();
38-
parseErrors.Add(new ParseError(message));
37+
parseErrors ??= new List<CliDiagnostic>();
38+
parseErrors.Add(new CliDiagnostic(new("", "", message, severity: CliDiagnosticSeverity.Error, null), []));
3939
return parseErrors;
4040
}
4141

‎src/System.CommandLine.Subsystems/ValidationSubsystem.cs

+5-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ private void ValidateValue(CliValueSymbol valueSymbol, ValidationContext validat
8181
var value = validationContext.GetValue(valueSymbol);
8282
var valueResult = validationContext.GetValueResult(valueSymbol);
8383

84-
do {
84+
do
85+
{
8586
ValidateValueCondition(value, valueSymbol, valueResult, enumerator.Current, validationContext);
8687
} while (enumerator.MoveNext());
8788
}
@@ -123,9 +124,9 @@ private void ValidateValueCondition(object? value, CliValueSymbol valueSymbol, C
123124
{
124125
if (condition.MustHaveValidator)
125126
{
126-
validationContext.AddError(new ParseError($"{valueSymbol.Name} must have {condition.Name} validator."));
127+
validationContext.AddError(new CliDiagnostic(new("", "", $"{valueSymbol.Name} must have {condition.Name} validator.", severity: CliDiagnosticSeverity.Error, null), [], cliSymbolResult: valueResult));
127128
}
128-
return;
129+
return;
129130
}
130131
validator.Validate(value, valueSymbol, valueResult, condition, validationContext);
131132

@@ -169,7 +170,7 @@ private void ValidateCommandCondition(CliCommandResult commandResult, CommandCon
169170
{
170171
if (condition.MustHaveValidator)
171172
{
172-
validationContext.AddError(new ParseError($"{commandResult.Command.Name} must have {condition.Name} validator."));
173+
validationContext.AddError(new CliDiagnostic(new("", "", $"{commandResult.Command.Name} must have {condition.Name} validator.", severity: CliDiagnosticSeverity.Error, null), []));
173174
}
174175
return;
175176
}

‎src/System.CommandLine.Subsystems/ValueConditions/Range.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ internal Range(ValueSource<T>? lowerBound, ValueSource<T>? upperBound, RangeBoun
4040
LowerBound = lowerBound;
4141
UpperBound = upperBound;
4242
RangeBound = rangeBound;
43-
}
44-
43+
}
44+
4545
/// <inheritdoc/>
4646
public void Validate(object? value,
4747
CliValueSymbol valueSymbol,
@@ -59,15 +59,15 @@ public void Validate(object? value,
5959
&& validationContext.TryGetTypedValue(LowerBound, out var lowerValue)
6060
&& comparableValue.CompareTo(lowerValue) < 0)
6161
{
62-
validationContext.AddError(new ParseError($"The value for '{valueSymbol.Name}' is below the lower bound of {LowerBound}"));
62+
validationContext.AddError(new CliDiagnostic(new("", "", $"The value for '{valueSymbol.Name}' is below the lower bound of {LowerBound}", severity: CliDiagnosticSeverity.Error, null), [], cliSymbolResult: valueResult));
6363
}
6464

6565

6666
if (UpperBound is not null
6767
&& validationContext.TryGetTypedValue(UpperBound, out var upperValue)
6868
&& comparableValue.CompareTo(upperValue) > 0)
6969
{
70-
validationContext.AddError(new ParseError($"The value for '{valueSymbol.Name}' is above the upper bound of {UpperBound}"));
70+
validationContext.AddError(new CliDiagnostic(new("", "", $"The value for '{valueSymbol.Name}' is above the upper bound of {UpperBound}", severity: CliDiagnosticSeverity.Error, null), [], cliSymbolResult: valueResult));
7171
}
7272
}
7373

‎src/System.CommandLine/ParseResult.cs

+2-6
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33

44
using System.Collections.Generic;
55
using System.CommandLine.Parsing;
6-
using System.Linq;
7-
using System.Threading.Tasks;
8-
using System.Threading;
96

107
namespace System.CommandLine
118
{
@@ -39,7 +36,7 @@ internal ParseResult(
3936
*/
4037
// TODO: unmatched tokens
4138
// List<CliToken>? unmatchedTokens,
42-
List<ParseError>? errors,
39+
List<CliDiagnostic>? errors,
4340
// TODO: commandLineText should be string array
4441
string? commandLineText = null //,
4542
// TODO: invocation
@@ -82,12 +79,11 @@ internal ParseResult(
8279
// TODO: unmatched tokens
8380
// _unmatchedTokens = unmatchedTokens is null ? Array.Empty<CliToken>() : unmatchedTokens;
8481

85-
Errors = errors is not null ? errors : Array.Empty<ParseError>();
82+
Errors = errors is not null ? errors : Array.Empty<CliDiagnostic>();
8683
}
8784

8885
public CliSymbol? GetSymbolByName(string name, bool valuesOnly = false)
8986
{
90-
9187
symbolLookupByName ??= new SymbolLookupByName(this);
9288
return symbolLookupByName.TryGetSymbol(name, out var symbol, valuesOnly: valuesOnly)
9389
? symbol

‎src/System.CommandLine/Parsing/CliArgumentResultInternal.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ public void OnlyTake(int numberOfTokens)
138138
public override string ToString() => $"{nameof(CliArgumentResultInternal)} {Argument.Name}: {string.Join(" ", Tokens.Select(t => $"<{t.Value}>"))}";
139139

140140
/// <inheritdoc/>
141-
internal override void AddError(string errorMessage)
141+
internal override void AddError(string errorMessage, CliValueResult valueResult)
142142
{
143-
SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, CliDiagnosticSeverity.Warning, null), [], symbolResult: AppliesToPublicSymbolResult));
143+
SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, CliDiagnosticSeverity.Warning, null), [], cliSymbolResult: valueResult));
144144
_conversionResult = ArgumentConversionResult.Failure(this, errorMessage, ArgumentConversionResultType.Failed);
145145
}
146146

@@ -218,7 +218,7 @@ ArgumentConversionResult ReportErrorIfNeeded(ArgumentConversionResult result)
218218
{
219219
if (result.Result >= ArgumentConversionResultType.Failed)
220220
{
221-
SymbolResultTree.AddError(new CliDiagnostic(new("ArgumentConversionResultTypeFailed", "Type Conversion Failed", result.ErrorMessage!, CliDiagnosticSeverity.Warning, null), [], symbolResult: AppliesToPublicSymbolResult));
221+
SymbolResultTree.AddError(new CliDiagnostic(new("ArgumentConversionResultTypeFailed", "Type Conversion Failed", result.ErrorMessage!, CliDiagnosticSeverity.Warning, null), [], cliSymbolResult: ValueResult));
222222
}
223223

224224
return result;

‎src/System.CommandLine/Parsing/CliCommandResultInternal.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ internal void Validate(bool completeValidation)
8484
if (Command.HasSubcommands)
8585
{
8686
SymbolResultTree.InsertFirstError(
87-
new CliDiagnostic(new("validateSubCommandError", "Validation Error", LocalizationResources.RequiredCommandWasNotProvided(), CliDiagnosticSeverity.Warning, null), [], symbolResult: this));
87+
new CliDiagnostic(new("validateSubCommandError", "Validation Error", LocalizationResources.RequiredCommandWasNotProvided(), CliDiagnosticSeverity.Warning, null), [], valueResult: ));
8888
}
8989
9090
// TODO: validators

‎src/System.CommandLine/Parsing/CliDiagnostic.cs

+8-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
// Copyright (c) .NET Foundation and contributors. All rights reserved.
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System.Collections.Immutable;
5+
using System.Diagnostics.CodeAnalysis;
56

67
namespace System.CommandLine.Parsing;
78

@@ -11,6 +12,7 @@ namespace System.CommandLine.Parsing;
1112
* https://github.com/mhutch/MonoDevelop.MSBuildEditor/blob/main/MonoDevelop.MSBuild/Analysis/MSBuildDiagnosticDescriptor.cs
1213
* https://github.com/dotnet/roslyn/blob/main/src/Compilers/Core/Portable/Diagnostic/DiagnosticDescriptor.cs
1314
* https://github.com/dotnet/roslyn/blob/main/src/Compilers/Core/Portable/Diagnostic/Diagnostic.cs
15+
* https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141791086
1416
*/
1517
internal static class ParseDiagnostics
1618
{
@@ -27,7 +29,7 @@ internal static class ParseDiagnostics
2729

2830
public sealed class CliDiagnosticDescriptor
2931
{
30-
public CliDiagnosticDescriptor(string id, string title, string messageFormat, CliDiagnosticSeverity severity, string? helpUri)
32+
public CliDiagnosticDescriptor(string id, string title, [StringSyntax(StringSyntaxAttribute.CompositeFormat)] string messageFormat, CliDiagnosticSeverity severity, string? helpUri)
3133
{
3234
Id = id;
3335
Title = title;
@@ -38,6 +40,7 @@ public CliDiagnosticDescriptor(string id, string title, string messageFormat, Cl
3840

3941
public string Id { get; }
4042
public string Title { get; }
43+
[StringSyntax(StringSyntaxAttribute.CompositeFormat)]
4144
public string MessageFormat { get; }
4245
public CliDiagnosticSeverity Severity { get; }
4346
public string? HelpUri { get; }
@@ -65,19 +68,18 @@ public sealed class CliDiagnostic
6568
/// <param name="descriptor">Contains information about the error.</param>
6669
/// <param name="messageArgs">The arguments to be passed to the <see cref="CliDiagnosticDescriptor.MessageFormat"/> in the <paramref name="descriptor"/>.</param>
6770
/// <param name="properties">Properties to be associated with the diagnostic.</param>
68-
/// <param name="symbolResult">The symbol result detailing the symbol that failed to parse and the tokens involved.</param>
71+
/// <param name="cliSymbolResult">Contains information about a single value entered.</param>
6972
/// <param name="location">The location of the error.</param>
7073
public CliDiagnostic(
7174
CliDiagnosticDescriptor descriptor,
7275
object?[]? messageArgs,
7376
ImmutableDictionary<string, object>? properties = null,
74-
SymbolResult? symbolResult = null,
77+
CliSymbolResult? cliSymbolResult = null,
7578
Location? location = null)
7679
{
7780
Descriptor = descriptor;
7881
MessageArgs = messageArgs;
7982
Properties = properties;
80-
SymbolResult = symbolResult;
8183
}
8284

8385
/// <summary>
@@ -101,10 +103,7 @@ public string Message
101103

102104
public object?[]? MessageArgs { get; }
103105

104-
/// <summary>
105-
/// Gets the symbol result detailing the symbol that failed to parse and the tokens involved.
106-
/// </summary>
107-
public SymbolResult? SymbolResult { get; }
106+
public CliSymbolResult? CliSymbolResult { get; }
108107

109108
/// <inheritdoc />
110109
public override string ToString() => Message;

‎src/System.CommandLine/Parsing/CliSymbolResultInternal.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ public IEnumerable<CliDiagnostic> Errors
6464
/// Adds an error message for this symbol result to it's parse tree.
6565
/// </summary>
6666
/// <remarks>Setting an error will cause the parser to indicate an error for the user and prevent invocation of the command line.</remarks>
67-
internal virtual void AddError(string errorMessage) => SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, severity: CliDiagnosticSeverity.Error, null), [], symbolResult: this));
67+
internal virtual void AddError(string errorMessage, CliValueResult valueResult) =>
68+
SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, severity: CliDiagnosticSeverity.Error, null), [], cliSymbolResult: valueResult));
6869
/// <summary>
6970
/// Finds a result for the specific argument anywhere in the parse tree, including parent and child symbol results.
7071
/// </summary>

‎src/System.CommandLine/Parsing/ParseOperation.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ internal ParseResult Parse()
7676
{
7777
if (_symbolResultTree.ErrorCount > 0)
7878
{
79-
_primaryAction = new ParseErrorAction();
79+
_primaryAction = new CliDiagnosticAction();
8080
}
8181
}
8282
*/

0 commit comments

Comments
 (0)