[clangd] Turn no-parse-completion on by when preamble isn't ready. Add flag to force it.

Reviewers: kadircet

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62135

llvm-svn: 361258
This commit is contained in:
Sam McCall 2019-05-21 13:40:31 +00:00
parent 8fa970c2d8
commit 0321b370f2
5 changed files with 49 additions and 27 deletions

View File

@ -200,10 +200,12 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
};
// We use a potentially-stale preamble because latency is critical here.
WorkScheduler.runWithPreamble("CodeComplete", File,
Opts.AllowFallback ? TUScheduler::StaleOrAbsent
: TUScheduler::Stale,
Bind(Task, File.str(), std::move(CB)));
WorkScheduler.runWithPreamble(
"CodeComplete", File,
(Opts.RunParser == CodeCompleteOptions::AlwaysParse)
? TUScheduler::Stale
: TUScheduler::StaleOrAbsent,
Bind(Task, File.str(), std::move(CB)));
}
void ClangdServer::signatureHelp(PathRef File, Position Pos,

View File

@ -1738,9 +1738,10 @@ codeComplete(PathRef FileName, const tooling::CompileCommand &Command,
auto Flow = CodeCompleteFlow(
FileName, Preamble ? Preamble->Includes : IncludeStructure(),
SpecFuzzyFind, Opts);
return Preamble ? std::move(Flow).run(
{FileName, Command, Preamble, Contents, *Offset, VFS})
: std::move(Flow).runWithoutSema(Contents, *Offset, VFS);
return (!Preamble || Opts.RunParser == CodeCompleteOptions::NeverParse)
? std::move(Flow).runWithoutSema(Contents, *Offset, VFS)
: std::move(Flow).run(
{FileName, Command, Preamble, Contents, *Offset, VFS});
}
SignatureHelp signatureHelp(PathRef FileName,

View File

@ -115,11 +115,18 @@ struct CodeCompleteOptions {
/// Such completions can insert scope qualifiers.
bool AllScopes = false;
/// Whether to allow falling back to code completion without compiling files
/// (using identifiers in the current file and symbol indexes), when file
/// cannot be built (e.g. missing compile command), or the build is not ready
/// (e.g. preamble is still being built).
bool AllowFallback = false;
/// Whether to use the clang parser, or fallback to text-based completion
/// (using identifiers in the current file and symbol indexes).
enum CodeCompletionParse {
/// Block until we can run the parser (e.g. preamble is built).
/// Return an error if this fails.
AlwaysParse,
/// Run the parser if inputs (preamble) are ready.
/// Otherwise, use text-based completion.
ParseIfReady,
/// Always use text-based completion.
NeverParse,
} RunParser = ParseIfReady;
};
// Semi-structured representation of a code-complete suggestion for our C++ API.

View File

@ -256,13 +256,18 @@ static llvm::cl::opt<OffsetEncoding> ForceOffsetEncoding(
"Offsets are in UTF-16 code units")),
llvm::cl::init(OffsetEncoding::UnsupportedEncoding));
static llvm::cl::opt<bool> AllowFallbackCompletion(
"allow-fallback-completion",
llvm::cl::desc(
"Allow falling back to code completion without compiling files (using "
"identifiers and symbol indexes), when file cannot be built or the "
"build is not ready."),
llvm::cl::init(false));
static llvm::cl::opt<CodeCompleteOptions::CodeCompletionParse>
CodeCompletionParse(
"completion-parse",
llvm::cl::desc("Whether the clang-parser is used for code-completion"),
llvm::cl::values(clEnumValN(CodeCompleteOptions::AlwaysParse, "always",
"Block until the parser can be used"),
clEnumValN(CodeCompleteOptions::ParseIfReady, "auto",
"Use text-based completion if the parser "
"is not ready"),
clEnumValN(CodeCompleteOptions::NeverParse, "never",
"Always used text-based completion")),
llvm::cl::init(CodeCompleteOptions().RunParser), llvm::cl::Hidden);
namespace {
@ -475,7 +480,7 @@ int main(int argc, char *argv[]) {
CCOpts.SpeculativeIndexRequest = Opts.StaticIndex;
CCOpts.EnableFunctionArgSnippets = EnableFunctionArgSnippets;
CCOpts.AllScopes = AllScopesCompletion;
CCOpts.AllowFallback = AllowFallbackCompletion;
CCOpts.RunParser = CodeCompletionParse;
RealFileSystemProvider FSProvider;
// Initialize and run ClangdLSPServer.

View File

@ -9,6 +9,7 @@
#include "Annotations.h"
#include "ClangdLSPServer.h"
#include "ClangdServer.h"
#include "CodeComplete.h"
#include "GlobalCompilationDatabase.h"
#include "Matchers.h"
#include "SyncAPI.h"
@ -1072,7 +1073,7 @@ TEST_F(ClangdVFSTest, FallbackWhenPreambleIsNotReady) {
FS.Files[FooCpp] = FooCpp;
auto Opts = clangd::CodeCompleteOptions();
Opts.AllowFallback = true;
Opts.RunParser = CodeCompleteOptions::ParseIfReady;
// This will make compile command broken and preamble absent.
CDB.ExtraClangFlags = {"yolo.cc"};
@ -1089,11 +1090,17 @@ TEST_F(ClangdVFSTest, FallbackWhenPreambleIsNotReady) {
CDB.ExtraClangFlags = {"-std=c++11"};
Server.addDocument(FooCpp, Code.code());
ASSERT_TRUE(Server.blockUntilIdleForTest());
EXPECT_THAT(cantFail(runCodeComplete(Server, FooCpp, Code.point(),
clangd::CodeCompleteOptions()))
.Completions,
ElementsAre(AllOf(Field(&CodeCompletion::Name, "xyz"),
Field(&CodeCompletion::Scope, "ns::"))));
EXPECT_THAT(
cantFail(runCodeComplete(Server, FooCpp, Code.point(), Opts)).Completions,
ElementsAre(AllOf(Field(&CodeCompletion::Name, "xyz"),
Field(&CodeCompletion::Scope, "ns::"))));
// Now force identifier-based completion.
Opts.RunParser = CodeCompleteOptions::NeverParse;
EXPECT_THAT(
cantFail(runCodeComplete(Server, FooCpp, Code.point(), Opts)).Completions,
ElementsAre(AllOf(Field(&CodeCompletion::Name, "xyz"),
Field(&CodeCompletion::Scope, ""))));
}
TEST_F(ClangdVFSTest, FallbackWhenWaitingForCompileCommand) {
@ -1140,7 +1147,7 @@ TEST_F(ClangdVFSTest, FallbackWhenWaitingForCompileCommand) {
// hasn't been scheduled.
std::this_thread::sleep_for(std::chrono::milliseconds(10));
auto Opts = clangd::CodeCompleteOptions();
Opts.AllowFallback = true;
Opts.RunParser = CodeCompleteOptions::ParseIfReady;
auto Res = cantFail(runCodeComplete(Server, FooCpp, Code.point(), Opts));
EXPECT_EQ(Res.Context, CodeCompletionContext::CCC_Recovery);