diff options
Diffstat (limited to 'clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp')
| -rw-r--r-- | clang-tools-extra/unittests/clangd/FindSymbolsTests.cpp | 203 |
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 |

