summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clangd/CodeComplete.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clangd/CodeComplete.cpp')
-rw-r--r--clang-tools-extra/clangd/CodeComplete.cpp41
1 files changed, 34 insertions, 7 deletions
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index dcbf00cad9e..45bc7026b9a 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -19,13 +19,16 @@
#include "Compiler.h"
#include "FuzzyMatch.h"
#include "Logger.h"
+#include "SourceCode.h"
#include "Trace.h"
#include "index/Index.h"
+#include "clang/Format/Format.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Index/USRGeneration.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/Sema.h"
+#include "clang/Tooling/Core/Replacement.h"
#include "llvm/Support/Format.h"
#include <queue>
@@ -249,7 +252,8 @@ struct CompletionCandidate {
}
// Builds an LSP completion item.
- CompletionItem build(const CompletionItemScores &Scores,
+ CompletionItem build(llvm::StringRef FileName,
+ const CompletionItemScores &Scores,
const CodeCompleteOptions &Opts,
CodeCompletionString *SemaCCS) const {
assert(bool(SemaResult) == bool(SemaCCS));
@@ -282,6 +286,28 @@ struct CompletionCandidate {
I.documentation = D->Documentation;
if (I.detail.empty())
I.detail = D->CompletionDetail;
+ // We only insert #include for items with details, since we can't tell
+ // whether the file URI of the canonical declaration would be the
+ // canonical #include without checking IncludeHeader in the detail.
+ // FIXME: delay creating include insertion command to
+ // "completionItem/resolve", when it is supported
+ if (!D->IncludeHeader.empty() ||
+ !IndexResult->CanonicalDeclaration.FileURI.empty()) {
+ // LSP favors additionalTextEdits over command. But we are still using
+ // command here because it would be expensive to calculate #include
+ // insertion edits for all candidates, and the include insertion edit
+ // is unlikely to conflict with the code completion edits.
+ Command Cmd;
+ // Command title is not added since this is not a user-facing command.
+ Cmd.command = ExecuteCommandParams::CLANGD_INSERT_HEADER_INCLUDE;
+ IncludeInsertion Insertion;
+ Insertion.header = D->IncludeHeader.empty()
+ ? IndexResult->CanonicalDeclaration.FileURI
+ : D->IncludeHeader;
+ Insertion.textDocument.uri = URIForFile(FileName);
+ Cmd.includeInsertion = std::move(Insertion);
+ I.command = std::move(Cmd);
+ }
}
}
I.scoreInfo = Scores;
@@ -806,6 +832,7 @@ clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
// This score is combined with the result quality score for the final score.
// - TopN determines the results with the best score.
class CodeCompleteFlow {
+ PathRef FileName;
const CodeCompleteOptions &Opts;
// Sema takes ownership of Recorder. Recorder is valid until Sema cleanup.
std::unique_ptr<CompletionRecorder> RecorderOwner;
@@ -816,9 +843,9 @@ class CodeCompleteFlow {
public:
// A CodeCompleteFlow object is only useful for calling run() exactly once.
- CodeCompleteFlow(const CodeCompleteOptions &Opts)
- : Opts(Opts), RecorderOwner(new CompletionRecorder(Opts)),
- Recorder(*RecorderOwner) {}
+ CodeCompleteFlow(PathRef FileName, const CodeCompleteOptions &Opts)
+ : FileName(FileName), Opts(Opts),
+ RecorderOwner(new CompletionRecorder(Opts)), Recorder(*RecorderOwner) {}
CompletionList run(const SemaCompleteInput &SemaCCInput) && {
trace::Span Tracer("CodeCompleteFlow");
@@ -956,7 +983,7 @@ private:
CodeCompletionString *SemaCCS = nullptr;
if (auto *SR = Candidate.SemaResult)
SemaCCS = Recorder.codeCompletionString(*SR, Opts.IncludeBriefComments);
- return Candidate.build(Scores, Opts, SemaCCS);
+ return Candidate.build(FileName, Scores, Opts, SemaCCS);
}
};
@@ -967,8 +994,8 @@ CompletionList codeComplete(PathRef FileName,
IntrusiveRefCntPtr<vfs::FileSystem> VFS,
std::shared_ptr<PCHContainerOperations> PCHs,
CodeCompleteOptions Opts) {
- return CodeCompleteFlow(Opts).run(
- {FileName, Command, Preamble, Contents, Pos, VFS, PCHs});
+ return CodeCompleteFlow(FileName, Opts)
+ .run({FileName, Command, Preamble, Contents, Pos, VFS, PCHs});
}
SignatureHelp signatureHelp(PathRef FileName,
OpenPOWER on IntegriCloud