Skip to content

Commit ae85349

Browse files
committed
Address PR feedback
1 parent 1c290f6 commit ae85349

File tree

8 files changed

+20
-29
lines changed

8 files changed

+20
-29
lines changed

src/System.CommandLine.Subsystems.Tests/ValidationSubsystemTests.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ public void Values_above_calculated_upper_bound_report_error()
143143
public void Values_below_relative_lower_bound_report_error()
144144
{
145145
var otherOption = new CliOption<int>("-a");
146-
var option = GetOptionWithRangeBounds("--intOpt", ValueSource.Create(otherOption, o => (true, (int)o + 1)), 50);
146+
var option = GetOptionWithRangeBounds("--intOpt", ValueSource.Create<int>(otherOption, o => (true, o + 1)), 50);
147147
var command = new CliCommand("cmd") { option, otherOption };
148148

149149
var pipelineResult = ExecutedPipelineResultForCommand(command, "--intOpt 0 -a 0");
@@ -159,7 +159,9 @@ public void Values_below_relative_lower_bound_report_error()
159159
public void Values_within_relative_range_do_not_report_error()
160160
{
161161
var otherOption = new CliOption<int>("-a");
162-
var option = GetOptionWithRangeBounds("--intOpt", ValueSource.Create(otherOption, o => (true, (int)o + 1)), ValueSource.Create(otherOption, o => (true, (int)o + 10)));
162+
var option = GetOptionWithRangeBounds("--intOpt",
163+
ValueSource.Create<int>(otherOption, o => (true, o + 1)),
164+
ValueSource.Create<int>(otherOption, o => (true, o + 10)));
163165
var command = new CliCommand("cmd") { option, otherOption };
164166

165167
var pipelineResult = ExecutedPipelineResultForCommand(command, "--intOpt 11 -a 3");
@@ -172,7 +174,7 @@ public void Values_within_relative_range_do_not_report_error()
172174
public void Values_above_relative_upper_bound_report_error()
173175
{
174176
var otherOption = new CliOption<int>("-a");
175-
var option = GetOptionWithRangeBounds("--intOpt", 0, ValueSource.Create(otherOption, o => (true, (int)o + 10)));
177+
var option = GetOptionWithRangeBounds("--intOpt", 0, ValueSource.Create<int>(otherOption, o => (true, o + 10)));
176178
var command = new CliCommand("cmd") { option, otherOption };
177179

178180
var pipelineResult = ExecutedPipelineResultForCommand(command, "--intOpt 9 -a -2");

src/System.CommandLine.Subsystems/Subsystems/Annotations/AnnotationResolver.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ public AnnotationResolver(PipelineResult pipelineResult)
4141
/// <returns>True if successful</returns>
4242
/// <remarks>
4343
/// This is intended for use by developers defining custom annotation IDs. Anyone defining an annotation
44-
/// ID should also define an accessor extension method on <see cref="AnnotationResolver"/> extension method
45-
/// on <see cref="CliSymbol"/> that subsystem authors can use to access the annotation value, such as
44+
/// ID should also define an accessor extension method on <see cref="AnnotationResolver"/>
45+
/// that subsystem authors can use to access the annotation value, such as
4646
/// <see cref="HelpAnnotationExtensions.GetDescription{TSymbol}(AnnotationResolver, TSymbol)"/> .
4747
/// <para>
4848
/// If the annotation value does not have a single expected type for this symbol, use the

src/System.CommandLine.Subsystems/Subsystems/Annotations/AnnotationStorageExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public static TSymbol WithAnnotation<TSymbol>(this TSymbol symbol, AnnotationId
103103
/// This is intended to be called by the implementation of specialized ID-specific accessors for CLI authors such as <see cref="HelpAnnotationExtensions.GetDescription{TSymbol}(TSymbol)"/>.
104104
/// <para>
105105
/// Subsystems should not call this directly, as it does not account for values from the pipeline's <see cref="IAnnotationProvider"/>.
106-
/// They should instead access annotations from the see cref="Pipeline.Annotations"/> property using
106+
/// They should instead access annotations from the <see cref="Pipeline.Annotations"/> property using
107107
/// <see cref="AnnotationResolver.TryGet{TValue}(CliSymbol, AnnotationId, out TValue?)"/> or an ID-specific
108108
/// extension method such as <see cref="HelpAnnotationExtensions.GetDescription{TSymbol}(TSymbol)" />.
109109
/// </para>

src/System.CommandLine.Subsystems/ValidationSubsystem.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@ private void ValidateValue(CliValueSymbol valueSymbol, ValidationContext validat
7070
{
7171
var valueConditions = valueSymbol.EnumerateValueConditions();
7272

73+
// manually implement the foreach so we can efficiently skip getting the
74+
// value if there are no conditions
7375
var enumerator = valueConditions.GetEnumerator();
7476
if (!enumerator.MoveNext())
7577
{
76-
// avoid getting the value if there are no conditions
7778
return;
7879
}
7980

@@ -89,6 +90,9 @@ private void ValidateCommand(CliCommandResult commandResult, ValidationContext v
8990
{
9091
var valueConditions = commandResult.Command.EnumerateCommandConditions();
9192

93+
// unlike ValidateValue we do not need to manually implement the foreach
94+
// to skip unnecessary work, as there is no additional work to be before
95+
// calling command validators
9296
foreach (var condition in valueConditions)
9397
{
9498
ValidateCommandCondition(commandResult, condition, validationContext);

src/System.CommandLine.Subsystems/ValueConditionAnnotationExtensions.cs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ public static class ValueConditionAnnotationExtensions
2020
/// <param name="symbol">The option or argument the range applies to.</param>
2121
/// <param name="lowerBound">The lower bound of the range.</param>
2222
/// <param name="upperBound">The upper bound of the range.</param>
23-
// TODO: Add RangeBounds
24-
// TODO: You should not have to set both...why not nullable?
23+
// TODO: can we eliminate this overload and just reply on the implicit cast to ValueSource<TValue>?
2524
public static void SetRange<TValueSymbol, TValue>(this TValueSymbol symbol, TValue lowerBound, TValue upperBound)
2625
where TValueSymbol : CliValueSymbol, ICliValueSymbol<TValue>
2726
where TValue : IComparable<TValue>
@@ -40,12 +39,9 @@ public static void SetRange<TValueSymbol, TValue>(this TValueSymbol symbol, TVal
4039
/// <param name="symbol">The option or argument the range applies to.</param>
4140
/// <param name="lowerBound">The <see cref="ValueSource"> that is the lower bound of the range.</param>
4241
/// <param name="upperBound">The <see cref="ValueSource"> that is the upper bound of the range.</param>
43-
// TODO: Add RangeBounds
44-
// TODO: You should not have to set both...why not nullable?
45-
public static void SetRange<TValueSymbol, TValue>(this TValueSymbol symbol, ValueSource<TValue> lowerBound, ValueSource<TValue> upperBound)
42+
public static void SetRange<TValueSymbol, TValue>(this TValueSymbol symbol, ValueSource<TValue>? lowerBound, ValueSource<TValue>? upperBound)
4643
where TValueSymbol : CliValueSymbol, ICliValueSymbol<TValue>
4744
where TValue : IComparable<TValue>
48-
// TODO: You should not have to set both...why not nullable?
4945
{
5046
var range = new Range<TValue>(lowerBound, upperBound);
5147

@@ -68,13 +64,11 @@ public static void SetRange<TValueSymbol, TValue>(this TValueSymbol symbol, Valu
6864
public static void SetInclusiveGroup(this CliCommand command, IEnumerable<CliValueSymbol> group)
6965
=> command.SetValueCondition(new InclusiveGroup(group));
7066

71-
// TODO: This should not be public if ValueConditions are not public
7267
public static void SetValueCondition<TValueSymbol, TValueCondition>(this TValueSymbol symbol, TValueCondition valueCondition)
7368
where TValueSymbol : CliValueSymbol
7469
where TValueCondition : ValueCondition
7570
=> symbol.AddAnnotation(ValueConditionAnnotations.ValueConditions, valueCondition);
7671

77-
// TODO: This should not be public if ValueConditions are not public
7872
public static void SetValueCondition<TCommandCondition>(this CliCommand symbol, TCommandCondition commandCondition)
7973
where TCommandCondition : CommandCondition
8074
=> symbol.AddAnnotation(ValueConditionAnnotations.ValueConditions, commandCondition);
@@ -84,8 +78,6 @@ public static void SetValueCondition<TCommandCondition>(this CliCommand symbol,
8478
/// </summary>
8579
/// <param name="command">The option or argument to get the conditions for.</param>
8680
/// <returns>The conditions that have been applied to the option or argument.</returns>
87-
///
88-
// TODO: This is public because it will be used by other subsystems we might not own. It could be an extension method the subsystem namespace
8981
public static IEnumerable<ValueCondition> EnumerateValueConditions(this CliValueSymbol symbol)
9082
=> symbol.EnumerateAnnotations<ValueCondition>(ValueConditionAnnotations.ValueConditions);
9183

@@ -94,8 +86,6 @@ public static IEnumerable<ValueCondition> EnumerateValueConditions(this CliValue
9486
/// </summary>
9587
/// <param name="command">The option or argument to get the conditions for.</param>
9688
/// <returns>The conditions that have been applied to the option or argument.</returns>
97-
///
98-
// TODO: This is public because it will be used by other subsystems we might not own. It could be an extension method the subsystem namespace
9989
public static IEnumerable<ValueCondition> EnumerateValueConditions(this AnnotationResolver resolver, CliValueSymbol symbol)
10090
=> resolver.Enumerate<ValueCondition>(symbol, ValueConditionAnnotations.ValueConditions);
10191

@@ -104,8 +94,6 @@ public static IEnumerable<ValueCondition> EnumerateValueConditions(this Annotati
10494
/// </summary>
10595
/// <param name="command">The command to get the conditions for.</param>
10696
/// <returns>The conditions that have been applied to the command.</returns>
107-
///
108-
// TODO: This is public because it will be used by other subsystems we might not own. It could be an extension method the subsystem namespace
10997
public static IEnumerable<CommandCondition> EnumerateCommandConditions(this CliCommand command)
11098
=> command.EnumerateAnnotations<CommandCondition>(ValueConditionAnnotations.ValueConditions);
11199

@@ -125,19 +113,16 @@ public static IEnumerable<CommandCondition> EnumerateCommandConditions(this Anno
125113
/// <typeparam name="TCondition">The type of condition to return.</typeparam>
126114
/// <param name="symbol">The option or argument that may contain the condition.</param>
127115
/// <returns>The condition if it exists on the option or argument, otherwise null.</returns>
128-
// This method feels useful because it clarifies that last should win and returns one, when only one should be applied
129-
// TODO: Consider removing user facing naming, other than the base type, that is Value or CommandCondition and just use Condition
130116
public static TCondition? GetValueCondition<TCondition>(this CliValueSymbol symbol)
131117
where TCondition : ValueCondition
132-
=> symbol.EnumerateValueConditions().OfType<TCondition>().LastOrDefault();
118+
=> symbol.EnumerateValueConditions().OfType<TCondition>().FirstOrDefault();
133119

134120
/// <summary>
135121
/// Gets the condition that matches the type, if it exists on this command.
136122
/// </summary>
137123
/// <typeparam name="TCondition">The type of condition to return.</typeparam>
138124
/// <param name="symbol">The command that may contain the condition.</param>
139125
/// <returns>The condition if it exists on the command, otherwise null.</returns>
140-
// This method feels useful because it clarifies that last should win and returns one, when only one should be applied
141126
public static TCondition? GetCommandCondition<TCondition>(this CliCommand symbol)
142127
where TCondition : CommandCondition
143128
=> symbol.EnumerateCommandConditions().OfType<TCondition>().FirstOrDefault();

src/System.CommandLine.Subsystems/ValueSources/RelativeToSymbolValueSource.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public sealed class RelativeToSymbolValueSource<T>
1717
internal RelativeToSymbolValueSource(
1818
CliValueSymbol otherSymbol,
1919
bool onlyUserEnteredValues = false,
20-
Func<object?, (bool success, T? value)>? calculation = null,
20+
Func<T?, (bool success, T? value)>? calculation = null,
2121
string? description = null)
2222
{
2323
OtherSymbol = otherSymbol;
@@ -29,7 +29,7 @@ internal RelativeToSymbolValueSource(
2929
public override string? Description { get; }
3030
public CliValueSymbol OtherSymbol { get; }
3131
public bool OnlyUserEnteredValues { get; }
32-
public Func<object?, (bool success, T? value)>? Calculation { get; }
32+
public Func<T?, (bool success, T? value)>? Calculation { get; }
3333

3434
/// <inheritdoc/>
3535
public override bool TryGetTypedValue(PipelineResult pipelineResult, out T? value)

src/System.CommandLine.Subsystems/ValueSources/ValueSource.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public static ValueSource<T> Create<T>(Func<(bool success, T? value)> calculatio
3131
=> new CalculatedValueSource<T>(calculation, description);
3232

3333
public static ValueSource<T> Create<T>(CliValueSymbol otherSymbol,
34-
Func<object?, (bool success, T? value)>? calculation = null,
34+
Func<T?, (bool success, T? value)>? calculation = null,
3535
bool userEnteredValueOnly = false,
3636
string? description = null)
3737
=> new RelativeToSymbolValueSource<T>(otherSymbol, userEnteredValueOnly, calculation, description);

src/System.CommandLine/ICliValueSymbol.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
namespace System.CommandLine;
55

66
/// <summary>
7-
/// This is applied to <see cref="CliArgument{T}"/> and <see cref="CliArgument{T}"/>, and allows
7+
/// This is implemented only by <see cref="CliOption{T}"/> and <see cref="CliArgument{T}"/>, and allows
88
/// allows methods with a <see cref="CliValueSymbol"/> argument to apply constraints based on the
99
/// value type.
1010
/// </summary>

0 commit comments

Comments
 (0)