[clangd] UI for completion items that would trigger include insertion.
Summary:
For completion items that would trigger include insertions (i.e. index symbols
that are not #included yet), add a visual indicator "+" before the completion
label. The inserted headers will appear in the completion detail.
Open to suggestions for better visual indicators; "+" was picked because it
seems cleaner than a few other candidates I've tried (*, #, @ ...).
The displayed header would be like a/b/c.h (without quote) or <vector> for system
headers. I didn't add quotation or "#include" because they can take up limited
space and do not provide additional information after users know what the
headers are. I think a header alone should be obvious for users to infer that
this is an include header..
To align indentation, also prepend ' ' to labels of candidates that would not
trigger include insertions (only for completions where index results are
possible).
Vim:
{F6357587}
vscode:
{F6357589}
{F6357591}
Reviewers: sammccall, ilya-biryukov, hokein
Reviewed By: sammccall
Subscribers: MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48163
llvm-svn: 334828
diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp
index c6f18fa..35ecbf3 100644
--- a/clang-tools-extra/clangd/Headers.cpp
+++ b/clang-tools-extra/clangd/Headers.cpp
@@ -72,13 +72,11 @@
/// FIXME(ioeric): we might not want to insert an absolute include path if the
/// path is not shortened.
-llvm::Expected<std::string> calculateIncludePath(
- PathRef File, StringRef BuildDir, HeaderSearch &HeaderSearchInfo,
- const std::vector<Inclusion> &Inclusions, const HeaderFile &DeclaringHeader,
- const HeaderFile &InsertedHeader) {
+bool IncludeInserter::shouldInsertInclude(
+ const HeaderFile &DeclaringHeader, const HeaderFile &InsertedHeader) const {
assert(DeclaringHeader.valid() && InsertedHeader.valid());
- if (File == DeclaringHeader.File || File == InsertedHeader.File)
- return "";
+ if (FileName == DeclaringHeader.File || FileName == InsertedHeader.File)
+ return false;
llvm::StringSet<> IncludedHeaders;
for (const auto &Inc : Inclusions) {
IncludedHeaders.insert(Inc.Written);
@@ -88,53 +86,31 @@
auto Included = [&](llvm::StringRef Header) {
return IncludedHeaders.find(Header) != IncludedHeaders.end();
};
- if (Included(DeclaringHeader.File) || Included(InsertedHeader.File))
- return "";
+ return !Included(DeclaringHeader.File) && !Included(InsertedHeader.File);
+}
- bool IsSystem = false;
-
+std::string
+IncludeInserter::calculateIncludePath(const HeaderFile &DeclaringHeader,
+ const HeaderFile &InsertedHeader) const {
+ assert(DeclaringHeader.valid() && InsertedHeader.valid());
if (InsertedHeader.Verbatim)
return InsertedHeader.File;
-
+ bool IsSystem = false;
std::string Suggested = HeaderSearchInfo.suggestPathToFileForDiagnostics(
InsertedHeader.File, BuildDir, &IsSystem);
if (IsSystem)
Suggested = "<" + Suggested + ">";
else
Suggested = "\"" + Suggested + "\"";
-
- log("Suggested #include for " + InsertedHeader.File + " is: " + Suggested);
return Suggested;
}
-Expected<Optional<TextEdit>>
-IncludeInserter::insert(const HeaderFile &DeclaringHeader,
- const HeaderFile &InsertedHeader) const {
- auto Validate = [](const HeaderFile &Header) {
- return Header.valid()
- ? llvm::Error::success()
- : llvm::make_error<llvm::StringError>(
- "Invalid HeaderFile: " + Header.File +
- " (verbatim=" + std::to_string(Header.Verbatim) + ").",
- llvm::inconvertibleErrorCode());
- };
- if (auto Err = Validate(DeclaringHeader))
- return std::move(Err);
- if (auto Err = Validate(InsertedHeader))
- return std::move(Err);
- auto Include =
- calculateIncludePath(FileName, BuildDir, HeaderSearchInfo, Inclusions,
- DeclaringHeader, InsertedHeader);
- if (!Include)
- return Include.takeError();
- if (Include->empty())
- return llvm::None;
- StringRef IncludeRef = *Include;
- auto Insertion =
- Inserter.insert(IncludeRef.trim("\"<>"), IncludeRef.startswith("<"));
- if (!Insertion)
- return llvm::None;
- return replacementToEdit(Code, *Insertion);
+Optional<TextEdit> IncludeInserter::insert(StringRef VerbatimHeader) const {
+ Optional<TextEdit> Edit = None;
+ if (auto Insertion = Inserter.insert(VerbatimHeader.trim("\"<>"),
+ VerbatimHeader.startswith("<")))
+ Edit = replacementToEdit(Code, *Insertion);
+ return Edit;
}
} // namespace clangd