-
Notifications
You must be signed in to change notification settings - Fork 391
/
Copy pathSymbolResult.cs
157 lines (138 loc) · 6.6 KB
/
SymbolResult.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// 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;
namespace System.CommandLine.Parsing
{
/// <summary>
/// A result produced during parsing for a specific symbol.
/// </summary>
public abstract class SymbolResult
{
// TODO: make this a property and protected if possible
internal readonly SymbolResultTree SymbolResultTree;
private protected List<CliToken>? _tokens;
private protected SymbolResult(SymbolResultTree symbolResultTree, SymbolResult? parent)
{
SymbolResultTree = symbolResultTree;
Parent = parent;
}
// TODO: this can be an extension method, do we need it?
/*
/// <summary>
/// The parse errors associated with this symbol result.
/// </summary>
public IEnumerable<CliDiagnostic> Errors
{
get
{
var parseErrors = SymbolResultTree.Errors;
if (parseErrors is null)
{
yield break;
}
for (var i = 0; i < parseErrors.Count; i++)
{
var parseError = parseErrors[i];
if (parseError.SymbolResult == this)
{
yield return parseError;
}
}
}
}
*/
/// <summary>
/// The parent symbol result in the parse tree.
/// </summary>
public SymbolResult? Parent { get; }
// TODO: make internal because exposes tokens
/// <summary>
/// The list of tokens associated with this symbol result during parsing.
/// </summary>
internal IReadOnlyList<CliToken> Tokens => _tokens is not null ? _tokens : Array.Empty<CliToken>();
internal void AddToken(CliToken token) => (_tokens ??= new()).Add(token);
// TODO: made nonpublic, should we make public again?
/// <summary>
/// Adds an error message for this symbol result to it's parse tree.
/// </summary>
/// <remarks>Setting an error will cause the parser to indicate an error for the user and prevent invocation of the command line.</remarks>
internal virtual void AddError(string errorMessage) => SymbolResultTree.AddError(new CliDiagnostic(new("", "", errorMessage, severity: CliDiagnosticSeverity.Error, null), [], symbolResult: this));
/// <summary>
/// Finds a result for the specific argument anywhere in the parse tree, including parent and child symbol results.
/// </summary>
/// <param name="argument">The argument for which to find a result.</param>
/// <returns>An argument result if the argument was matched by the parser or has a default value; otherwise, <c>null</c>.</returns>
public ArgumentResult? GetResult(CliArgument argument) => SymbolResultTree.GetResult(argument);
/// <summary>
/// Finds a result for the specific command anywhere in the parse tree, including parent and child symbol results.
/// </summary>
/// <param name="command">The command for which to find a result.</param>
/// <returns>An command result if the command was matched by the parser; otherwise, <c>null</c>.</returns>
public CommandResult? GetResult(CliCommand command) => SymbolResultTree.GetResult(command);
/// <summary>
/// Finds a result for the specific option anywhere in the parse tree, including parent and child symbol results.
/// </summary>
/// <param name="option">The option for which to find a result.</param>
/// <returns>An option result if the option was matched by the parser or has a default value; otherwise, <c>null</c>.</returns>
public OptionResult? GetResult(CliOption option) => SymbolResultTree.GetResult(option);
// TODO: directives
/*
/// <summary>
/// Finds a result for the specific directive anywhere in the parse tree.
/// </summary>
/// <param name="directive">The directive for which to find a result.</param>
/// <returns>A directive result if the directive was matched by the parser, <c>null</c> otherwise.</returns>
public DirectiveResult? GetResult(CliDirective directive) => SymbolResultTree.GetResult(directive);
*/
/// <summary>
/// Finds a result for a symbol having the specified name anywhere in the parse tree.
/// </summary>
/// <param name="name">The name of the symbol for which to find a result.</param>
/// <returns>An argument result if the argument was matched by the parser or has a default value; otherwise, <c>null</c>.</returns>
public SymbolResult? GetResult(string name) =>
SymbolResultTree.GetResult(name);
/// <inheritdoc cref="ParseResult.GetValue{T}(CliArgument{T})"/>
public T? GetValue<T>(CliArgument<T> argument)
{
if (GetResult(argument) is { } result &&
result.GetValueOrDefault<T>() is { } t)
{
return t;
}
return CliArgument<T>.CreateDefaultValue();
}
/// <inheritdoc cref="ParseResult.GetValue{T}(CliOption{T})"/>
public T? GetValue<T>(CliOption<T> option)
{
if (GetResult(option) is { } result &&
result.GetValueOrDefault<T>() is { } t)
{
return t;
}
return CliArgument<T>.CreateDefaultValue();
}
/// <summary>
/// Gets the value for a symbol having the specified name anywhere in the parse tree.
/// </summary>
/// <param name="name">The name of the symbol for which to find a result.</param>
/// <returns>An argument result if the argument was matched by the parser or has a default value; otherwise, <c>null</c>.</returns>
public T? GetValue<T>(string name)
{
if (GetResult(name) is { } result)
{
if (result is OptionResult optionResult &&
optionResult.GetValueOrDefault<T>() is { } optionValue)
{
return optionValue;
}
if (result is ArgumentResult argumentResult &&
argumentResult.GetValueOrDefault<T>() is { } argumentValue)
{
return argumentValue;
}
}
return CliArgument<T>.CreateDefaultValue();
}
internal virtual bool UseDefaultValueFor(ArgumentResult argumentResult) => false;
}
}