[clang-tools-extra] 1f8963c - [clangd] Parameter hints for dependent calls
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Sun May 2 23:03:27 PDT 2021
Author: Nathan Ridge
Date: 2021-05-03T02:03:16-04:00
New Revision: 1f8963c80195aa86d02e81acedcf1ff3da127842
URL: https://github.com/llvm/llvm-project/commit/1f8963c80195aa86d02e81acedcf1ff3da127842
DIFF: https://github.com/llvm/llvm-project/commit/1f8963c80195aa86d02e81acedcf1ff3da127842.diff
LOG: [clangd] Parameter hints for dependent calls
Differential Revision: https://reviews.llvm.org/D100742
Added:
Modified:
clang-tools-extra/clangd/HeuristicResolver.cpp
clang-tools-extra/clangd/HeuristicResolver.h
clang-tools-extra/clangd/InlayHints.cpp
clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp b/clang-tools-extra/clangd/HeuristicResolver.cpp
index aacc90369fec5..316b7d11224b0 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.cpp
+++ b/clang-tools-extra/clangd/HeuristicResolver.cpp
@@ -130,6 +130,15 @@ HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const {
return {};
}
+std::vector<const NamedDecl *>
+HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const {
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(CE->getCalleeDecl())) {
+ return {ND};
+ }
+
+ return resolveExprToDecls(CE->getCallee());
+}
+
std::vector<const NamedDecl *> HeuristicResolver::resolveUsingValueDecl(
const UnresolvedUsingValueDecl *UUVD) const {
return resolveDependentMember(UUVD->getQualifier()->getAsType(),
@@ -163,18 +172,30 @@ const Type *resolveDeclsToType(const std::vector<const NamedDecl *> &Decls) {
return nullptr;
}
-const Type *HeuristicResolver::resolveExprToType(const Expr *E) const {
+std::vector<const NamedDecl *>
+HeuristicResolver::resolveExprToDecls(const Expr *E) const {
if (const auto *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) {
- return resolveDeclsToType(resolveMemberExpr(ME));
+ return resolveMemberExpr(ME);
}
if (const auto *RE = dyn_cast<DependentScopeDeclRefExpr>(E)) {
- return resolveDeclsToType(resolveDeclRefExpr(RE));
+ return resolveDeclRefExpr(RE);
+ }
+ if (const auto *OE = dyn_cast<OverloadExpr>(E)) {
+ return {OE->decls_begin(), OE->decls_end()};
}
if (const auto *CE = dyn_cast<CallExpr>(E)) {
- return resolveDeclsToType(resolveTypeOfCallExpr(CE));
+ return resolveTypeOfCallExpr(CE);
}
if (const auto *ME = dyn_cast<MemberExpr>(E))
- return resolveDeclsToType({ME->getMemberDecl()});
+ return {ME->getMemberDecl()};
+
+ return {};
+}
+
+const Type *HeuristicResolver::resolveExprToType(const Expr *E) const {
+ std::vector<const NamedDecl *> Decls = resolveExprToDecls(E);
+ if (!Decls.empty())
+ return resolveDeclsToType(Decls);
return E->getType().getTypePtr();
}
diff --git a/clang-tools-extra/clangd/HeuristicResolver.h b/clang-tools-extra/clangd/HeuristicResolver.h
index dd906245da524..c66e1d1895699 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.h
+++ b/clang-tools-extra/clangd/HeuristicResolver.h
@@ -56,6 +56,8 @@ class HeuristicResolver {
std::vector<const NamedDecl *>
resolveTypeOfCallExpr(const CallExpr *CE) const;
std::vector<const NamedDecl *>
+ resolveCalleeOfCallExpr(const CallExpr *CE) const;
+ std::vector<const NamedDecl *>
resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD) const;
std::vector<const NamedDecl *>
resolveDependentNameType(const DependentNameType *DNT) const;
@@ -87,6 +89,7 @@ class HeuristicResolver {
// Try to heuristically resolve the type of a possibly-dependent expression
// `E`.
const Type *resolveExprToType(const Expr *E) const;
+ std::vector<const NamedDecl *> resolveExprToDecls(const Expr *E) const;
// Given the type T of a dependent expression that appears of the LHS of a
// "->", heuristically find a corresponding pointee type in whose scope we
diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp
index a9f3100a187e1..3880273f85908 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "InlayHints.h"
+#include "HeuristicResolver.h"
#include "ParsedAST.h"
#include "support/Logger.h"
#include "clang/AST/DeclarationName.h"
@@ -20,7 +21,8 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
public:
InlayHintVisitor(std::vector<InlayHint> &Results, ParsedAST &AST)
: Results(Results), AST(AST.getASTContext()),
- MainFileID(AST.getSourceManager().getMainFileID()) {
+ MainFileID(AST.getSourceManager().getMainFileID()),
+ Resolver(AST.getHeuristicResolver()) {
bool Invalid = false;
llvm::StringRef Buf =
AST.getSourceManager().getBufferData(MainFileID, &Invalid);
@@ -50,9 +52,18 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
return true;
- processCall(E->getRParenLoc(),
- dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()),
- {E->getArgs(), E->getNumArgs()});
+ auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E);
+ if (CalleeDecls.size() != 1)
+ return true;
+ const FunctionDecl *Callee = nullptr;
+ if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecls[0]))
+ Callee = FD;
+ else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CalleeDecls[0]))
+ Callee = FTD->getTemplatedDecl();
+ if (!Callee)
+ return true;
+
+ processCall(E->getRParenLoc(), Callee, {E->getArgs(), E->getNumArgs()});
return true;
}
@@ -266,6 +277,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
ASTContext &AST;
FileID MainFileID;
StringRef MainFileBuf;
+ const HeuristicResolver *Resolver;
};
std::vector<InlayHint> inlayHints(ParsedAST &AST) {
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 23f0e9ef11d3e..3cf1c6d70c0d3 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -244,19 +244,35 @@ TEST(ParameterHints, LeadingUnderscore) {
ExpectedHint{"p3: ", "p3"});
}
-TEST(ParameterHints, DependentCall) {
- // FIXME: This doesn't currently produce a hint but should.
+TEST(ParameterHints, DependentCalls) {
assertParameterHints(R"cpp(
template <typename T>
- void foo(T param);
+ void nonmember(T par1);
+
+ template <typename T>
+ struct A {
+ void member(T par2);
+ static void static_member(T par3);
+ };
+
+ void overload(int anInt);
+ void overload(double aDouble);
template <typename T>
struct S {
- void bar(T par) {
- foo($param[[par]]);
+ void bar(A<T> a, T t) {
+ nonmember($par1[[t]]);
+ a.member($par2[[t]]);
+ // FIXME: This one does not work yet.
+ A<T>::static_member($par3[[t]]);
+ // We don't want to arbitrarily pick between
+ // "anInt" or "aDouble", so just show no hint.
+ overload(T{});
}
};
- )cpp");
+ )cpp",
+ ExpectedHint{"par1: ", "par1"},
+ ExpectedHint{"par2: ", "par2"});
}
TEST(ParameterHints, VariadicFunction) {
@@ -362,4 +378,4 @@ TEST(ParameterHints, SetterFunctions) {
} // namespace
} // namespace clangd
-} // namespace clang
+} // namespace clang
\ No newline at end of file
More information about the cfe-commits
mailing list