[clangd] collect symbol #include & insert #include in global code completion.
Summary:
o Collect suitable #include paths for index symbols. This also does smart mapping
for STL symbols and IWYU pragma (code borrowed from include-fixer).
o For global code completion, add a command for inserting new #include in each code
completion item.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: klimek, mgorny, ilya-biryukov, jkorous-apple, hintonda, cfe-commits
Differential Revision: https://reviews.llvm.org/D42640
llvm-svn: 325343
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 4b59dd5..2203c92 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -9,6 +9,7 @@
#include "ClangdServer.h"
#include "CodeComplete.h"
+#include "Headers.h"
#include "SourceCode.h"
#include "XRefs.h"
#include "index/Merge.h"
@@ -310,6 +311,47 @@
BindWithForward(Action, File.str(), NewName.str(), std::move(Callback)));
}
+Expected<tooling::Replacements>
+ClangdServer::insertInclude(PathRef File, StringRef Code,
+ llvm::StringRef Header) {
+ std::string ToInclude;
+ if (Header.startswith("<") || Header.startswith("\"")) {
+ ToInclude = Header;
+ } else {
+ auto U = URI::parse(Header);
+ if (!U)
+ return U.takeError();
+ auto Resolved = URI::resolve(*U, /*HintPath=*/File);
+ if (!Resolved)
+ return Resolved.takeError();
+
+ auto FS = FSProvider.getTaggedFileSystem(File).Value;
+ tooling::CompileCommand CompileCommand =
+ CompileArgs.getCompileCommand(File);
+ FS->setCurrentWorkingDirectory(CompileCommand.Directory);
+
+ auto Include =
+ shortenIncludePath(File, Code, *Resolved, CompileCommand, FS);
+ if (!Include)
+ return Include.takeError();
+ if (Include->empty())
+ return tooling::Replacements();
+ ToInclude = std::move(*Include);
+ }
+
+ auto Style = format::getStyle("file", File, "llvm");
+ if (!Style) {
+ llvm::consumeError(Style.takeError());
+ // FIXME(ioeric): needs more consistent style support in clangd server.
+ Style = format::getLLVMStyle();
+ }
+ // Replacement with offset UINT_MAX and length 0 will be treated as include
+ // insertion.
+ tooling::Replacement R(File, /*Offset=*/UINT_MAX, 0, "#include " + ToInclude);
+ return format::cleanupAroundReplacements(Code, tooling::Replacements(R),
+ *Style);
+}
+
llvm::Optional<std::string> ClangdServer::getDocument(PathRef File) {
auto Latest = DraftMgr.getDraft(File);
if (!Latest.Draft)