kadircet updated this revision to Diff 236842.
kadircet marked 5 inline comments as done.
kadircet added a comment.
- Address comments
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D71555/new/
https://reviews.llvm.org/D71555
Files:
clang-tools-extra/clangd/Hover.cpp
clang-tools-extra/clangd/test/hover.test
clang-tools-extra/clangd/unittests/HoverTests.cpp
Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -1606,6 +1606,100 @@
}
}
}
+TEST(Hover, Present) {
+ struct {
+ const std::function<void(HoverInfo &)> Builder;
+ llvm::StringRef ExpectedRender;
+ } Cases[] = {
+ {
+ [](HoverInfo &HI) { HI.Kind = index::SymbolKind::Unknown; },
+ R"(<unknown>)",
+ },
+ {
+ [](HoverInfo &HI) {
+ HI.Kind = index::SymbolKind::Class;
+ HI.Name = "foo";
+ },
+ R"(Class foo)",
+ },
+ {
+ [](HoverInfo &HI) {
+ HI.Kind = index::SymbolKind::NamespaceAlias;
+ HI.Name = "foo";
+ },
+ R"(Namespace Alias foo)",
+ },
+ {
+ [](HoverInfo &HI) {
+ HI.Kind = index::SymbolKind::Class;
+ HI.TemplateParameters = {
+ {std::string("typename"), std::string("T"), llvm::None},
+ {std::string("typename"), std::string("C"),
+ std::string("bool")},
+ };
+ HI.Documentation = "documentation";
+ HI.Definition =
+ "template <typename T, typename C = bool> class Foo {}";
+ HI.Name = "foo";
+ HI.NamespaceScope.emplace();
+ },
+ R"(Class foo
+documentation
+
+template <typename T, typename C = bool> class Foo {})",
+ },
+ {
+ [](HoverInfo &HI) {
+ HI.Kind = index::SymbolKind::Function;
+ HI.Name = "foo";
+ HI.Type = "type";
+ HI.ReturnType = "ret_type";
+ HI.Parameters.emplace();
+ HoverInfo::Param P;
+ HI.Parameters->push_back(P);
+ P.Type = "type";
+ HI.Parameters->push_back(P);
+ P.Name = "foo";
+ HI.Parameters->push_back(P);
+ P.Default = "default";
+ HI.Parameters->push_back(P);
+ HI.NamespaceScope = "ns::";
+ HI.Definition = "ret_type foo(params) {}";
+ },
+ R"(Function foo
+Returns: ret_type
+-
+- type
+- type foo
+- type foo = default
+
+// In namespace ns
+ret_type foo(params) {})",
+ },
+ {
+ [](HoverInfo &HI) {
+ HI.Kind = index::SymbolKind::Variable;
+ HI.LocalScope = "test::bar::";
+ HI.Value = "value";
+ HI.Name = "foo";
+ HI.Type = "type";
+ HI.Definition = "def";
+ },
+ R"(Variable foo : type
+Value: value
+
+// In test::bar
+def)",
+ },
+ };
+
+ for (const auto &C : Cases) {
+ HoverInfo HI;
+ C.Builder(HI);
+ EXPECT_EQ(HI.present().asPlainText(), C.ExpectedRender);
+ }
+}
+
} // namespace
} // namespace clangd
} // namespace clang
Index: clang-tools-extra/clangd/test/hover.test
===================================================================
--- clang-tools-extra/clangd/test/hover.test
+++ clang-tools-extra/clangd/test/hover.test
@@ -9,7 +9,7 @@
# CHECK-NEXT: "result": {
# CHECK-NEXT: "contents": {
# CHECK-NEXT: "kind": "plaintext",
-# CHECK-NEXT: "value": "Declared in global namespace\n\nvoid foo()"
+# CHECK-NEXT: "value": "Function foo\nReturns: void\n\nvoid foo()"
# CHECK-NEXT: },
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
@@ -37,7 +37,7 @@
# CHECK-NEXT: "result": {
# CHECK-NEXT: "contents": {
# CHECK-NEXT: "kind": "plaintext",
-# CHECK-NEXT: "value": "Declared in global namespace\n\nenum foo {}"
+# CHECK-NEXT: "value": "Enum foo\n\nenum foo {}"
# CHECK-NEXT: },
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
Index: clang-tools-extra/clangd/Hover.cpp
===================================================================
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -25,8 +25,9 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Casting.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
namespace clang {
@@ -224,8 +225,8 @@
// Populates Type, ReturnType, and Parameters for function-like decls.
void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D,
- const FunctionDecl *FD,
- const PrintingPolicy &Policy) {
+ const FunctionDecl *FD,
+ const PrintingPolicy &Policy) {
HI.Parameters.emplace();
for (const ParmVarDecl *PVD : FD->parameters()) {
HI.Parameters->emplace_back();
@@ -250,11 +251,11 @@
}
}
- if (const auto* CCD = llvm::dyn_cast<CXXConstructorDecl>(FD)) {
+ if (const auto *CCD = llvm::dyn_cast<CXXConstructorDecl>(FD)) {
// Constructor's "return type" is the class type.
HI.ReturnType = declaredType(CCD->getParent()).getAsString(Policy);
// Don't provide any type for the constructor itself.
- } else if (llvm::isa<CXXDestructorDecl>(FD)){
+ } else if (llvm::isa<CXXDestructorDecl>(FD)) {
HI.ReturnType = "void";
} else {
HI.ReturnType = FD->getReturnType().getAsString(Policy);
@@ -414,6 +415,20 @@
}
return HI;
}
+
+// Converts a string of the form `word1-word2-...` into `Word1 Word2 ...`.
+std::string beautify(llvm::StringRef Input) {
+ std::string Res;
+ llvm::SmallVector<llvm::StringRef, 2> Out;
+ llvm::SplitString(Input, Out, "-");
+ llvm::for_each(Out, [&Res](llvm::StringRef Word) {
+ if (!Res.empty())
+ Res += ' ';
+ Res += llvm::toUpper(Word.front());
+ Res.append(Word.drop_front());
+ });
+ return Res;
+}
} // namespace
llvm::Optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
@@ -460,34 +475,73 @@
tooling::applyAllReplacements(HI->Definition, Replacements))
HI->Definition = *Formatted;
- HI->SymRange = getTokenRange(AST.getSourceManager(),
- AST.getLangOpts(), SourceLocationBeg);
+ HI->SymRange = getTokenRange(AST.getSourceManager(), AST.getLangOpts(),
+ SourceLocationBeg);
return HI;
}
markup::Document HoverInfo::present() const {
markup::Document Output;
- if (NamespaceScope) {
- auto &P = Output.addParagraph();
- P.appendText("Declared in");
- // Drop trailing "::".
- if (!LocalScope.empty())
- P.appendCode(llvm::StringRef(LocalScope).drop_back(2));
- else if (NamespaceScope->empty())
- P.appendCode("global namespace");
- else
- P.appendCode(llvm::StringRef(*NamespaceScope).drop_back(2));
+ // Header contains a text of the form:
+ // Variable `var` : `int`
+ // or
+ // `class X`
+ markup::Paragraph &Header = Output.addParagraph();
+ Header.appendText(beautify(index::getSymbolKindString(Kind)));
+ if (!Name.empty()) {
+ Header.appendCode(Name);
+ if (Type && !ReturnType) {
+ Header.appendText(":");
+ Header.appendCode(*Type);
+ }
}
- if (!Definition.empty()) {
- Output.addCodeBlock(Definition);
- } else {
- // Builtin types
- Output.addCodeBlock(Name);
+ // For functions we display signature in a list form, e.g.:
+ // Returns: `int`
+ // - `bool param1`
+ // - `int param2 = 5`
+ if (ReturnType) {
+ markup::Paragraph &P = Output.addParagraph();
+ P.appendText("Returns: ");
+ P.appendCode(*ReturnType);
+ }
+ if (Parameters && !Parameters->empty()) {
+ markup::BulletList &L = Output.addBulletList();
+ for (const auto &Param : *Parameters) {
+ std::string Buffer;
+ llvm::raw_string_ostream OS(Buffer);
+ OS << Param;
+ L.addItem().addParagraph().appendCode(std::move(OS.str()));
+ }
+ }
+
+ if (Value) {
+ markup::Paragraph &P = Output.addParagraph();
+ P.appendText("Value: ");
+ P.appendCode(*Value);
}
if (!Documentation.empty())
Output.addParagraph().appendText(Documentation);
+
+ if (!Definition.empty()) {
+ std::string Code;
+ llvm::raw_string_ostream OS(Code);
+ // Drop trailing "::".
+ if (!LocalScope.empty()) {
+ // Container name, e.g. class, method, function.
+ // We might want to propogate some info about container type to print
+ // function foo, class X, method X::bar, etc.
+ OS << "// In " << llvm::StringRef(LocalScope).rtrim(':') << '\n';
+ } else if (NamespaceScope && !NamespaceScope->empty()) {
+ OS << "// In namespace " << llvm::StringRef(*NamespaceScope).rtrim(':')
+ << '\n';
+ }
+ // Note that we don't print anything for global namespace, to not annoy
+ // non-c++ projects or projects that are not making use of namespaces.
+ OS << Definition;
+ Output.addCodeBlock(OS.str());
+ }
return Output;
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits