[clang-tools-extra] r363237 - [clangd] Treat lambdas as functions when preparing hover response
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 13 01:51:44 PDT 2019
Author: kadircet
Date: Thu Jun 13 01:51:44 2019
New Revision: 363237
URL: http://llvm.org/viewvc/llvm-project?rev=363237&view=rev
Log:
[clangd] Treat lambdas as functions when preparing hover response
Reviewers: sammccall, ilya-biryukov
Subscribers: MaskRay, jkorous, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62814
Modified:
clang-tools-extra/trunk/clangd/XRefs.cpp
clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp
Modified: clang-tools-extra/trunk/clangd/XRefs.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/XRefs.cpp?rev=363237&r1=363236&r2=363237&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/XRefs.cpp (original)
+++ clang-tools-extra/trunk/clangd/XRefs.cpp Thu Jun 13 01:51:44 2019
@@ -19,7 +19,9 @@
#include "index/SymbolLocation.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/Type.h"
@@ -620,6 +622,23 @@ static llvm::Optional<Range> getTokenRan
CharSourceRange::getCharRange(Loc, End));
}
+static const FunctionDecl *getUnderlyingFunction(const Decl *D) {
+ // Extract lambda from variables.
+ if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) {
+ auto QT = VD->getType();
+ if (!QT.isNull()) {
+ while (!QT->getPointeeType().isNull())
+ QT = QT->getPointeeType();
+
+ if (const auto *CD = QT->getAsCXXRecordDecl())
+ return CD->getLambdaCallOperator();
+ }
+ }
+
+ // Non-lambda functions.
+ return D->getAsFunction();
+}
+
/// Generate a \p Hover object given the declaration \p D.
static HoverInfo getHoverContents(const Decl *D) {
HoverInfo HI;
@@ -654,27 +673,21 @@ static HoverInfo getHoverContents(const
}
// Fill in types and params.
- if (const FunctionDecl *FD = D->getAsFunction()) {
+ if (const FunctionDecl *FD = getUnderlyingFunction(D)) {
HI.ReturnType.emplace();
- llvm::raw_string_ostream OS(*HI.ReturnType);
- FD->getReturnType().print(OS, Policy);
-
- HI.Type.emplace();
- llvm::raw_string_ostream TypeOS(*HI.Type);
- FD->getReturnType().print(TypeOS, Policy);
- TypeOS << '(';
+ {
+ llvm::raw_string_ostream OS(*HI.ReturnType);
+ FD->getReturnType().print(OS, Policy);
+ }
HI.Parameters.emplace();
for (const ParmVarDecl *PVD : FD->parameters()) {
- if (HI.Parameters->size())
- TypeOS << ", ";
HI.Parameters->emplace_back();
auto &P = HI.Parameters->back();
if (!PVD->getType().isNull()) {
P.Type.emplace();
llvm::raw_string_ostream OS(*P.Type);
PVD->getType().print(OS, Policy);
- PVD->getType().print(TypeOS, Policy);
} else {
std::string Param;
llvm::raw_string_ostream OS(Param);
@@ -690,11 +703,17 @@ static HoverInfo getHoverContents(const
PVD->getDefaultArg()->printPretty(Out, nullptr, Policy);
}
}
- TypeOS << ')';
+
+ HI.Type.emplace();
+ llvm::raw_string_ostream TypeOS(*HI.Type);
+ // Lambdas
+ if (const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
+ VD->getType().getDesugaredType(D->getASTContext()).print(TypeOS, Policy);
+ // Functions
+ else
+ FD->getType().print(TypeOS, Policy);
// FIXME: handle variadics.
} else if (const auto *VD = dyn_cast<ValueDecl>(D)) {
- // FIXME: Currently lambdas are also handled as ValueDecls, they should be
- // more similar to functions.
HI.Type.emplace();
llvm::raw_string_ostream OS(*HI.Type);
VD->getType().print(OS, Policy);
Modified: clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp?rev=363237&r1=363236&r2=363237&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp (original)
+++ clang-tools-extra/trunk/clangd/unittests/XRefsTests.cpp Thu Jun 13 01:51:44 2019
@@ -22,6 +22,7 @@
#include "llvm/Support/ScopedPrinter.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include <string>
namespace clang {
namespace clangd {
@@ -588,7 +589,7 @@ TEST(Hover, Structured) {
HI.Documentation = "Best foo ever.";
HI.Definition = "void foo()";
HI.ReturnType = "void";
- HI.Type = "void()";
+ HI.Type = "void ()";
HI.Parameters.emplace();
}},
// Inside namespace
@@ -605,7 +606,7 @@ TEST(Hover, Structured) {
HI.Documentation = "Best foo ever.";
HI.Definition = "void foo()";
HI.ReturnType = "void";
- HI.Type = "void()";
+ HI.Type = "void ()";
HI.Parameters.emplace();
}},
// Field
@@ -733,7 +734,7 @@ class Foo {})cpp";
bool Q = false, class... Ts>
void foo())cpp";
HI.ReturnType = "void";
- HI.Type = "void()";
+ HI.Type = "void ()";
HI.Parameters.emplace();
HI.TemplateParameters = {
{std::string("template <typename, bool...> class"),
@@ -759,12 +760,76 @@ void foo())cpp";
HI.Kind = SymbolKind::Function;
HI.Definition = "Foo<bool, true, false> foo(int, bool T = false)";
HI.ReturnType = "Foo<bool, true, false>";
- HI.Type = "Foo<bool, true, false>(int, bool)";
+ HI.Type = "Foo<bool, true, false> (int, bool)";
HI.Parameters = {
{std::string("int"), llvm::None, llvm::None},
{std::string("bool"), std::string("T"), std::string("false")},
};
}},
+ // Pointers to lambdas
+ {R"cpp(
+ void foo() {
+ auto lamb = [](int T, bool B) -> bool { return T && B; };
+ auto *b = &lamb;
+ auto *[[^c]] = &b;
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.NamespaceScope = "";
+ HI.LocalScope = "foo::";
+ HI.Name = "c";
+ HI.Kind = SymbolKind::Variable;
+ HI.Definition = "auto *c = &b";
+ HI.Type = "class (lambda) **";
+ HI.ReturnType = "bool";
+ HI.Parameters = {
+ {std::string("int"), std::string("T"), llvm::None},
+ {std::string("bool"), std::string("B"), llvm::None},
+ };
+ return HI;
+ }},
+ // Lambda parameter with decltype reference
+ {R"cpp(
+ auto lamb = [](int T, bool B) -> bool { return T && B; };
+ void foo(decltype(lamb)& bar) {
+ [[ba^r]](0, false);
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.NamespaceScope = "";
+ HI.LocalScope = "foo::";
+ HI.Name = "bar";
+ HI.Kind = SymbolKind::Variable;
+ HI.Definition = "decltype(lamb) &bar";
+ HI.Type = "decltype(lamb) &";
+ HI.ReturnType = "bool";
+ HI.Parameters = {
+ {std::string("int"), std::string("T"), llvm::None},
+ {std::string("bool"), std::string("B"), llvm::None},
+ };
+ return HI;
+ }},
+ // Lambda parameter with decltype
+ {R"cpp(
+ auto lamb = [](int T, bool B) -> bool { return T && B; };
+ void foo(decltype(lamb) bar) {
+ [[ba^r]](0, false);
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.NamespaceScope = "";
+ HI.LocalScope = "foo::";
+ HI.Name = "bar";
+ HI.Kind = SymbolKind::Variable;
+ HI.Definition = "decltype(lamb) bar";
+ HI.Type = "class (lambda)";
+ HI.ReturnType = "bool";
+ HI.Parameters = {
+ {std::string("int"), std::string("T"), llvm::None},
+ {std::string("bool"), std::string("B"), llvm::None},
+ };
+ return HI;
+ }},
// Lambda variable
{R"cpp(
void foo() {
@@ -779,7 +844,12 @@ void foo())cpp";
HI.Name = "lamb";
HI.Kind = SymbolKind::Variable;
HI.Definition = "auto lamb = [&bar](int T, bool B) -> bool {}";
- HI.Type = std::string("class (lambda)");
+ HI.Type = "class (lambda)";
+ HI.ReturnType = "bool";
+ HI.Parameters = {
+ {std::string("int"), std::string("T"), llvm::None},
+ {std::string("bool"), std::string("B"), llvm::None},
+ };
return HI;
}},
// Local variable in lambda
More information about the cfe-commits
mailing list