5
5
using System ;
6
6
using System . Collections . Generic ;
7
7
using System . CommandLine ;
8
- using System . CommandLine . Invocation ;
8
+ using System . IO ;
9
9
using System . Linq ;
10
-
11
- using Microsoft . AspNetCore . Authentication ;
12
10
using Microsoft . DotNet . Watcher . Tools ;
13
11
using Microsoft . Extensions . Tools . Internal ;
14
12
@@ -76,112 +74,131 @@ dotnet watch test
76
74
public required IReadOnlyList < string > RemainingArguments { get ; init ; }
77
75
public RunCommandLineOptions ? RunOptions { get ; init ; }
78
76
79
- public static CommandLineOptions ? Parse ( string [ ] args , IReporter reporter , out int errorCode , System . CommandLine . IConsole ? console = null )
77
+ public static CommandLineOptions ? Parse ( string [ ] args , IReporter reporter , out int errorCode , TextWriter ? output = null , TextWriter ? error = null )
80
78
{
81
- var quietOption = new Option < bool > ( new [ ] { "--quiet" , "-q" } , "Suppresses all output except warnings and errors" ) ;
82
- var verboseOption = new Option < bool > ( new [ ] { "--verbose" , "-v" } , "Show verbose output" ) ;
79
+ var quietOption = new CliOption < bool > ( "--quiet" , "-q" )
80
+ {
81
+ Description = "Suppresses all output except warnings and errors"
82
+ } ;
83
83
84
- verboseOption . AddValidator ( v =>
84
+ var verboseOption = new CliOption < bool > ( "--verbose" , "-v" )
85
85
{
86
- if ( v . FindResultFor ( quietOption ) is not null && v . FindResultFor ( verboseOption ) is not null )
86
+ Description = "Show verbose output"
87
+ } ;
88
+
89
+ verboseOption . Validators . Add ( v =>
90
+ {
91
+ if ( v . GetResult ( quietOption ) is not null && v . GetResult ( verboseOption ) is not null )
87
92
{
88
- v . ErrorMessage = Resources . Error_QuietAndVerboseSpecified ;
93
+ v . AddError ( Resources . Error_QuietAndVerboseSpecified ) ;
89
94
}
90
95
} ) ;
91
96
92
- var listOption = new Option < bool > ( "--list" , "Lists all discovered files without starting the watcher." ) ;
93
- var shortProjectOption = new Option < string > ( "-p" , "The project to watch." ) { IsHidden = true } ;
94
- var longProjectOption = new Option < string > ( "--project" , "The project to watch" ) ;
97
+ var listOption = new CliOption < bool > ( "--list" ) { Description = "Lists all discovered files without starting the watcher." } ;
98
+ var shortProjectOption = new CliOption < string > ( "-p" ) { Description = "The project to watch." , Hidden = true } ;
99
+ var longProjectOption = new CliOption < string > ( "--project" ) { Description = "The project to watch" } ;
95
100
96
101
// launch profile used by dotnet-watch
97
- var launchProfileWatchOption = new Option < string > ( new [ ] { "-lp" , LaunchProfileOptionName } , "The launch profile to start the project with (case-sensitive)." ) ;
98
- var noLaunchProfileWatchOption = new Option < bool > ( new [ ] { NoLaunchProfileOptionName } , "Do not attempt to use launchSettings.json to configure the application." ) ;
102
+ var launchProfileWatchOption = new CliOption < string > ( LaunchProfileOptionName , "-lp" )
103
+ {
104
+ Description = "The launch profile to start the project with (case-sensitive)."
105
+ } ;
106
+ var noLaunchProfileWatchOption = new CliOption < bool > ( NoLaunchProfileOptionName )
107
+ {
108
+ Description = "Do not attempt to use launchSettings.json to configure the application."
109
+ } ;
99
110
100
111
// launch profile used by dotnet-run
101
- var launchProfileRunOption = new Option < string > ( new [ ] { "-lp" , LaunchProfileOptionName } ) { IsHidden = true } ;
102
- var noLaunchProfileRunOption = new Option < bool > ( new [ ] { NoLaunchProfileOptionName } ) { IsHidden = true } ;
112
+ var launchProfileRunOption = new CliOption < string > ( LaunchProfileOptionName , "-lp" ) { Hidden = true } ;
113
+ var noLaunchProfileRunOption = new CliOption < bool > ( NoLaunchProfileOptionName ) { Hidden = true } ;
103
114
104
- var targetFrameworkOption = new Option < string > ( new [ ] { "-f" , "--framework" } , "The target framework to run for. The target framework must also be specified in the project file." ) ;
105
- var propertyOption = new Option < string [ ] > ( new [ ] { "--property" } , "Properties to be passed to MSBuild." ) ;
115
+ var targetFrameworkOption = new CliOption < string > ( "--framework" , "-f" )
116
+ {
117
+ Description = "The target framework to run for. The target framework must also be specified in the project file."
118
+ } ;
119
+ var propertyOption = new CliOption < string [ ] > ( "--property" )
120
+ {
121
+ Description = "Properties to be passed to MSBuild."
122
+ } ;
106
123
107
- propertyOption . AddValidator ( v =>
124
+ propertyOption . Validators . Add ( v =>
108
125
{
109
126
var invalidProperty = v . GetValue ( propertyOption ) ? . FirstOrDefault (
110
127
property => ! ( property . IndexOf ( '=' ) is > 0 and var index && index < property . Length - 1 && property [ ..index ] . Trim ( ) . Length > 0 ) ) ;
111
128
112
129
if ( invalidProperty != null )
113
130
{
114
- v . ErrorMessage = $ "Invalid property format: '{ invalidProperty } '. Expected 'name=value'.";
131
+ v . AddError ( $ "Invalid property format: '{ invalidProperty } '. Expected 'name=value'.") ;
115
132
}
116
133
} ) ;
117
134
118
- var noHotReloadOption = new Option < bool > ( "--no-hot-reload" , "Suppress hot reload for supported apps." ) ;
119
- var nonInteractiveOption = new Option < bool > (
120
- "--non-interactive" ,
121
- "Runs dotnet-watch in non-interactive mode. This option is only supported when running with Hot Reload enabled. " +
122
- "Use this option to prevent console input from being captured." ) ;
135
+ var noHotReloadOption = new CliOption < bool > ( "--no-hot-reload" ) { Description = "Suppress hot reload for supported apps." } ;
136
+ var nonInteractiveOption = new CliOption < bool > ( "--non-interactive" )
137
+ {
138
+ Description = "Runs dotnet-watch in non-interactive mode. This option is only supported when running with Hot Reload enabled. " +
139
+ "Use this option to prevent console input from being captured."
140
+ } ;
123
141
124
- var remainingWatchArgs = new Argument < string [ ] > ( "forwardedArgs" , "Arguments to pass to the child dotnet process." ) ;
125
- var remainingRunArgs = new Argument < string [ ] > ( name : null ) ;
142
+ var remainingWatchArgs = new CliArgument < string [ ] > ( "forwardedArgs" ) { Description = "Arguments to pass to the child dotnet process." } ;
143
+ var remainingRunArgs = new CliArgument < string [ ] > ( "remainingRunArgs" ) ;
126
144
127
- var runCommand = new Command ( "run" ) { IsHidden = true } ;
128
- var rootCommand = new RootCommand ( Description ) ;
129
- addOptions ( runCommand ) ;
130
- addOptions ( rootCommand ) ;
145
+ var runCommand = new CliCommand ( "run" ) { Hidden = true } ;
146
+ var rootCommand = new CliRootCommand ( Description ) ;
147
+ AddSymbols ( runCommand ) ;
148
+ AddSymbols ( rootCommand ) ;
131
149
132
- void addOptions ( Command command )
150
+ void AddSymbols ( CliCommand command )
133
151
{
134
- command . Add ( quietOption ) ;
135
- command . Add ( verboseOption ) ;
136
- command . Add ( noHotReloadOption ) ;
137
- command . Add ( nonInteractiveOption ) ;
138
- command . Add ( longProjectOption ) ;
139
- command . Add ( shortProjectOption ) ;
152
+ command . Options . Add ( quietOption ) ;
153
+ command . Options . Add ( verboseOption ) ;
154
+ command . Options . Add ( noHotReloadOption ) ;
155
+ command . Options . Add ( nonInteractiveOption ) ;
156
+ command . Options . Add ( longProjectOption ) ;
157
+ command . Options . Add ( shortProjectOption ) ;
140
158
141
159
if ( command == runCommand )
142
160
{
143
- command . Add ( launchProfileRunOption ) ;
144
- command . Add ( noLaunchProfileRunOption ) ;
161
+ command . Options . Add ( launchProfileRunOption ) ;
162
+ command . Options . Add ( noLaunchProfileRunOption ) ;
145
163
}
146
164
else
147
165
{
148
- command . Add ( launchProfileWatchOption ) ;
149
- command . Add ( noLaunchProfileWatchOption ) ;
166
+ command . Options . Add ( launchProfileWatchOption ) ;
167
+ command . Options . Add ( noLaunchProfileWatchOption ) ;
150
168
}
151
169
152
- command . Add ( targetFrameworkOption ) ;
153
- command . Add ( propertyOption ) ;
170
+ command . Options . Add ( targetFrameworkOption ) ;
171
+ command . Options . Add ( propertyOption ) ;
154
172
155
- command . Add ( listOption ) ;
173
+ command . Options . Add ( listOption ) ;
156
174
157
175
if ( command == runCommand )
158
176
{
159
- command . Add ( remainingRunArgs ) ;
177
+ command . Arguments . Add ( remainingRunArgs ) ;
160
178
}
161
179
else
162
180
{
163
- command . Add ( runCommand ) ;
164
- command . Add ( remainingWatchArgs ) ;
181
+ command . Subcommands . Add ( runCommand ) ;
182
+ command . Arguments . Add ( remainingWatchArgs ) ;
165
183
}
166
184
} ;
167
185
168
186
CommandLineOptions ? options = null ;
169
187
170
- runCommand . SetHandler ( context =>
188
+ runCommand . SetAction ( parseResult =>
171
189
{
172
- RootHandler ( context , new ( )
190
+ RootHandler ( parseResult , new ( )
173
191
{
174
- LaunchProfileName = context . ParseResult . GetValue ( launchProfileRunOption ) ,
175
- NoLaunchProfile = context . ParseResult . GetValue ( noLaunchProfileRunOption ) ,
176
- RemainingArguments = context . ParseResult . GetValue ( remainingRunArgs ) ,
192
+ LaunchProfileName = parseResult . GetValue ( launchProfileRunOption ) ,
193
+ NoLaunchProfile = parseResult . GetValue ( noLaunchProfileRunOption ) ,
194
+ RemainingArguments = parseResult . GetValue ( remainingRunArgs ) ?? Array . Empty < string > ( ) ,
177
195
} ) ;
178
196
} ) ;
179
197
180
- rootCommand . SetHandler ( context => RootHandler ( context , runOptions : null ) ) ;
198
+ rootCommand . SetAction ( parseResult => RootHandler ( parseResult , runOptions : null ) ) ;
181
199
182
- void RootHandler ( InvocationContext context , RunCommandLineOptions ? runOptions )
200
+ void RootHandler ( ParseResult parseResults , RunCommandLineOptions ? runOptions )
183
201
{
184
- var parseResults = context . ParseResult ;
185
202
var projectValue = parseResults . GetValue ( longProjectOption ) ;
186
203
if ( string . IsNullOrEmpty ( projectValue ) )
187
204
{
@@ -206,12 +223,17 @@ void RootHandler(InvocationContext context, RunCommandLineOptions? runOptions)
206
223
TargetFramework = parseResults . GetValue ( targetFrameworkOption ) ,
207
224
BuildProperties = parseResults . GetValue ( propertyOption ) ?
208
225
. Select ( p => ( p [ ..p . IndexOf ( '=' ) ] . Trim ( ) , p [ ( p . IndexOf ( '=' ) + 1 ) ..] ) ) . ToArray ( ) ,
209
- RemainingArguments = parseResults . GetValue ( remainingWatchArgs ) ,
226
+ RemainingArguments = parseResults . GetValue ( remainingWatchArgs ) ?? Array . Empty < string > ( ) ,
210
227
RunOptions = runOptions ,
211
228
} ;
212
229
}
213
230
214
- errorCode = rootCommand . Invoke ( args , console ) ;
231
+ errorCode = new CliConfiguration ( rootCommand )
232
+ {
233
+ Output = output ?? Console . Out ,
234
+ Error = error ?? Console . Error
235
+ } . Invoke ( args ) ;
236
+
215
237
return options ;
216
238
}
217
239
0 commit comments