From eba3ee04d450230f7ac1f88b1abd7b09c600c82d Mon Sep 17 00:00:00 2001 From: Adam Czachorowski Date: Wed, 2 Jun 2021 19:45:11 +0200 Subject: [PATCH] [clangd] Run code completion on each token coverd by --check-lines In --check mode we do not run code completion because it is too slow, especially on larger files. With the introducation of --check-lines we can narrow down the scope and thus we can afford to do code completion. We vlog() the top completion result, but that's not really the point. The most value will come from being able to reproduce crashes that occur during code completion and require preamble build or index (and thus are more difficult to reproduce with -code-complete-at). Differential Revision: https://reviews.llvm.org/D103538 --- clang-tools-extra/clangd/tool/Check.cpp | 20 +++++++++++++++----- clang-tools-extra/clangd/tool/ClangdMain.cpp | 9 +++++++-- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp index 89487bd8607f..88eb945d20d4 100644 --- a/clang-tools-extra/clangd/tool/Check.cpp +++ b/clang-tools-extra/clangd/tool/Check.cpp @@ -193,10 +193,15 @@ public: // Run AST-based features at each token in the file. void testLocationFeatures( - llvm::function_ref ShouldCheckLine) { + llvm::function_ref ShouldCheckLine, + const bool EnableCodeCompletion) { log("Testing features at each token (may be slow in large files)"); auto &SM = AST->getSourceManager(); auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID()); + + CodeCompleteOptions CCOpts = Opts.CodeComplete; + CCOpts.Index = &Index; + for (const auto &Tok : SpelledTokens) { unsigned Start = AST->getSourceManager().getFileOffset(Tok.location()); unsigned End = Start + Tok.length(); @@ -233,8 +238,12 @@ public: auto Hover = getHover(*AST, Pos, Style, &Index); vlog(" hover: {0}", Hover.hasValue()); - // FIXME: it'd be nice to include code completion, but it's too slow. - // Maybe in combination with a line restriction? + if (EnableCodeCompletion) { + Position EndPos = offsetToPosition(Inputs.Contents, End); + auto CC = codeComplete(File, EndPos, Preamble.get(), Inputs, CCOpts); + vlog(" code completion: {0}", + CC.Completions.empty() ? "" : CC.Completions[0].Name); + } } } }; @@ -243,7 +252,8 @@ public: bool check(llvm::StringRef File, llvm::function_ref ShouldCheckLine, - const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts) { + const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, + bool EnableCodeCompletion) { llvm::SmallString<0> FakeFile; llvm::Optional Contents; if (File.empty()) { @@ -267,7 +277,7 @@ bool check(llvm::StringRef File, if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) || !C.buildAST()) return false; - C.testLocationFeatures(ShouldCheckLine); + C.testLocationFeatures(ShouldCheckLine, EnableCodeCompletion); log("All checks completed, {0} errors", C.ErrCount); return C.ErrCount == 0; diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index f0aa89b8091f..0f9e5c89e42c 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -62,7 +62,8 @@ namespace clangd { // Implemented in Check.cpp. bool check(const llvm::StringRef File, llvm::function_ref ShouldCheckLine, - const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts); + const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, + bool EnableCodeCompletion); namespace { @@ -929,7 +930,11 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var uint32_t Line = Pos.line + 1; // Position::line is 0-based. return Line >= Begin && Line <= End; }; - return check(Path, ShouldCheckLine, TFS, Opts) + // For now code completion is enabled any time the range is limited via + // --check-lines. If it turns out to be to slow, we can introduce a + // dedicated flag for that instead. + return check(Path, ShouldCheckLine, TFS, Opts, + /*EnableCodeCompletion=*/!CheckFileLines.empty()) ? 0 : static_cast(ErrorResultCode::CheckFailed); }