[clang-tools-extra] r313029 - [clangd] Add support for snippet completions
Ilya Biryukov via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 12 06:57:14 PDT 2017
Author: ibiryukov
Date: Tue Sep 12 06:57:14 2017
New Revision: 313029
URL: http://llvm.org/viewvc/llvm-project?rev=313029&view=rev
Log:
[clangd] Add support for snippet completions
Enhances CompletionItemsCollector in such a way that snippet
completions can be presented to the client. Enable snippet completion
items by specifying -enable-snippets while invoking the clangd
executable.
See: https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md#completion-request
See: https://github.com/Microsoft/vscode/blob/master/src/vs/editor/contrib/snippet/browser/snippet.md
Patch by Raoul Wols.
Added:
clang-tools-extra/trunk/test/clangd/completion-snippet.test
- copied, changed from r312948, clang-tools-extra/trunk/test/clangd/completion.test
Modified:
clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
clang-tools-extra/trunk/clangd/ClangdLSPServer.h
clang-tools-extra/trunk/clangd/ClangdServer.cpp
clang-tools-extra/trunk/clangd/ClangdServer.h
clang-tools-extra/trunk/clangd/ClangdUnit.cpp
clang-tools-extra/trunk/clangd/ClangdUnit.h
clang-tools-extra/trunk/clangd/Protocol.cpp
clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
clang-tools-extra/trunk/test/clangd/authority-less-uri.test
clang-tools-extra/trunk/test/clangd/completion.test
clang-tools-extra/trunk/test/clangd/protocol.test
clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.cpp Tue Sep 12 06:57:14 2017
@@ -221,9 +221,11 @@ void ClangdLSPServer::LSPProtocolCallbac
}
ClangdLSPServer::ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
+ bool SnippetCompletions,
llvm::Optional<StringRef> ResourceDir)
: Out(Out), DiagConsumer(*this),
- Server(CDB, DiagConsumer, FSProvider, AsyncThreadsCount, ResourceDir) {}
+ Server(CDB, DiagConsumer, FSProvider, AsyncThreadsCount,
+ SnippetCompletions, ResourceDir) {}
void ClangdLSPServer::run(std::istream &In) {
assert(!IsDone && "Run was called before");
Modified: clang-tools-extra/trunk/clangd/ClangdLSPServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdLSPServer.h?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdLSPServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdLSPServer.h Tue Sep 12 06:57:14 2017
@@ -27,6 +27,7 @@ class JSONOutput;
class ClangdLSPServer {
public:
ClangdLSPServer(JSONOutput &Out, unsigned AsyncThreadsCount,
+ bool SnippetCompletions,
llvm::Optional<StringRef> ResourceDir);
/// Run LSP server loop, receiving input for it from \p In. \p In must be
Modified: clang-tools-extra/trunk/clangd/ClangdServer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.cpp?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.cpp Tue Sep 12 06:57:14 2017
@@ -144,12 +144,13 @@ ClangdScheduler::~ClangdScheduler() {
ClangdServer::ClangdServer(GlobalCompilationDatabase &CDB,
DiagnosticsConsumer &DiagConsumer,
FileSystemProvider &FSProvider,
- unsigned AsyncThreadsCount,
+ unsigned AsyncThreadsCount, bool SnippetCompletions,
llvm::Optional<StringRef> ResourceDir)
: CDB(CDB), DiagConsumer(DiagConsumer), FSProvider(FSProvider),
ResourceDir(ResourceDir ? ResourceDir->str() : getStandardResourceDir()),
PCHs(std::make_shared<PCHContainerOperations>()),
- WorkScheduler(AsyncThreadsCount) {}
+ WorkScheduler(AsyncThreadsCount), SnippetCompletions(SnippetCompletions) {
+}
std::future<void> ClangdServer::addDocument(PathRef File, StringRef Contents) {
DocVersion Version = DraftMgr.updateDraft(File, Contents);
@@ -206,10 +207,10 @@ ClangdServer::codeComplete(PathRef File,
assert(Resources && "Calling completion on non-added file");
auto Preamble = Resources->getPossiblyStalePreamble();
- std::vector<CompletionItem> Result =
- clangd::codeComplete(File, Resources->getCompileCommand(),
- Preamble ? &Preamble->Preamble : nullptr,
- *OverridenContents, Pos, TaggedFS.Value, PCHs);
+ std::vector<CompletionItem> Result = clangd::codeComplete(
+ File, Resources->getCompileCommand(),
+ Preamble ? &Preamble->Preamble : nullptr, *OverridenContents, Pos,
+ TaggedFS.Value, PCHs, SnippetCompletions);
return make_tagged(std::move(Result), TaggedFS.Tag);
}
Modified: clang-tools-extra/trunk/clangd/ClangdServer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdServer.h?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdServer.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdServer.h Tue Sep 12 06:57:14 2017
@@ -179,6 +179,9 @@ public:
/// AsyncThreadsCount worker threads. However, if \p AsyncThreadsCount is 0,
/// all requests will be processed on the calling thread.
///
+ /// When \p SnippetCompletions is true, completion items will be presented
+ /// with embedded snippets. Otherwise, plaintext items will be presented.
+ ///
/// ClangdServer uses \p FSProvider to get an instance of vfs::FileSystem for
/// each parsing request. Results of code completion and diagnostics also
/// include a tag, that \p FSProvider returns along with the vfs::FileSystem.
@@ -201,6 +204,7 @@ public:
ClangdServer(GlobalCompilationDatabase &CDB,
DiagnosticsConsumer &DiagConsumer,
FileSystemProvider &FSProvider, unsigned AsyncThreadsCount,
+ bool SnippetCompletions,
llvm::Optional<StringRef> ResourceDir = llvm::None);
/// Add a \p File to the list of tracked C++ files or update the contents if
@@ -274,6 +278,7 @@ private:
// called before all other members to stop the worker thread that references
// ClangdServer
ClangdScheduler WorkScheduler;
+ bool SnippetCompletions;
};
} // namespace clangd
Modified: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.cpp?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp Tue Sep 12 06:57:14 2017
@@ -272,14 +272,22 @@ CompletionItemKind getKind(CXCursorKind
}
}
+std::string escapeSnippet(const llvm::StringRef Text) {
+ std::string Result;
+ Result.reserve(Text.size()); // Assume '$', '}' and '\\' are rare.
+ for (const auto Character : Text) {
+ if (Character == '$' || Character == '}' || Character == '\\')
+ Result.push_back('\\');
+ Result.push_back(Character);
+ }
+ return Result;
+}
+
class CompletionItemsCollector : public CodeCompleteConsumer {
- std::vector<CompletionItem> *Items;
- std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
- CodeCompletionTUInfo CCTUInfo;
public:
- CompletionItemsCollector(std::vector<CompletionItem> *Items,
- const CodeCompleteOptions &CodeCompleteOpts)
+ CompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+ std::vector<CompletionItem> &Items)
: CodeCompleteConsumer(CodeCompleteOpts, /*OutputIsBinary=*/false),
Items(Items),
Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
@@ -287,53 +295,237 @@ public:
void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context,
CodeCompletionResult *Results,
- unsigned NumResults) override {
- for (unsigned I = 0; I != NumResults; ++I) {
- CodeCompletionResult &Result = Results[I];
- CodeCompletionString *CCS = Result.CreateCodeCompletionString(
+ unsigned NumResults) override final {
+ Items.reserve(NumResults);
+ for (unsigned I = 0; I < NumResults; ++I) {
+ auto &Result = Results[I];
+ const auto *CCS = Result.CreateCodeCompletionString(
S, Context, *Allocator, CCTUInfo,
CodeCompleteOpts.IncludeBriefComments);
- if (CCS) {
- CompletionItem Item;
- for (CodeCompletionString::Chunk C : *CCS) {
- switch (C.Kind) {
- case CodeCompletionString::CK_ResultType:
- Item.detail = C.Text;
- break;
- case CodeCompletionString::CK_Optional:
- break;
- default:
- Item.label += C.Text;
- break;
- }
- }
- assert(CCS->getTypedText());
- Item.kind = getKind(Result.CursorKind);
- // Priority is a 16-bit integer, hence at most 5 digits.
- assert(CCS->getPriority() < 99999 && "Expecting code completion result "
- "priority to have at most "
- "5-digits");
- llvm::raw_string_ostream(Item.sortText)
- << llvm::format("%05d%s", CCS->getPriority(), CCS->getTypedText());
- Item.insertText = Item.filterText = CCS->getTypedText();
- if (CCS->getBriefComment())
- Item.documentation = CCS->getBriefComment();
- Items->push_back(std::move(Item));
- }
+ assert(CCS && "Expected the CodeCompletionString to be non-null");
+ Items.push_back(ProcessCodeCompleteResult(Result, *CCS));
}
}
GlobalCodeCompletionAllocator &getAllocator() override { return *Allocator; }
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
-};
+
+private:
+ CompletionItem
+ ProcessCodeCompleteResult(const CodeCompletionResult &Result,
+ const CodeCompletionString &CCS) const {
+
+ // Adjust this to InsertTextFormat::Snippet iff we encounter a
+ // CK_Placeholder chunk in SnippetCompletionItemsCollector.
+ CompletionItem Item;
+ Item.insertTextFormat = InsertTextFormat::PlainText;
+
+ FillDocumentation(CCS, Item);
+
+ // Fill in the label, detail, insertText and filterText fields of the
+ // CompletionItem.
+ ProcessChunks(CCS, Item);
+
+ // Fill in the kind field of the CompletionItem.
+ Item.kind = getKind(Result.CursorKind);
+
+ FillSortText(CCS, Item);
+
+ return Item;
+ }
+
+ virtual void ProcessChunks(const CodeCompletionString &CCS,
+ CompletionItem &Item) const = 0;
+
+ void FillDocumentation(const CodeCompletionString &CCS,
+ CompletionItem &Item) const {
+ // Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this
+ // information in the documentation field.
+ const unsigned AnnotationCount = CCS.getAnnotationCount();
+ if (AnnotationCount > 0) {
+ Item.documentation += "Annotation";
+ if (AnnotationCount == 1) {
+ Item.documentation += ": ";
+ } else /* AnnotationCount > 1 */ {
+ Item.documentation += "s: ";
+ }
+ for (unsigned I = 0; I < AnnotationCount; ++I) {
+ Item.documentation += CCS.getAnnotation(I);
+ Item.documentation.push_back(I == AnnotationCount - 1 ? '\n' : ' ');
+ }
+ }
+
+ // Add brief documentation (if there is any).
+ if (CCS.getBriefComment() != nullptr) {
+ if (!Item.documentation.empty()) {
+ // This means we previously added annotations. Add an extra newline
+ // character to make the annotations stand out.
+ Item.documentation.push_back('\n');
+ }
+ Item.documentation += CCS.getBriefComment();
+ }
+ }
+
+ void FillSortText(const CodeCompletionString &CCS,
+ CompletionItem &Item) const {
+ // Fill in the sortText of the CompletionItem.
+ assert(CCS.getPriority() < 99999 && "Expecting code completion result "
+ "priority to have at most 5-digits");
+ llvm::raw_string_ostream(Item.sortText)
+ << llvm::format("%05d%s", CCS.getPriority(), Item.filterText.c_str());
+ }
+
+ std::vector<CompletionItem> &Items;
+ std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
+ CodeCompletionTUInfo CCTUInfo;
+
+}; // CompletionItemsCollector
+
+class PlainTextCompletionItemsCollector final
+ : public CompletionItemsCollector {
+
+public:
+ PlainTextCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+ std::vector<CompletionItem> &Items)
+ : CompletionItemsCollector(CodeCompleteOpts, Items) {}
+
+private:
+ void ProcessChunks(const CodeCompletionString &CCS,
+ CompletionItem &Item) const override {
+ for (const auto &Chunk : CCS) {
+ switch (Chunk.Kind) {
+ case CodeCompletionString::CK_TypedText:
+ // There's always exactly one CK_TypedText chunk.
+ Item.insertText = Item.filterText = Chunk.Text;
+ Item.label += Chunk.Text;
+ break;
+ case CodeCompletionString::CK_ResultType:
+ assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
+ Item.detail = Chunk.Text;
+ break;
+ case CodeCompletionString::CK_Optional:
+ break;
+ default:
+ Item.label += Chunk.Text;
+ break;
+ }
+ }
+ }
+}; // PlainTextCompletionItemsCollector
+
+class SnippetCompletionItemsCollector final : public CompletionItemsCollector {
+
+public:
+ SnippetCompletionItemsCollector(const CodeCompleteOptions &CodeCompleteOpts,
+ std::vector<CompletionItem> &Items)
+ : CompletionItemsCollector(CodeCompleteOpts, Items) {}
+
+private:
+ void ProcessChunks(const CodeCompletionString &CCS,
+ CompletionItem &Item) const override {
+ unsigned ArgCount = 0;
+ for (const auto &Chunk : CCS) {
+ switch (Chunk.Kind) {
+ case CodeCompletionString::CK_TypedText:
+ // The piece of text that the user is expected to type to match
+ // the code-completion string, typically a keyword or the name of
+ // a declarator or macro.
+ Item.filterText = Chunk.Text;
+ // Note intentional fallthrough here.
+ case CodeCompletionString::CK_Text:
+ // A piece of text that should be placed in the buffer,
+ // e.g., parentheses or a comma in a function call.
+ Item.label += Chunk.Text;
+ Item.insertText += Chunk.Text;
+ break;
+ case CodeCompletionString::CK_Optional:
+ // A code completion string that is entirely optional.
+ // For example, an optional code completion string that
+ // describes the default arguments in a function call.
+
+ // FIXME: Maybe add an option to allow presenting the optional chunks?
+ break;
+ case CodeCompletionString::CK_Placeholder:
+ // A string that acts as a placeholder for, e.g., a function call
+ // argument.
+ ++ArgCount;
+ Item.insertText += "${" + std::to_string(ArgCount) + ':' +
+ escapeSnippet(Chunk.Text) + '}';
+ Item.label += Chunk.Text;
+ Item.insertTextFormat = InsertTextFormat::Snippet;
+ break;
+ case CodeCompletionString::CK_Informative:
+ // A piece of text that describes something about the result
+ // but should not be inserted into the buffer.
+ // For example, the word "const" for a const method, or the name of
+ // the base class for methods that are part of the base class.
+ Item.label += Chunk.Text;
+ // Don't put the informative chunks in the insertText.
+ break;
+ case CodeCompletionString::CK_ResultType:
+ // A piece of text that describes the type of an entity or,
+ // for functions and methods, the return type.
+ assert(Item.detail.empty() && "Unexpected extraneous CK_ResultType");
+ Item.detail = Chunk.Text;
+ break;
+ case CodeCompletionString::CK_CurrentParameter:
+ // A piece of text that describes the parameter that corresponds to
+ // the code-completion location within a function call, message send,
+ // macro invocation, etc.
+ //
+ // This should never be present while collecting completion items,
+ // only while collecting overload candidates.
+ llvm_unreachable("Unexpected CK_CurrentParameter while collecting "
+ "CompletionItems");
+ break;
+ case CodeCompletionString::CK_LeftParen:
+ // A left parenthesis ('(').
+ case CodeCompletionString::CK_RightParen:
+ // A right parenthesis (')').
+ case CodeCompletionString::CK_LeftBracket:
+ // A left bracket ('[').
+ case CodeCompletionString::CK_RightBracket:
+ // A right bracket (']').
+ case CodeCompletionString::CK_LeftBrace:
+ // A left brace ('{').
+ case CodeCompletionString::CK_RightBrace:
+ // A right brace ('}').
+ case CodeCompletionString::CK_LeftAngle:
+ // A left angle bracket ('<').
+ case CodeCompletionString::CK_RightAngle:
+ // A right angle bracket ('>').
+ case CodeCompletionString::CK_Comma:
+ // A comma separator (',').
+ case CodeCompletionString::CK_Colon:
+ // A colon (':').
+ case CodeCompletionString::CK_SemiColon:
+ // A semicolon (';').
+ case CodeCompletionString::CK_Equal:
+ // An '=' sign.
+ case CodeCompletionString::CK_HorizontalSpace:
+ // Horizontal whitespace (' ').
+ Item.insertText += Chunk.Text;
+ Item.label += Chunk.Text;
+ break;
+ case CodeCompletionString::CK_VerticalSpace:
+ // Vertical whitespace ('\n' or '\r\n', depending on the
+ // platform).
+ Item.insertText += Chunk.Text;
+ // Don't even add a space to the label.
+ break;
+ }
+ }
+ }
+}; // SnippetCompletionItemsCollector
} // namespace
std::vector<CompletionItem>
clangd::codeComplete(PathRef FileName, tooling::CompileCommand Command,
PrecompiledPreamble const *Preamble, StringRef Contents,
Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs) {
+ std::shared_ptr<PCHContainerOperations> PCHs,
+ bool SnippetCompletions) {
std::vector<const char *> ArgStrs;
for (const auto &S : Command.CommandLine)
ArgStrs.push_back(S.c_str());
@@ -371,8 +563,6 @@ clangd::codeComplete(PathRef FileName, t
FrontendOpts.SkipFunctionBodies = true;
FrontendOpts.CodeCompleteOpts.IncludeGlobals = true;
- // we don't handle code patterns properly yet, disable them.
- FrontendOpts.CodeCompleteOpts.IncludeCodePatterns = false;
FrontendOpts.CodeCompleteOpts.IncludeMacros = true;
FrontendOpts.CodeCompleteOpts.IncludeBriefComments = true;
@@ -381,8 +571,15 @@ clangd::codeComplete(PathRef FileName, t
FrontendOpts.CodeCompletionAt.Column = Pos.character + 1;
std::vector<CompletionItem> Items;
- Clang->setCodeCompletionConsumer(
- new CompletionItemsCollector(&Items, FrontendOpts.CodeCompleteOpts));
+ if (SnippetCompletions) {
+ FrontendOpts.CodeCompleteOpts.IncludeCodePatterns = true;
+ Clang->setCodeCompletionConsumer(new SnippetCompletionItemsCollector(
+ FrontendOpts.CodeCompleteOpts, Items));
+ } else {
+ FrontendOpts.CodeCompleteOpts.IncludeCodePatterns = false;
+ Clang->setCodeCompletionConsumer(new PlainTextCompletionItemsCollector(
+ FrontendOpts.CodeCompleteOpts, Items));
+ }
SyntaxOnlyAction Action;
if (!Action.BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) {
Modified: clang-tools-extra/trunk/clangd/ClangdUnit.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/ClangdUnit.h?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/ClangdUnit.h (original)
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h Tue Sep 12 06:57:14 2017
@@ -253,7 +253,8 @@ std::vector<CompletionItem>
codeComplete(PathRef FileName, tooling::CompileCommand Command,
PrecompiledPreamble const *Preamble, StringRef Contents,
Position Pos, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
- std::shared_ptr<PCHContainerOperations> PCHs);
+ std::shared_ptr<PCHContainerOperations> PCHs,
+ bool SnippetCompletions);
/// Get definition of symbol at a specified \p Pos.
std::vector<Location> findDefinitions(ParsedAST &AST, Position Pos);
Modified: clang-tools-extra/trunk/clangd/Protocol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Protocol.cpp?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Protocol.cpp (original)
+++ clang-tools-extra/trunk/clangd/Protocol.cpp Tue Sep 12 06:57:14 2017
@@ -724,8 +724,8 @@ std::string CompletionItem::unparse(cons
if (!CI.insertText.empty())
Os << R"("insertText":")" << llvm::yaml::escape(CI.insertText) << R"(",)";
if (CI.insertTextFormat != InsertTextFormat::Missing) {
- Os << R"("insertTextFormat":")" << static_cast<int>(CI.insertTextFormat)
- << R"(",)";
+ Os << R"("insertTextFormat":)" << static_cast<int>(CI.insertTextFormat)
+ << R"(,)";
}
if (CI.textEdit)
Os << R"("textEdit":)" << TextEdit::unparse(*CI.textEdit) << ',';
Modified: clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json (original)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json Tue Sep 12 06:57:14 2017
@@ -5,7 +5,7 @@
"version": "0.0.1",
"publisher": "Unpublished",
"engines": {
- "vscode": "^1.8.0"
+ "vscode": "^1.15.0"
},
"categories": [
"Languages",
@@ -24,8 +24,8 @@
"test": "node ./node_modules/vscode/bin/test"
},
"dependencies": {
- "vscode-languageclient": "^2.6.3",
- "vscode-languageserver": "^2.6.2"
+ "vscode-languageclient": "^3.3.0",
+ "vscode-languageserver": "^3.3.0"
},
"devDependencies": {
"typescript": "^2.0.3",
Modified: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts (original)
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts Tue Sep 12 06:57:14 2017
@@ -42,7 +42,7 @@ export function activate(context: vscode
if (textEditor && textEditor.document.uri.toString(true) === uri) {
textEditor.edit(mutator => {
for (const edit of edits) {
- mutator.replace(vscodelc.Protocol2Code.asRange(edit.range), edit.newText);
+ mutator.replace(clangdClient.protocol2CodeConverter.asRange(edit.range), edit.newText);
}
}).then((success) => {
if (!success) {
Modified: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp (original)
+++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp Tue Sep 12 06:57:14 2017
@@ -26,6 +26,12 @@ static llvm::cl::opt<unsigned>
llvm::cl::desc("Number of async workers used by clangd"),
llvm::cl::init(getDefaultAsyncThreadsCount()));
+static llvm::cl::opt<bool> EnableSnippets(
+ "enable-snippets",
+ llvm::cl::desc(
+ "Present snippet completions instead of plaintext completions"),
+ llvm::cl::init(false));
+
static llvm::cl::opt<bool> RunSynchronously(
"run-synchronously",
llvm::cl::desc("Parse on main thread. If set, -j is ignored"),
@@ -61,6 +67,7 @@ int main(int argc, char *argv[]) {
if (!ResourceDir.empty())
ResourceDirRef = ResourceDir;
- ClangdLSPServer LSPServer(Out, WorkerThreadsCount, ResourceDirRef);
+ ClangdLSPServer LSPServer(Out, WorkerThreadsCount, EnableSnippets,
+ ResourceDirRef);
LSPServer.run(std::cin);
}
Modified: clang-tools-extra/trunk/test/clangd/authority-less-uri.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/authority-less-uri.test?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/authority-less-uri.test (original)
+++ clang-tools-extra/trunk/test/clangd/authority-less-uri.test Tue Sep 12 06:57:14 2017
@@ -16,7 +16,7 @@ Content-Length: 146
# Test authority-less URI
#
# CHECK: {"jsonrpc":"2.0","id":1,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
# CHECK: ]}
Content-Length: 172
@@ -25,7 +25,7 @@ Content-Length: 172
# Test params parsing in the presence of a 1.x-compatible client (inlined "uri")
#
# CHECK: {"jsonrpc":"2.0","id":2,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
# CHECK: ]}
Content-Length: 44
Copied: clang-tools-extra/trunk/test/clangd/completion-snippet.test (from r312948, clang-tools-extra/trunk/test/clangd/completion.test)
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion-snippet.test?p2=clang-tools-extra/trunk/test/clangd/completion-snippet.test&p1=clang-tools-extra/trunk/test/clangd/completion.test&r1=312948&r2=313029&rev=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/completion.test (original)
+++ clang-tools-extra/trunk/test/clangd/completion-snippet.test Tue Sep 12 06:57:14 2017
@@ -1,4 +1,4 @@
-# RUN: clangd -run-synchronously < %s | FileCheck %s
+# RUN: clangd -run-synchronously -enable-snippets < %s | FileCheck %s
# It is absolutely vital that this file has CRLF line endings.
#
Content-Length: 125
@@ -16,12 +16,12 @@ Content-Length: 148
# nondeterministic, so we check regardless of order.
#
# CHECK: {"jsonrpc":"2.0","id":1,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
-# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb"}
-# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc"}
-# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator="}
-# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake"}
-# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}
+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}
+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator=(${1:const fake &})","insertTextFormat":2}
+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake()","insertTextFormat":1}
+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f(${1:int i}, ${2:const float f})","insertTextFormat":2}
# CHECK: ]}
Content-Length: 148
@@ -29,12 +29,12 @@ Content-Length: 148
# Repeat the completion request, expect the same results.
#
# CHECK: {"jsonrpc":"2.0","id":2,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
-# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb"}
-# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc"}
-# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator="}
-# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake"}
-# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}
+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}
+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator=(${1:const fake &})","insertTextFormat":2}
+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake()","insertTextFormat":1}
+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f(${1:int i}, ${2:const float f})","insertTextFormat":2}
# CHECK: ]}
# Update the source file and check for completions again.
Content-Length: 226
@@ -47,7 +47,7 @@ Content-Length: 148
# Repeat the completion request, expect the same results.
#
# CHECK: {"jsonrpc":"2.0","id":3,"result":[
-# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"00034func","filterText":"func","insertText":"func"}
+# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"00034func","filterText":"func","insertText":"func()","insertTextFormat":1}
# CHECK: ]}
Content-Length: 44
Modified: clang-tools-extra/trunk/test/clangd/completion.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/completion.test?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/completion.test (original)
+++ clang-tools-extra/trunk/test/clangd/completion.test Tue Sep 12 06:57:14 2017
@@ -16,12 +16,12 @@ Content-Length: 148
# nondeterministic, so we check regardless of order.
#
# CHECK: {"jsonrpc":"2.0","id":1,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
-# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb"}
-# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc"}
-# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator="}
-# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake"}
-# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}
+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}
+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator=","insertTextFormat":1}
+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake","insertTextFormat":1}
+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f","insertTextFormat":1}
# CHECK: ]}
Content-Length: 148
@@ -29,12 +29,12 @@ Content-Length: 148
# Repeat the completion request, expect the same results.
#
# CHECK: {"jsonrpc":"2.0","id":2,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
-# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb"}
-# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc"}
-# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator="}
-# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake"}
-# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
+# CHECK-DAG: {"label":"bb","kind":5,"detail":"int","sortText":"00035bb","filterText":"bb","insertText":"bb","insertTextFormat":1}
+# CHECK-DAG: {"label":"ccc","kind":5,"detail":"int","sortText":"00035ccc","filterText":"ccc","insertText":"ccc","insertTextFormat":1}
+# CHECK-DAG: {"label":"operator=(const fake &)","kind":2,"detail":"fake &","sortText":"00034operator=","filterText":"operator=","insertText":"operator=","insertTextFormat":1}
+# CHECK-DAG: {"label":"~fake()","kind":4,"detail":"void","sortText":"00034~fake","filterText":"~fake","insertText":"~fake","insertTextFormat":1}
+# CHECK-DAG: {"label":"f(int i, const float f) const","kind":2,"detail":"int","sortText":"00035f","filterText":"f","insertText":"f","insertTextFormat":1}
# CHECK: ]}
# Update the source file and check for completions again.
Content-Length: 226
@@ -47,7 +47,7 @@ Content-Length: 148
# Repeat the completion request, expect the same results.
#
# CHECK: {"jsonrpc":"2.0","id":3,"result":[
-# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"00034func","filterText":"func","insertText":"func"}
+# CHECK-DAG: {"label":"func()","kind":2,"detail":"int (*)(int, int)","sortText":"00034func","filterText":"func","insertText":"func","insertTextFormat":1}
# CHECK: ]}
Content-Length: 44
Modified: clang-tools-extra/trunk/test/clangd/protocol.test
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/protocol.test?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clangd/protocol.test (original)
+++ clang-tools-extra/trunk/test/clangd/protocol.test Tue Sep 12 06:57:14 2017
@@ -31,7 +31,7 @@ Content-Length: 146
# Test message with Content-Type before Content-Length
#
# CHECK: {"jsonrpc":"2.0","id":1,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
# CHECK: ]}
X-Test: Testing
@@ -50,7 +50,7 @@ Content-Length: 146
# Test message with duplicate Content-Length headers
#
# CHECK: {"jsonrpc":"2.0","id":3,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
# CHECK: ]}
# STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.
@@ -69,7 +69,7 @@ Content-Length: 146
# Test message with Content-Type before Content-Length
#
# CHECK: {"jsonrpc":"2.0","id":5,"result":[
-# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a"}
+# CHECK-DAG: {"label":"a","kind":5,"detail":"int","sortText":"00035a","filterText":"a","insertText":"a","insertTextFormat":1}
# CHECK: ]}
Content-Length: 1024
Modified: clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp?rev=313029&r1=313028&r2=313029&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/ClangdTests.cpp Tue Sep 12 06:57:14 2017
@@ -301,7 +301,8 @@ protected:
MockFSProvider FS;
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
- ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount());
+ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+ /*SnippetCompletions=*/false);
for (const auto &FileWithContents : ExtraFiles)
FS.Files[getVirtualTestFilePath(FileWithContents.first)] =
FileWithContents.second;
@@ -363,7 +364,8 @@ TEST_F(ClangdVFSTest, Reparse) {
MockFSProvider FS;
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
- ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount());
+ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+ /*SnippetCompletions=*/false);
const auto SourceContents = R"cpp(
#include "foo.h"
@@ -407,7 +409,8 @@ TEST_F(ClangdVFSTest, ReparseOnHeaderCha
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
- ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount());
+ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+ /*SnippetCompletions=*/false);
const auto SourceContents = R"cpp(
#include "foo.h"
@@ -454,7 +457,7 @@ TEST_F(ClangdVFSTest, CheckVersions) {
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
// Run ClangdServer synchronously.
ClangdServer Server(CDB, DiagConsumer, FS,
- /*AsyncThreadsCount=*/0);
+ /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false);
auto FooCpp = getVirtualTestFilePath("foo.cpp");
const auto SourceContents = "int a;";
@@ -487,7 +490,7 @@ TEST_F(ClangdVFSTest, SearchLibDir) {
"-stdlib=libstdc++"});
// Run ClangdServer synchronously.
ClangdServer Server(CDB, DiagConsumer, FS,
- /*AsyncThreadsCount=*/0);
+ /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false);
// Just a random gcc version string
SmallString<8> Version("4.9.3");
@@ -535,7 +538,7 @@ TEST_F(ClangdVFSTest, ForceReparseCompil
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
ClangdServer Server(CDB, DiagConsumer, FS,
- /*AsyncThreadsCount=*/0);
+ /*AsyncThreadsCount=*/0, /*SnippetCompletions=*/false);
// No need to sync reparses, because reparses are performed on the calling
// thread to true.
@@ -593,7 +596,8 @@ TEST_F(ClangdCompletionTest, CheckConten
ErrorCheckingDiagConsumer DiagConsumer;
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
- ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount());
+ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+ /*SnippetCompletions=*/false);
auto FooCpp = getVirtualTestFilePath("foo.cpp");
const auto SourceContents = R"cpp(
@@ -740,7 +744,8 @@ int d;
TestDiagConsumer DiagConsumer;
{
MockCompilationDatabase CDB(/*AddFreestandingFlag=*/true);
- ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount());
+ ClangdServer Server(CDB, DiagConsumer, FS, getDefaultAsyncThreadsCount(),
+ /*SnippetCompletions=*/false);
// Prepare some random distributions for the test.
std::random_device RandGen;
More information about the cfe-commits
mailing list