@@ -193,11 +193,30 @@ public struct Driver {
193
193
diagnosticsHandler: @escaping DiagnosticsEngine . DiagnosticsHandler = Driver . stderrDiagnosticsHandler
194
194
) throws {
195
195
self . env = env
196
-
197
- // FIXME: Determine if we should run as subcommand.
198
196
199
197
self . diagnosticEngine = DiagnosticsEngine ( handlers: [ diagnosticsHandler] )
200
198
var args = try Self . expandResponseFiles ( args, diagnosticsEngine: self . diagnosticEngine) [ ... ]
199
+
200
+ switch try Self . invocationRunMode ( forArgs: Array ( args) ) {
201
+ case . normal( let isRepl) :
202
+ if isRepl {
203
+ args. remove ( at: 1 )
204
+ }
205
+ case . subcommand( let subcommand) :
206
+
207
+ args. remove ( at: 1 )
208
+
209
+ // We are running as a subcommand, try to find the subcommand
210
+ // adjacent to the executable we are running as.
211
+ let subcommandPath = Process . findExecutable ( args [ 0 ] ) ? . parentDirectory. appending ( component: subcommand)
212
+ // If we didn't find the tool there, let the OS search for it.
213
+ // If there was an error, ignore it and just let the exec fail.
214
+ ?? Process . findExecutable ( subcommand)
215
+
216
+ // Execute the subcommand.
217
+ try exec ( path: subcommandPath? . pathString ?? " " , args: Array ( args) )
218
+ }
219
+
201
220
self . driverKind = try Self . determineDriverKind ( args: & args)
202
221
self . optionTable = OptionTable ( )
203
222
self . parsedOptions = try optionTable. parse ( Array ( args) )
@@ -444,6 +463,41 @@ extension Driver {
444
463
}
445
464
}
446
465
466
+ extension Driver {
467
+
468
+ public enum InvocationRunMode : Equatable {
469
+ case normal( isRepl: Bool )
470
+ case subcommand( String )
471
+ }
472
+
473
+ public static func invocationRunMode( forArgs args: [ String ] ) throws -> InvocationRunMode {
474
+
475
+ assert ( !args. isEmpty)
476
+
477
+ let execName = try VirtualPath ( path: args [ 0 ] ) . basenameWithoutExt
478
+
479
+ // If we are not run as 'swift' or there are no program arguments, always invoke as normal.
480
+ guard execName == " swift " , args. count > 1 else { return . normal( isRepl: false ) }
481
+
482
+ // Otherwise, we have a program argument.
483
+ let firstArg = args [ 1 ]
484
+
485
+ // If it looks like an option or a path, then invoke in interactive mode with the arguments as given.
486
+ if firstArg. hasPrefix ( " - " ) || firstArg. hasPrefix ( " / " ) || firstArg. contains ( " . " ) {
487
+ return . normal( isRepl: false )
488
+ }
489
+
490
+ // Otherwise, we should have some sort of subcommand.
491
+
492
+ // If it is the "built-in" 'repl', then use the normal driver.
493
+ if firstArg == " repl " {
494
+ return . normal( isRepl: true )
495
+ }
496
+
497
+ return . subcommand( " swift- \( firstArg) " )
498
+ }
499
+ }
500
+
447
501
extension Driver {
448
502
/// Determine the driver kind based on the command-line arguments, consuming the arguments
449
503
/// conveying this information.
0 commit comments