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

feat: Change ParseError to CliDiagnostic #2493

Draft
wants to merge 3 commits into
base: main-powderhouse
Choose a base branch
from
Draft
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
9 changes: 3 additions & 6 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<Project>

<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
<!-- Using multiple feeds isn't supported by Maestro: https://github.com/dotnet/arcade/issues/14155. -->
<NoWarn>$(NoWarn);NU1507</NoWarn>
</PropertyGroup>

<ItemGroup>
<!-- Roslyn dependencies -->
<PackageVersion Include="Microsoft.CodeAnalysis" Version="4.0.1" />
Expand All @@ -24,14 +22,13 @@
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.2" />
<PackageVersion Include="System.Memory" Version="4.5.4" />
<PackageVersion Include="System.Collections.Immutable" Version="8.0.0" />
<PackageVersion Include="System.Memory" Version="4.5.5" />
<PackageVersion Include="system.reactive.core" Version="5.0.0" />
</ItemGroup>

<ItemGroup Condition="'$(DisableArcade)' == '1'">
<!-- The xunit version should be kept in sync with the one that Arcade promotes -->
<PackageVersion Include="xunit" Version="2.4.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.3" />
</ItemGroup>

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

/*
Expand Down Expand Up @@ -56,9 +56,9 @@ public void Help_display_can_be_disabled()

var result = rootCommand.Parse("oops", config);

if (result.Action is ParseErrorAction parseError)
if (result.Action is CliDiagnosticAction cliDiagnostic)
{
parseError.ShowHelp = false;
cliDiagnostic.ShowHelp = false;
}

result.Invoke();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.CommandLine.Parsing;
using FluentAssertions;
using Xunit;
using System.CommandLine.Parsing;

namespace System.CommandLine.Subsystems.Tests;

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

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

Expand All @@ -39,7 +39,7 @@ public void Report_when_multiple_error_writes_to_console_hack()
[Fact]
public void Report_when_no_errors_writes_nothing_to_console_hack()
{
var errors = new List<ParseError> { };
var errors = new List<CliDiagnostic> { };
var errorSubsystem = new ErrorReportingSubsystem();
var consoleHack = new ConsoleHack().RedirectToBuffer(true);

Expand All @@ -53,7 +53,7 @@ public void Report_when_no_errors_writes_nothing_to_console_hack()
[InlineData("-non_existant_option")]
public void GetIsActivated_GivenInvalidInput_SubsystemIsActive(string input)
{
var rootCommand = new CliRootCommand {new CliOption<bool>("-v")};
var rootCommand = new CliRootCommand { new CliOption<bool>("-v") };
var configuration = new CliConfiguration(rootCommand);
var errorSubsystem = new ErrorReportingSubsystem();
IReadOnlyList<string> args = [""];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public override void Execute(PipelineResult pipelineResult)
pipelineResult.SetSuccess();
}

public void Report(ConsoleHack consoleHack, IReadOnlyList<ParseError> errors)
public void Report(ConsoleHack consoleHack, IReadOnlyList<CliDiagnostic> errors)
{
ConsoleHelpers.ResetTerminalForegroundColor();
ConsoleHelpers.SetTerminalForegroundRed();
Expand Down
12 changes: 6 additions & 6 deletions src/System.CommandLine.Subsystems/PipelineResult.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

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

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


public void AddErrors(IEnumerable<ParseError> errors)
public void AddErrors(IEnumerable<CliDiagnostic> errors)
{
if (errors is not null)
{
this.errors.AddRange(errors);
}
}

public void AddError(ParseError error)
public void AddError(CliDiagnostic error)
=> errors.Add(error);

public IEnumerable<ParseError> GetErrors(bool excludeParseErrors = false)
public IEnumerable<CliDiagnostic> GetErrors(bool excludeParseErrors = false)
=> excludeParseErrors || ParseResult is null
? errors
: ParseResult.Errors.Concat(errors);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public override void Validate(CliCommandResult commandResult,
// TODO: Rework to allow localization
var pluralToBe = "are";
var singularToBe = "is";
validationContext.AddError(new ParseError( $"The members {string.Join(", ", groupMembers.Select(m => m.Name))} " +
$"must all be used if one is used. {string.Join(", ", missingMembers.Select(m => m.Name))} " +
$"{(missingMembers.Skip(1).Any() ? pluralToBe : singularToBe)} missing."));
validationContext.AddError(new CliDiagnostic(new("", "", "The members {groupMembers} " +
"must all be used if one is used. {missingMembers} " +
"{toBe} missing.", severity: CliDiagnosticSeverity.Error, null), [string.Join(", ", groupMembers.Select(m => m.Name)), string.Join(", ", missingMembers.Select(m => m.Name)), (missingMembers.Skip(1).Any() ? pluralToBe : singularToBe)]));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ public override void Validate(object? value, CliValueSymbol valueSymbol,
}
if (valueCondition.MustHaveValidator)
{
validationContext.AddError(new ParseError($"Range validator missing for {valueSymbol.Name}"));
validationContext.AddError(new CliDiagnostic(new("", "", "Range validator missing for {valueSymbol}", severity: CliDiagnosticSeverity.Error, null), [valueSymbol.Name], cliSymbolResult: valueResult));
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.CommandLine.Parsing;
using System.CommandLine.ValueSources;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace System.CommandLine.Validation;

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

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions src/System.CommandLine.Subsystems/Validation/Validator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ internal Validator(string name, Type valueConditionType, params Type[] moreValue
/// <remarks>
/// This method needs to be evolved as we replace ParseError with CliError
/// </remarks>
protected static List<ParseError> AddValidationError(ref List<ParseError>? parseErrors, string message, IEnumerable<object?> errorValues)
protected static List<CliDiagnostic> AddValidationError(ref List<CliDiagnostic>? parseErrors, string message, IEnumerable<object?> errorValues)
{
// 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.
parseErrors ??= new List<ParseError>();
parseErrors.Add(new ParseError(message));
parseErrors ??= new List<CliDiagnostic>();
parseErrors.Add(new CliDiagnostic(new("", "", message, severity: CliDiagnosticSeverity.Error, null), []));
return parseErrors;
}

Expand Down
9 changes: 5 additions & 4 deletions src/System.CommandLine.Subsystems/ValidationSubsystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ private void ValidateValue(CliValueSymbol valueSymbol, ValidationContext validat
var value = validationContext.GetValue(valueSymbol);
var valueResult = validationContext.GetValueResult(valueSymbol);

do {
do
{
ValidateValueCondition(value, valueSymbol, valueResult, enumerator.Current, validationContext);
} while (enumerator.MoveNext());
}
Expand Down Expand Up @@ -123,9 +124,9 @@ private void ValidateValueCondition(object? value, CliValueSymbol valueSymbol, C
{
if (condition.MustHaveValidator)
{
validationContext.AddError(new ParseError($"{valueSymbol.Name} must have {condition.Name} validator."));
validationContext.AddError(new CliDiagnostic(new("", "", "{valueSymbol} must have {condition} validator.", severity: CliDiagnosticSeverity.Error, null), [valueSymbol.Name, condition.Name], cliSymbolResult: valueResult));
}
return;
return;
}
validator.Validate(value, valueSymbol, valueResult, condition, validationContext);

Expand Down Expand Up @@ -169,7 +170,7 @@ private void ValidateCommandCondition(CliCommandResult commandResult, CommandCon
{
if (condition.MustHaveValidator)
{
validationContext.AddError(new ParseError($"{commandResult.Command.Name} must have {condition.Name} validator."));
validationContext.AddError(new CliDiagnostic(new("", "", "{commandResult} must have {condition} validator.", severity: CliDiagnosticSeverity.Error, null), [commandResult.Command.Name, condition.Name]));
}
return;
}
Expand Down
8 changes: 4 additions & 4 deletions src/System.CommandLine.Subsystems/ValueConditions/Range.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ internal Range(ValueSource<T>? lowerBound, ValueSource<T>? upperBound, RangeBoun
LowerBound = lowerBound;
UpperBound = upperBound;
RangeBound = rangeBound;
}
}

/// <inheritdoc/>
public void Validate(object? value,
CliValueSymbol valueSymbol,
Expand All @@ -59,15 +59,15 @@ public void Validate(object? value,
&& validationContext.TryGetTypedValue(LowerBound, out var lowerValue)
&& comparableValue.CompareTo(lowerValue) < 0)
{
validationContext.AddError(new ParseError($"The value for '{valueSymbol.Name}' is below the lower bound of {LowerBound}"));
validationContext.AddError(new CliDiagnostic(new("", "", "The value for '{valueSymbol}' is below the lower bound of {lowerBound}", severity: CliDiagnosticSeverity.Error, null), [valueSymbol.Name, LowerBound], cliSymbolResult: valueResult));
}


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

Expand Down
12 changes: 4 additions & 8 deletions src/System.CommandLine/ParseResult.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
using System.CommandLine.Parsing;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;

namespace System.CommandLine
{
Expand Down Expand Up @@ -39,7 +36,7 @@ internal ParseResult(
*/
// TODO: unmatched tokens
// List<CliToken>? unmatchedTokens,
List<ParseError>? errors,
List<CliDiagnostic>? errors,
// TODO: commandLineText should be string array
string? commandLineText = null //,
// TODO: invocation
Expand Down Expand Up @@ -82,12 +79,11 @@ internal ParseResult(
// TODO: unmatched tokens
// _unmatchedTokens = unmatchedTokens is null ? Array.Empty<CliToken>() : unmatchedTokens;

Errors = errors is not null ? errors : Array.Empty<ParseError>();
Errors = errors is not null ? errors : Array.Empty<CliDiagnostic>();
}

public CliSymbol? GetSymbolByName(string name, bool valuesOnly = false)
{

symbolLookupByName ??= new SymbolLookupByName(this);
return symbolLookupByName.TryGetSymbol(name, out var symbol, valuesOnly: valuesOnly)
? symbol
Expand Down Expand Up @@ -121,7 +117,7 @@ internal ParseResult(
/// <summary>
/// Gets the parse errors found while parsing command line input.
/// </summary>
public IReadOnlyList<ParseError> Errors { get; }
public IReadOnlyList<CliDiagnostic> Errors { get; }

/*
// TODO: don't expose tokens
Expand Down
7 changes: 3 additions & 4 deletions src/System.CommandLine/Parsing/CliArgumentResultInternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ public void OnlyTake(int numberOfTokens)
public override string ToString() => $"{nameof(CliArgumentResultInternal)} {Argument.Name}: {string.Join(" ", Tokens.Select(t => $"<{t.Value}>"))}";

/// <inheritdoc/>
internal override void AddError(string errorMessage)
internal override void AddError(string errorMessage, CliValueResult valueResult)
{
SymbolResultTree.AddError(new ParseError(errorMessage, AppliesToPublicSymbolResult));
SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, CliDiagnosticSeverity.Warning, null), [], cliSymbolResult: valueResult));
_conversionResult = ArgumentConversionResult.Failure(this, errorMessage, ArgumentConversionResultType.Failed);
}

Expand Down Expand Up @@ -170,7 +170,6 @@ private ArgumentConversionResult ValidateAndConvert(bool useValidators)
}
}
*/

// TODO: defaults
/*
if (Parent!.UseDefaultValueFor(this))
Expand Down Expand Up @@ -222,7 +221,7 @@ ArgumentConversionResult ReportErrorIfNeeded(ArgumentConversionResult result)
{
if (result.Result >= ArgumentConversionResultType.Failed)
{
SymbolResultTree.AddError(new ParseError(result.ErrorMessage!, AppliesToPublicSymbolResult));
SymbolResultTree.AddError(new CliDiagnostic(new("ArgumentConversionResultTypeFailed", "Type Conversion Failed", result.ErrorMessage!, CliDiagnosticSeverity.Warning, null), [], cliSymbolResult: ValueResult));
}

return result;
Expand Down
4 changes: 2 additions & 2 deletions src/System.CommandLine/Parsing/CliCommandResultInternal.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections.Generic;
Expand Down Expand Up @@ -84,7 +84,7 @@ internal void Validate(bool completeValidation)
if (Command.HasSubcommands)
{
SymbolResultTree.InsertFirstError(
new ParseError(LocalizationResources.RequiredCommandWasNotProvided(), this));
new CliDiagnostic(new("validateSubCommandError", "Validation Error", LocalizationResources.RequiredCommandWasNotProvided(), CliDiagnosticSeverity.Warning, null), [], valueResult: ));
}

// TODO: validators
Expand Down
Loading
Loading