4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import { groupBy } from 'vs/base/common/arrays' ;
7
+ import { createCancelablePromise } from 'vs/base/common/async' ;
7
8
import { CancellationToken } from 'vs/base/common/cancellation' ;
8
9
import { Codicon } from 'vs/base/common/codicons' ;
9
10
import { Event } from 'vs/base/common/event' ;
@@ -20,7 +21,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
20
21
import { ILogService } from 'vs/platform/log/common/log' ;
21
22
import { IProductService } from 'vs/platform/product/common/productService' ;
22
23
import { ProgressLocation } from 'vs/platform/progress/common/progress' ;
23
- import { IQuickInputService , IQuickPickItem , QuickPickInput } from 'vs/platform/quickinput/common/quickInput' ;
24
+ import { IQuickInputService , IQuickPick , IQuickPickItem , QuickPickInput } from 'vs/platform/quickinput/common/quickInput' ;
24
25
import { Registry } from 'vs/platform/registry/common/platform' ;
25
26
import { Extensions as WorkbenchExtensions , IWorkbenchContribution , IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions' ;
26
27
import { ViewContainerLocation } from 'vs/workbench/common/views' ;
@@ -48,7 +49,11 @@ type SourcePick = IQuickPickItem & { action: ISourceAction };
48
49
function isSourcePick ( item : QuickPickInput < IQuickPickItem > ) : item is SourcePick {
49
50
return 'action' in item ;
50
51
}
51
- type KernelQuickPickItem = IQuickPickItem | KernelPick | SourcePick ;
52
+ type InstallExtensionPick = IQuickPickItem & { extensionId : string } ;
53
+ function isInstallExtensionPick ( item : QuickPickInput < IQuickPickItem > ) : item is InstallExtensionPick {
54
+ return item . id === 'installSuggested' && 'extensionId' in item ;
55
+ }
56
+ type KernelQuickPickItem = IQuickPickItem | InstallExtensionPick | KernelPick | SourcePick ;
52
57
const KERNEL_PICKER_UPDATE_DEBOUNCE = 200 ;
53
58
54
59
registerAction2 ( class extends Action2 {
@@ -180,14 +185,18 @@ registerAction2(class extends Action2 {
180
185
}
181
186
182
187
const quickPick = quickInputService . createQuickPick < KernelQuickPickItem > ( ) ;
183
- const quickPickItemSuggestions = this . _getKernelPickerQuickPickItems ( notebook , matchResult , notebookKernelService , scopedContextKeyService ) ;
184
- let suggestedExtension = quickPickItemSuggestions . suggestedExtension ;
185
- quickPick . items = quickPickItemSuggestions . quickPickItems ;
188
+ const quickPickItems = this . _getKernelPickerQuickPickItems ( notebook , matchResult , notebookKernelService , scopedContextKeyService ) ;
189
+ quickPick . items = quickPickItems ;
186
190
quickPick . canSelectMany = false ;
187
191
quickPick . placeholder = selected
188
192
? nls . localize ( 'prompt.placeholder.change' , "Change kernel for '{0}'" , labelService . getUriLabel ( notebook . uri , { relative : true } ) )
189
193
: nls . localize ( 'prompt.placeholder.select' , "Select kernel for '{0}'" , labelService . getUriLabel ( notebook . uri , { relative : true } ) ) ;
190
194
195
+ // run extension recommendataion task if quickPickItems is empty
196
+ const extensionRecommendataionPromise = quickPickItems . length === 0
197
+ ? createCancelablePromise ( token => this . _showInstallKernelExtensionRecommendation ( notebook , quickPick , extensionWorkbenchService , token ) )
198
+ : undefined ;
199
+
191
200
const kernelChangeEventListener = Event . debounce < void , void > (
192
201
Event . any (
193
202
notebookKernelService . onDidChangeSourceActions ,
@@ -197,31 +206,34 @@ registerAction2(class extends Action2 {
197
206
) ,
198
207
( last , _current ) => last ,
199
208
KERNEL_PICKER_UPDATE_DEBOUNCE
200
- ) ( ( ) => {
209
+ ) ( async ( ) => {
210
+ // reset quick pick progress
211
+ quickPick . busy = false ;
212
+ extensionRecommendataionPromise ?. cancel ( ) ;
213
+
201
214
const currentActiveItems = quickPick . activeItems ;
202
215
const matchResult = notebookKernelService . getMatchingKernel ( notebook ) ;
203
- const quickPickItemSuggestions = this . _getKernelPickerQuickPickItems ( notebook , matchResult , notebookKernelService , scopedContextKeyService ) ;
204
- suggestedExtension = quickPickItemSuggestions . suggestedExtension ;
216
+ const quickPickItems = this . _getKernelPickerQuickPickItems ( notebook , matchResult , notebookKernelService , scopedContextKeyService ) ;
205
217
quickPick . keepScrollPosition = true ;
206
218
207
219
// recalcuate active items
208
220
const activeItems : KernelQuickPickItem [ ] = [ ] ;
209
221
for ( const item of currentActiveItems ) {
210
222
if ( isKernelPick ( item ) ) {
211
223
const kernelId = item . kernel . id ;
212
- const sameItem = quickPickItemSuggestions . quickPickItems . find ( pi => isKernelPick ( pi ) && pi . kernel . id === kernelId ) as KernelPick | undefined ;
224
+ const sameItem = quickPickItems . find ( pi => isKernelPick ( pi ) && pi . kernel . id === kernelId ) as KernelPick | undefined ;
213
225
if ( sameItem ) {
214
226
activeItems . push ( sameItem ) ;
215
227
}
216
228
} else if ( isSourcePick ( item ) ) {
217
- const sameItem = quickPickItemSuggestions . quickPickItems . find ( pi => isSourcePick ( pi ) && pi . action . action . id === item . action . action . id ) as SourcePick | undefined ;
229
+ const sameItem = quickPickItems . find ( pi => isSourcePick ( pi ) && pi . action . action . id === item . action . action . id ) as SourcePick | undefined ;
218
230
if ( sameItem ) {
219
231
activeItems . push ( sameItem ) ;
220
232
}
221
233
}
222
234
}
223
235
224
- quickPick . items = quickPickItemSuggestions . quickPickItems ;
236
+ quickPick . items = quickPickItems ;
225
237
quickPick . activeItems = activeItems ;
226
238
} , this ) ;
227
239
@@ -261,13 +273,13 @@ registerAction2(class extends Action2 {
261
273
notebook . viewType
262
274
) ;
263
275
// suggestedExtension must be defined for this option to be shown, but still check to make TS happy
264
- } else if ( pick . id === 'installSuggested' && suggestedExtension ) {
276
+ } else if ( isInstallExtensionPick ( pick ) ) {
265
277
await this . _showKernelExtension (
266
278
paneCompositeService ,
267
279
extensionWorkbenchService ,
268
280
extensionHostService ,
269
281
notebook . viewType ,
270
- suggestedExtension . extensionId ,
282
+ pick . extensionId ,
271
283
productService . quality !== 'stable'
272
284
) ;
273
285
} else if ( isSourcePick ( pick ) ) {
@@ -284,7 +296,7 @@ registerAction2(class extends Action2 {
284
296
matchResult : INotebookKernelMatchResult ,
285
297
notebookKernelService : INotebookKernelService ,
286
298
scopedContextKeyService : IContextKeyService
287
- ) : { quickPickItems : QuickPickInput < KernelQuickPickItem > [ ] ; suggestedExtension : INotebookExtensionRecommendation | undefined } {
299
+ ) : QuickPickInput < KernelQuickPickItem > [ ] {
288
300
const { selected, all, suggestions, hidden } = matchResult ;
289
301
290
302
function toQuickPick ( kernel : INotebookKernel ) {
@@ -346,29 +358,62 @@ registerAction2(class extends Action2 {
346
358
} ) ;
347
359
}
348
360
349
- let suggestedExtension : INotebookExtensionRecommendation | undefined ;
350
- if ( ! all . length && ! sourceActions . length ) {
351
- const language = this . getSuggestedLanguage ( notebookTextModel ) ;
352
- suggestedExtension = language ? this . getSuggestedKernelFromLanguage ( notebookTextModel . viewType , language ) : undefined ;
353
- if ( suggestedExtension ) {
354
- // We have a suggested kernel, show an option to install it
355
- quickPickItems . push ( {
356
- id : 'installSuggested' ,
357
- description : suggestedExtension . displayName ?? suggestedExtension . extensionId ,
358
- label : `$(${ Codicon . lightbulb . id } ) ` + nls . localize ( 'installSuggestedKernel' , 'Install suggested extensions' ) ,
359
- } ) ;
361
+ return quickPickItems ;
362
+ }
363
+
364
+ private async _showInstallKernelExtensionRecommendation (
365
+ notebookTextModel : NotebookTextModel ,
366
+ quickPick : IQuickPick < KernelQuickPickItem > ,
367
+ extensionWorkbenchService : IExtensionsWorkbenchService ,
368
+ token : CancellationToken
369
+ ) {
370
+ quickPick . busy = true ;
371
+
372
+ const newQuickPickItems = await this . _getKernelRecommendationsQuickPickItems ( notebookTextModel , extensionWorkbenchService ) ;
373
+ quickPick . busy = false ;
374
+
375
+ if ( token . isCancellationRequested ) {
376
+ return ;
377
+ }
378
+
379
+ if ( newQuickPickItems && quickPick . items . length === 0 ) {
380
+ quickPick . items = newQuickPickItems ;
381
+ }
382
+ }
383
+
384
+
385
+ private async _getKernelRecommendationsQuickPickItems (
386
+ notebookTextModel : NotebookTextModel ,
387
+ extensionWorkbenchService : IExtensionsWorkbenchService ,
388
+ ) : Promise < QuickPickInput < KernelQuickPickItem > [ ] | undefined > {
389
+ const quickPickItems : QuickPickInput < KernelQuickPickItem > [ ] = [ ] ;
390
+
391
+ const language = this . getSuggestedLanguage ( notebookTextModel ) ;
392
+ const suggestedExtension : INotebookExtensionRecommendation | undefined = language ? this . getSuggestedKernelFromLanguage ( notebookTextModel . viewType , language ) : undefined ;
393
+ if ( suggestedExtension ) {
394
+ await extensionWorkbenchService . queryLocal ( ) ;
395
+ const extension = extensionWorkbenchService . installed . find ( e => e . identifier . id === suggestedExtension . extensionId ) ;
396
+
397
+ if ( extension ) {
398
+ // it's installed but might be detecting kernels
399
+ return undefined ;
360
400
}
361
- // there is no kernel, show the install from marketplace
401
+
402
+ // We have a suggested kernel, show an option to install it
362
403
quickPickItems . push ( {
363
- id : 'install' ,
364
- label : nls . localize ( 'searchForKernels' , "Browse marketplace for kernel extensions" ) ,
404
+ id : 'installSuggested' ,
405
+ description : suggestedExtension . displayName ?? suggestedExtension . extensionId ,
406
+ label : `$(${ Codicon . lightbulb . id } ) ` + nls . localize ( 'installSuggestedKernel' , 'Install suggested extensions' ) ,
407
+ extensionId : suggestedExtension . extensionId
365
408
} ) ;
366
409
}
410
+ // there is no kernel, show the install from marketplace
411
+ quickPickItems . push ( {
412
+ id : 'install' ,
413
+ label : nls . localize ( 'searchForKernels' , "Browse marketplace for kernel extensions" ) ,
414
+ } ) ;
367
415
368
- return {
369
- quickPickItems,
370
- suggestedExtension
371
- } ;
416
+ return quickPickItems ;
372
417
}
373
418
374
419
/**
0 commit comments