nridge updated this revision to Diff 343963.
nridge added a comment.
test formatting fix
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D102148/new/
https://reviews.llvm.org/D102148
Files:
clang-tools-extra/clangd/InlayHints.cpp
clang-tools-extra/clangd/Protocol.cpp
clang-tools-extra/clangd/Protocol.h
clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Index: clang-tools-extra/clangd/unittests/InlayHintTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -15,14 +15,19 @@
namespace clang {
namespace clangd {
+
+std::ostream &operator<<(std::ostream &Stream, const InlayHint &Hint) {
+ return Stream << Hint.label;
+}
+
namespace {
using ::testing::UnorderedElementsAre;
-std::vector<InlayHint> parameterHints(ParsedAST &AST) {
+std::vector<InlayHint> hintsOfKind(ParsedAST &AST, InlayHintKind Kind) {
std::vector<InlayHint> Result;
for (auto &Hint : inlayHints(AST)) {
- if (Hint.kind == InlayHintKind::ParameterHint)
+ if (Hint.kind == Kind)
Result.push_back(Hint);
}
return Result;
@@ -31,6 +36,11 @@
struct ExpectedHint {
std::string Label;
std::string RangeName;
+
+ friend std::ostream &operator<<(std::ostream &Stream,
+ const ExpectedHint &Hint) {
+ return Stream << Hint.RangeName << ": " << Hint.Label;
+ }
};
MATCHER_P2(HintMatcher, Expected, Code, "") {
@@ -39,17 +49,29 @@
}
template <typename... ExpectedHints>
-void assertParameterHints(llvm::StringRef AnnotatedSource,
- ExpectedHints... Expected) {
+void assertHints(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
+ ExpectedHints... Expected) {
Annotations Source(AnnotatedSource);
TestTU TU = TestTU::withCode(Source.code());
- TU.ExtraArgs.push_back("-std=c++11");
+ TU.ExtraArgs.push_back("-std=c++14");
auto AST = TU.build();
- EXPECT_THAT(parameterHints(AST),
+ EXPECT_THAT(hintsOfKind(AST, Kind),
UnorderedElementsAre(HintMatcher(Expected, Source)...));
}
+template <typename... ExpectedHints>
+void assertParameterHints(llvm::StringRef AnnotatedSource,
+ ExpectedHints... Expected) {
+ assertHints(InlayHintKind::ParameterHint, AnnotatedSource, Expected...);
+}
+
+template <typename... ExpectedHints>
+void assertTypeHints(llvm::StringRef AnnotatedSource,
+ ExpectedHints... Expected) {
+ assertHints(InlayHintKind::TypeHint, AnnotatedSource, Expected...);
+}
+
TEST(ParameterHints, Smoke) {
assertParameterHints(R"cpp(
void foo(int param);
@@ -376,6 +398,97 @@
ExpectedHint{"timeout_millis: ", "timeout_millis"});
}
+TEST(TypeHints, Smoke) {
+ assertTypeHints(R"cpp(
+ auto $waldo[[waldo]] = 42;
+ )cpp",
+ ExpectedHint{": int", "waldo"});
+}
+
+TEST(TypeHints, Decorations) {
+ assertTypeHints(R"cpp(
+ int x = 42;
+ auto* $var1[[var1]] = &x;
+ auto&& $var2[[var2]] = x;
+ const auto& $var3[[var3]] = x;
+ )cpp",
+ ExpectedHint{": int *", "var1"},
+ ExpectedHint{": int &", "var2"},
+ ExpectedHint{": const int &", "var3"});
+}
+
+TEST(TypeHints, DecltypeAuto) {
+ assertTypeHints(R"cpp(
+ int x = 42;
+ int& y = x;
+ decltype(auto) $z[[z]] = y;
+ )cpp",
+ ExpectedHint{": int &", "z"});
+}
+
+TEST(TypeHints, NoNamespaces) {
+ assertTypeHints(R"cpp(
+ namespace A {
+ namespace B {
+ struct S {};
+ S foo();
+ auto $x[[x]] = foo();
+ }
+ }
+ )cpp",
+ ExpectedHint{": S", "x"});
+}
+
+TEST(TypeHints, Lambda) {
+ // Do not print something overly verbose like the lambda's location.
+ assertTypeHints(R"cpp(
+ auto $L[[L]] = [](int a, int b) { return a + b; };
+ )cpp",
+ ExpectedHint{": (lambda)", "L"});
+}
+
+TEST(TypeHints, StructuredBindings) {
+ // FIXME: Not handled yet.
+ // To handle it, we could print:
+ // - the aggregate type next to the 'auto', or
+ // - the individual types inside the brackets
+ assertTypeHints(R"cpp(
+ struct Point {
+ int x;
+ int y;
+ };
+ Point foo();
+ auto [x, y] = foo();
+ )cpp");
+}
+
+TEST(TypeHints, ReturnTypeDeduction) {
+ // FIXME: Not handled yet.
+ // This test is currently here mostly because a naive implementation
+ // might have us print something not super helpful like the function type.
+ assertTypeHints(R"cpp(
+ auto func(int x) {
+ return x + 1;
+ }
+ )cpp");
+}
+
+TEST(TypeHint, DependentType) {
+ assertTypeHints(R"cpp(
+ template <typename T>
+ void foo(T arg) {
+ // The hint would just be "auto" and we can't do any better.
+ auto var1 = arg.method();
+ // FIXME: It would be nice to show "T" as the hint.
+ auto var2 = arg;
+ }
+ )cpp");
+}
+
+// Annoyances:
+// - auto x = dyn_cast<LongTypeName>(y);
+// - stdlib algos return unwieldy __normal_iterator<X*, ...> type
+
} // namespace
} // namespace clangd
} // namespace clang
\ No newline at end of file
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1493,9 +1493,14 @@
/// which shows the name of the corresponding parameter.
ParameterHint,
+ /// The hint corresponds to information about a deduced type.
+ /// An example of a type hint is a hint in this position:
+ /// auto var ^ = expr;
+ /// which shows the deduced type of the variable.
+ TypeHint,
+
/// Other ideas for hints that are not currently implemented:
///
- /// * Type hints, showing deduced types.
/// * Chaining hints, showing the types of intermediate expressions
/// in a chain of function calls.
/// * Hints indicating implicit conversions or implicit constructor calls.
Index: clang-tools-extra/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -1306,6 +1306,8 @@
switch (K) {
case InlayHintKind::ParameterHint:
return "parameter";
+ case InlayHintKind::TypeHint:
+ return "type";
}
llvm_unreachable("Unknown clang.clangd.InlayHintKind");
}
Index: clang-tools-extra/clangd/InlayHints.cpp
===================================================================
--- clang-tools-extra/clangd/InlayHints.cpp
+++ clang-tools-extra/clangd/InlayHints.cpp
@@ -22,11 +22,16 @@
InlayHintVisitor(std::vector<InlayHint> &Results, ParsedAST &AST)
: Results(Results), AST(AST.getASTContext()),
MainFileID(AST.getSourceManager().getMainFileID()),
- Resolver(AST.getHeuristicResolver()) {
+ Resolver(AST.getHeuristicResolver()),
+ TypeHintPolicy(this->AST.getPrintingPolicy()) {
bool Invalid = false;
llvm::StringRef Buf =
AST.getSourceManager().getBufferData(MainFileID, &Invalid);
MainFileBuf = Invalid ? StringRef{} : Buf;
+
+ TypeHintPolicy.SuppressScope = true; // keep type names short
+ TypeHintPolicy.AnonymousTagLocations =
+ false; // do not print lambda locations
}
bool VisitCXXConstructExpr(CXXConstructExpr *E) {
@@ -67,6 +72,20 @@
return true;
}
+ bool VisitVarDecl(VarDecl *D) {
+ // Structured binding - not handled yet.
+ if (isa<DecompositionDecl>(D))
+ return true;
+
+ if (auto *AT = D->getType()->getContainedAutoType()) {
+ if (!D->getType()->isDependentType()) {
+ addInlayHint(D->getLocation(), InlayHintKind::TypeHint,
+ ": " + D->getType().getAsString(TypeHintPolicy));
+ }
+ }
+ return true;
+ }
+
// FIXME: Handle RecoveryExpr to try to hint some invalid calls.
private:
@@ -278,6 +297,7 @@
FileID MainFileID;
StringRef MainFileBuf;
const HeuristicResolver *Resolver;
+ PrintingPolicy TypeHintPolicy;
};
std::vector<InlayHint> inlayHints(ParsedAST &AST) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits