diff --git a/Directory.Packages.props b/Directory.Packages.props
index f46c178e87..1233827813 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,12 +1,10 @@
-
truefalse$(NoWarn);NU1507
-
@@ -24,14 +22,13 @@
-
+
+
-
-
-
+
\ No newline at end of file
diff --git a/src/System.CommandLine.Subsystems.Tests/ErrorReportingFunctionalTests.cs b/src/System.CommandLine.Subsystems.Tests/ErrorReportingFunctionalTests.cs
index 47e4808c18..f3e43ea5a0 100644
--- a/src/System.CommandLine.Subsystems.Tests/ErrorReportingFunctionalTests.cs
+++ b/src/System.CommandLine.Subsystems.Tests/ErrorReportingFunctionalTests.cs
@@ -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.
/*
@@ -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();
diff --git a/src/System.CommandLine.Subsystems.Tests/ErrorReportingSubsystemTests.cs b/src/System.CommandLine.Subsystems.Tests/ErrorReportingSubsystemTests.cs
index 1ce30a9422..b8284a71b5 100644
--- a/src/System.CommandLine.Subsystems.Tests/ErrorReportingSubsystemTests.cs
+++ b/src/System.CommandLine.Subsystems.Tests/ErrorReportingSubsystemTests.cs
@@ -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;
@@ -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 { error };
+ var error = new CliDiagnostic(new("", "", "a sweet error message", CliDiagnosticSeverity.Warning, null), []);
+ var errors = new List { error };
var errorSubsystem = new ErrorReportingSubsystem();
var consoleHack = new ConsoleHack().RedirectToBuffer(true);
@@ -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 { 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 { error, anotherError };
var errorSubsystem = new ErrorReportingSubsystem();
var consoleHack = new ConsoleHack().RedirectToBuffer(true);
@@ -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 { };
+ var errors = new List { };
var errorSubsystem = new ErrorReportingSubsystem();
var consoleHack = new ConsoleHack().RedirectToBuffer(true);
@@ -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("-v")};
+ var rootCommand = new CliRootCommand { new CliOption("-v") };
var configuration = new CliConfiguration(rootCommand);
var errorSubsystem = new ErrorReportingSubsystem();
IReadOnlyList args = [""];
diff --git a/src/System.CommandLine.Subsystems/ErrorReportingSubsystem.cs b/src/System.CommandLine.Subsystems/ErrorReportingSubsystem.cs
index 27f43ab9f2..039e700217 100644
--- a/src/System.CommandLine.Subsystems/ErrorReportingSubsystem.cs
+++ b/src/System.CommandLine.Subsystems/ErrorReportingSubsystem.cs
@@ -33,7 +33,7 @@ public override void Execute(PipelineResult pipelineResult)
pipelineResult.SetSuccess();
}
- public void Report(ConsoleHack consoleHack, IReadOnlyList errors)
+ public void Report(ConsoleHack consoleHack, IReadOnlyList errors)
{
ConsoleHelpers.ResetTerminalForegroundColor();
ConsoleHelpers.SetTerminalForegroundRed();
diff --git a/src/System.CommandLine.Subsystems/PipelineResult.cs b/src/System.CommandLine.Subsystems/PipelineResult.cs
index cb1763c3d1..8af9b55eda 100644
--- a/src/System.CommandLine.Subsystems/PipelineResult.cs
+++ b/src/System.CommandLine.Subsystems/PipelineResult.cs
@@ -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;
@@ -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 errors = [];
- private ValueProvider valueProvider { get; }
+ private readonly List errors = [];
+ private ValueProvider valueProvider { get; }
public PipelineResult(ParseResult parseResult, string rawInput, Pipeline? pipeline, ConsoleHack? consoleHack = null)
{
@@ -44,7 +44,7 @@ public PipelineResult(ParseResult parseResult, string rawInput, Pipeline? pipeli
=> ParseResult.GetValueResult(valueSymbol);
- public void AddErrors(IEnumerable errors)
+ public void AddErrors(IEnumerable errors)
{
if (errors is not null)
{
@@ -52,10 +52,10 @@ public void AddErrors(IEnumerable errors)
}
}
- public void AddError(ParseError error)
+ public void AddError(CliDiagnostic error)
=> errors.Add(error);
- public IEnumerable GetErrors(bool excludeParseErrors = false)
+ public IEnumerable GetErrors(bool excludeParseErrors = false)
=> excludeParseErrors || ParseResult is null
? errors
: ParseResult.Errors.Concat(errors);
diff --git a/src/System.CommandLine.Subsystems/Validation/InclusiveGroupValidator.cs b/src/System.CommandLine.Subsystems/Validation/InclusiveGroupValidator.cs
index 6c8a1c28e5..961b4538ab 100644
--- a/src/System.CommandLine.Subsystems/Validation/InclusiveGroupValidator.cs
+++ b/src/System.CommandLine.Subsystems/Validation/InclusiveGroupValidator.cs
@@ -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)]));
}
}
}
diff --git a/src/System.CommandLine.Subsystems/Validation/RangeValidator.cs b/src/System.CommandLine.Subsystems/Validation/RangeValidator.cs
index cfab72a183..5f0e682a45 100644
--- a/src/System.CommandLine.Subsystems/Validation/RangeValidator.cs
+++ b/src/System.CommandLine.Subsystems/Validation/RangeValidator.cs
@@ -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));
}
}
-
-
}
diff --git a/src/System.CommandLine.Subsystems/Validation/ValidationContext.cs b/src/System.CommandLine.Subsystems/Validation/ValidationContext.cs
index 3f22a12280..93c8bfe22d 100644
--- a/src/System.CommandLine.Subsystems/Validation/ValidationContext.cs
+++ b/src/System.CommandLine.Subsystems/Validation/ValidationContext.cs
@@ -3,7 +3,6 @@
using System.CommandLine.Parsing;
using System.CommandLine.ValueSources;
-using static System.Runtime.InteropServices.JavaScript.JSType;
namespace System.CommandLine.Validation;
@@ -24,7 +23,7 @@ internal ValidationContext(PipelineResult pipelineResult, ValidationSubsystem va
/// Adds an error to the PipelineContext.
///
/// The to add
- public void AddError(ParseError error)
+ public void AddError(CliDiagnostic error)
=> pipelineResult.AddError(error);
///
diff --git a/src/System.CommandLine.Subsystems/Validation/Validator.cs b/src/System.CommandLine.Subsystems/Validation/Validator.cs
index e33f732c11..e8d64e4a2e 100644
--- a/src/System.CommandLine.Subsystems/Validation/Validator.cs
+++ b/src/System.CommandLine.Subsystems/Validation/Validator.cs
@@ -31,11 +31,11 @@ internal Validator(string name, Type valueConditionType, params Type[] moreValue
///
/// This method needs to be evolved as we replace ParseError with CliError
///
- protected static List AddValidationError(ref List? parseErrors, string message, IEnumerable
/// Setting an error will cause the parser to indicate an error for the user and prevent invocation of the command line.
- internal virtual void AddError(string errorMessage) => SymbolResultTree.AddError(new ParseError(errorMessage, this));
+ internal virtual void AddError(string errorMessage, CliValueResult valueResult) =>
+ SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, severity: CliDiagnosticSeverity.Error, null), [], cliSymbolResult: valueResult));
///
/// Finds a result for the specific argument anywhere in the parse tree, including parent and child symbol results.
///
diff --git a/src/System.CommandLine/Parsing/Location.cs b/src/System.CommandLine/Parsing/Location.cs
index 30d3a5285e..dea0ccaa30 100644
--- a/src/System.CommandLine/Parsing/Location.cs
+++ b/src/System.CommandLine/Parsing/Location.cs
@@ -49,6 +49,7 @@ public Location(string text, string source, int index, Location? outerLocation,
public bool IsImplicit
=> Source == Implicit;
+ ///
public override string ToString()
=> $"{(OuterLocation is null ? "" : OuterLocation.ToString() + "; ")}{Text} from {Source}[{Index}, {Length}, {Offset}]";
diff --git a/src/System.CommandLine/Parsing/ParseDiagnostics.cs b/src/System.CommandLine/Parsing/ParseDiagnostics.cs
new file mode 100644
index 0000000000..b814c441e6
--- /dev/null
+++ b/src/System.CommandLine/Parsing/ParseDiagnostics.cs
@@ -0,0 +1,17 @@
+// 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.
+
+namespace System.CommandLine.Parsing;
+
+internal static class ParseDiagnostics
+{
+ public const string DirectiveIsNotDefinedId = "CMD0001";
+ public static readonly CliDiagnosticDescriptor DirectiveIsNotDefined =
+ new(
+ DirectiveIsNotDefinedId,
+ //TODO: use localized strings
+ "Directive is not defined",
+ "The directive '{0}' is not defined.",
+ CliDiagnosticSeverity.Error,
+ null);
+}
diff --git a/src/System.CommandLine/Parsing/ParseError.cs b/src/System.CommandLine/Parsing/ParseError.cs
deleted file mode 100644
index 9be6314ef3..0000000000
--- a/src/System.CommandLine/Parsing/ParseError.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.
-
-namespace System.CommandLine.Parsing
-{
- ///
- /// Describes an error that occurs while parsing command line input.
- ///
- public sealed class ParseError
- {
- // TODO: add position
- // TODO: reevaluate whether we should be exposing a CliSymbolResultInternal here
- internal ParseError(
- string message,
- CliSymbolResultInternal? symbolResult = null)
- {
- if (string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentException("Value cannot be null or whitespace.", nameof(message));
- }
-
- Message = message;
- /*
- CliSymbolResultInternal = symbolResult;
- */
- }
-
- public ParseError(
- string message)
- {
- if (string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentException("Value cannot be null or whitespace.", nameof(message));
- }
-
- Message = message;
- }
-
- ///
- /// A message to explain the error to a user.
- ///
- public string Message { get; }
-
- /* Consider how results are attached to errors now that we have ValueResult and CommandValueResult. Should there be a common base?
- ///
- /// The symbol result detailing the symbol that failed to parse and the tokens involved.
- ///
- public CliSymbolResultInternal? CliSymbolResultInternal { get; }
- */
-
- ///
- public override string ToString() => Message;
- }
-}
diff --git a/src/System.CommandLine/Parsing/ParseOperation.cs b/src/System.CommandLine/Parsing/ParseOperation.cs
index 3c941ecf97..50185de4a6 100644
--- a/src/System.CommandLine/Parsing/ParseOperation.cs
+++ b/src/System.CommandLine/Parsing/ParseOperation.cs
@@ -76,7 +76,7 @@ internal ParseResult Parse()
{
if (_symbolResultTree.ErrorCount > 0)
{
- _primaryAction = new ParseErrorAction();
+ _primaryAction = new CliDiagnosticAction();
}
}
*/
diff --git a/src/System.CommandLine/Parsing/SymbolResultTree.cs b/src/System.CommandLine/Parsing/SymbolResultTree.cs
index 571403bc27..1a6b3aeb9a 100644
--- a/src/System.CommandLine/Parsing/SymbolResultTree.cs
+++ b/src/System.CommandLine/Parsing/SymbolResultTree.cs
@@ -1,15 +1,14 @@
-// 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.Linq;
namespace System.CommandLine.Parsing
{
internal sealed class SymbolResultTree : Dictionary
{
private readonly CliCommand _rootCommand;
- internal List? Errors;
+ internal List? Errors;
// TODO: unmatched tokens
/*
internal List? UnmatchedTokens;
@@ -26,11 +25,13 @@ internal SymbolResultTree(
if (tokenizeErrors is not null)
{
- Errors = new List(tokenizeErrors.Count);
+ Errors = new List(tokenizeErrors.Count);
for (var i = 0; i < tokenizeErrors.Count; i++)
{
- Errors.Add(new ParseError(tokenizeErrors[i]));
+ Errors.Add(new CliDiagnostic(new("", "",
+ tokenizeErrors[i], CliDiagnosticSeverity.Warning, null), [],
+ cliSymbolResult: null));
}
}
}
@@ -82,8 +83,8 @@ internal IReadOnlyDictionary BuildValueResultDictiona
return dict;
}
- internal void AddError(ParseError parseError) => (Errors ??= new()).Add(parseError);
- internal void InsertFirstError(ParseError parseError) => (Errors ??= new()).Insert(0, parseError);
+ internal void AddError(CliDiagnostic CliDiagnostic) => (Errors ??= new()).Add(CliDiagnostic);
+ internal void InsertFirstError(CliDiagnostic CliDiagnostic) => (Errors ??= new()).Insert(0, CliDiagnostic);
internal void AddUnmatchedToken(CliToken token, CliCommandResultInternal commandResult, CliCommandResultInternal rootCommandResult)
{
@@ -99,7 +100,7 @@ internal void AddUnmatchedToken(CliToken token, CliCommandResultInternal command
}
*/
- AddError(new ParseError(LocalizationResources.UnrecognizedCommandOrArgument(token.Value), commandResult));
+ AddError(new CliDiagnostic(new("", "", LocalizationResources.UnrecognizedCommandOrArgument(token.Value), CliDiagnosticSeverity.Warning, null), []));
/*
}
*/
diff --git a/src/System.CommandLine/System.CommandLine.csproj b/src/System.CommandLine/System.CommandLine.csproj
index bee122292b..ea33049a7b 100644
--- a/src/System.CommandLine/System.CommandLine.csproj
+++ b/src/System.CommandLine/System.CommandLine.csproj
@@ -29,7 +29,10 @@
+
+
+
@@ -58,7 +61,7 @@
-
+
@@ -76,6 +79,7 @@
+