//===-- SymbolInfoTests.cpp -----------------------*- C++ -*--------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "Annotations.h" #include "ClangdUnit.h" #include "Compiler.h" #include "Matchers.h" #include "SyncAPI.h" #include "TestFS.h" #include "TestTU.h" #include "XRefs.h" #include "index/FileIndex.h" #include "index/SymbolCollector.h" #include "clang/Index/IndexingAction.h" #include "llvm/Support/Path.h" #include "gmock/gmock.h" #include "gtest/gtest.h" namespace clang { namespace clangd { namespace { using testing::ElementsAreArray; auto CreateExpectedSymbolDetails = [](const std::string &name, const std::string &container, const std::string &USR) { return SymbolDetails{name, container, USR, SymbolID(USR)}; }; TEST(SymbolInfoTests, All) { std::pair> TestInputExpectedOutput[] = { { R"cpp( // Simple function reference - declaration void foo(); int bar() { fo^o(); } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}}, { R"cpp( // Simple function reference - definition void foo() {} int bar() { fo^o(); } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}}, { R"cpp( // Function in namespace reference namespace bar { void foo(); int baz() { fo^o(); } } )cpp", {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}}, { R"cpp( // Function in different namespace reference namespace bar { void foo(); } namespace barbar { int baz() { bar::fo^o(); } } )cpp", {CreateExpectedSymbolDetails("foo", "bar::", "c:@N@bar@F@foo#")}}, { R"cpp( // Function in global namespace reference void foo(); namespace Nbar { namespace Nbaz { int baz() { ::fo^o(); } } } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#")}}, { R"cpp( // Function in anonymous namespace reference namespace { void foo(); } namespace barbar { int baz() { fo^o(); } } )cpp", {CreateExpectedSymbolDetails("foo", "(anonymous)", "c:TestTU.cpp@aN@F@foo#")}}, { R"cpp( // Function reference - ADL namespace bar { struct BarType {}; void foo(const BarType&); } namespace barbar { int baz() { bar::BarType b; fo^o(b); } } )cpp", {CreateExpectedSymbolDetails( "foo", "bar::", "c:@N@bar@F@foo#&1$@N@bar@S@BarType#")}}, { R"cpp( // Global value reference int value; void foo(int) { } void bar() { foo(val^ue); } )cpp", {CreateExpectedSymbolDetails("value", "", "c:@value")}}, { R"cpp( // Local value reference void foo() { int aaa; int bbb = aa^a; } )cpp", {CreateExpectedSymbolDetails("aaa", "foo", "c:TestTU.cpp@49@F@foo#@aaa")}}, { R"cpp( // Function param void bar(int aaa) { int bbb = a^aa; } )cpp", {CreateExpectedSymbolDetails("aaa", "bar", "c:TestTU.cpp@38@F@bar#I#@aaa")}}, { R"cpp( // Lambda capture int ii; auto lam = [ii]() { return i^i; }; )cpp", {CreateExpectedSymbolDetails("ii", "", "c:@ii")}}, { R"cpp( // Macro reference #define MACRO 5\nint i = MAC^RO; )cpp", {CreateExpectedSymbolDetails("MACRO", "", "c:TestTU.cpp@55@macro@MACRO")}}, { R"cpp( // Multiple symbols returned - using overloaded function name void foo() {} void foo(bool) {} void foo(int) {} namespace bar { using ::fo^o; } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@F@foo#"), CreateExpectedSymbolDetails("foo", "", "c:@F@foo#b#"), CreateExpectedSymbolDetails("foo", "", "c:@F@foo#I#")}}, { R"cpp( // Multiple symbols returned - implicit conversion struct foo {}; struct bar { bar(const foo&) {} }; void func_baz1(bar) {} void func_baz2() { foo ff; func_baz1(f^f); } )cpp", { CreateExpectedSymbolDetails( "ff", "func_baz2", "c:TestTU.cpp@218@F@func_baz2#@ff"), CreateExpectedSymbolDetails( "bar", "bar::", "c:@S@bar@F@bar#&1$@S@foo#"), }}, { R"cpp( // Type reference - declaration struct foo; void bar(fo^o*); )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}}, { R"cpp( // Type reference - definition struct foo {}; void bar(fo^o*); )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}}, { R"cpp( // Type Reference - template argumen struct foo {}; template struct bar {}; void baz() { bar b; } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@S@foo")}}, { R"cpp( // Template parameter reference - type param template struct bar { T^T t; }; )cpp", {/* not implemented */}}, { R"cpp( // Template parameter reference - type param template struct bar { int a = N^N; }; )cpp", {/* not implemented */}}, { R"cpp( // Class member reference - objec struct foo { int aa; }; void bar() { foo f; f.a^a; } )cpp", {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}}, { R"cpp( // Class member reference - pointer struct foo { int aa; }; void bar() { &foo::a^a; } )cpp", {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@FI@aa")}}, { R"cpp( // Class method reference - objec struct foo { void aa() {} }; void bar() { foo f; f.a^a(); } )cpp", {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}}, { R"cpp( // Class method reference - pointer struct foo { void aa() {} }; void bar() { &foo::a^a; } )cpp", {CreateExpectedSymbolDetails("aa", "foo::", "c:@S@foo@F@aa#")}}, { R"cpp( // Typedef typedef int foo; void bar() { fo^o a; } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:TestTU.cpp@T@foo")}}, { R"cpp( // Type alias using foo = int; void bar() { fo^o a; } )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@foo")}}, { R"cpp( // Namespace reference namespace foo {} using namespace fo^o; )cpp", {CreateExpectedSymbolDetails("foo", "", "c:@N@foo")}}, { R"cpp( // Enum value reference enum foo { bar, baz }; void f() { foo fff = ba^r; } )cpp", {CreateExpectedSymbolDetails("bar", "foo", "c:@E@foo@bar")}}, { R"cpp( // Enum class value reference enum class foo { bar, baz }; void f() { foo fff = foo::ba^r; } )cpp", {CreateExpectedSymbolDetails("bar", "foo::", "c:@E@foo@bar")}}, { R"cpp( // Type inferrence with auto keyword struct foo {}; foo getfoo() { return foo{}; } void f() { au^to a = getfoo(); } )cpp", {/* not implemented */}}, { R"cpp( // decltype struct foo {}; void f() { foo f; declt^ype(f); } )cpp", {/* not implemented */}}, }; for (const auto &T : TestInputExpectedOutput) { Annotations TestInput(T.first); auto AST = TestTU::withCode(TestInput.code()).build(); EXPECT_THAT(getSymbolInfo(AST, TestInput.point()), ElementsAreArray(T.second)) << T.first; } } } // namespace } // namespace clangd } // namespace clang