-
Notifications
You must be signed in to change notification settings - Fork 417
Expand file tree
/
Copy pathRange.cs
More file actions
90 lines (76 loc) · 3.33 KB
/
Range.cs
File metadata and controls
90 lines (76 loc) · 3.33 KB
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
// 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 System.CommandLine.Validation;
using System.CommandLine.ValueSources;
namespace System.CommandLine.ValueConditions;
/// <summary>
/// Declares the range condition for the option or argument.
/// </summary>
/// <remarks>
/// The non-generic version is used by the <see cref="RangeValidator/>.
/// </remarks>
public abstract class Range : ValueCondition
{
protected Range(Type valueType)
: base(nameof(Range))
{
ValueType = valueType;
}
/// <summary>
/// The type of the symbol the range applies to.
/// </summary>
public Type ValueType { get; }
}
/// <summary>
/// Declares the range condition for the option or argument. Instances
/// of this method are created via extension methods on <see cref="ValueSymbol"/>
/// </summary>
/// <typeparam name="T">The type of the symbol the range applies to.</typeparam>
public class Range<T> : Range, IValueValidator
where T : IComparable<T>
{
internal Range(ValueSource<T>? lowerBound, ValueSource<T>? upperBound, RangeBounds rangeBound = 0) : base(typeof(T))
{
LowerBound = lowerBound;
UpperBound = upperBound;
RangeBound = rangeBound;
}
/// <inheritdoc/>
public void Validate(object? value,
CliValueSymbol valueSymbol,
CliValueResult? valueResult,
ValueCondition valueCondition,
ValidationContext validationContext)
{
if (valueCondition != this) throw new InvalidOperationException("Unexpected value condition type");
if (value is not T comparableValue) throw new InvalidOperationException("Unexpected value type");
if (comparableValue is null) return; // nothing to do
// TODO: Replace the strings we are comparing with a diagnostic ID when we update ParseError
if (LowerBound is not null
&& validationContext.TryGetTypedValue(LowerBound, out var lowerValue)
&& comparableValue.CompareTo(lowerValue) < 0)
{
validationContext.AddError(new CliDiagnostic(new("", "", "The value for '{valueSymbol}' is below the lower bound of {lowerBound}", severity: CliDiagnosticSeverity.Error, null), [valueSymbol.Name, LowerBound], cliSymbolResult: valueResult));
}
if (UpperBound is not null
&& validationContext.TryGetTypedValue(UpperBound, out var upperValue)
&& comparableValue.CompareTo(upperValue) > 0)
{
validationContext.AddError(new CliDiagnostic(new("", "", "The value for '{valueSymbol}' is above the upper bound of {upperBound}", severity: CliDiagnosticSeverity.Error, null), [valueSymbol.Name, UpperBound], cliSymbolResult: valueResult));
}
}
/// <summary>
/// The lower bound of the range.
/// </summary>
public ValueSource<T>? LowerBound { get; init; }
/// <summary>
/// The upper bound of the range.
/// </summary>
public ValueSource<T>? UpperBound { get; init; }
/// <summary>
/// Whether values of the range are considered part of the
/// range (inclusive) or not (exclusive)
/// </summary>
public RangeBounds RangeBound { get; }
}