@@ -20,7 +20,7 @@ import {
20
20
import { LSPConnection } from '../../../connection' ;
21
21
import { Session } from '@jupyterlab/services' ;
22
22
import ICompletionItemsResponseType = CompletionHandler . ICompletionItemsResponseType ;
23
-
23
+ import { kernelIcon } from '@jupyterlab/ui-components' ;
24
24
25
25
/**
26
26
* A LSP connector for completion handlers.
@@ -268,23 +268,29 @@ export class LSPConnector
268
268
reply : CompletionHandler . IReply
269
269
) : CompletionHandler . ICompletionItemsReply {
270
270
console . log ( '[LSP][Completer] Transforming kernel reply:' , reply ) ;
271
- const items = new Array < CompletionHandler . ICompletionItem > ( ) ;
271
+ let items : CompletionHandler . ICompletionItem [ ] ;
272
272
const metadata = reply . metadata || { } ;
273
273
const types = metadata . _jupyter_types_experimental as JSONArray ;
274
274
275
275
if ( types ) {
276
- types . forEach ( ( item : JSONObject ) => {
277
- const text = item . text as string ;
278
- const type = item . type as string ;
279
- items . push ( { label : text , type } ) ;
276
+ items = types . map ( ( item : JSONObject ) => {
277
+ return {
278
+ label : item . text as string ,
279
+ insertText : item . text as string ,
280
+ type : item . type as string ,
281
+ icon : typeof item . type === 'undefined' ? kernelIcon : undefined
282
+ } ;
280
283
} ) ;
281
284
} else {
282
- const matches = reply . matches ;
283
- matches . forEach ( match => {
284
- items . push ( { label : match } ) ;
285
+ items = reply . matches . map ( match => {
286
+ return {
287
+ label : match ,
288
+ insertText : match ,
289
+ icon : kernelIcon
290
+ } ;
285
291
} ) ;
286
292
}
287
- return { ... reply , items } ;
293
+ return { start : reply . start , end : reply . end , items } ;
288
294
}
289
295
290
296
private merge_replies (
@@ -293,34 +299,60 @@ export class LSPConnector
293
299
editor : CodeEditor . IEditor
294
300
) : CompletionHandler . ICompletionItemsReply {
295
301
console . log ( '[LSP][Completer] Merging completions:' , lsp , kernel ) ;
302
+
296
303
if ( ! kernel . items . length ) {
297
304
return lsp ;
298
305
}
299
306
if ( ! lsp . items . length ) {
300
307
return kernel ;
301
308
}
302
309
303
- // combine completions, de-duping by label; LSP completions will show up first, kernel second.
304
- const aggregatedItems = lsp . items . concat ( kernel . items ) ;
305
- const labelSet = new Set < string > ( ) ;
310
+ let prefix = '' ;
311
+
312
+ // if the kernel used a wider range, get the previous characters to strip the prefix off,
313
+ // so that both use the same range
314
+ if ( lsp . start > kernel . start ) {
315
+ const cursor = editor . getCursorPosition ( ) ;
316
+ const line = editor . getLine ( cursor . line ) ;
317
+ prefix = line . substring ( kernel . start , lsp . start ) ;
318
+ console . log ( '[LSP][Completer] Removing kernel prefix: ' , prefix ) ;
319
+ } else if ( lsp . start < kernel . start ) {
320
+ console . warn ( '[LSP][Completer] Kernel start > LSP start' ) ;
321
+ }
322
+
323
+ // combine completions, de-duping by insertText; LSP completions will show up first, kernel second.
324
+ const aggregatedItems = lsp . items . concat (
325
+ kernel . items . map ( item => {
326
+ return {
327
+ ...item ,
328
+ label : item . label . startsWith ( prefix )
329
+ ? item . label . substr ( prefix . length )
330
+ : item . label ,
331
+ insertText : item . insertText . startsWith ( prefix )
332
+ ? item . insertText . substr ( prefix . length )
333
+ : item . insertText
334
+ } ;
335
+ } )
336
+ ) ;
337
+ const insertTextSet = new Set < string > ( ) ;
306
338
const processedItems = new Array < CompletionHandler . ICompletionItem > ( ) ;
307
339
308
- // TODO: Integrate prefix stripping?
309
340
aggregatedItems . forEach ( item => {
310
341
if (
311
342
// For some reason the _jupyter_types_experimental list has two entries
312
343
// for each match, with one having a type of "<unknown>". Discard those
313
344
// and use undefined to indicate an unknown type.
314
- labelSet . has ( item . label ) ||
345
+ insertTextSet . has ( item . insertText ) ||
315
346
( item . type && item . type === '<unknown>' )
316
347
) {
317
348
return ;
318
349
}
319
- labelSet . add ( item . label ) ;
350
+ insertTextSet . add ( item . insertText ) ;
320
351
processedItems . push ( item ) ;
321
352
} ) ;
322
353
// TODO: Sort items
323
354
// Return reply with processed items.
355
+ console . log ( '[LSP][Completer] Merged: ' , { ...lsp , items : processedItems } ) ;
324
356
return { ...lsp , items : processedItems } ;
325
357
}
326
358
0 commit comments