summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp')
-rw-r--r--clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp203
1 files changed, 150 insertions, 53 deletions
diff --git a/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp b/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp
index 8dca41ed066..56df54c7444 100644
--- a/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp
+++ b/clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp
@@ -14,6 +14,8 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+using namespace llvm;
+
namespace clang {
namespace clangd {
@@ -23,6 +25,7 @@ using ::testing::AllOf;
using ::testing::AnyOf;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
+using ::testing::Field;
using ::testing::IsEmpty;
using ::testing::UnorderedElementsAre;
@@ -37,9 +40,17 @@ MATCHER_P(QName, Name, "") {
return arg.name == Name;
return (arg.containerName + "::" + arg.name) == Name;
}
+MATCHER_P(WithName, N, "") { return arg.name == N; }
MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; }
MATCHER_P(SymRange, Range, "") { return arg.location.range == Range; }
+// GMock helpers for matching DocumentSymbol.
+MATCHER_P(SymNameRange, Range, "") { return arg.selectionRange == Range; }
+template <class... ChildMatchers>
+testing::Matcher<DocumentSymbol> Children(ChildMatchers... ChildrenM) {
+ return Field(&DocumentSymbol::children, ElementsAre(ChildrenM...));
+}
+
ClangdServer::Options optsForTests() {
auto ServerOpts = ClangdServer::optsForTest();
ServerOpts.WorkspaceRoot = testRoot();
@@ -300,7 +311,7 @@ protected:
IgnoreDiagnostics DiagConsumer;
ClangdServer Server;
- std::vector<SymbolInformation> getSymbols(PathRef File) {
+ std::vector<DocumentSymbol> getSymbols(PathRef File) {
EXPECT_TRUE(Server.blockUntilIdleForTest()) << "Waiting for preamble";
auto SymbolInfos = runDocumentSymbols(Server, File);
EXPECT_TRUE(bool(SymbolInfos)) << "documentSymbols returned an error";
@@ -363,31 +374,46 @@ TEST_F(DocumentSymbolsTest, BasicSymbols) {
)");
addFile(FilePath, Main.code());
- EXPECT_THAT(getSymbols(FilePath),
- ElementsAreArray(
- {AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
- AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
- AllOf(QName("Foo::Foo"), WithKind(SymbolKind::Method)),
- AllOf(QName("Foo::Foo"), WithKind(SymbolKind::Method)),
- AllOf(QName("Foo::f"), WithKind(SymbolKind::Method)),
- AllOf(QName("f1"), WithKind(SymbolKind::Function)),
- AllOf(QName("Foo::operator="), WithKind(SymbolKind::Method)),
- AllOf(QName("Foo::~Foo"), WithKind(SymbolKind::Method)),
- AllOf(QName("Foo::Nested"), WithKind(SymbolKind::Class)),
- AllOf(QName("Foo::Nested::f"), WithKind(SymbolKind::Method)),
- AllOf(QName("Friend"), WithKind(SymbolKind::Class)),
- AllOf(QName("f1"), WithKind(SymbolKind::Function)),
- AllOf(QName("f2"), WithKind(SymbolKind::Function)),
- AllOf(QName("KInt"), WithKind(SymbolKind::Variable)),
- AllOf(QName("kStr"), WithKind(SymbolKind::Variable)),
- AllOf(QName("f1"), WithKind(SymbolKind::Function)),
- AllOf(QName("foo"), WithKind(SymbolKind::Namespace)),
- AllOf(QName("foo::int32"), WithKind(SymbolKind::Class)),
- AllOf(QName("foo::int32_t"), WithKind(SymbolKind::Class)),
- AllOf(QName("foo::v1"), WithKind(SymbolKind::Variable)),
- AllOf(QName("foo::bar"), WithKind(SymbolKind::Namespace)),
- AllOf(QName("foo::bar::v2"), WithKind(SymbolKind::Variable)),
- AllOf(QName("foo::baz"), WithKind(SymbolKind::Namespace))}));
+ EXPECT_THAT(
+ getSymbols(FilePath),
+ ElementsAreArray(
+ {AllOf(WithName("Foo"), WithKind(SymbolKind::Class), Children()),
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
+ Children(AllOf(WithName("Foo"), WithKind(SymbolKind::Method),
+ Children()),
+ AllOf(WithName("Foo"), WithKind(SymbolKind::Method),
+ Children()),
+ AllOf(WithName("f"), WithKind(SymbolKind::Method),
+ Children()),
+ AllOf(WithName("operator="),
+ WithKind(SymbolKind::Method), Children()),
+ AllOf(WithName("~Foo"), WithKind(SymbolKind::Method),
+ Children()),
+ AllOf(WithName("Nested"), WithKind(SymbolKind::Class),
+ Children(AllOf(WithName("f"),
+ WithKind(SymbolKind::Method),
+ Children()))))),
+ AllOf(WithName("Friend"), WithKind(SymbolKind::Class), Children()),
+ AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
+ AllOf(WithName("f2"), WithKind(SymbolKind::Function), Children()),
+ AllOf(WithName("KInt"), WithKind(SymbolKind::Variable), Children()),
+ AllOf(WithName("kStr"), WithKind(SymbolKind::Variable), Children()),
+ AllOf(WithName("f1"), WithKind(SymbolKind::Function), Children()),
+ AllOf(WithName("foo"), WithKind(SymbolKind::Namespace),
+ Children(
+ AllOf(WithName("int32"), WithKind(SymbolKind::Class),
+ Children()),
+ AllOf(WithName("int32_t"), WithKind(SymbolKind::Class),
+ Children()),
+ AllOf(WithName("v1"), WithKind(SymbolKind::Variable),
+ Children()),
+ AllOf(WithName("bar"), WithKind(SymbolKind::Namespace),
+ Children(AllOf(WithName("v2"),
+ WithKind(SymbolKind::Variable),
+ Children()))),
+ AllOf(WithName("baz"), WithKind(SymbolKind::Namespace),
+ Children()),
+ AllOf(WithName("v2"), WithKind(SymbolKind::Variable))))}));
}
TEST_F(DocumentSymbolsTest, DeclarationDefinition) {
@@ -402,11 +428,12 @@ TEST_F(DocumentSymbolsTest, DeclarationDefinition) {
addFile(FilePath, Main.code());
EXPECT_THAT(getSymbols(FilePath),
- ElementsAre(AllOf(QName("Foo"), WithKind(SymbolKind::Class)),
- AllOf(QName("Foo::f"), WithKind(SymbolKind::Method),
- SymRange(Main.range("decl"))),
- AllOf(QName("Foo::f"), WithKind(SymbolKind::Method),
- SymRange(Main.range("def")))));
+ ElementsAre(AllOf(WithName("Foo"), WithKind(SymbolKind::Class),
+ Children(AllOf(
+ WithName("f"), WithKind(SymbolKind::Method),
+ SymNameRange(Main.range("decl"))))),
+ AllOf(WithName("f"), WithKind(SymbolKind::Method),
+ SymNameRange(Main.range("def")))));
}
TEST_F(DocumentSymbolsTest, ExternSymbol) {
@@ -429,7 +456,7 @@ TEST_F(DocumentSymbolsTest, NoLocals) {
struct LocalClass {};
int local_var;
})cpp");
- EXPECT_THAT(getSymbols(FilePath), ElementsAre(QName("test")));
+ EXPECT_THAT(getSymbols(FilePath), ElementsAre(WithName("test")));
}
TEST_F(DocumentSymbolsTest, Unnamed) {
@@ -442,9 +469,12 @@ TEST_F(DocumentSymbolsTest, Unnamed) {
)cpp");
EXPECT_THAT(
getSymbols(FilePath),
- ElementsAre(AllOf(QName("UnnamedStruct"), WithKind(SymbolKind::Variable)),
- AllOf(QName("(anonymous struct)::InUnnamed"),
- WithKind(SymbolKind::Field))));
+ ElementsAre(
+ AllOf(WithName("(anonymous struct)"), WithKind(SymbolKind::Struct),
+ Children(AllOf(WithName("InUnnamed"),
+ WithKind(SymbolKind::Field), Children()))),
+ AllOf(WithName("UnnamedStruct"), WithKind(SymbolKind::Variable),
+ Children())));
}
TEST_F(DocumentSymbolsTest, InHeaderFile) {
@@ -461,23 +491,46 @@ TEST_F(DocumentSymbolsTest, InHeaderFile) {
addFile("foo.cpp", R"cpp(
#include "foo.h"
)cpp");
- EXPECT_THAT(getSymbols(FilePath), ElementsAre(QName("test")));
+ EXPECT_THAT(getSymbols(FilePath), ElementsAre(WithName("test")));
}
TEST_F(DocumentSymbolsTest, Template) {
std::string FilePath = testPath("foo.cpp");
addFile(FilePath, R"(
- // Primary templates and specializations are included but instantiations
- // are not.
template <class T> struct Tmpl {T x = 0;};
- template <> struct Tmpl<int> {};
+ template <> struct Tmpl<int> {
+ int y = 0;
+ };
extern template struct Tmpl<float>;
template struct Tmpl<double>;
+
+ template <class T, class U, class Z = float>
+ int funcTmpl(U a);
+ template <>
+ int funcTmpl<int>(double a);
+
+ template <class T, class U = double>
+ int varTmpl = T();
+ template <>
+ double varTmpl<int> = 10.0;
)");
- EXPECT_THAT(getSymbols(FilePath),
- ElementsAre(AllOf(QName("Tmpl"), WithKind(SymbolKind::Struct)),
- AllOf(QName("Tmpl::x"), WithKind(SymbolKind::Field)),
- AllOf(QName("Tmpl"), WithKind(SymbolKind::Struct))));
+ EXPECT_THAT(
+ getSymbols(FilePath),
+ ElementsAre(
+ AllOf(WithName("Tmpl"), WithKind(SymbolKind::Struct),
+ Children(AllOf(WithName("x"), WithKind(SymbolKind::Field)))),
+ AllOf(WithName("Tmpl<int>"), WithKind(SymbolKind::Struct),
+ Children(WithName("y"))),
+ AllOf(WithName("Tmpl<float>"), WithKind(SymbolKind::Struct),
+ Children()),
+ AllOf(WithName("Tmpl<double>"), WithKind(SymbolKind::Struct),
+ Children()),
+ AllOf(WithName("funcTmpl"), Children()),
+ // FIXME(ibiryukov): template args should be <int> to match the code.
+ AllOf(WithName("funcTmpl<int, double, float>"), Children()),
+ AllOf(WithName("varTmpl"), Children()),
+ // FIXME(ibiryukov): template args should be <int> to match the code.
+ AllOf(WithName("varTmpl<int, double>"), Children())));
}
TEST_F(DocumentSymbolsTest, Namespaces) {
@@ -507,10 +560,15 @@ TEST_F(DocumentSymbolsTest, Namespaces) {
)cpp");
EXPECT_THAT(
getSymbols(FilePath),
- ElementsAreArray({QName("ans1"), QName("ans1::ai1"), QName("ans1::ans2"),
- QName("ans1::ans2::ai2"), QName("test"), QName("na"),
- QName("na::nb"), QName("na::Foo"), QName("na"),
- QName("na::nb"), QName("na::Bar")}));
+ ElementsAreArray<testing::Matcher<DocumentSymbol>>(
+ {AllOf(WithName("ans1"),
+ Children(AllOf(WithName("ai1"), Children()),
+ AllOf(WithName("ans2"), Children(WithName("ai2"))))),
+ AllOf(WithName("(anonymous namespace)"), Children(WithName("test"))),
+ AllOf(WithName("na"),
+ Children(AllOf(WithName("nb"), Children(WithName("Foo"))))),
+ AllOf(WithName("na"),
+ Children(AllOf(WithName("nb"), Children(WithName("Bar")))))}));
}
TEST_F(DocumentSymbolsTest, Enums) {
@@ -531,10 +589,14 @@ TEST_F(DocumentSymbolsTest, Enums) {
};
}
)");
- EXPECT_THAT(getSymbols(FilePath),
- ElementsAre(QName("Red"), QName("Color"), QName("Green"),
- QName("Color2"), QName("Color2::Yellow"), QName("ns"),
- QName("ns::Black")));
+ EXPECT_THAT(
+ getSymbols(FilePath),
+ ElementsAre(
+ AllOf(WithName("(anonymous enum)"), Children(WithName("Red"))),
+ AllOf(WithName("Color"), Children(WithName("Green"))),
+ AllOf(WithName("Color2"), Children(WithName("Yellow"))),
+ AllOf(WithName("ns"), Children(AllOf(WithName("(anonymous enum)"),
+ Children(WithName("Black")))))));
}
TEST_F(DocumentSymbolsTest, FromMacro) {
@@ -553,8 +615,43 @@ TEST_F(DocumentSymbolsTest, FromMacro) {
addFile(FilePath, Main.code());
EXPECT_THAT(
getSymbols(FilePath),
- ElementsAre(AllOf(QName("abc_Test"), SymRange(Main.range("expansion"))),
- AllOf(QName("Test"), SymRange(Main.range("spelling")))));
+ ElementsAre(
+ AllOf(WithName("abc_Test"), SymNameRange(Main.range("expansion"))),
+ AllOf(WithName("Test"), SymNameRange(Main.range("spelling")))));
+}
+
+TEST_F(DocumentSymbolsTest, FuncTemplates) {
+ std::string FilePath = testPath("foo.cpp");
+ Annotations Source(R"cpp(
+ template <class T>
+ T foo() {}
+
+ auto x = foo<int>();
+ auto y = foo<double>()
+ )cpp");
+ addFile(FilePath, Source.code());
+ // Make sure we only see the template declaration, not instantiations.
+ EXPECT_THAT(getSymbols(FilePath),
+ ElementsAre(WithName("foo"), WithName("x"), WithName("y")));
+}
+
+TEST_F(DocumentSymbolsTest, UsingDirectives) {
+ std::string FilePath = testPath("foo.cpp");
+ Annotations Source(R"cpp(
+ namespace ns {
+ int foo;
+ }
+
+ namespace ns_alias = ns;
+
+ using namespace ::ns; // check we don't loose qualifiers.
+ using namespace ns_alias; // and namespace aliases.
+ )cpp");
+ addFile(FilePath, Source.code());
+ EXPECT_THAT(getSymbols(FilePath),
+ ElementsAre(WithName("ns"), WithName("ns_alias"),
+ WithName("using namespace ::ns"),
+ WithName("using namespace ns_alias")));
}
} // namespace clangd
OpenPOWER on IntegriCloud