10
10
using System . Threading ;
11
11
using System . Threading . Tasks ;
12
12
13
- namespace System . Management . Automation . Subsystem
13
+ namespace System . Management . Automation . Subsystem . Prediction
14
14
{
15
15
/// <summary>
16
16
/// The class represents the prediction result from a predictor.
@@ -59,9 +59,9 @@ public static class CommandPrediction
59
59
/// <param name="ast">The <see cref="Ast"/> object from parsing the current command line input.</param>
60
60
/// <param name="astTokens">The <see cref="Token"/> objects from parsing the current command line input.</param>
61
61
/// <returns>A list of <see cref="PredictionResult"/> objects.</returns>
62
- public static Task < List < PredictionResult > ? > PredictInput ( string client , Ast ast , Token [ ] astTokens )
62
+ public static Task < List < PredictionResult > ? > PredictInputAsync ( PredictionClient client , Ast ast , Token [ ] astTokens )
63
63
{
64
- return PredictInput ( client , ast , astTokens , millisecondsTimeout : 20 ) ;
64
+ return PredictInputAsync ( client , ast , astTokens , millisecondsTimeout : 20 ) ;
65
65
}
66
66
67
67
/// <summary>
@@ -72,7 +72,7 @@ public static class CommandPrediction
72
72
/// <param name="astTokens">The <see cref="Token"/> objects from parsing the current command line input.</param>
73
73
/// <param name="millisecondsTimeout">The milliseconds to timeout.</param>
74
74
/// <returns>A list of <see cref="PredictionResult"/> objects.</returns>
75
- public static async Task < List < PredictionResult > ? > PredictInput ( string client , Ast ast , Token [ ] astTokens , int millisecondsTimeout )
75
+ public static async Task < List < PredictionResult > ? > PredictInputAsync ( PredictionClient client , Ast ast , Token [ ] astTokens , int millisecondsTimeout )
76
76
{
77
77
Requires . Condition ( millisecondsTimeout > 0 , nameof ( millisecondsTimeout ) ) ;
78
78
@@ -86,17 +86,13 @@ public static class CommandPrediction
86
86
var tasks = new Task < PredictionResult ? > [ predictors . Count ] ;
87
87
using var cancellationSource = new CancellationTokenSource ( ) ;
88
88
89
+ Func < object ? , PredictionResult ? > callBack = GetCallBack ( client , context , cancellationSource ) ;
90
+
89
91
for ( int i = 0 ; i < predictors . Count ; i ++ )
90
92
{
91
93
ICommandPredictor predictor = predictors [ i ] ;
92
-
93
94
tasks [ i ] = Task . Factory . StartNew (
94
- state =>
95
- {
96
- var predictor = ( ICommandPredictor ) state ! ;
97
- SuggestionPackage pkg = predictor . GetSuggestion ( client , context , cancellationSource . Token ) ;
98
- return pkg . SuggestionEntries ? . Count > 0 ? new PredictionResult ( predictor . Id , predictor . Name , pkg . Session , pkg . SuggestionEntries ) : null ;
99
- } ,
95
+ callBack ,
100
96
predictor ,
101
97
cancellationSource . Token ,
102
98
TaskCreationOptions . DenyChildAttach ,
@@ -122,14 +118,29 @@ await Task.WhenAny(
122
118
}
123
119
124
120
return resultList ;
121
+
122
+ // A local helper function to avoid creating an instance of the generated delegate helper class
123
+ // when no predictor is registered.
124
+ static Func < object ? , PredictionResult ? > GetCallBack (
125
+ PredictionClient client ,
126
+ PredictionContext context ,
127
+ CancellationTokenSource cancellationSource )
128
+ {
129
+ return state =>
130
+ {
131
+ var predictor = ( ICommandPredictor ) state ! ;
132
+ SuggestionPackage pkg = predictor . GetSuggestion ( client , context , cancellationSource . Token ) ;
133
+ return pkg . SuggestionEntries ? . Count > 0 ? new PredictionResult ( predictor . Id , predictor . Name , pkg . Session , pkg . SuggestionEntries ) : null ;
134
+ } ;
135
+ }
125
136
}
126
137
127
138
/// <summary>
128
139
/// Allow registered predictors to do early processing when a command line is accepted.
129
140
/// </summary>
130
141
/// <param name="client">Represents the client that initiates the call.</param>
131
142
/// <param name="history">History command lines provided as references for prediction.</param>
132
- public static void OnCommandLineAccepted ( string client , IReadOnlyList < string > history )
143
+ public static void OnCommandLineAccepted ( PredictionClient client , IReadOnlyList < string > history )
133
144
{
134
145
Requires . NotNull ( history , nameof ( history ) ) ;
135
146
@@ -139,16 +150,54 @@ public static void OnCommandLineAccepted(string client, IReadOnlyList<string> hi
139
150
return ;
140
151
}
141
152
153
+ Action < ICommandPredictor > ? callBack = null ;
154
+ foreach ( ICommandPredictor predictor in predictors )
155
+ {
156
+ if ( predictor . CanAcceptFeedback ( client , PredictorFeedbackKind . CommandLineAccepted ) )
157
+ {
158
+ callBack ??= GetCallBack ( client , history ) ;
159
+ ThreadPool . QueueUserWorkItem < ICommandPredictor > ( callBack , predictor , preferLocal : false ) ;
<
FAB2
code>160 + }
161
+ }
162
+
163
+ // A local helper function to avoid creating an instance of the generated delegate helper class
164
+ // when no predictor is registered, or no registered predictor accepts this feedback.
165
+ static Action < ICommandPredictor > GetCallBack ( PredictionClient client , IReadOnlyList < string > history )
166
+ {
167
+ return predictor => predictor . OnCommandLineAccepted ( client , history ) ;
168
+ }
169
+ }
170
+
171
+ /// <summary>
172
+ /// Allow registered predictors to know the execution result (success/failure) of the last accepted command line.
173
+ /// </summary>
174
+ /// <param name="client">Represents the client that initiates the call.</param>
175
+ /// <param name="commandLine">The last accepted command line.</param>
176
+ /// <param name="success">Whether the execution of the last command line was successful.</param>
177
+ public static void OnCommandLineExecuted ( PredictionClient client , string commandLine , bool success )
178
+ {
179
+ var predictors = SubsystemManager . GetSubsystems < ICommandPredictor > ( ) ;
180
+ if ( predictors . Count == 0 )
181
+ {
182
+ return ;
183
+ }
184
+
185
+ Action < ICommandPredictor > ? callBack = null ;
142
186
foreach ( ICommandPredictor predictor in predictors )
143
187
{
144
- if ( predictor . SupportEarlyProcessing )
188
+ if ( predictor . CanAcceptFeedback ( client , PredictorFeedbackKind . CommandLineExecuted ) )
145
189
{
146
- ThreadPool . QueueUserWorkItem < ICommandPredictor > (
147
- state => state . StartEarlyProcessing ( client , history ) ,
148
- predictor ,
149
- preferLocal : false ) ;
190
+ callBack ??= GetCallBack ( client , commandLine , success ) ;
191
+ ThreadPool . QueueUserWorkItem < ICommandPredictor > ( callBack , predictor , preferLocal : false ) ;
150
192
}
151
193
}
194
+
195
+ // A local helper function to avoid creating an instance of the generated delegate helper class
196
+ // when no predictor is registered, or no registered predictor accepts this feedback.
197
+ static Action < ICommandPredictor > GetCallBack ( PredictionClient client , string commandLine , bool success )
198
+ {
199
+ return predictor => predictor . OnCommandLineExecuted (
F438
client , commandLine , success ) ;
200
+ }
152
201
}
153
202
154
203
/// <summary>
@@ -161,7 +210,7 @@ public static void OnCommandLineAccepted(string client, IReadOnlyList<string> hi
161
210
/// When the value is greater than 0, it's the number of displayed suggestions from the list returned in <paramref name="session"/>, starting from the index 0.
162
211
/// When the value is less than or equal to 0, it means a single suggestion from the list got displayed, and the index is the absolute value.
163
212
/// </param>
164
- public static void OnSuggestionDisplayed ( string client , Guid predictorId , uint session , int countOrIndex )
213
+ public static void OnSuggestionDisplayed ( PredictionClient client , Guid predictorId , uint session , int countOrIndex )
165
214
{
166
215
var predictors = SubsystemManager . GetSubsystems < ICommandPredictor > ( ) ;
167
216
if ( predictors . Count == 0 )
@@ -171,14 +220,24 @@ public static void OnSuggestionDisplayed(string client, Guid predictorId, uint s
171
220
172
221
foreach ( ICommandPredictor predictor in predictors )
173
222
{
174
- if ( predictor . AcceptFeedback && predictor . Id == predictorId )
223
+ if ( predictor . Id == predictorId )
175
224
{
176
- ThreadPool . QueueUserWorkItem < ICommandPredictor > (
177
- state => state . OnSuggestionDisplayed ( client , session , countOrIndex ) ,
178
- predictor ,
179
- preferLocal : false ) ;
225
+ if ( predictor . CanAcceptFeedback ( client , PredictorFeedbackKind . SuggestionDisplayed ) )
226
+ {
227
+ Action < ICommandPredictor > callBack = GetCallBack ( client , session , countOrIndex ) ;
228
+ ThreadPool . QueueUserWorkItem < ICommandPredictor > ( callBack , predictor , preferLocal : false ) ;
229
+ }
230
+
231
+ break ;
180
232
}
181
233
}
234
+
235
+ // A local helper function to avoid creating an instance of the generated delegate helper class
236
+ // when no predictor is registered, or no registered predictor accepts this feedback.
237
+ static Action < ICommandPredictor > GetCallBack ( PredictionClient client , uint session , int countOrIndex )
238
+ {
239
+ return predictor => predictor . OnSuggestionDisplayed ( client , session , countOrIndex ) ;
240
+ }
182
241
}
183
242
184
243
/// <summary>
@@ -188,7 +247,7 @@ public static void OnSuggestionDisplayed(string client, Guid predictorId, uint s
188
247
/// <param name="predictorId">The identifier of the predictor whose prediction result was accepted.</param>
189
248
/// <param name="session">The mini-session where the accepted suggestion came from.</param>
190
249
/// <param name="suggestionText">The accepted suggestion text.</param>
191
- public static void OnSuggestionAccepted ( string client , Guid predictorId , uint session , string suggestionText )
250
+ public static void OnSuggestionAccepted ( PredictionClient client , Guid predictorId , uint session , string suggestionText )
192
251
{
193
252
Requires . NotNullOrEmpty ( suggestionText , nameof ( suggestionText ) ) ;
194
253
@@ -200,14 +259,24 @@ public static void OnSuggestionAccepted(string client, Guid predictorId, uint se
200
259
201
260
foreach ( ICommandPredictor predictor in predictors )
202
261
{
203
- if ( predictor . AcceptFeedback && predictor . Id == predictorId )
262
+ if ( predictor . Id == predictorId )
204
263
{
205
- ThreadPool . QueueUserWorkItem < ICommandPredictor > (
206
- state => state . OnSuggestionAccepted ( client , session , suggestionText ) ,
207
- predictor ,
208
- preferLocal : false ) ;
264
+ if ( predictor . CanAcceptFeedback ( client , PredictorFeedbackKind . SuggestionAccepted ) )
265
+ {
266
+ Action < ICommandPredictor > callBack = GetCallBack ( client , session , suggestionText ) ;
267
+ ThreadPool . QueueUserWorkItem < ICommandPredictor > ( callBack , predictor , preferLocal : false ) ;
268
+ }
269
+
270
+ break ;
209
271
}
210
272
}
273
+
274
+ // A local helper function to avoid creating an instance of the generated delegate helper class
275
+ // when no predictor is registered, or no registered predictor accepts this feedback.
276
+ static Action < ICommandPredictor > GetCallBack ( PredictionClient client , uint session , string suggestionText )
277
+ {
278
+ return predictor => predictor . OnSuggestionAccepted ( client , session , suggestionText ) ;
279
+ }
211
280
}
212
281
}
213
282
}
0 commit comments