@@ -489,17 +489,40 @@ class CodeCompletionSession {
489489      let  text  =  rewriteSourceKitPlaceholders ( in:  insertText,  clientSupportsSnippets:  clientSupportsSnippets) 
490490      let  isInsertTextSnippet  =  clientSupportsSnippets && text !=  insertText
491491
492-       let  textEdit :  TextEdit ? 
493-       let  edit  =  self . computeCompletionTextEdit ( 
492+       var  textEdit  =  self . computeCompletionTextEdit ( 
494493        completionPos:  completionPos, 
495494        requestPosition:  requestPosition, 
496495        utf8CodeUnitsToErase:  utf8CodeUnitsToErase, 
497496        newText:  text, 
498497        snapshot:  snapshot
499498      ) 
500-       textEdit =  edit
501499
502-       if  utf8CodeUnitsToErase !=  0 ,  filterName !=  nil ,  let  textEdit =  textEdit { 
500+       let  kind :  sourcekitd_api_uid_t ? =  value [ sourcekitd. keys. kind] 
501+       let  completionKind  =  kind? . asCompletionItemKind ( sourcekitd. values)  ??  . value
502+ 
503+       if  completionKind ==  . method || completionKind ==  . function,  name. first ==  " ( " ,  name. last ==  " ) "  { 
504+         // sourcekitd makes an assumption that the editor inserts a matching `)` when the user types a `(` to start
505+         // argument completions and thus does not contain the closing parentheses in the insert text. Since we can't
506+         // make that assumption of any editor using SourceKit-LSP, add the closing parenthesis when we are completing
507+         // function arguments, indicated by the completion kind and the completion's name being wrapped in parentheses.
508+         textEdit. newText +=  " ) " 
509+ 
510+         let  requestIndex  =  snapshot. index ( of:  requestPosition) 
511+         if  snapshot. text [ requestIndex]  ==  " ) " , 
512+           let  nextIndex =  snapshot. text. index ( requestIndex,  offsetBy:  1 ,  limitedBy:  snapshot. text. endIndex) 
513+         { 
514+           // Now, in case the editor already added the matching closing parenthesis, replace it by the parenthesis we
515+           // are adding as part of the completion above. While this might seem un-intuitive, it is the behavior that
516+           // VS Code expects. If the text edit's insert text does not contain the ')' and the user types the closing
517+           // parenthesis of a function that takes no arguments, VS Code's completion position is after the closing
518+           // parenthesis but no new completion request is sent since no character has been inserted (only the implicitly
519+           // inserted `)` has been overwritten). VS Code will now delete anything from the position that the completion
520+           // request was run, leaving the user without the closing `)`.
521+           textEdit. range =  textEdit. range. lowerBound..< snapshot. position ( of:  nextIndex) 
522+         } 
523+       } 
524+ 
525+       if  utf8CodeUnitsToErase !=  0 ,  filterName !=  nil  { 
503526        // To support the case where the client is doing prefix matching on the TextEdit range,
504527        // we need to prepend the deleted text to filterText.
505528        // This also works around a behaviour in VS Code that causes completions to not show up
@@ -545,18 +568,17 @@ class CodeCompletionSession {
545568          nil 
546569        } 
547570
548-       let  kind :  sourcekitd_api_uid_t ? =  value [ sourcekitd. keys. kind] 
549571      return  CompletionItem ( 
550572        label:  name, 
551-         kind:  kind ? . asCompletionItemKind ( sourcekitd . values )   ??   . value , 
573+         kind:  completionKind , 
552574        detail:  typeName, 
553575        documentation:  nil , 
554576        deprecated:  notRecommended, 
555577        sortText:  sortText, 
556578        filterText:  filterName, 
557579        insertText:  text, 
558580        insertTextFormat:  isInsertTextSnippet ?  . snippet :  . plain, 
559-         textEdit:  textEdit . map ( CompletionItemEdit . textEdit) , 
581+         textEdit:  CompletionItemEdit . textEdit ( textEdit) , 
560582        data:  data. encodeToLSPAny ( ) 
561583      ) 
562584    } 
0 commit comments