[PATCH] D67224: [clangd] Enable completions with fixes in VSCode

Ilya Biryukov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 5 07:00:13 PDT 2019


ilya-biryukov created this revision.
Herald added subscribers: cfe-commits, kadircet, arphaman, mgrang, jkorous, MaskRay.
Herald added a project: clang.

Currently, the completions are not shown to the user as VSCode tries to match
'filterText' against the text in the edit range. Since the text contains '.'
or '->', we end up trying to match 'field' against '->field' and fail.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D67224

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts


Index: clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
===================================================================
--- clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
@@ -65,6 +65,14 @@
   }
 }
 
+class EnableEditsNearCursorFeature implements vscodelc.StaticFeature {
+  fillClientCapabilities(capabilities: vscodelc.ClientCapabilities): void {
+    const extendedCompletionCapabilities: any = capabilities.textDocument.completion;
+    extendedCompletionCapabilities.editsNearCursor = true;
+  }
+  initialize(capabilities: vscodelc.ServerCapabilities, documentSelector: (string | { language: string; scheme?: string; pattern?: string; } | { language?: string; scheme: string; pattern?: string; } | { language?: string; scheme?: string; pattern: string; })[]): void {
+  }
+}
 /**
  *  this method is called when your extension is activate
  *  your extension is activated the very first time the command is executed
@@ -114,6 +122,7 @@
   context.subscriptions.push(
       vscode.Disposable.from(semanticHighlightingFeature));
   clangdClient.registerFeature(semanticHighlightingFeature);
+  clangdClient.registerFeature(new EnableEditsNearCursorFeature);
   console.log('Clang Language Server is now active!');
   context.subscriptions.push(clangdClient.start());
   context.subscriptions.push(vscode.commands.registerCommand(
Index: clang-tools-extra/clangd/CodeComplete.h
===================================================================
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -175,9 +175,13 @@
   // thse includes may not be accurate for all of them.
   llvm::SmallVector<IncludeCandidate, 1> Includes;
 
+  struct FixIt {
+    std::string Before;
+    TextEdit Edit;
+  };
   /// Holds information about small corrections that needs to be done. Like
   /// converting '->' to '.' on member access.
-  std::vector<TextEdit> FixIts;
+  std::vector<FixIt> FixIts;
 
   /// Holds the range of the token we are going to replace with this completion.
   Range CompletionTokenRange;
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -277,12 +277,25 @@
           Completion.Name.back() == '/')
         Completion.Kind = CompletionItemKind::Folder;
       for (const auto &FixIt : C.SemaResult->FixIts) {
-        Completion.FixIts.push_back(toTextEdit(
-            FixIt, ASTCtx->getSourceManager(), ASTCtx->getLangOpts()));
+        // FIXME: this should live in SourceCode.h
+        auto &SM = ASTCtx->getSourceManager();
+        CharSourceRange Range = Lexer::makeFileCharRange(FixIt.RemoveRange, SM,
+                                                         ASTCtx->getLangOpts());
+        FileID FID;
+        unsigned StartOffset;
+        std::tie(FID, StartOffset) = SM.getDecomposedLoc(Range.getBegin());
+
+        std::string Code = SM.getBufferData(FID).substr(
+            StartOffset, SM.getFileOffset(Range.getEnd()) - StartOffset);
+
+        Completion.FixIts.push_back(CodeCompletion::FixIt{
+            std::move(Code), toTextEdit(FixIt, ASTCtx->getSourceManager(),
+                                        ASTCtx->getLangOpts())});
       }
-      llvm::sort(Completion.FixIts, [](const TextEdit &X, const TextEdit &Y) {
-        return std::tie(X.range.start.line, X.range.start.character) <
-               std::tie(Y.range.start.line, Y.range.start.character);
+      llvm::sort(Completion.FixIts, [](const CodeCompletion::FixIt &X,
+                                       const CodeCompletion::FixIt &Y) {
+        return std::tie(X.Edit.range.start.line, X.Edit.range.start.character) <
+               std::tie(Y.Edit.range.start.line, Y.Edit.range.start.character);
       });
       Completion.Deprecated |=
           (C.SemaResult->Availability == CXAvailability_Deprecated);
@@ -1817,11 +1830,12 @@
   // is mainly to help LSP clients again, so that changes do not effect each
   // other.
   for (const auto &FixIt : FixIts) {
-    if (isRangeConsecutive(FixIt.range, LSP.textEdit->range)) {
-      LSP.textEdit->newText = FixIt.newText + LSP.textEdit->newText;
-      LSP.textEdit->range.start = FixIt.range.start;
+    if (isRangeConsecutive(FixIt.Edit.range, LSP.textEdit->range)) {
+      LSP.textEdit->newText = FixIt.Edit.newText + LSP.textEdit->newText;
+      LSP.textEdit->range.start = FixIt.Edit.range.start;
+      LSP.filterText = FixIt.Before + LSP.filterText;
     } else {
-      LSP.additionalTextEdits.push_back(FixIt);
+      LSP.additionalTextEdits.push_back(FixIt.Edit);
     }
   }
   if (Opts.EnableSnippets)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67224.218910.patch
Type: text/x-patch
Size: 4796 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190905/980119d2/attachment-0001.bin>


More information about the cfe-commits mailing list