From 49b42177210994230703961c2dca58f758cfcfdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Fri, 13 Sep 2024 11:51:37 +0900 Subject: [PATCH 01/13] Add source when throwing format exception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- lib/src/arg_parser_exception.dart | 2 +- lib/src/parser.dart | 50 ++++++++++++++++++------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/lib/src/arg_parser_exception.dart b/lib/src/arg_parser_exception.dart index d727d70..078d355 100644 --- a/lib/src/arg_parser_exception.dart +++ b/lib/src/arg_parser_exception.dart @@ -9,6 +9,6 @@ class ArgParserException extends FormatException { /// This will be empty if the error was on the root parser. final List commands; - ArgParserException(super.message, [Iterable? commands]) + ArgParserException(super.message, super.source, [Iterable? commands]) : commands = commands == null ? const [] : List.unmodifiable(commands); } diff --git a/lib/src/parser.dart b/lib/src/parser.dart index 3c5dfed..935aacf 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -63,7 +63,8 @@ class Parser { // options so that commands can have option-like names. var command = _grammar.commands[_current]; if (command != null) { - _validate(_rest.isEmpty, 'Cannot specify arguments before a command.'); + _validate(_rest.isEmpty, 'Cannot specify arguments before a command.', + _current); var commandName = _args.removeFirst(); var commandParser = Parser(commandName, command, _args, this, _rest); @@ -71,7 +72,7 @@ class Parser { commandResults = commandParser.parse(); } on ArgParserException catch (error) { throw ArgParserException( - error.message, [commandName, ...error.commands]); + error.message, error.source, [commandName, ...error.commands]); } // All remaining arguments were passed to command so clear them here. @@ -101,7 +102,7 @@ class Parser { // Check if an option is mandatory and was passed; if not, throw an // exception. if (option.mandatory && parsedOption == null) { - throw ArgParserException('Option $name is mandatory.'); + throw ArgParserException('Option $name is mandatory.', name); } // ignore: avoid_dynamic_calls @@ -120,7 +121,8 @@ class Parser { /// Validates that there is a valid value there. void _readNextArgAsValue(Option option) { // Take the option argument from the next command line arg. - _validate(_args.isNotEmpty, 'Missing argument for "${option.name}".'); + _validate(_args.isNotEmpty, 'Missing argument for "${option.name}".', + option.name); _setOption(_results, option, _current); _args.removeFirst(); @@ -145,7 +147,8 @@ class Parser { var option = _grammar.findByAbbreviation(opt); if (option == null) { // Walk up to the parent command if possible. - _validate(_parent != null, 'Could not find an option or flag "-$opt".'); + _validate(_parent != null, 'Could not find an option or flag "-$opt".', + '-$opt'); return _parent!._handleSoloOption(opt); } @@ -193,8 +196,8 @@ class Parser { var first = _grammar.findByAbbreviation(c); if (first == null) { // Walk up to the parent command if possible. - _validate( - _parent != null, 'Could not find an option with short name "-$c".'); + _validate(_parent != null, + 'Could not find an option with short name "-$c".', '-$c'); return _parent! ._handleAbbreviation(lettersAndDigits, rest, innermostCommand); } else if (!first.isFlag) { @@ -208,7 +211,8 @@ class Parser { _validate( rest == '', 'Option "-$c" is a flag and cannot handle value ' - '"${lettersAndDigits.substring(1)}$rest".'); + '"${lettersAndDigits.substring(1)}$rest".', + '-$c'); // Not an option, so all characters should be flags. // We use "innermostCommand" here so that if a parent command parses the @@ -228,16 +232,16 @@ class Parser { var option = _grammar.findByAbbreviation(c); if (option == null) { // Walk up to the parent command if possible. - _validate( - _parent != null, 'Could not find an option with short name "-$c".'); + _validate(_parent != null, + 'Could not find an option with short name "-$c".', '-$c'); _parent!._parseShortFlag(c); return; } // In a list of short options, only the first can be a non-flag. If // we get here we've checked that already. - _validate( - option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".'); + _validate(option.isFlag, + 'Option "-$c" must be a flag to be in a collapsed "-".', '-$c'); _setFlag(_results, option, true); } @@ -269,8 +273,8 @@ class Parser { if (option != null) { _args.removeFirst(); if (option.isFlag) { - _validate( - value == null, 'Flag option "$name" should not be given a value.'); + _validate(value == null, + 'Flag option "$name" should not be given a value.', name); _setFlag(_results, option, true); } else if (value != null) { @@ -286,18 +290,20 @@ class Parser { option = _grammar.findByNameOrAlias(positiveName); if (option == null) { // Walk up to the parent command if possible. - _validate(_parent != null, 'Could not find an option named "$name".'); + _validate( + _parent != null, 'Could not find an option named "$name".', name); return _parent!._handleLongOption(name, value); } _args.removeFirst(); - _validate(option.isFlag, 'Cannot negate non-flag option "$name".'); - _validate(option.negatable!, 'Cannot negate option "$name".'); + _validate(option.isFlag, 'Cannot negate non-flag option "$name".', name); + _validate(option.negatable!, 'Cannot negate option "$name".', name); _setFlag(_results, option, false); } else { // Walk up to the parent command if possible. - _validate(_parent != null, 'Could not find an option named "$name".'); + _validate( + _parent != null, 'Could not find an option named "$name".', name); return _parent!._handleLongOption(name, value); } @@ -307,8 +313,10 @@ class Parser { /// Called during parsing to validate the arguments. /// /// Throws an [ArgParserException] if [condition] is `false`. - void _validate(bool condition, String message) { - if (!condition) throw ArgParserException(message); + void _validate(bool condition, String message, String source) { + if (!condition) { + throw ArgParserException(message, source); + } } /// Validates and stores [value] as the value for [option], which must not be @@ -347,7 +355,7 @@ class Parser { if (option.allowed == null) return; _validate(option.allowed!.contains(value), - '"$value" is not an allowed value for option "${option.name}".'); + '"$value" is not an allowed value for option "${option.name}".', value); } } From 68fee373e8f502c28e5cea1140810b8f8ea0f513 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Fri, 13 Sep 2024 11:55:41 +0900 Subject: [PATCH 02/13] update CHANGELOG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e572ec..27c98f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 2.5.1-wip +* Added source argument when throwing a `ArgParserException`. * Require Dart 3.3 ## 2.5.0 From 8de726bfa14963261215ee890a6bd662e22d894f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Sat, 14 Sep 2024 23:58:51 +0900 Subject: [PATCH 03/13] update parameter in a backward-compatible way MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- lib/src/arg_parser_exception.dart | 3 ++- lib/src/parser.dart | 11 ++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/src/arg_parser_exception.dart b/lib/src/arg_parser_exception.dart index 078d355..8e25277 100644 --- a/lib/src/arg_parser_exception.dart +++ b/lib/src/arg_parser_exception.dart @@ -9,6 +9,7 @@ class ArgParserException extends FormatException { /// This will be empty if the error was on the root parser. final List commands; - ArgParserException(super.message, super.source, [Iterable? commands]) + ArgParserException(super.message, + [Iterable? commands, super.source, super.offset]) : commands = commands == null ? const [] : List.unmodifiable(commands); } diff --git a/lib/src/parser.dart b/lib/src/parser.dart index 935aacf..25bb1a2 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -71,8 +71,8 @@ class Parser { try { commandResults = commandParser.parse(); } on ArgParserException catch (error) { - throw ArgParserException( - error.message, error.source, [commandName, ...error.commands]); + throw ArgParserException(error.message, + [commandName, ...error.commands], error.source, error.offset); } // All remaining arguments were passed to command so clear them here. @@ -102,7 +102,7 @@ class Parser { // Check if an option is mandatory and was passed; if not, throw an // exception. if (option.mandatory && parsedOption == null) { - throw ArgParserException('Option $name is mandatory.', name); + throw ArgParserException('Option $name is mandatory.', null, name); } // ignore: avoid_dynamic_calls @@ -313,9 +313,10 @@ class Parser { /// Called during parsing to validate the arguments. /// /// Throws an [ArgParserException] if [condition] is `false`. - void _validate(bool condition, String message, String source) { + void _validate(bool condition, String message, + [dynamic source, int? offset]) { if (!condition) { - throw ArgParserException(message, source); + throw ArgParserException(message, null, source, offset); } } From fa6838b370a118dcecf6e12aeec7cc6e8b13b31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Sun, 15 Sep 2024 01:04:17 +0900 Subject: [PATCH 04/13] chore clean up test code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- test/command_parse_test.dart | 6 +++--- test/parse_test.dart | 24 ++++++++++++------------ test/test_utils.dart | 6 ++++-- test/trailing_options_test.dart | 4 +++- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/test/command_parse_test.dart b/test/command_parse_test.dart index b6437c1..cfab871 100644 --- a/test/command_parse_test.dart +++ b/test/command_parse_test.dart @@ -139,7 +139,7 @@ void main() { var command = parser.addCommand('install'); command.addOption('path', abbr: 'p'); - throwsFormat(parser, ['-p', 'foo', 'install']); + throwsArgParserException(parser, ['-p', 'foo', 'install']); }); test('does not parse a command option before the command', () { @@ -147,7 +147,7 @@ void main() { var command = parser.addCommand('install'); command.addOption('path'); - throwsFormat(parser, ['--path', 'foo', 'install']); + throwsArgParserException(parser, ['--path', 'foo', 'install']); }); test('does not parse a command abbreviation before the command', () { @@ -156,7 +156,7 @@ void main() { command.addFlag('debug', abbr: 'd'); command.addFlag('verbose', abbr: 'v'); - throwsFormat(parser, ['-dv', 'install']); + throwsArgParserException(parser, ['-dv', 'install']); }); test('assigns collapsed options to the proper command', () { diff --git a/test/parse_test.dart b/test/parse_test.dart index b2dda44..bc0b517 100644 --- a/test/parse_test.dart +++ b/test/parse_test.dart @@ -50,7 +50,7 @@ void main() { var parser = ArgParser(); parser.addFlag('verbose'); - throwsFormat(parser, ['--verbose=true']); + throwsArgParserException(parser, ['--verbose=true']); }); test('are case-sensitive', () { @@ -189,7 +189,7 @@ void main() { var parser = ArgParser(); parser.addFlag('strum', negatable: false); - throwsFormat(parser, ['--no-strum']); + throwsArgParserException(parser, ['--no-strum']); }); }); @@ -399,14 +399,14 @@ void main() { test('throw if unknown', () { var parser = ArgParser(); - throwsFormat(parser, ['-f']); + throwsArgParserException(parser, ['-f']); }); test('throw if the value is missing', () { var parser = ArgParser(); parser.addOption('file', abbr: 'f'); - throwsFormat(parser, ['-f']); + throwsArgParserException(parser, ['-f']); }); test('does not throw if the value looks like an option', () { @@ -424,7 +424,7 @@ void main() { var parser = ArgParser(); parser.addOption('mode', abbr: 'm', allowed: ['debug', 'release']); - throwsFormat(parser, ['-mprofile']); + throwsArgParserException(parser, ['-mprofile']); }); group('throw if a comma-separated value is not allowed', () { @@ -433,7 +433,7 @@ void main() { parser .addMultiOption('mode', abbr: 'm', allowed: ['debug', 'release']); - throwsFormat(parser, ['-mdebug,profile']); + throwsArgParserException(parser, ['-mdebug,profile']); }); }); @@ -443,7 +443,7 @@ void main() { parser.addOption('banana', abbr: 'b'); // Takes an argument. parser.addFlag('cherry', abbr: 'c'); - throwsFormat(parser, ['-abc']); + throwsArgParserException(parser, ['-abc']); }); test('throw if it has a value but the option is a flag', () { @@ -452,7 +452,7 @@ void main() { parser.addFlag('banana', abbr: 'b'); // The '?!' means this can only be understood as '--apple b?!c'. - throwsFormat(parser, ['-ab?!c']); + throwsArgParserException(parser, ['-ab?!c']); }); test('are case-sensitive', () { @@ -496,14 +496,14 @@ void main() { test('throw if unknown', () { var parser = ArgParser(); - throwsFormat(parser, ['--unknown']); - throwsFormat(parser, ['--nobody']); // Starts with "no". + throwsArgParserException(parser, ['--unknown']); + throwsArgParserException(parser, ['--nobody']); // Starts with "no". }); test('throw if the arg does not include a value', () { var parser = ArgParser(); parser.addOption('mode'); - throwsFormat(parser, ['--mode']); + throwsArgParserException(parser, ['--mode']); }); test('do not throw if the value looks like an option', () { @@ -538,7 +538,7 @@ void main() { test('throw if the value is not in the allowed set', () { var parser = ArgParser(); parser.addOption('mode', allowed: ['debug', 'release']); - throwsFormat(parser, ['--mode=profile']); + throwsArgParserException(parser, ['--mode=profile']); }); test('returns last provided value', () { diff --git a/test/test_utils.dart b/test/test_utils.dart index f19da6d..9e4a22e 100644 --- a/test/test_utils.dart +++ b/test/test_utils.dart @@ -343,8 +343,10 @@ void throwsIllegalArg(void Function() function, {String? reason}) { expect(function, throwsArgumentError, reason: reason); } -void throwsFormat(ArgParser parser, List args) { - expect(() => parser.parse(args), throwsFormatException); +void throwsArgParserException(ArgParser parser, List args, + {String? reason}) { + expect(() => parser.parse(args), throwsA(isA()), + reason: reason); } Matcher throwsUsageException(Object? message, Object? usage) => diff --git a/test/trailing_options_test.dart b/test/trailing_options_test.dart index 505b6b1..0580090 100644 --- a/test/trailing_options_test.dart +++ b/test/trailing_options_test.dart @@ -5,6 +5,8 @@ import 'package:args/args.dart'; import 'package:test/test.dart'; +import 'test_utils.dart'; + void main() { test('allowTrailingOptions defaults to true', () { var parser = ArgParser(); @@ -18,7 +20,7 @@ void main() { }); void expectThrows(List args) { - expect(() => parser.parse(args), throwsFormatException, + throwsArgParserException(parser, args, reason: 'with allowTrailingOptions: true'); } From 7859972c7e0727db1b80ba421373440c9f0c3b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Sun, 15 Sep 2024 02:42:49 +0900 Subject: [PATCH 05/13] fix inconsistent `FormatException` messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- lib/src/arg_results.dart | 10 ++++---- lib/src/parser.dart | 43 +++++++++++++++++---------------- test/command_parse_test.dart | 6 ++--- test/command_runner_test.dart | 10 ++++---- test/parse_test.dart | 25 ++++++++++--------- test/test_utils.dart | 13 +++++++--- test/trailing_options_test.dart | 12 ++++----- 7 files changed, 64 insertions(+), 55 deletions(-) diff --git a/lib/src/arg_results.dart b/lib/src/arg_results.dart index 9fa87cd..72c4410 100644 --- a/lib/src/arg_results.dart +++ b/lib/src/arg_results.dart @@ -66,7 +66,7 @@ class ArgResults { /// > flags, [option] for options, and [multiOption] for multi-options. dynamic operator [](String name) { if (!_parser.options.containsKey(name)) { - throw ArgumentError('Could not find an option named "$name".'); + throw ArgumentError('Could not find an option named "--$name".'); } final option = _parser.options[name]!; @@ -83,7 +83,7 @@ class ArgResults { bool flag(String name) { var option = _parser.options[name]; if (option == null) { - throw ArgumentError('Could not find an option named "$name".'); + throw ArgumentError('Could not find an option named "--$name".'); } if (!option.isFlag) { throw ArgumentError('"$name" is not a flag.'); @@ -97,7 +97,7 @@ class ArgResults { String? option(String name) { var option = _parser.options[name]; if (option == null) { - throw ArgumentError('Could not find an option named "$name".'); + throw ArgumentError('Could not find an option named "--$name".'); } if (!option.isSingle) { throw ArgumentError('"$name" is a multi-option.'); @@ -111,7 +111,7 @@ class ArgResults { List multiOption(String name) { var option = _parser.options[name]; if (option == null) { - throw ArgumentError('Could not find an option named "$name".'); + throw ArgumentError('Could not find an option named "--$name".'); } if (!option.isMultiple) { throw ArgumentError('"$name" is not a multi-option.'); @@ -143,7 +143,7 @@ class ArgResults { /// [name] must be a valid option name in the parser. bool wasParsed(String name) { if (!_parser.options.containsKey(name)) { - throw ArgumentError('Could not find an option named "$name".'); + throw ArgumentError('Could not find an option named "--$name".'); } return _parsed.containsKey(name); diff --git a/lib/src/parser.dart b/lib/src/parser.dart index 25bb1a2..24c7fb1 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -119,12 +119,11 @@ class Parser { /// Pulls the value for [option] from the second argument in [_args]. /// /// Validates that there is a valid value there. - void _readNextArgAsValue(Option option) { + void _readNextArgAsValue(Option option, String source) { // Take the option argument from the next command line arg. - _validate(_args.isNotEmpty, 'Missing argument for "${option.name}".', - option.name); + _validate(_args.isNotEmpty, 'Missing argument for "$source".', source); - _setOption(_results, option, _current); + _setOption(_results, option, _current, source); _args.removeFirst(); } @@ -157,7 +156,7 @@ class Parser { if (option.isFlag) { _setFlag(_results, option, true); } else { - _readNextArgAsValue(option); + _readNextArgAsValue(option, '-$opt'); } return true; @@ -204,7 +203,7 @@ class Parser { // The first character is a non-flag option, so the rest must be the // value. var value = '${lettersAndDigits.substring(1)}$rest'; - _setOption(_results, first, value); + _setOption(_results, first, value, '-$c'); } else { // If we got some non-flag characters, then it must be a value, but // if we got here, it's a flag, which is wrong. @@ -274,15 +273,15 @@ class Parser { _args.removeFirst(); if (option.isFlag) { _validate(value == null, - 'Flag option "$name" should not be given a value.', name); + 'Flag option "--$name" should not be given a value.', '--$name'); _setFlag(_results, option, true); } else if (value != null) { // We have a value like --foo=bar. - _setOption(_results, option, value); + _setOption(_results, option, value, '--$name'); } else { // Option like --foo, so look for the value as the next arg. - _readNextArgAsValue(option); + _readNextArgAsValue(option, '--$name'); } } else if (name.startsWith('no-')) { // See if it's a negated flag. @@ -290,20 +289,22 @@ class Parser { option = _grammar.findByNameOrAlias(positiveName); if (option == null) { // Walk up to the parent command if possible. - _validate( - _parent != null, 'Could not find an option named "$name".', name); + _validate(_parent != null, 'Could not find an option named "--$name".', + '--$name'); return _parent!._handleLongOption(name, value); } _args.removeFirst(); - _validate(option.isFlag, 'Cannot negate non-flag option "$name".', name); - _validate(option.negatable!, 'Cannot negate option "$name".', name); + _validate( + option.isFlag, 'Cannot negate non-flag option "--$name".', '--$name'); + _validate( + option.negatable!, 'Cannot negate option "--$name".', '--$name'); _setFlag(_results, option, false); } else { // Walk up to the parent command if possible. - _validate( - _parent != null, 'Could not find an option named "$name".', name); + _validate(_parent != null, 'Could not find an option named "--$name".', + '--$name'); return _parent!._handleLongOption(name, value); } @@ -322,11 +323,11 @@ class Parser { /// Validates and stores [value] as the value for [option], which must not be /// a flag. - void _setOption(Map results, Option option, String value) { + void _setOption(Map results, Option option, String value, String source) { assert(!option.isFlag); if (!option.isMultiple) { - _validateAllowed(option, value); + _validateAllowed(option, value, source); results[option.name] = value; return; } @@ -335,11 +336,11 @@ class Parser { if (option.splitCommas) { for (var element in value.split(',')) { - _validateAllowed(option, element); + _validateAllowed(option, element, source); list.add(element); } } else { - _validateAllowed(option, value); + _validateAllowed(option, value, source); list.add(value); } } @@ -352,11 +353,11 @@ class Parser { } /// Validates that [value] is allowed as a value of [option]. - void _validateAllowed(Option option, String value) { + void _validateAllowed(Option option, String value, String source) { if (option.allowed == null) return; _validate(option.allowed!.contains(value), - '"$value" is not an allowed value for option "${option.name}".', value); + '"$value" is not an allowed value for option "$source".', source); } } diff --git a/test/command_parse_test.dart b/test/command_parse_test.dart index cfab871..e1b2f11 100644 --- a/test/command_parse_test.dart +++ b/test/command_parse_test.dart @@ -139,7 +139,7 @@ void main() { var command = parser.addCommand('install'); command.addOption('path', abbr: 'p'); - throwsArgParserException(parser, ['-p', 'foo', 'install']); + throwsArgParserException(parser, ['-p', 'foo', 'install'], '-p'); }); test('does not parse a command option before the command', () { @@ -147,7 +147,7 @@ void main() { var command = parser.addCommand('install'); command.addOption('path'); - throwsArgParserException(parser, ['--path', 'foo', 'install']); + throwsArgParserException(parser, ['--path', 'foo', 'install'], '--path'); }); test('does not parse a command abbreviation before the command', () { @@ -156,7 +156,7 @@ void main() { command.addFlag('debug', abbr: 'd'); command.addFlag('verbose', abbr: 'v'); - throwsArgParserException(parser, ['-dv', 'install']); + throwsArgParserException(parser, ['-dv', 'install'], '-d'); }); test('assigns collapsed options to the proper command', () { diff --git a/test/command_runner_test.dart b/test/command_runner_test.dart index cc80c6b..b9fde8a 100644 --- a/test/command_runner_test.dart +++ b/test/command_runner_test.dart @@ -583,7 +583,7 @@ Run "test help" to see global options. expect( runner.run(['--asdf']), throwsUsageException( - 'Could not find an option named "asdf".', _defaultUsage)); + 'Could not find an option named "--asdf".', _defaultUsage)); }); test('for a command throws the command usage', () { @@ -591,7 +591,7 @@ Run "test help" to see global options. runner.addCommand(command); expect(runner.run(['foo', '--asdf']), - throwsUsageException('Could not find an option named "asdf".', ''' + throwsUsageException('Could not find an option named "--asdf".', ''' Usage: test foo [arguments] -h, --help Print this usage information. @@ -616,7 +616,7 @@ Also, footer!''')); test('includes the footer in usage errors', () { expect( runner.run(['--bad']), - throwsUsageException('Could not find an option named "bad".', + throwsUsageException('Could not find an option named "--bad".', '$_defaultUsage\nAlso, footer!')); }); }); @@ -652,7 +652,7 @@ newlines properly.''')); test('includes the footer in usage errors', () { expect(runner.run(['--bad']), - throwsUsageException('Could not find an option named "bad".', ''' + throwsUsageException('Could not find an option named "--bad".', ''' Usage: test [arguments] Global options: @@ -679,7 +679,7 @@ newlines properly.''')); expect( runner.run(['--bad']), throwsUsageException( - 'Could not find an option named "bad".', _defaultUsage)); + 'Could not find an option named "--bad".', _defaultUsage)); }); test("a top-level command doesn't exist", () { diff --git a/test/parse_test.dart b/test/parse_test.dart index bc0b517..3b41ee9 100644 --- a/test/parse_test.dart +++ b/test/parse_test.dart @@ -50,7 +50,7 @@ void main() { var parser = ArgParser(); parser.addFlag('verbose'); - throwsArgParserException(parser, ['--verbose=true']); + throwsArgParserException(parser, ['--verbose=true'], '--verbose'); }); test('are case-sensitive', () { @@ -189,7 +189,7 @@ void main() { var parser = ArgParser(); parser.addFlag('strum', negatable: false); - throwsArgParserException(parser, ['--no-strum']); + throwsArgParserException(parser, ['--no-strum'], '--no-strum'); }); }); @@ -399,14 +399,14 @@ void main() { test('throw if unknown', () { var parser = ArgParser(); - throwsArgParserException(parser, ['-f']); + throwsArgParserException(parser, ['-f'], '-f'); }); test('throw if the value is missing', () { var parser = ArgParser(); parser.addOption('file', abbr: 'f'); - throwsArgParserException(parser, ['-f']); + throwsArgParserException(parser, ['-f'], '-f'); }); test('does not throw if the value looks like an option', () { @@ -424,7 +424,7 @@ void main() { var parser = ArgParser(); parser.addOption('mode', abbr: 'm', allowed: ['debug', 'release']); - throwsArgParserException(parser, ['-mprofile']); + throwsArgParserException(parser, ['-mprofile'], '-m'); }); group('throw if a comma-separated value is not allowed', () { @@ -433,7 +433,7 @@ void main() { parser .addMultiOption('mode', abbr: 'm', allowed: ['debug', 'release']); - throwsArgParserException(parser, ['-mdebug,profile']); + throwsArgParserException(parser, ['-mdebug,profile'], '-m'); }); }); @@ -443,7 +443,7 @@ void main() { parser.addOption('banana', abbr: 'b'); // Takes an argument. parser.addFlag('cherry', abbr: 'c'); - throwsArgParserException(parser, ['-abc']); + throwsArgParserException(parser, ['-abc'], '-b'); }); test('throw if it has a value but the option is a flag', () { @@ -452,7 +452,7 @@ void main() { parser.addFlag('banana', abbr: 'b'); // The '?!' means this can only be understood as '--apple b?!c'. - throwsArgParserException(parser, ['-ab?!c']); + throwsArgParserException(parser, ['-ab?!c'], '-a'); }); test('are case-sensitive', () { @@ -496,14 +496,15 @@ void main() { test('throw if unknown', () { var parser = ArgParser(); - throwsArgParserException(parser, ['--unknown']); - throwsArgParserException(parser, ['--nobody']); // Starts with "no". + throwsArgParserException(parser, ['--unknown'], '--unknown'); + throwsArgParserException( + parser, ['--nobody'], '--nobody'); // Starts with "no". }); test('throw if the arg does not include a value', () { var parser = ArgParser(); parser.addOption('mode'); - throwsArgParserException(parser, ['--mode']); + throwsArgParserException(parser, ['--mode'], '--mode'); }); test('do not throw if the value looks like an option', () { @@ -538,7 +539,7 @@ void main() { test('throw if the value is not in the allowed set', () { var parser = ArgParser(); parser.addOption('mode', allowed: ['debug', 'release']); - throwsArgParserException(parser, ['--mode=profile']); + throwsArgParserException(parser, ['--mode=profile'], '--mode'); }); test('returns last provided value', () { diff --git a/test/test_utils.dart b/test/test_utils.dart index 9e4a22e..9b67e9a 100644 --- a/test/test_utils.dart +++ b/test/test_utils.dart @@ -343,10 +343,17 @@ void throwsIllegalArg(void Function() function, {String? reason}) { expect(function, throwsArgumentError, reason: reason); } -void throwsArgParserException(ArgParser parser, List args, +void throwsArgParserException( + ArgParser parser, List args, String? source, {String? reason}) { - expect(() => parser.parse(args), throwsA(isA()), - reason: reason); + try { + parser.parse(args); + fail('Expected an ArgParserException'); + } on ArgParserException catch (e) { + expect(e.source, source); + } catch (e) { + fail('Expected an ArgParserException, but got $e'); + } } Matcher throwsUsageException(Object? message, Object? usage) => diff --git a/test/trailing_options_test.dart b/test/trailing_options_test.dart index 0580090..0cd4e68 100644 --- a/test/trailing_options_test.dart +++ b/test/trailing_options_test.dart @@ -19,8 +19,8 @@ void main() { parser = ArgParser(allowTrailingOptions: true); }); - void expectThrows(List args) { - throwsArgParserException(parser, args, + void expectThrows(List args, String source) { + throwsArgParserException(parser, args, source, reason: 'with allowTrailingOptions: true'); } @@ -58,7 +58,7 @@ void main() { test('throws on a trailing option missing its value', () { parser.addOption('opt'); - expectThrows(['arg', '--opt']); + expectThrows(['arg', '--opt'], '--opt'); }); test('parses a trailing option', () { @@ -69,16 +69,16 @@ void main() { }); test('throws on a trailing unknown flag', () { - expectThrows(['arg', '--xflag']); + expectThrows(['arg', '--xflag'], '--xflag'); }); test('throws on a trailing unknown option and value', () { - expectThrows(['arg', '--xopt', 'v']); + expectThrows(['arg', '--xopt', 'v'], '--xopt'); }); test('throws on a command', () { parser.addCommand('com'); - expectThrows(['arg', 'com']); + expectThrows(['arg', 'com'], 'com'); }); }); From 4be08f6a569c556081c6ccb6a3b1cf53e82f543c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Sun, 15 Sep 2024 02:44:00 +0900 Subject: [PATCH 06/13] update CHANGELOG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27c98f7..26f4c5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.5.1-wip * Added source argument when throwing a `ArgParserException`. +* Fix inconsistent `FormatException` messages * Require Dart 3.3 ## 2.5.0 From 7550d120cab612a18a75e62a2722d8cfe937e9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Wed, 25 Sep 2024 10:19:21 +0900 Subject: [PATCH 07/13] update: rename source to arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- lib/src/arg_parser_exception.dart | 5 ++++- lib/src/parser.dart | 30 +++++++++++++++++------------- test/test_utils.dart | 5 ++--- test/trailing_options_test.dart | 4 ++-- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/lib/src/arg_parser_exception.dart b/lib/src/arg_parser_exception.dart index 8e25277..dda5366 100644 --- a/lib/src/arg_parser_exception.dart +++ b/lib/src/arg_parser_exception.dart @@ -9,7 +9,10 @@ class ArgParserException extends FormatException { /// This will be empty if the error was on the root parser. final List commands; + /// The argument that were being parsed when the error was discovered. + final String? arg; + ArgParserException(super.message, - [Iterable? commands, super.source, super.offset]) + [Iterable? commands, this.arg, super.source, super.offset]) : commands = commands == null ? const [] : List.unmodifiable(commands); } diff --git a/lib/src/parser.dart b/lib/src/parser.dart index 24c7fb1..354ed2f 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -71,8 +71,12 @@ class Parser { try { commandResults = commandParser.parse(); } on ArgParserException catch (error) { - throw ArgParserException(error.message, - [commandName, ...error.commands], error.source, error.offset); + throw ArgParserException( + error.message, + [commandName, ...error.commands], + error.arg, + error.source, + error.offset); } // All remaining arguments were passed to command so clear them here. @@ -119,11 +123,11 @@ class Parser { /// Pulls the value for [option] from the second argument in [_args]. /// /// Validates that there is a valid value there. - void _readNextArgAsValue(Option option, String source) { + void _readNextArgAsValue(Option option, String arg) { // Take the option argument from the next command line arg. - _validate(_args.isNotEmpty, 'Missing argument for "$source".', source); + _validate(_args.isNotEmpty, 'Missing argument for "$arg".', arg); - _setOption(_results, option, _current, source); + _setOption(_results, option, _current, arg); _args.removeFirst(); } @@ -315,19 +319,19 @@ class Parser { /// /// Throws an [ArgParserException] if [condition] is `false`. void _validate(bool condition, String message, - [dynamic source, int? offset]) { + [String? args, List? source, int? offset]) { if (!condition) { - throw ArgParserException(message, null, source, offset); + throw ArgParserException(message, null, args, source, offset); } } /// Validates and stores [value] as the value for [option], which must not be /// a flag. - void _setOption(Map results, Option option, String value, String source) { + void _setOption(Map results, Option option, String value, String arg) { assert(!option.isFlag); if (!option.isMultiple) { - _validateAllowed(option, value, source); + _validateAllowed(option, value, arg); results[option.name] = value; return; } @@ -336,11 +340,11 @@ class Parser { if (option.splitCommas) { for (var element in value.split(',')) { - _validateAllowed(option, element, source); + _validateAllowed(option, element, arg); list.add(element); } } else { - _validateAllowed(option, value, source); + _validateAllowed(option, value, arg); list.add(value); } } @@ -353,11 +357,11 @@ class Parser { } /// Validates that [value] is allowed as a value of [option]. - void _validateAllowed(Option option, String value, String source) { + void _validateAllowed(Option option, String value, String arg) { if (option.allowed == null) return; _validate(option.allowed!.contains(value), - '"$value" is not an allowed value for option "$source".', source); + '"$value" is not an allowed value for option "$arg".', arg); } } diff --git a/test/test_utils.dart b/test/test_utils.dart index 9b67e9a..f1680cf 100644 --- a/test/test_utils.dart +++ b/test/test_utils.dart @@ -343,14 +343,13 @@ void throwsIllegalArg(void Function() function, {String? reason}) { expect(function, throwsArgumentError, reason: reason); } -void throwsArgParserException( - ArgParser parser, List args, String? source, +void throwsArgParserException(ArgParser parser, List args, String? arg, {String? reason}) { try { parser.parse(args); fail('Expected an ArgParserException'); } on ArgParserException catch (e) { - expect(e.source, source); + expect(e.arg, arg); } catch (e) { fail('Expected an ArgParserException, but got $e'); } diff --git a/test/trailing_options_test.dart b/test/trailing_options_test.dart index 0cd4e68..fb6bba0 100644 --- a/test/trailing_options_test.dart +++ b/test/trailing_options_test.dart @@ -19,8 +19,8 @@ void main() { parser = ArgParser(allowTrailingOptions: true); }); - void expectThrows(List args, String source) { - throwsArgParserException(parser, args, source, + void expectThrows(List args, String arg) { + throwsArgParserException(parser, args, arg, reason: 'with allowTrailingOptions: true'); } From fd5e80339f93434064e69b699633b1b8a7f36f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= Date: Wed, 25 Sep 2024 12:36:55 +0900 Subject: [PATCH 08/13] add test and cleanup test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: ふぁ --- test/command_parse_test.dart | 6 +-- test/parse_test.dart | 74 +++++++++++++++++++++++++++------ test/test_utils.dart | 11 ++++- test/trailing_options_test.dart | 3 +- 4 files changed, 74 insertions(+), 20 deletions(-) diff --git a/test/command_parse_test.dart b/test/command_parse_test.dart index e1b2f11..b6437c1 100644 --- a/test/command_parse_test.dart +++ b/test/command_parse_test.dart @@ -139,7 +139,7 @@ void main() { var command = parser.addCommand('install'); command.addOption('path', abbr: 'p'); - throwsArgParserException(parser, ['-p', 'foo', 'install'], '-p'); + throwsFormat(parser, ['-p', 'foo', 'install']); }); test('does not parse a command option before the command', () { @@ -147,7 +147,7 @@ void main() { var command = parser.addCommand('install'); command.addOption('path'); - throwsArgParserException(parser, ['--path', 'foo', 'install'], '--path'); + throwsFormat(parser, ['--path', 'foo', 'install']); }); test('does not parse a command abbreviation before the command', () { @@ -156,7 +156,7 @@ void main() { command.addFlag('debug', abbr: 'd'); command.addFlag('verbose', abbr: 'v'); - throwsArgParserException(parser, ['-dv', 'install'], '-d'); + throwsFormat(parser, ['-dv', 'install']); }); test('assigns collapsed options to the proper command', () { diff --git a/test/parse_test.dart b/test/parse_test.dart index 3b41ee9..9501b5d 100644 --- a/test/parse_test.dart +++ b/test/parse_test.dart @@ -50,7 +50,7 @@ void main() { var parser = ArgParser(); parser.addFlag('verbose'); - throwsArgParserException(parser, ['--verbose=true'], '--verbose'); + throwsFormat(parser, ['--verbose=true']); }); test('are case-sensitive', () { @@ -189,7 +189,7 @@ void main() { var parser = ArgParser(); parser.addFlag('strum', negatable: false); - throwsArgParserException(parser, ['--no-strum'], '--no-strum'); + throwsFormat(parser, ['--no-strum']); }); }); @@ -399,14 +399,14 @@ void main() { test('throw if unknown', () { var parser = ArgParser(); - throwsArgParserException(parser, ['-f'], '-f'); + throwsFormat(parser, ['-f']); }); test('throw if the value is missing', () { var parser = ArgParser(); parser.addOption('file', abbr: 'f'); - throwsArgParserException(parser, ['-f'], '-f'); + throwsFormat(parser, ['-f']); }); test('does not throw if the value looks like an option', () { @@ -424,7 +424,7 @@ void main() { var parser = ArgParser(); parser.addOption('mode', abbr: 'm', allowed: ['debug', 'release']); - throwsArgParserException(parser, ['-mprofile'], '-m'); + throwsFormat(parser, ['-mprofile']); }); group('throw if a comma-separated value is not allowed', () { @@ -433,7 +433,7 @@ void main() { parser .addMultiOption('mode', abbr: 'm', allowed: ['debug', 'release']); - throwsArgParserException(parser, ['-mdebug,profile'], '-m'); + throwsFormat(parser, ['-mdebug,profile']); }); }); @@ -443,7 +443,7 @@ void main() { parser.addOption('banana', abbr: 'b'); // Takes an argument. parser.addFlag('cherry', abbr: 'c'); - throwsArgParserException(parser, ['-abc'], '-b'); + throwsFormat(parser, ['-abc']); }); test('throw if it has a value but the option is a flag', () { @@ -452,7 +452,7 @@ void main() { parser.addFlag('banana', abbr: 'b'); // The '?!' means this can only be understood as '--apple b?!c'. - throwsArgParserException(parser, ['-ab?!c'], '-a'); + throwsFormat(parser, ['-ab?!c']); }); test('are case-sensitive', () { @@ -496,15 +496,14 @@ void main() { test('throw if unknown', () { var parser = ArgParser(); - throwsArgParserException(parser, ['--unknown'], '--unknown'); - throwsArgParserException( - parser, ['--nobody'], '--nobody'); // Starts with "no". + throwsFormat(parser, ['--unknown']); + throwsFormat(parser, ['--nobody']); // Starts with "no". }); test('throw if the arg does not include a value', () { var parser = ArgParser(); parser.addOption('mode'); - throwsArgParserException(parser, ['--mode'], '--mode'); + throwsFormat(parser, ['--mode']); }); test('do not throw if the value looks like an option', () { @@ -539,7 +538,7 @@ void main() { test('throw if the value is not in the allowed set', () { var parser = ArgParser(); parser.addOption('mode', allowed: ['debug', 'release']); - throwsArgParserException(parser, ['--mode=profile'], '--mode'); + throwsFormat(parser, ['--mode=profile']); }); test('returns last provided value', () { @@ -767,5 +766,54 @@ void main() { expect(results.rest, equals(['stop', '--', 'arg'])); }); }); + + group('ArgParser Exception Tests', () { + test('throws exception for unknown option', () { + var parser = ArgParser(); + throwsArgParserException(parser, ['--verbose'], + 'Could not find an option named "--verbose".', [], '--verbose'); + throwsArgParserException( + parser, ['-v'], 'Could not find an option or flag "-v".', [], '-v'); + }); + + test('throws exception for flag with value', () { + var parser = ArgParser(); + parser.addFlag('flag', abbr: 'f'); + throwsArgParserException(parser, ['--flag=1'], + 'Flag option "--flag" should not be given a value.', [], '--flag'); + throwsArgParserException(parser, ['-f=1'], + 'Option "-f" is a flag and cannot handle value "=1".', [], '-f'); + }); + + test('throws exception after parsing multiple options', () { + var parser = ArgParser(); + parser.addOption('first'); + parser.addOption('second'); + throwsArgParserException( + parser, + ['--first', '1', '--second', '2', '--verbose', '3'], + 'Could not find an option named "--verbose".', + [], + '--verbose'); + }); + + test('throws exception for option with invalid value', () { + var parser = ArgParser(); + parser.addOption('first', allowed: ['a', 'b']); + throwsArgParserException(parser, ['--first', 'c'], + '"c" is not an allowed value for option "--first".', [], '--first'); + }); + + test('throws exception after parsing command', () { + var parser = ArgParser(); + parser.addCommand('command', ArgParser()); + throwsArgParserException( + parser, + ['command', '--verbose'], + 'Could not find an option named "--verbose".', + ['command'], + '--verbose'); + }); + }); }); } diff --git a/test/test_utils.dart b/test/test_utils.dart index f1680cf..e0e6c9f 100644 --- a/test/test_utils.dart +++ b/test/test_utils.dart @@ -343,12 +343,19 @@ void throwsIllegalArg(void Function() function, {String? reason}) { expect(function, throwsArgumentError, reason: reason); } -void throwsArgParserException(ArgParser parser, List args, String? arg, - {String? reason}) { +void throwsFormat(ArgParser parser, List args, {String? reason}) { + expect(() => parser.parse(args), throwsA(isA()), + reason: reason); +} + +void throwsArgParserException(ArgParser parser, List args, + String message, List commands, String arg) { try { parser.parse(args); fail('Expected an ArgParserException'); } on ArgParserException catch (e) { + expect(e.message, message); + expect(e.commands, commands); expect(e.arg, arg); } catch (e) { fail('Expected an ArgParserException, but got $e'); diff --git a/test/trailing_options_test.dart b/test/trailing_options_test.dart index fb6bba0..db502d1 100644 --- a/test/trailing_options_test.dart +++ b/test/trailing_options_test.dart @@ -20,8 +20,7 @@ void main() { }); void expectThrows(List args, String arg) { - throwsArgParserException(parser, args, arg, - reason: 'with allowTrailingOptions: true'); + throwsFormat(parser, args, reason: 'with allowTrailingOptions: true'); } test('collects non-options in rest', () { From b01f125a6a8abae3b6b21a0c12d39dc888c80ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=B5=E3=81=81?= <34892635+fa0311@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:11:40 +0900 Subject: [PATCH 09/13] Update lib/src/arg_parser_exception.dart Co-authored-by: Nate Bosch --- lib/src/arg_parser_exception.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/arg_parser_exception.dart b/lib/src/arg_parser_exception.dart index dda5366..b1bdd25 100644 --- a/lib/src/arg_parser_exception.dart +++ b/lib/src/arg_parser_exception.dart @@ -9,7 +9,7 @@ class ArgParserException extends FormatException { /// This will be empty if the error was on the root parser. final List commands; - /// The argument that were being parsed when the error was discovered. + /// The argument name that was being parsed when the error was discovered. final String? arg; ArgParserException(super.message, From 290d75bb8edb5faa8b3e2708ca6611e149903720 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 30 Sep 2024 19:36:56 +0000 Subject: [PATCH 10/13] Change to feature version bump Code using the new argument should depend on this version. --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26f4c5c..a205299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.5.1-wip +## 2.6.0-wip * Added source argument when throwing a `ArgParserException`. * Fix inconsistent `FormatException` messages diff --git a/pubspec.yaml b/pubspec.yaml index 2b70992..8e59181 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: args -version: 2.5.1-wip +version: 2.6.0-wip description: >- Library for defining parsers for parsing raw command-line arguments into a set of options and values using GNU and POSIX style options. From 4e48231e4d2f032b7cd2cffc0eff79c631b1439b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 30 Sep 2024 19:50:35 +0000 Subject: [PATCH 11/13] Use a more specific name Avoiding the acronym to follow Effective Dart, even though other names still use the abbreviation. Adding "Name" so the meaning is unambiguous. --- lib/src/arg_parser_exception.dart | 9 ++++++--- lib/src/parser.dart | 2 +- test/test_utils.dart | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/src/arg_parser_exception.dart b/lib/src/arg_parser_exception.dart index b1bdd25..e6a1868 100644 --- a/lib/src/arg_parser_exception.dart +++ b/lib/src/arg_parser_exception.dart @@ -9,10 +9,13 @@ class ArgParserException extends FormatException { /// This will be empty if the error was on the root parser. final List commands; - /// The argument name that was being parsed when the error was discovered. - final String? arg; + /// The name of the argument that was being parsed when the error was discovered. + final String? argumentName; ArgParserException(super.message, - [Iterable? commands, this.arg, super.source, super.offset]) + [Iterable? commands, + this.argumentName, + super.source, + super.offset]) : commands = commands == null ? const [] : List.unmodifiable(commands); } diff --git a/lib/src/parser.dart b/lib/src/parser.dart index 354ed2f..63ac111 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -74,7 +74,7 @@ class Parser { throw ArgParserException( error.message, [commandName, ...error.commands], - error.arg, + argumentNameerror.argumentName, error.source, error.offset); } diff --git a/test/test_utils.dart b/test/test_utils.dart index e0e6c9f..f7d8b8a 100644 --- a/test/test_utils.dart +++ b/test/test_utils.dart @@ -356,7 +356,7 @@ void throwsArgParserException(ArgParser parser, List args, } on ArgParserException catch (e) { expect(e.message, message); expect(e.commands, commands); - expect(e.arg, arg); + expect(e.argumentName, arg); } catch (e) { fail('Expected an ArgParserException, but got $e'); } From 5ace87547f1b7d0744071029d1ddd4b3662b5987 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 30 Sep 2024 20:40:59 +0000 Subject: [PATCH 12/13] fix bad replace --- lib/src/parser.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/parser.dart b/lib/src/parser.dart index 63ac111..660e56d 100644 --- a/lib/src/parser.dart +++ b/lib/src/parser.dart @@ -74,7 +74,7 @@ class Parser { throw ArgParserException( error.message, [commandName, ...error.commands], - argumentNameerror.argumentName, + error.argumentName, error.source, error.offset); } From 3b1b0bef1675b91717b44030b075f1dd87b7153f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 30 Sep 2024 20:43:21 +0000 Subject: [PATCH 13/13] Reflow comment --- lib/src/arg_parser_exception.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/arg_parser_exception.dart b/lib/src/arg_parser_exception.dart index e6a1868..fbee82b 100644 --- a/lib/src/arg_parser_exception.dart +++ b/lib/src/arg_parser_exception.dart @@ -9,7 +9,8 @@ class ArgParserException extends FormatException { /// This will be empty if the error was on the root parser. final List commands; - /// The name of the argument that was being parsed when the error was discovered. + /// The name of the argument that was being parsed when the error was + /// discovered. final String? argumentName; ArgParserException(super.message,