2
2
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
3
4
4
using System . CommandLine . Subsystems . Annotations ;
5
+ using System . CommandLine . ValueSources ;
6
+ using System . Diagnostics . CodeAnalysis ;
5
7
6
8
namespace System . CommandLine ;
7
9
8
10
internal class ValueProvider
9
11
{
10
12
private Dictionary < CliSymbol , object ? > cachedValues = [ ] ;
11
- private ParseResult ? parseResult = null ;
13
+ private PipelineResult pipelineResult ;
12
14
13
- public ValueProvider ( ParseResult parseResult )
15
+ public ValueProvider ( PipelineResult pipelineResult )
14
16
{
15
- this . parseResult = parseResult ;
17
+ this . pipelineResult = pipelineResult ;
16
18
}
17
19
18
20
private void SetValue ( CliSymbol symbol , object ? value )
@@ -33,32 +35,55 @@ private bool TryGetValue<T>(CliSymbol symbol, out T? value)
33
35
return false ;
34
36
}
35
37
36
- public T GetValue < T > ( CliValueSymbol valueSymbol )
38
+ public T ? GetValue < T > ( CliValueSymbol valueSymbol )
37
39
=> GetValueInternal < T > ( valueSymbol ) ;
38
40
39
- private T GetValueInternal < T > ( CliValueSymbol ? valueSymbol )
41
+ private T ? GetValueInternal < T > ( CliValueSymbol valueSymbol )
40
42
{
41
- // TODO: This method is definitely WRONG. If there is a relative or env variable, it does not continue if it is not found
43
+ var _ = valueSymbol ?? throw new ArgumentNullException ( nameof ( valueSymbol ) ) ;
44
+ if ( TryGetValue < T > ( valueSymbol , out var value ) )
45
+ {
46
+ return value ;
47
+ }
48
+ if ( pipelineResult . ParseResult ? . GetValueResult ( valueSymbol ) is { } valueResult )
49
+ {
50
+ return UseValue ( valueSymbol , valueResult . GetValue < T > ( ) ) ;
51
+ }
52
+ if ( valueSymbol . TryGetDefaultValueSource ( out ValueSource ? defaultValueSource ) )
53
+ {
54
+ if ( defaultValueSource is not ValueSource < T > typedValueSource )
55
+ {
56
+ throw new InvalidOperationException ( "Unexpected ValueSource type" ) ;
57
+ }
58
+ ( var success , var defaultValue ) = typedValueSource . GetTypedValue ( pipelineResult ) ;
59
+ if ( success )
60
+ {
61
+ return UseValue ( valueSymbol , defaultValue ) ;
62
+ }
63
+ }
64
+ return UseValue ( valueSymbol , default ( T ) ) ;
65
+
66
+ // TODO: The following logic is definitely WRONG. If there is a relative or env variable, it does not continue if it is not found
42
67
// TODO: Replace this method with an AggregateValueSource
43
68
// NOTE: We use the subsystem's TryGetAnnotation here instead of the GetDefaultValue etc
44
69
// extension methods, as the subsystem's TryGetAnnotation respects its annotation provider
45
- return valueSymbol switch
46
- {
47
- { } when TryGetValue < T > ( valueSymbol , out var value )
48
- => value , // It has already been retrieved at least once
49
- { } when parseResult ? . GetValueResult ( valueSymbol ) is { } valueResult // GetValue not used because it would always return a value
50
- => UseValue ( valueSymbol , valueResult . GetValue < T > ( ) ) , // Value was supplied during parsing,
51
- // Value was not supplied during parsing, determine default now
52
- // configuration values go here in precedence
53
- //not null when GetDefaultFromEnvironmentVariable<T>(symbol, out var envName)
54
- // => UseValue(symbol, GetEnvByName(envName)),
55
- { } when valueSymbol . TryGetAnnotation ( ValueAnnotations . DefaultValueCalculation , out Func < T ? > ? defaultValueCalculation )
56
- => UseValue ( valueSymbol , CalculatedDefault < T > ( valueSymbol , ( Func < T ? > ) defaultValueCalculation ) ) ,
57
- { } when valueSymbol . TryGetAnnotation ( ValueAnnotations . DefaultValue , out T ? explicitValue )
58
- => UseValue ( valueSymbol , explicitValue ) ,
59
- null => throw new ArgumentNullException ( nameof ( valueSymbol ) ) ,
60
- _ => UseValue ( valueSymbol , default ( T ) )
61
- } ;
70
+ // return valueSymbol switch
71
+ // {
72
+ // { } when TryGetValue<T>(valueSymbol, out var value)
73
+ // => value, // It has already been retrieved at least once
74
+ // { } when parseResult?.GetValueResult(valueSymbol) is { } valueResult // GetValue not used because it would always return a value
75
+ // => UseValue(valueSymbol, valueResult.GetValue<T>()), // Value was supplied during parsing,
76
+ // // Value was not supplied during parsing, determine default now
77
+ // // configuration values go here in precedence
78
+ // //not null when GetDefaultFromEnvironmentVariable<T>(symbol, out var envName)
79
+ // // => UseValue(symbol, GetEnvByName(envName)),
80
+ // { } when valueSymbol.TryGetAnnotation(ValueAnnotations.DefaultValueCalculation, out Func<T?>? defaultValueCalculation)
81
+ // => UseValue(valueSymbol, CalculatedDefault<T>(valueSymbol, (Func<T?>)defaultValueCalculation)),
82
+ // { } when valueSymbol.TryGetAnnotation(ValueAnnotations.DefaultValue, out T? explicitValue)
83
+ // => UseValue(valueSymbol, explicitValue),
84
+ // null => throw new ArgumentNullException(nameof(valueSymbol)),
85
+ // _ => UseValue(valueSymbol, default(T))
86
+ // };
62
87
63
88
TValue UseValue < TValue > ( CliSymbol symbol , TValue value )
64
89
{
0 commit comments