[clang-tools-extra] 13b2a0c - [clangd] Support hover on __func__ etc (PredefinedExpr)
Sam McCall via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 19 05:58:14 PDT 2022
Author: Sam McCall
Date: 2022-08-19T14:51:46+02:00
New Revision: 13b2a0c69ba69c1317308b6e5a8279160561c4b2
URL: https://github.com/llvm/llvm-project/commit/13b2a0c69ba69c1317308b6e5a8279160561c4b2
DIFF: https://github.com/llvm/llvm-project/commit/13b2a0c69ba69c1317308b6e5a8279160561c4b2.diff
LOG: [clangd] Support hover on __func__ etc (PredefinedExpr)
Expose these as variables as that's what the standard calls them (and D131175).
To make this work, we also fix a bug in SelectionTree: PredefinedExpr has
an implicit/invisible StringLiteral, and SelectionTree should not traverse
implicit things.
Reviewed By: ckandeler
Differential Revision: https://reviews.llvm.org/D132135
Added:
Modified:
clang-tools-extra/clangd/Hover.cpp
clang-tools-extra/clangd/Selection.cpp
clang-tools-extra/clangd/unittests/HoverTests.cpp
clang-tools-extra/clangd/unittests/SelectionTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index f599f067d6ee..eb44d1e915af 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -32,6 +32,7 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
+#include "clang/Basic/CharInfo.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TokenKinds.h"
@@ -640,6 +641,29 @@ HoverInfo getHoverContents(const NamedDecl *D, const PrintingPolicy &PP,
return HI;
}
+/// The standard defines __func__ as a "predefined variable".
+llvm::Optional<HoverInfo>
+getPredefinedExprHoverContents(const PredefinedExpr &PE, ASTContext &Ctx,
+ const PrintingPolicy &PP) {
+ HoverInfo HI;
+ HI.Name = PE.getIdentKindName();
+ HI.Kind = index::SymbolKind::Variable;
+ HI.Documentation = "Name of the current function (predefined variable)";
+ if (const StringLiteral *Name = PE.getFunctionName()) {
+ HI.Value.emplace();
+ llvm::raw_string_ostream OS(*HI.Value);
+ Name->outputString(OS);
+ HI.Type = printType(Name->getType(), Ctx, PP);
+ } else {
+ // Inside templates, the approximate type `const char[]` is still useful.
+ QualType StringType = Ctx.getIncompleteArrayType(
+ Ctx.CharTy.withConst(), ArrayType::ArraySizeModifier::Normal,
+ /*IndexTypeQuals=*/0);
+ HI.Type = printType(StringType, Ctx, PP);
+ }
+ return HI;
+}
+
/// Generate a \p Hover object given the macro \p MacroDecl.
HoverInfo getHoverContents(const DefinedMacro &Macro, ParsedAST &AST) {
HoverInfo HI;
@@ -764,6 +788,8 @@ llvm::Optional<HoverInfo> getHoverContents(const Expr *E, ParsedAST &AST,
// For `this` expr we currently generate hover with pointee type.
if (const CXXThisExpr *CTE = dyn_cast<CXXThisExpr>(E))
return getThisExprHoverContents(CTE, AST.getASTContext(), PP);
+ if (const PredefinedExpr *PE = dyn_cast<PredefinedExpr>(E))
+ return getPredefinedExprHoverContents(*PE, AST.getASTContext(), PP);
// For expressions we currently print the type and the value, iff it is
// evaluatable.
if (auto Val = printExprValue(E, AST.getASTContext())) {
diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index e11b43047ec1..80763701d167 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -720,6 +720,14 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
return Base::TraverseTypeConstraint(C);
}
+ // Override child traversal for certain node types.
+ using RecursiveASTVisitor::getStmtChildren;
+ // PredefinedExpr like __func__ has a StringLiteral child for its value.
+ // It's not written, so don't traverse it.
+ Stmt::child_range getStmtChildren(PredefinedExpr *) {
+ return {StmtIterator{}, StmtIterator{}};
+ }
+
private:
using Base = RecursiveASTVisitor<SelectionVisitor>;
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 53e4f55c2e3a..997b761e6a69 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -139,6 +139,33 @@ TEST(Hover, Structured) {
HI.Definition = "int bar";
HI.Type = "int";
}},
+ // Predefined variable
+ {R"cpp(
+ void foo() {
+ [[__f^unc__]];
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "__func__";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.Documentation =
+ "Name of the current function (predefined variable)";
+ HI.Value = "\"foo\"";
+ HI.Type = "const char[4]";
+ }},
+ // Predefined variable (dependent)
+ {R"cpp(
+ template<int> void foo() {
+ [[__f^unc__]];
+ }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "__func__";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.Documentation =
+ "Name of the current function (predefined variable)";
+ HI.Type = "const char[]";
+ }},
// Anon namespace and local scope.
{R"cpp(
namespace ns1 { namespace {
diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index 73d6d0d23827..f7a518f3e995 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -527,6 +527,10 @@ TEST(SelectionTest, CommonAncestor) {
/*error-ok*/
void func() [[{^]])cpp",
"CompoundStmt"},
+ {R"cpp(
+ void func() { [[__^func__]]; }
+ )cpp",
+ "PredefinedExpr"},
};
for (const Case &C : Cases) {
More information about the cfe-commits
mailing list