@@ -10,38 +10,52 @@ internal static class InvocationPipeline
1010 {
1111 internal static async Task < int > InvokeAsync ( ParseResult parseResult , CancellationToken cancellationToken )
1212 {
13- if ( parseResult . Action is null )
14- {
15- return ReturnCodeForMissingAction ( parseResult ) ;
16- }
17-
1813 ProcessTerminationHandler ? terminationHandler = null ;
1914 using CancellationTokenSource cts = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
2015
2116 try
2217 {
18+ int exitCode = 0 ;
19+
2320 if ( parseResult . PreActions is not null )
2421 {
2522 for ( int i = 0 ; i < parseResult . PreActions . Count ; i ++ )
2623 {
2724 var action = parseResult . PreActions [ i ] ;
25+ int preActionResult ;
2826
2927 switch ( action )
3028 {
3129 case SynchronousCommandLineAction syncAction :
32- syncAction . Invoke ( parseResult ) ;
30+ preActionResult = syncAction . Invoke ( parseResult ) ;
3331 break ;
3432 case AsynchronousCommandLineAction asyncAction :
35- await asyncAction . InvokeAsync ( parseResult , cts . Token ) ;
33+ preActionResult = await asyncAction . InvokeAsync ( parseResult , cts . Token ) ;
34+ break ;
35+ default :
36+ preActionResult = 0 ;
3637 break ;
3738 }
39+
40+ if ( exitCode == 0 )
41+ {
42+ exitCode = preActionResult ;
43+ }
3844 }
3945 }
4046
47+ if ( parseResult . Action is null )
48+ {
49+ return exitCode != 0 ? exitCode : ReturnCodeForMissingAction ( parseResult ) ;
50+ }
51+
52+ int actionResult ;
53+
4154 switch ( parseResult . Action )
4255 {
4356 case SynchronousCommandLineAction syncAction :
44- return syncAction . Invoke ( parseResult ) ;
57+ actionResult = syncAction . Invoke ( parseResult ) ;
58+ break ;
4559
4660 case AsynchronousCommandLineAction asyncAction :
4761 var startedInvocation = asyncAction . InvokeAsync ( parseResult , cts . Token ) ;
@@ -55,20 +69,23 @@ internal static async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
5569
5670 if ( terminationHandler is null )
5771 {
58- return await startedInvocation ;
72+ actionResult = await startedInvocation ;
5973 }
6074 else
6175 {
6276 // Handlers may not implement cancellation.
6377 // In such cases, when CancelOnProcessTermination is configured and user presses Ctrl+C,
6478 // ProcessTerminationCompletionSource completes first, with the result equal to native exit code for given signal.
6579 Task < int > firstCompletedTask = await Task . WhenAny ( startedInvocation , terminationHandler . ProcessTerminationCompletionSource . Task ) ;
66- return await firstCompletedTask ; // return the result or propagate the exception
80+ actionResult = await firstCompletedTask ; // return the result or propagate the exception
6781 }
82+ break ;
6883
6984 default :
7085 throw new ArgumentOutOfRangeException ( nameof ( parseResult . Action ) ) ;
7186 }
87+
88+ return exitCode != 0 ? exitCode : actionResult ;
7289 }
7390 catch ( Exception ex ) when ( parseResult . InvocationConfiguration . EnableDefaultExceptionHandler )
7491 {
@@ -82,48 +99,55 @@ internal static async Task<int> InvokeAsync(ParseResult parseResult, Cancellatio
8299
83100 internal static int Invoke ( ParseResult parseResult )
84101 {
85- switch ( parseResult . Action )
102+ try
86103 {
87- case null :
88- return ReturnCodeForMissingAction ( parseResult ) ;
104+ int exitCode = 0 ;
89105
90- case SynchronousCommandLineAction syncAction :
91- try
106+ if ( parseResult . PreActions is not null )
107+ {
108+ #if DEBUG
109+ for ( var i = 0 ; i < parseResult . PreActions . Count ; i ++ )
92110 {
93- if ( parseResult . PreActions is not null )
111+ var action = parseResult . PreActions [ i ] ;
112+
113+ if ( action is not SynchronousCommandLineAction )
94114 {
95- #if DEBUG
96- for ( var i = 0 ; i < parseResult . PreActions . Count ; i ++ )
97- {
98- var action = parseResult . PreActions [ i ] ;
99-
100- if ( action is not SynchronousCommandLineAction )
101- {
102- parseResult . InvocationConfiguration . EnableDefaultExceptionHandler = false ;
103- throw new Exception (
104- $ "This should not happen. An instance of { nameof ( AsynchronousCommandLineAction ) } ({ action } ) was called within { nameof ( InvocationPipeline ) } .{ nameof ( Invoke ) } . This is supposed to be detected earlier resulting in a call to { nameof ( InvocationPipeline ) } { nameof ( InvokeAsync ) } ") ;
105- }
106- }
115+ parseResult . InvocationConfiguration . EnableDefaultExceptionHandler = false ;
116+ throw new Exception (
117+ $ "This should not happen. An instance of { nameof ( AsynchronousCommandLineAction ) } ({ action } ) was called within { nameof ( InvocationPipeline ) } .{ nameof ( Invoke ) } . This is supposed to be detected earlier resulting in a call to { nameof ( InvocationPipeline ) } { nameof ( InvokeAsync ) } ") ;
118+ }
119+ }
107120#endif
108121
109- for ( var i = 0 ; i < parseResult . PreActions . Count ; i ++ )
122+ for ( var i = 0 ; i < parseResult . PreActions . Count ; i ++ )
123+ {
124+ if ( parseResult . PreActions [ i ] is SynchronousCommandLineAction syncPreAction )
125+ {
126+ int preActionResult = syncPreAction . Invoke ( parseResult ) ;
127+ if ( exitCode == 0 )
110128 {
111- if ( parseResult . PreActions [ i ] is SynchronousCommandLineAction syncPreAction )
112- {
113- syncPreAction . Invoke ( parseResult ) ;
114- }
129+ exitCode = preActionResult ;
115130 }
116131 }
117-
118- return syncAction . Invoke ( parseResult ) ;
119- }
120- catch ( Exception ex ) when ( parseResult . InvocationConfiguration . EnableDefaultExceptionHandler )
121- {
122- return DefaultExceptionHandler ( ex , parseResult ) ;
123132 }
133+ }
134+
135+ switch ( parseResult . Action )
136+ {
137+ case null :
138+ return exitCode != 0 ? exitCode : ReturnCodeForMissingAction ( parseResult ) ;
124139
125- default :
126- throw new InvalidOperationException ( $ "{ nameof ( AsynchronousCommandLineAction ) } called within non-async invocation.") ;
140+ case SynchronousCommandLineAction syncAction :
141+ int actionResult = syncAction . Invoke ( parseResult ) ;
142+ return exitCode != 0 ? exitCode : actionResult ;
143+
144+ default :
145+ throw new InvalidOperationException ( $ "{ nameof ( AsynchronousCommandLineAction ) } called within non-async invocation.") ;
146+ }
147+ }
148+ catch ( Exception ex ) when ( parseResult . InvocationConfiguration . EnableDefaultExceptionHandler )
149+ {
150+ return DefaultExceptionHandler ( ex , parseResult ) ;
127151 }
128152 }
129153
0 commit comments