Skip to content

More parsing improvements #2016

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

Merged
merged 12 commits into from
Jan 12, 2023
Merged
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
2 changes: 1 addition & 1 deletion src/System.CommandLine/ArgumentArity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public override int GetHashCode()
var argumentResult = symbolResult switch
{
ArgumentResult a => a,
_ => symbolResult.Root!.FindResultFor(argument)
_ => symbolResult.FindResultFor(argument)
};

var tokenCount = argumentResult?.Tokens.Count ?? 0;
Expand Down
18 changes: 11 additions & 7 deletions src/System.CommandLine/ParseResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,26 +224,30 @@ currentSymbol is not null
? currentSymbol.GetCompletions(context)
: Array.Empty<CompletionItem>();

string[] optionsWithArgumentLimitReached = currentSymbolResult is CommandResult commandResult
? OptionsWithArgumentLimitReached(commandResult)
: Array.Empty<string>();

completions =
completions.Where(item => OptionsWithArgumentLimitReached(currentSymbolResult).All(s => s != item.Label));
completions.Where(item => optionsWithArgumentLimitReached.All(s => s != item.Label));

return completions;

static IEnumerable<string> OptionsWithArgumentLimitReached(SymbolResult symbolResult) =>
symbolResult
static string[] OptionsWithArgumentLimitReached(CommandResult commandResult) =>
commandResult
.Children
.Where(c => c.IsArgumentLimitReached)
.OfType<OptionResult>()
.Select(o => o.Symbol)
.OfType<IdentifierSymbol>()
.SelectMany(c => c.Aliases);
.Select(o => o.Option)
.SelectMany(c => c.Aliases)
.ToArray();
}

private SymbolResult SymbolToComplete(int? position = null)
{
var commandResult = CommandResult;

var allSymbolResultsForCompletion = AllSymbolResultsForCompletion().ToArray();
var allSymbolResultsForCompletion = AllSymbolResultsForCompletion();

var currentSymbol = allSymbolResultsForCompletion.Last();

Expand Down
2 changes: 1 addition & 1 deletion src/System.CommandLine/Parsing/ArgumentResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace System.CommandLine.Parsing
/// <summary>
/// A result produced when parsing an <see cref="Argument"/>.
/// </summary>
public class ArgumentResult : SymbolResult
public sealed class ArgumentResult : SymbolResult
{
private ArgumentConversionResult? _conversionResult;

Expand Down
4 changes: 2 additions & 2 deletions src/System.CommandLine/Parsing/CommandArgumentNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

namespace System.CommandLine.Parsing
{
internal class CommandArgumentNode : SyntaxNode
internal sealed class CommandArgumentNode : SyntaxNode
{
public CommandArgumentNode(
Token token,
Argument argument,
CommandNode parent) : base(token, parent)
CommandNode parent) : base(token)
{
Debug.Assert(token.Type == TokenType.Argument, $"Incorrect token type: {token}");

Expand Down
5 changes: 2 additions & 3 deletions src/System.CommandLine/Parsing/CommandNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

namespace System.CommandLine.Parsing
{
internal class CommandNode : NonterminalSyntaxNode
internal sealed class CommandNode : NonterminalSyntaxNode
{
public CommandNode(
Token token,
Command command,
CommandNode? parent) : base(token, parent)
Command command) : base(token)
{
Command = command;
}
Expand Down
5 changes: 2 additions & 3 deletions src/System.CommandLine/Parsing/DirectiveNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@

namespace System.CommandLine.Parsing
{
internal class DirectiveNode : SyntaxNode
internal sealed class DirectiveNode : SyntaxNode
{
public DirectiveNode(
Token token,
CommandNode parent,
string name,
string? value) : base(token, parent)
string? value) : base(token)
{
Debug.Assert(token.Type == TokenType.Directive, $"Incorrect token type: {token}");

Expand Down
4 changes: 2 additions & 2 deletions src/System.CommandLine/Parsing/NonterminalSyntaxNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ internal abstract class NonterminalSyntaxNode : SyntaxNode
{
private List<SyntaxNode>? _children;

protected NonterminalSyntaxNode(Token token, SyntaxNode? parent) : base(token, parent)
protected NonterminalSyntaxNode(Token token) : base(token)
{
}

public IReadOnlyList<SyntaxNode> Children => _children is not null ? _children : Array.Empty<SyntaxNode>();
public IReadOnlyList<SyntaxNode>? Children => _children;

internal void AddChildNode(SyntaxNode node) => (_children ??= new()).Add(node);
}
Expand Down
4 changes: 2 additions & 2 deletions src/System.CommandLine/Parsing/OptionArgumentNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

namespace System.CommandLine.Parsing
{
internal class OptionArgumentNode : SyntaxNode
internal sealed class OptionArgumentNode : SyntaxNode
{
public OptionArgumentNode(
Token token,
Argument argument,
OptionNode parent) : base(token, parent)
OptionNode parent) : base(token)
{
Debug.Assert(token.Type == TokenType.Argument, $"Incorrect token type: {token}");

Expand Down
5 changes: 2 additions & 3 deletions src/System.CommandLine/Parsing/OptionNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

namespace System.CommandLine.Parsing
{
internal class OptionNode : NonterminalSyntaxNode
internal sealed class OptionNode : NonterminalSyntaxNode
{
public OptionNode(
Token token,
Option option,
CommandNode parent) : base(token, parent)
Option option) : base(token)
{
Option = option;
}
Expand Down
2 changes: 1 addition & 1 deletion src/System.CommandLine/Parsing/OptionResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace System.CommandLine.Parsing
/// <summary>
/// A result produced when parsing an <see cref="Option" />.
/// </summary>
public class OptionResult : SymbolResult
public sealed class OptionResult : SymbolResult
{
private ArgumentConversionResult? _argumentConversionResult;
private Dictionary<Argument, ArgumentResult>? _defaultArgumentValues;
Expand Down
12 changes: 5 additions & 7 deletions src/System.CommandLine/Parsing/ParseOperation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace System.CommandLine.Parsing
{
internal class ParseOperation
internal sealed class ParseOperation
{
private readonly List<Token> _tokens;
private readonly CommandLineConfiguration _configuration;
Expand Down Expand Up @@ -43,8 +43,7 @@ private CommandNode ParseRootCommand()
{
var rootCommandNode = new CommandNode(
CurrentToken,
_configuration.RootCommand,
null);
_configuration.RootCommand);

Advance();

Expand All @@ -57,7 +56,7 @@ private CommandNode ParseRootCommand()

private void ParseSubcommand(CommandNode parentNode)
{
var commandNode = new CommandNode(CurrentToken, (Command)CurrentToken.Symbol!, parentNode);
var commandNode = new CommandNode(CurrentToken, (Command)CurrentToken.Symbol!);

Advance();

Expand Down Expand Up @@ -135,8 +134,7 @@ private void ParseOption(CommandNode parent)
{
OptionNode optionNode = new(
CurrentToken,
(Option)CurrentToken.Symbol!,
parent);
(Option)CurrentToken.Symbol!);

Advance();

Expand Down Expand Up @@ -209,7 +207,7 @@ void ParseDirective(CommandNode parent)
? withoutBrackets.Slice(indexOfColon + 1).ToString()
: null;

var directiveNode = new DirectiveNode(token, parent, key, value);
var directiveNode = new DirectiveNode(token, key, value);

parent.AddChildNode(directiveNode);

Expand Down
61 changes: 27 additions & 34 deletions src/System.CommandLine/Parsing/ParseResultVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ internal sealed class ParseResultVisitor

private readonly Dictionary<Symbol, SymbolResult> _symbolResults = new();

private List<OptionResult>? _optionResults;
private List<ArgumentResult>? _argumentResults;

private RootCommandResult? _rootCommandResult;
Expand Down Expand Up @@ -52,9 +51,11 @@ internal ParseResultVisitor(
}
}

public void Visit(SyntaxNode node)
internal void Visit(CommandNode rootCommandNode)
{
VisitInternal(node);
VisitRootCommandNode(rootCommandNode);

VisitChildren(rootCommandNode);

Stop();
}
Expand All @@ -69,29 +70,16 @@ private void VisitInternal(SyntaxNode node)
break;

case CommandNode commandNode:
if (commandNode.Parent is null)
{
VisitRootCommandNode(commandNode);
}
else
{
VisitCommandNode(commandNode);
}
VisitCommandNode(commandNode);

for (var i = 0; i < commandNode.Children.Count; i++)
{
VisitInternal(commandNode.Children[i]);
}
VisitChildren(commandNode);

break;

case OptionNode optionNode:
VisitOptionNode(optionNode);

for (var i = 0; i < optionNode.Children.Count; i++)
{
VisitInternal(optionNode.Children[i]);
}
VisitChildren(optionNode);

break;

Expand All @@ -116,10 +104,7 @@ private void AddToResult(CommandResult result)
private void AddToResult(OptionResult result)
{
_innermostCommandResult?.AddChild(result);
if (_symbolResults.TryAdd(result.Option, result))
{
(_optionResults ??= new()).Add(result);
}
_symbolResults.TryAdd(result.Option, result);
}

private void AddToResult(ArgumentResult result)
Expand Down Expand Up @@ -241,6 +226,17 @@ private void VisitDirectiveNode(DirectiveNode directiveNode)
}
}

private void VisitChildren(NonterminalSyntaxNode parentNode)
{
if (parentNode.Children is not null)
{
for (var i = 0; i < parentNode.Children.Count; i++)
{
VisitInternal(parentNode.Children[i]);
}
}
}

private void Stop()
{
if (_isHelpRequested)
Expand All @@ -254,9 +250,9 @@ private void Stop()

ValidateCommandResult();

if (_optionResults is not null)
foreach (var symbolPair in _symbolResults)
{
foreach (var optionResult in _optionResults)
if (symbolPair.Value is OptionResult optionResult)
{
ValidateAndConvertOptionResult(optionResult);
}
Expand Down Expand Up @@ -307,7 +303,7 @@ private void ValidateAndConvertArgumentResults(IList<Argument> arguments, List<A
AddToResult(nextArgumentResult);
}

_symbolResults.TryAdd(nextArgumentResult.Symbol, nextArgumentResult);
_symbolResults.TryAdd(nextArgumentResult.Argument, nextArgumentResult);
}

if (commandArgumentResultCount >= argumentResults.Count)
Expand Down Expand Up @@ -560,8 +556,8 @@ private void PopulateDefaultValues()
var options = commandResult.Command.Options;
for (var i = 0; i < options.Count; i++)
{
Symbol symbol = options[i];
Handle(_rootCommandResult!.FindResultForSymbol(symbol), symbol);
Option option = options[i];
Handle(_rootCommandResult!.FindResultFor(option), option);
}
}

Expand All @@ -570,8 +566,8 @@ private void PopulateDefaultValues()
var arguments = commandResult.Command.Arguments;
for (var i = 0; i < arguments.Count; i++)
{
Symbol symbol = arguments[i];
Handle(_rootCommandResult!.FindResultForSymbol(symbol), symbol);
Argument argument = arguments[i];
Handle(_rootCommandResult!.FindResultFor(argument), argument);
}
}

Expand Down Expand Up @@ -608,10 +604,7 @@ void Handle(SymbolResult? symbolResult, Symbol symbol)

optionResult.AddChild(childArgumentResult);
commandResult.AddChild(optionResult);
if (_symbolResults.TryAdd(optionResult.Symbol, optionResult))
{
(_optionResults ??= new()).Add(optionResult);
}
_symbolResults.TryAdd(optionResult.Option, optionResult);

break;

Expand Down
Loading