[clang-tools-extra] c5adbac - [clangd] Switch Hover.All to structured tests
Kadir Cetinkaya via cfe-commits
cfe-commits at lists.llvm.org
Fri Dec 6 04:45:58 PST 2019
Author: Kadir Cetinkaya
Date: 2019-12-06T13:40:22+01:00
New Revision: c5adbac9b85a53112a9fc9b72e64d2615e3e4df9
URL: https://github.com/llvm/llvm-project/commit/c5adbac9b85a53112a9fc9b72e64d2615e3e4df9
DIFF: https://github.com/llvm/llvm-project/commit/c5adbac9b85a53112a9fc9b72e64d2615e3e4df9.diff
LOG: [clangd] Switch Hover.All to structured tests
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70911
Added:
Modified:
clang-tools-extra/clangd/Hover.h
clang-tools-extra/clangd/unittests/HoverTests.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clangd/Hover.h b/clang-tools-extra/clangd/Hover.h
index f332f5d9eeea..f42e7f3a7b54 100644
--- a/clang-tools-extra/clangd/Hover.h
+++ b/clang-tools-extra/clangd/Hover.h
@@ -12,6 +12,7 @@
#include "FormattedString.h"
#include "ParsedAST.h"
#include "Protocol.h"
+#include "clang/Index/IndexSymbol.h"
namespace clang {
namespace clangd {
@@ -53,7 +54,7 @@ struct HoverInfo {
/// Name of the symbol, does not contain any "::".
std::string Name;
llvm::Optional<Range> SymRange;
- index::SymbolKind Kind;
+ index::SymbolKind Kind = index::SymbolKind::Unknown;
std::string Documentation;
/// Source code containing the definition of the symbol.
std::string Definition;
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index bd6a33d8d67e..5862b1d03bf4 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -11,9 +11,14 @@
#include "TestIndex.h"
#include "TestTU.h"
#include "index/MemIndex.h"
+#include "clang/Index/IndexSymbol.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringRef.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include <string>
+#include <vector>
namespace clang {
namespace clangd {
@@ -532,252 +537,333 @@ void foo())cpp";
}
}
-TEST(Hover, All) {
- struct OneTest {
- StringRef Input;
- StringRef ExpectedHover;
- };
-
- OneTest Tests[] = {
- {
- R"cpp(// No hover
- ^int main() {
+TEST(Hover, NoHover) {
+ llvm::StringRef Tests[] = {
+ "^int main() {}",
+ "void foo() {^}",
+ R"cpp(// structured binding. Not supported yet
+ struct Bar {};
+ void foo() {
+ Bar a[2];
+ ^auto [x,y] = a;
+ }
+ )cpp",
+ R"cpp(// Template auto parameter. Nothing (Not useful).
+ template<^auto T>
+ void func() {
+ }
+ void foo() {
+ func<1>();
}
)cpp",
- "",
- },
+ };
+
+ for (const auto &Test : Tests) {
+ SCOPED_TRACE(Test);
+
+ Annotations T(Test);
+ TestTU TU = TestTU::withCode(T.code());
+ TU.ExtraArgs.push_back("-std=c++17");
+ auto AST = TU.build();
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ auto H = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
+ ASSERT_FALSE(H);
+ }
+}
+
+TEST(Hover, All) {
+ struct {
+ const char *const Code;
+ const std::function<void(HoverInfo &)> ExpectedBuilder;
+ } Cases[] = {
{
R"cpp(// Local variable
int main() {
int bonjour;
- ^bonjour = 2;
+ ^[[bonjour]] = 2;
int test1 = bonjour;
}
)cpp",
- "text[Declared in]code[main]\n"
- "codeblock(cpp) [\n"
- "int bonjour\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "bonjour";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "main::";
+ HI.Type = "int";
+ HI.Definition = "int bonjour";
+ }},
{
R"cpp(// Local variable in method
struct s {
void method() {
int bonjour;
- ^bonjour = 2;
+ ^[[bonjour]] = 2;
}
};
)cpp",
- "text[Declared in]code[s::method]\n"
- "codeblock(cpp) [\n"
- "int bonjour\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "bonjour";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "s::method::";
+ HI.Type = "int";
+ HI.Definition = "int bonjour";
+ }},
{
R"cpp(// Struct
namespace ns1 {
struct MyClass {};
} // namespace ns1
int main() {
- ns1::My^Class* Params;
+ ns1::[[My^Class]]* Params;
}
)cpp",
- "text[Declared in]code[ns1]\n"
- "codeblock(cpp) [\n"
- "struct MyClass {}\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "MyClass";
+ HI.Kind = index::SymbolKind::Struct;
+ HI.NamespaceScope = "ns1::";
+ HI.Definition = "struct MyClass {}";
+ }},
{
R"cpp(// Class
namespace ns1 {
class MyClass {};
} // namespace ns1
int main() {
- ns1::My^Class* Params;
+ ns1::[[My^Class]]* Params;
}
)cpp",
- "text[Declared in]code[ns1]\n"
- "codeblock(cpp) [\n"
- "class MyClass {}\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "MyClass";
+ HI.Kind = index::SymbolKind::Class;
+ HI.NamespaceScope = "ns1::";
+ HI.Definition = "class MyClass {}";
+ }},
{
R"cpp(// Union
namespace ns1 {
union MyUnion { int x; int y; };
} // namespace ns1
int main() {
- ns1::My^Union Params;
+ ns1::[[My^Union]] Params;
}
)cpp",
- "text[Declared in]code[ns1]\n"
- "codeblock(cpp) [\n"
- "union MyUnion {}\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "MyUnion";
+ HI.Kind = index::SymbolKind::Union;
+ HI.NamespaceScope = "ns1::";
+ HI.Definition = "union MyUnion {}";
+ }},
{
R"cpp(// Function definition via pointer
- int foo(int) {}
+ void foo(int) {}
int main() {
- auto *X = &^foo;
+ auto *X = &^[[foo]];
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "int foo(int)\n"
- "]\n"
- "text[Function definition via pointer]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "";
+ HI.Type = "void (int)";
+ HI.Definition = "void foo(int)";
+ HI.Documentation = "Function definition via pointer";
+ HI.ReturnType = "void";
+ HI.Parameters = {
+ {std::string("int"), llvm::None, llvm::None},
+ };
+ }},
{
R"cpp(// Function declaration via call
int foo(int);
int main() {
- return ^foo(42);
+ return ^[[foo]](42);
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "int foo(int)\n"
- "]\n"
- "text[Function declaration via call]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "";
+ HI.Type = "int (int)";
+ HI.Definition = "int foo(int)";
+ HI.Documentation = "Function declaration via call";
+ HI.ReturnType = "int";
+ HI.Parameters = {
+ {std::string("int"), llvm::None, llvm::None},
+ };
+ }},
{
R"cpp(// Field
struct Foo { int x; };
int main() {
Foo bar;
- bar.^x;
+ (void)bar.^[[x]];
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "int x\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int";
+ HI.Definition = "int x";
+ }},
{
R"cpp(// Field with initialization
struct Foo { int x = 5; };
int main() {
Foo bar;
- bar.^x;
+ (void)bar.^[[x]];
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "int x = 5\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int";
+ HI.Definition = "int x = 5";
+ }},
{
R"cpp(// Static field
struct Foo { static int x; };
int main() {
- Foo::^x;
+ (void)Foo::^[[x]];
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "static int x\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::StaticProperty;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int";
+ HI.Definition = "static int x";
+ }},
{
R"cpp(// Field, member initializer
struct Foo {
int x;
- Foo() : ^x(0) {}
+ Foo() : ^[[x]](0) {}
};
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "int x\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int";
+ HI.Definition = "int x";
+ }},
{
R"cpp(// Field, GNU old-style field designator
struct Foo { int x; };
int main() {
- Foo bar = { ^x : 1 };
+ Foo bar = { ^[[x]] : 1 };
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "int x\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int";
+ HI.Definition = "int x";
+ HI.Value = "{1}";
+ }},
{
R"cpp(// Field, field designator
struct Foo { int x; };
int main() {
- Foo bar = { .^x = 2 };
+ Foo bar = { .^[[x]] = 2 };
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "int x\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int";
+ HI.Definition = "int x";
+ HI.Value = "{2}";
+ }},
{
R"cpp(// Method call
struct Foo { int x(); };
int main() {
Foo bar;
- bar.^x();
+ bar.^[[x]]();
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "int x()\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::InstanceMethod;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int ()";
+ HI.Definition = "int x()";
+ HI.ReturnType = "int";
+ HI.Parameters = std::vector<HoverInfo::Param>{};
+ }},
{
R"cpp(// Static method call
struct Foo { static int x(); };
int main() {
- Foo::^x();
+ Foo::^[[x]]();
}
)cpp",
- "text[Declared in]code[Foo]\n"
- "codeblock(cpp) [\n"
- "static int x()\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "x";
+ HI.Kind = index::SymbolKind::StaticMethod;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Foo::";
+ HI.Type = "int ()";
+ HI.Definition = "static int x()";
+ HI.ReturnType = "int";
+ HI.Parameters = std::vector<HoverInfo::Param>{};
+ }},
{
R"cpp(// Typedef
typedef int Foo;
int main() {
- ^Foo bar;
+ ^[[Foo]] bar;
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "typedef int Foo\n"
- "]\n"
- "text[Typedef]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "Foo";
+ HI.Kind = index::SymbolKind::TypeAlias;
+ HI.NamespaceScope = "";
+ HI.Definition = "typedef int Foo";
+ HI.Documentation = "Typedef";
+ // FIXME: Maybe put underlying type into HI.Type for aliases?
+ }},
{
R"cpp(// Typedef with embedded definition
typedef struct Bar {} Foo;
int main() {
- ^Foo bar;
+ ^[[Foo]] bar;
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "typedef struct Bar Foo\n"
- "]\n"
- "text[Typedef with embedded definition]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "Foo";
+ HI.Kind = index::SymbolKind::TypeAlias;
+ HI.NamespaceScope = "";
+ HI.Definition = "typedef struct Bar Foo";
+ HI.Documentation = "Typedef with embedded definition";
+ }},
{
R"cpp(// Namespace
namespace ns {
- struct Foo { static void bar(); }
+ struct Foo { static void bar(); };
} // namespace ns
- int main() { ^ns::Foo::bar(); }
+ int main() { ^[[ns]]::Foo::bar(); }
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "namespace ns {}\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "ns";
+ HI.Kind = index::SymbolKind::Namespace;
+ HI.NamespaceScope = "";
+ HI.Definition = "namespace ns {}";
+ }},
{
R"cpp(// Anonymous namespace
namespace ns {
@@ -785,168 +871,203 @@ TEST(Hover, All) {
int foo;
} // anonymous namespace
} // namespace ns
- int main() { ns::f^oo++; }
+ int main() { ns::[[f^oo]]++; }
)cpp",
- "text[Declared in]code[ns::(anonymous)]\n"
- "codeblock(cpp) [\n"
- "int foo\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "ns::(anonymous)::";
+ HI.Type = "int";
+ HI.Definition = "int foo";
+ }},
{
R"cpp(// Macro
#define MACRO 0
- #define MACRO 1
- int main() { return ^MACRO; }
- #define MACRO 2
- #undef macro
- )cpp",
- "codeblock(cpp) [\n"
- "#define MACRO 1\n"
- "]",
- },
+ int main() { return ^[[MACRO]]; }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "MACRO";
+ HI.Kind = index::SymbolKind::Macro;
+ HI.Definition = "#define MACRO 0";
+ }},
{
R"cpp(// Macro
#define MACRO 0
- #define MACRO2 ^MACRO
+ #define MACRO2 ^[[MACRO]]
)cpp",
- "codeblock(cpp) [\n"
- "#define MACRO 0\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "MACRO";
+ HI.Kind = index::SymbolKind::Macro;
+ HI.Definition = "#define MACRO 0";
+ }},
{
R"cpp(// Macro
#define MACRO {\
return 0;\
}
- int main() ^MACRO
+ int main() ^[[MACRO]]
)cpp",
- R"cpp(codeblock(cpp) [
-#define MACRO \
- { return 0; }
-])cpp",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "MACRO";
+ HI.Kind = index::SymbolKind::Macro;
+ HI.Definition =
+ R"cpp(#define MACRO \
+ { return 0; })cpp";
+ }},
{
R"cpp(// Forward class declaration
class Foo;
class Foo {};
- F^oo* foo();
- )cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "class Foo {}\n"
- "]\n"
- "text[Forward class declaration]",
- },
+ [[F^oo]]* foo();
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "Foo";
+ HI.Kind = index::SymbolKind::Class;
+ HI.NamespaceScope = "";
+ HI.Definition = "class Foo {}";
+ HI.Documentation = "Forward class declaration";
+ }},
{
R"cpp(// Function declaration
void foo();
- void g() { f^oo(); }
+ void g() { [[f^oo]](); }
void foo() {}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "void foo()\n"
- "]\n"
- "text[Function declaration]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "";
+ HI.Type = "void ()";
+ HI.Definition = "void foo()";
+ HI.Documentation = "Function declaration";
+ HI.ReturnType = "void";
+ HI.Parameters = std::vector<HoverInfo::Param>{};
+ }},
{
R"cpp(// Enum declaration
enum Hello {
ONE, TWO, THREE,
};
void foo() {
- Hel^lo hello = ONE;
+ [[Hel^lo]] hello = ONE;
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "enum Hello {}\n"
- "]\n"
- "text[Enum declaration]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "Hello";
+ HI.Kind = index::SymbolKind::Enum;
+ HI.NamespaceScope = "";
+ HI.Definition = "enum Hello {}";
+ HI.Documentation = "Enum declaration";
+ }},
{
R"cpp(// Enumerator
enum Hello {
ONE, TWO, THREE,
};
void foo() {
- Hello hello = O^NE;
+ Hello hello = [[O^NE]];
}
)cpp",
- "text[Declared in]code[Hello]\n"
- "codeblock(cpp) [\n"
- "ONE\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "ONE";
+ HI.Kind = index::SymbolKind::EnumConstant;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "Hello::";
+ HI.Type = "enum Hello";
+ HI.Definition = "ONE";
+ HI.Value = "0";
+ }},
{
R"cpp(// Enumerator in anonymous enum
enum {
ONE, TWO, THREE,
};
void foo() {
- int hello = O^NE;
+ int hello = [[O^NE]];
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "ONE\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "ONE";
+ HI.Kind = index::SymbolKind::EnumConstant;
+ HI.NamespaceScope = "";
+ // FIXME: This should be `(anon enum)::`
+ HI.LocalScope = "";
+ HI.Type = "enum (anonymous)";
+ HI.Definition = "ONE";
+ HI.Value = "0";
+ }},
{
R"cpp(// Global variable
static int hey = 10;
void foo() {
- he^y++;
+ [[he^y]]++;
}
)cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "static int hey = 10\n"
- "]\n"
- "text[Global variable]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "hey";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.Type = "int";
+ HI.Definition = "static int hey = 10";
+ HI.Documentation = "Global variable";
+ // FIXME: Value shouldn't be set in this case
+ HI.Value = "10";
+ }},
{
R"cpp(// Global variable in namespace
namespace ns1 {
static int hey = 10;
}
void foo() {
- ns1::he^y++;
+ ns1::[[he^y]]++;
}
)cpp",
- "text[Declared in]code[ns1]\n"
- "codeblock(cpp) [\n"
- "static int hey = 10\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "hey";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "ns1::";
+ HI.Type = "int";
+ HI.Definition = "static int hey = 10";
+ HI.Value = "10";
+ }},
{
R"cpp(// Field in anonymous struct
static struct {
int hello;
} s;
void foo() {
- s.he^llo++;
+ s.[[he^llo]]++;
}
)cpp",
- "text[Declared in]code[(anonymous struct)]\n"
- "codeblock(cpp) [\n"
- "int hello\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "hello";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "(anonymous struct)::";
+ HI.Type = "int";
+ HI.Definition = "int hello";
+ }},
{
R"cpp(// Templated function
template <typename T>
T foo() {
return 17;
}
- void g() { auto x = f^oo<int>(); }
- )cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "template <typename T> T foo()\n"
- "]\n"
- "text[Templated function]",
- },
+ void g() { auto x = [[f^oo]]<int>(); }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "foo";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "";
+ HI.Type = "T ()";
+ HI.Definition = "template <typename T> T foo()";
+ HI.Documentation = "Templated function";
+ HI.ReturnType = "T";
+ HI.Parameters = std::vector<HoverInfo::Param>{};
+ HI.TemplateParameters = {
+ {std::string("typename"), std::string("T"), llvm::None},
+ };
+ }},
{
R"cpp(// Anonymous union
struct outer {
@@ -954,84 +1075,73 @@ TEST(Hover, All) {
int abc, def;
} v;
};
- void g() { struct outer o; o.v.d^ef++; }
+ void g() { struct outer o; o.v.[[d^ef]]++; }
)cpp",
- "text[Declared in]code[outer::(anonymous union)]\n"
- "codeblock(cpp) [\n"
- "int def\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "def";
+ HI.Kind = index::SymbolKind::Field;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "outer::(anonymous union)::";
+ HI.Type = "int";
+ HI.Definition = "int def";
+ }},
{
R"cpp(// documentation from index
int nextSymbolIsAForwardDeclFromIndexWithNoLocalDocs;
void indexSymbol();
- void g() { ind^exSymbol(); }
- )cpp",
- "text[Declared in]code[global namespace]\n"
- "codeblock(cpp) [\n"
- "void indexSymbol()\n"
- "]\n"
- "text[comment from index]",
- },
- {
- R"cpp(// Nothing
- void foo() {
- ^
- }
- )cpp",
- "",
- },
+ void g() { [[ind^exSymbol]](); }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "indexSymbol";
+ HI.Kind = index::SymbolKind::Function;
+ HI.NamespaceScope = "";
+ HI.Type = "void ()";
+ HI.Definition = "void indexSymbol()";
+ HI.ReturnType = "void";
+ HI.Parameters = std::vector<HoverInfo::Param>{};
+ HI.Documentation = "comment from index";
+ }},
{
R"cpp(// Simple initialization with auto
void foo() {
- ^auto i = 1;
+ ^[[auto]] i = 1;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "int";
+ // FIXME: Should be Builtin/Integral.
+ HI.Kind = index::SymbolKind::Unknown;
+ }},
{
R"cpp(// Simple initialization with const auto
void foo() {
- const ^auto i = 1;
+ const ^[[auto]] i = 1;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Simple initialization with const auto&
void foo() {
- const ^auto& i = 1;
+ const ^[[auto]]& i = 1;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Simple initialization with auto&
void foo() {
- ^auto& i = 1;
+ int x;
+ ^[[auto]]& i = x;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Simple initialization with auto*
void foo() {
int a = 1;
- ^auto* i = &a;
+ ^[[auto]]* i = &a;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Auto with initializer list.
namespace std
@@ -1040,238 +1150,190 @@ TEST(Hover, All) {
class initializer_list {};
}
void foo() {
- ^auto i = {1,2};
+ ^[[auto]] i = {1,2};
}
)cpp",
- "codeblock(cpp) [\n"
- "class std::initializer_list<int>\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "class std::initializer_list<int>";
+ HI.Kind = index::SymbolKind::Class;
+ }},
{
R"cpp(// User defined conversion to auto
struct Bar {
- operator ^auto() const { return 10; }
+ operator ^[[auto]]() const { return 10; }
};
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Simple initialization with decltype(auto)
void foo() {
- ^decltype(auto) i = 1;
+ ^[[decltype]](auto) i = 1;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Simple initialization with const decltype(auto)
void foo() {
const int j = 0;
- ^decltype(auto) i = j;
+ ^[[decltype]](auto) i = j;
}
)cpp",
- "codeblock(cpp) [\n"
- "const int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "const int"; }},
{
R"cpp(// Simple initialization with const& decltype(auto)
void foo() {
int k = 0;
const int& j = k;
- ^decltype(auto) i = j;
+ ^[[decltype]](auto) i = j;
}
)cpp",
- "codeblock(cpp) [\n"
- "const int &\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "const int &"; }},
{
R"cpp(// Simple initialization with & decltype(auto)
void foo() {
int k = 0;
int& j = k;
- ^decltype(auto) i = j;
+ ^[[decltype]](auto) i = j;
}
)cpp",
- "codeblock(cpp) [\n"
- "int &\n"
- "]",
- },
- {
- R"cpp(// decltype with initializer list: nothing
- namespace std
- {
- template<class _E>
- class initializer_list {};
- }
- void foo() {
- ^decltype(auto) i = {1,2};
- }
- )cpp",
- "",
- },
+ [](HoverInfo &HI) { HI.Name = "int &"; }},
{
R"cpp(// simple trailing return type
- ^auto main() -> int {
+ ^[[auto]] main() -> int {
return 0;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// auto function return with trailing type
struct Bar {};
- ^auto test() -> decltype(Bar()) {
+ ^[[auto]] test() -> decltype(Bar()) {
return Bar();
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// trailing return type
struct Bar {};
- auto test() -> ^decltype(Bar()) {
+ auto test() -> ^[[decltype]](Bar()) {
return Bar();
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// auto in function return
struct Bar {};
- ^auto test() {
+ ^[[auto]] test() {
return Bar();
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// auto& in function return
struct Bar {};
- ^auto& test() {
- return Bar();
+ ^[[auto]]& test() {
+ static Bar x;
+ return x;
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// auto* in function return
struct Bar {};
- ^auto* test() {
+ ^[[auto]]* test() {
Bar* bar;
return bar;
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// const auto& in function return
struct Bar {};
- const ^auto& test() {
- return Bar();
+ const ^[[auto]]& test() {
+ static Bar x;
+ return x;
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// decltype(auto) in function return
struct Bar {};
- ^decltype(auto) test() {
+ ^[[decltype]](auto) test() {
return Bar();
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// decltype(auto) reference in function return
- struct Bar {};
- ^decltype(auto) test() {
- int a;
+ ^[[decltype]](auto) test() {
+ static int a;
return (a);
}
)cpp",
- "codeblock(cpp) [\n"
- "int &\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int &"; }},
{
R"cpp(// decltype lvalue reference
void foo() {
int I = 0;
- ^decltype(I) J = I;
+ ^[[decltype]](I) J = I;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// decltype lvalue reference
void foo() {
int I= 0;
int &K = I;
- ^decltype(K) J = I;
+ ^[[decltype]](K) J = I;
}
)cpp",
- "codeblock(cpp) [\n"
- "int &\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int &"; }},
{
R"cpp(// decltype lvalue reference parenthesis
void foo() {
int I = 0;
- ^decltype((I)) J = I;
+ ^[[decltype]]((I)) J = I;
}
)cpp",
- "codeblock(cpp) [\n"
- "int &\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int &"; }},
{
R"cpp(// decltype rvalue reference
void foo() {
int I = 0;
- ^decltype(static_cast<int&&>(I)) J = static_cast<int&&>(I);
+ ^[[decltype]](static_cast<int&&>(I)) J = static_cast<int&&>(I);
}
)cpp",
- "codeblock(cpp) [\n"
- "int &&\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int &&"; }},
{
R"cpp(// decltype rvalue reference function call
int && bar();
void foo() {
int I = 0;
- ^decltype(bar()) J = bar();
+ ^[[decltype]](bar()) J = bar();
}
)cpp",
- "codeblock(cpp) [\n"
- "int &&\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int &&"; }},
{
R"cpp(// decltype of function with trailing return type.
struct Bar {};
@@ -1279,65 +1341,42 @@ TEST(Hover, All) {
return Bar();
}
void foo() {
- ^decltype(test()) i = test();
+ ^[[decltype]](test()) i = test();
}
)cpp",
- "codeblock(cpp) [\n"
- "struct Bar\n"
- "]",
- },
+ [](HoverInfo &HI) {
+ HI.Name = "struct Bar";
+ HI.Kind = index::SymbolKind::Struct;
+ }},
{
R"cpp(// decltype of var with decltype.
void foo() {
int I = 0;
decltype(I) J = I;
- ^decltype(J) K = J;
+ ^[[decltype]](J) K = J;
}
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
- {
- R"cpp(// structured binding. Not supported yet
- struct Bar {};
- void foo() {
- Bar a[2];
- ^auto [x,y] = a;
- }
- )cpp",
- "",
- },
- {
- R"cpp(// Template auto parameter. Nothing (Not useful).
- template<^auto T>
- void func() {
- }
- void foo() {
- func<1>();
- }
- )cpp",
- "",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// More compilcated structured types.
int bar();
- ^auto (*foo)() = bar;
+ ^[[auto]] (*foo)() = bar;
)cpp",
- "codeblock(cpp) [\n"
- "int\n"
- "]",
- },
+ [](HoverInfo &HI) { HI.Name = "int"; }},
{
R"cpp(// Should not crash when evaluating the initializer.
struct Test {};
- void test() { Test && te^st = {}; }
- )cpp",
- "text[Declared in]code[test]\n"
- "codeblock(cpp) [\n"
- "struct Test &&test = {}\n"
- "]",
- },
+ void test() { Test && [[te^st]] = {}; }
+ )cpp",
+ [](HoverInfo &HI) {
+ HI.Name = "test";
+ HI.Kind = index::SymbolKind::Variable;
+ HI.NamespaceScope = "";
+ HI.LocalScope = "test::";
+ HI.Type = "struct Test &&";
+ HI.Definition = "struct Test &&test = {}";
+ HI.Value = "{}";
+ }},
};
// Create a tiny index, so tests above can verify documentation is fetched.
@@ -1348,18 +1387,36 @@ TEST(Hover, All) {
auto Index =
MemIndex::build(std::move(Symbols).build(), RefSlab(), RelationSlab());
- for (const OneTest &Test : Tests) {
- Annotations T(Test.Input);
+ for (const auto &Case : Cases) {
+ SCOPED_TRACE(Case.Code);
+
+ Annotations T(Case.Code);
TestTU TU = TestTU::withCode(T.code());
TU.ExtraArgs.push_back("-std=c++17");
+ TU.ExtraArgs.push_back("-Wno-gnu-designator");
auto AST = TU.build();
- if (auto H =
- getHover(AST, T.point(), format::getLLVMStyle(), Index.get())) {
- EXPECT_NE("", Test.ExpectedHover) << Test.Input;
- EXPECT_EQ(H->present().renderForTests(), Test.ExpectedHover.str())
- << Test.Input;
- } else
- EXPECT_EQ("", Test.ExpectedHover.str()) << Test.Input;
+ for (const auto &D : AST.getDiagnostics())
+ ADD_FAILURE() << D;
+ ASSERT_TRUE(AST.getDiagnostics().empty());
+
+ auto H = getHover(AST, T.point(), format::getLLVMStyle(), Index.get());
+ ASSERT_TRUE(H);
+ HoverInfo Expected;
+ Expected.SymRange = T.range();
+ Case.ExpectedBuilder(Expected);
+
+ EXPECT_EQ(H->NamespaceScope, Expected.NamespaceScope);
+ EXPECT_EQ(H->LocalScope, Expected.LocalScope);
+ EXPECT_EQ(H->Name, Expected.Name);
+ EXPECT_EQ(H->Kind, Expected.Kind);
+ EXPECT_EQ(H->Documentation, Expected.Documentation);
+ EXPECT_EQ(H->Definition, Expected.Definition);
+ EXPECT_EQ(H->Type, Expected.Type);
+ EXPECT_EQ(H->ReturnType, Expected.ReturnType);
+ EXPECT_EQ(H->Parameters, Expected.Parameters);
+ EXPECT_EQ(H->TemplateParameters, Expected.TemplateParameters);
+ EXPECT_EQ(H->SymRange, Expected.SymRange);
+ EXPECT_EQ(H->Value, Expected.Value);
}
}
More information about the cfe-commits
mailing list