@@ -307,6 +307,13 @@ export class CompletionProvider implements ICompletionProvider<CompletionItem> {
307307 return true ;
308308 }
309309}
310+
311+ function stripQuotes ( path : string ) : string {
312+ return path . slice (
313+ path . startsWith ( "'" ) || path . startsWith ( '"' ) ? 1 : 0 ,
314+ path . endsWith ( "'" ) || path . endsWith ( '"' ) ? - 1 : path . length
315+ ) ;
316+ }
310317export function transformLSPCompletions < T > (
311318 token : CodeEditor . IToken ,
312319 positionInToken : number ,
@@ -317,6 +324,7 @@ export function transformLSPCompletions<T>(
317324 let prefix = token . value . slice ( 0 , positionInToken + 1 ) ;
318325 let allNonPrefixed = true ;
319326 let items : T [ ] = [ ] ;
327+ let prefixLength = prefix . length ;
320328 lspCompletionItems . forEach ( match => {
321329 let kind = match . kind ? CompletionItemKind [ match . kind ] : '' ;
322330
@@ -338,22 +346,27 @@ export function transformLSPCompletions<T>(
338346 }
339347 }
340348 // add prefix if needed
341- else if ( token . type === 'string ' && prefix . includes ( '/' ) ) {
349+ else if ( token . type === 'String ' && prefix . includes ( '/' ) ) {
342350 // special case for path completion in strings, ensuring that:
343351 // '/Com<tab> → '/Completion.ipynb
344352 // when the returned insert text is `Completion.ipynb` (the token here is `'/Com`)
345353 // developed against pyls and pylsp server, may not work well in other cases
346- const parts = prefix . split ( '/' ) ;
354+
355+ const parts = stripQuotes ( prefix ) . split ( '/' ) ;
347356 if (
348357 text . toLowerCase ( ) . startsWith ( parts [ parts . length - 1 ] . toLowerCase ( ) )
349358 ) {
350359 let pathPrefix = parts . slice ( 0 , - 1 ) . join ( '/' ) + '/' ;
351- match . insertText = pathPrefix + text ;
352- // for label removing the prefix quote if present
353- if ( pathPrefix . startsWith ( "'" ) || pathPrefix . startsWith ( '"' ) ) {
354- pathPrefix = pathPrefix . substr ( 1 ) ;
355- }
360+ const withStartingQuote =
361+ ( prefix . startsWith ( "'" ) || prefix . startsWith ( '"' ) ? prefix [ 0 ] : '' ) +
362+ pathPrefix +
363+ text ;
364+ match . insertText = withStartingQuote ;
365+ // for label without quotes
356366 match . label = pathPrefix + match . label ;
367+ if ( prefix . endsWith ( "'" ) || prefix . endsWith ( '"' ) ) {
368+ prefixLength = prefix . length - 1 ;
369+ }
357370 allNonPrefixed = false ;
358371 }
359372 }
@@ -369,8 +382,8 @@ export function transformLSPCompletions<T>(
369382 // completion of dictionaries for Python with jedi-language-server was
370383 // causing an issue for dic['<tab>'] case; to avoid this let's make
371384 // sure that prefix.length >= prefix.offset
372- if ( allNonPrefixed && prefixOffset > prefix . length ) {
373- prefixOffset = prefix . length ;
385+ if ( allNonPrefixed && prefixOffset > prefixLength ) {
386+ prefixOffset = prefixLength ;
374387 }
375388
376389 let response = {
@@ -384,7 +397,7 @@ export function transformLSPCompletions<T>(
384397 // text = token.value + text;
385398 // but it did not work for "from statistics <tab>" and lead to "from statisticsimport" (no space)
386399 start : token . offset + ( allNonPrefixed ? prefixOffset : 0 ) ,
387- end : token . offset + prefix . length ,
400+ end : token . offset + prefixLength ,
388401 items : items ,
389402 source : 'LSP'
390403 } ;
0 commit comments