dgoldman updated this revision to Diff 340653.
dgoldman marked 2 inline comments as done.
dgoldman added a comment.

Address review comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D98984/new/

https://reviews.llvm.org/D98984

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -676,8 +676,7 @@
         @end
         @interface $Class_decl[[Klass]] <$Interface[[Protocol]]>
         @end
-        // FIXME: protocol list in ObjCObjectType should be highlighted.
-        id<Protocol> $Variable_decl[[x]];
+        id<$Interface[[Protocol]]> $Variable_decl[[x]];
       )cpp",
       R"cpp(
         // ObjC: Categories
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -943,14 +943,32 @@
   )cpp";
   EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo");
 
+  Code = R"cpp(
+    @class C;
+    @protocol Foo
+    @end
+    void test([[C]]<Foo> *p);
+  )cpp";
+  EXPECT_DECLS("ObjCInterfaceTypeLoc", "@class C;");
+
   Code = R"cpp(
     @class C;
     @protocol Foo
     @end
     void test(C<[[Foo]]> *p);
   )cpp";
-  // FIXME: there's no AST node corresponding to 'Foo', so we're stuck.
-  EXPECT_DECLS("ObjCObjectTypeLoc");
+  EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo");
+
+  Code = R"cpp(
+    @class C;
+    @protocol Foo
+    @end
+    @protocol Bar
+    @end
+    void test(C<[[Foo]], Bar> *p);
+  )cpp";
+  // FIXME: We currently can't disambiguate between multiple protocols.
+  EXPECT_DECLS("ObjCObjectTypeLoc", "@protocol Foo", "@protocol Bar");
 }
 
 class FindExplicitReferencesTest : public ::testing::Test {
@@ -1036,37 +1054,36 @@
 
 TEST_F(FindExplicitReferencesTest, All) {
   std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =
-      {
-          // Simple expressions.
-          {R"cpp(
+      {// Simple expressions.
+       {R"cpp(
         int global;
         int func();
         void foo(int param) {
           $0^global = $1^param + $2^func();
         }
         )cpp",
-           "0: targets = {global}\n"
-           "1: targets = {param}\n"
-           "2: targets = {func}\n"},
-          {R"cpp(
+        "0: targets = {global}\n"
+        "1: targets = {param}\n"
+        "2: targets = {func}\n"},
+       {R"cpp(
         struct X { int a; };
         void foo(X x) {
           $0^x.$1^a = 10;
         }
         )cpp",
-           "0: targets = {x}\n"
-           "1: targets = {X::a}\n"},
-          {R"cpp(
+        "0: targets = {x}\n"
+        "1: targets = {X::a}\n"},
+       {R"cpp(
         // error-ok: testing with broken code
         int bar();
         int foo() {
           return $0^bar() + $1^bar(42);
         }
         )cpp",
-           "0: targets = {bar}\n"
-           "1: targets = {bar}\n"},
-          // Namespaces and aliases.
-          {R"cpp(
+        "0: targets = {bar}\n"
+        "1: targets = {bar}\n"},
+       // Namespaces and aliases.
+       {R"cpp(
           namespace ns {}
           namespace alias = ns;
           void foo() {
@@ -1074,19 +1091,19 @@
             using namespace $1^alias;
           }
         )cpp",
-           "0: targets = {ns}\n"
-           "1: targets = {alias}\n"},
-          // Using declarations.
-          {R"cpp(
+        "0: targets = {ns}\n"
+        "1: targets = {alias}\n"},
+       // Using declarations.
+       {R"cpp(
           namespace ns { int global; }
           void foo() {
             using $0^ns::$1^global;
           }
         )cpp",
-           "0: targets = {ns}\n"
-           "1: targets = {ns::global}, qualifier = 'ns::'\n"},
-          // Simple types.
-          {R"cpp(
+        "0: targets = {ns}\n"
+        "1: targets = {ns::global}, qualifier = 'ns::'\n"},
+       // Simple types.
+       {R"cpp(
          struct Struct { int a; };
          using Typedef = int;
          void foo() {
@@ -1095,13 +1112,13 @@
            static_cast<$4^Struct*>(0);
          }
        )cpp",
-           "0: targets = {Struct}\n"
-           "1: targets = {x}, decl\n"
-           "2: targets = {Typedef}\n"
-           "3: targets = {y}, decl\n"
-           "4: targets = {Struct}\n"},
-          // Name qualifiers.
-          {R"cpp(
+        "0: targets = {Struct}\n"
+        "1: targets = {x}, decl\n"
+        "2: targets = {Typedef}\n"
+        "3: targets = {y}, decl\n"
+        "4: targets = {Struct}\n"},
+       // Name qualifiers.
+       {R"cpp(
          namespace a { namespace b { struct S { typedef int type; }; } }
          void foo() {
            $0^a::$1^b::$2^S $3^x;
@@ -1109,16 +1126,16 @@
            $6^S::$7^type $8^y;
          }
         )cpp",
-           "0: targets = {a}\n"
-           "1: targets = {a::b}, qualifier = 'a::'\n"
-           "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
-           "3: targets = {x}, decl\n"
-           "4: targets = {a}\n"
-           "5: targets = {a::b}, qualifier = 'a::'\n"
-           "6: targets = {a::b::S}\n"
-           "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
-           "8: targets = {y}, decl\n"},
-          {R"cpp(
+        "0: targets = {a}\n"
+        "1: targets = {a::b}, qualifier = 'a::'\n"
+        "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
+        "3: targets = {x}, decl\n"
+        "4: targets = {a}\n"
+        "5: targets = {a::b}, qualifier = 'a::'\n"
+        "6: targets = {a::b::S}\n"
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
+        "8: targets = {y}, decl\n"},
+       {R"cpp(
          void foo() {
            $0^ten: // PRINT "HELLO WORLD!"
            goto $1^ten;
@@ -1135,12 +1152,12 @@
             $2^vector<bool> $3^vb;
           }
         )cpp",
-           "0: targets = {vector<int>}\n"
-           "1: targets = {vi}, decl\n"
-           "2: targets = {vector<bool>}\n"
-           "3: targets = {vb}, decl\n"},
-          // Template type aliases.
-          {R"cpp(
+        "0: targets = {vector<int>}\n"
+        "1: targets = {vi}, decl\n"
+        "2: targets = {vector<bool>}\n"
+        "3: targets = {vb}, decl\n"},
+       // Template type aliases.
+       {R"cpp(
             template <class T> struct vector { using value_type = T; };
             template <> struct vector<bool> { using value_type = bool; };
             template <class T> using valias = vector<T>;
@@ -1149,12 +1166,12 @@
               $2^valias<bool> $3^vb;
             }
           )cpp",
-           "0: targets = {valias}\n"
-           "1: targets = {vi}, decl\n"
-           "2: targets = {valias}\n"
-           "3: targets = {vb}, decl\n"},
-          // Injected class name.
-          {R"cpp(
+        "0: targets = {valias}\n"
+        "1: targets = {vi}, decl\n"
+        "2: targets = {valias}\n"
+        "3: targets = {vb}, decl\n"},
+       // Injected class name.
+       {R"cpp(
             namespace foo {
               template <typename $0^T>
               class $1^Bar {
@@ -1163,13 +1180,13 @@
               };
             }
           )cpp",
-           "0: targets = {foo::Bar::T}, decl\n"
-           "1: targets = {foo::Bar}, decl\n"
-           "2: targets = {foo::Bar}\n"
-           "3: targets = {foo::Bar::f}, decl\n"
-           "4: targets = {foo::Bar}\n"},
-          // MemberExpr should know their using declaration.
-          {R"cpp(
+        "0: targets = {foo::Bar::T}, decl\n"
+        "1: targets = {foo::Bar}, decl\n"
+        "2: targets = {foo::Bar}\n"
+        "3: targets = {foo::Bar::f}, decl\n"
+        "4: targets = {foo::Bar}\n"},
+       // MemberExpr should know their using declaration.
+       {R"cpp(
             struct X { void func(int); };
             struct Y : X {
               using X::func;
@@ -1178,10 +1195,10 @@
               $0^y.$1^func(1);
             }
         )cpp",
-           "0: targets = {y}\n"
-           "1: targets = {Y::func}\n"},
-          // DeclRefExpr should know their using declaration.
-          {R"cpp(
+        "0: targets = {y}\n"
+        "1: targets = {Y::func}\n"},
+       // DeclRefExpr should know their using declaration.
+       {R"cpp(
             namespace ns { void bar(int); }
             using ns::bar;
 
@@ -1189,9 +1206,9 @@
               $0^bar(10);
             }
         )cpp",
-           "0: targets = {bar}\n"},
-          // References from a macro.
-          {R"cpp(
+        "0: targets = {bar}\n"},
+       // References from a macro.
+       {R"cpp(
             #define FOO a
             #define BAR b
 
@@ -1199,10 +1216,10 @@
               $0^FOO+$1^BAR;
             }
         )cpp",
-           "0: targets = {a}\n"
-           "1: targets = {b}\n"},
-          // No references from implicit nodes.
-          {R"cpp(
+        "0: targets = {a}\n"
+        "1: targets = {b}\n"},
+       // No references from implicit nodes.
+       {R"cpp(
             struct vector {
               int *begin();
               int *end();
@@ -1214,15 +1231,15 @@
               }
             }
         )cpp",
-           "0: targets = {x}, decl\n"
-           "1: targets = {vector}\n"
-           "2: targets = {x}\n"},
+        "0: targets = {x}, decl\n"
+        "1: targets = {vector}\n"
+        "2: targets = {x}\n"},
 // Handle UnresolvedLookupExpr.
 // FIXME
 // This case fails when expensive checks are enabled.
 // Seems like the order of ns1::func and ns2::func isn't defined.
 #ifndef EXPENSIVE_CHECKS
-          {R"cpp(
+       {R"cpp(
             namespace ns1 { void func(char*); }
             namespace ns2 { void func(int*); }
             using namespace ns1;
@@ -1233,11 +1250,11 @@
               $0^func($1^t);
             }
         )cpp",
-           "0: targets = {ns1::func, ns2::func}\n"
-           "1: targets = {t}\n"},
+        "0: targets = {ns1::func, ns2::func}\n"
+        "1: targets = {t}\n"},
 #endif
-          // Handle UnresolvedMemberExpr.
-          {R"cpp(
+       // Handle UnresolvedMemberExpr.
+       {R"cpp(
             struct X {
               void func(char*);
               void func(int*);
@@ -1248,11 +1265,11 @@
               $0^x.$1^func($2^t);
             }
         )cpp",
-           "0: targets = {x}\n"
-           "1: targets = {X::func, X::func}\n"
-           "2: targets = {t}\n"},
-          // Handle DependentScopeDeclRefExpr.
-          {R"cpp(
+        "0: targets = {x}\n"
+        "1: targets = {X::func, X::func}\n"
+        "2: targets = {t}\n"},
+       // Handle DependentScopeDeclRefExpr.
+       {R"cpp(
             template <class T>
             struct S {
               static int value;
@@ -1263,11 +1280,11 @@
               $0^S<$1^T>::$2^value;
             }
        )cpp",
-           "0: targets = {S}\n"
-           "1: targets = {T}\n"
-           "2: targets = {S::value}, qualifier = 'S<T>::'\n"},
-          // Handle CXXDependentScopeMemberExpr.
-          {R"cpp(
+        "0: targets = {S}\n"
+        "1: targets = {T}\n"
+        "2: targets = {S::value}, qualifier = 'S<T>::'\n"},
+       // Handle CXXDependentScopeMemberExpr.
+       {R"cpp(
             template <class T>
             struct S {
               int value;
@@ -1278,10 +1295,10 @@
               $0^t.$1^value;
             }
        )cpp",
-           "0: targets = {t}\n"
-           "1: targets = {S::value}\n"},
-          // Type template parameters.
-          {R"cpp(
+        "0: targets = {t}\n"
+        "1: targets = {S::value}\n"},
+       // Type template parameters.
+       {R"cpp(
             template <class T>
             void foo() {
               static_cast<$0^T>(0);
@@ -1289,21 +1306,21 @@
               $2^T $3^t;
             }
         )cpp",
-           "0: targets = {T}\n"
-           "1: targets = {T}\n"
-           "2: targets = {T}\n"
-           "3: targets = {t}, decl\n"},
-          // Non-type template parameters.
-          {R"cpp(
+        "0: targets = {T}\n"
+        "1: targets = {T}\n"
+        "2: targets = {T}\n"
+        "3: targets = {t}, decl\n"},
+       // Non-type template parameters.
+       {R"cpp(
             template <int I>
             void foo() {
               int $0^x = $1^I;
             }
         )cpp",
-           "0: targets = {x}, decl\n"
-           "1: targets = {I}\n"},
-          // Template template parameters.
-          {R"cpp(
+        "0: targets = {x}, decl\n"
+        "1: targets = {I}\n"},
+       // Template template parameters.
+       {R"cpp(
             template <class T> struct vector {};
 
             template <template<class> class TT, template<class> class ...TP>
@@ -1314,16 +1331,16 @@
               $6^foo<$7^TP...>();
             }
         )cpp",
-           "0: targets = {TT}\n"
-           "1: targets = {x}, decl\n"
-           "2: targets = {foo}\n"
-           "3: targets = {TT}\n"
-           "4: targets = {foo}\n"
-           "5: targets = {vector}\n"
-           "6: targets = {foo}\n"
-           "7: targets = {TP}\n"},
-          // Non-type template parameters with declarations.
-          {R"cpp(
+        "0: targets = {TT}\n"
+        "1: targets = {x}, decl\n"
+        "2: targets = {foo}\n"
+        "3: targets = {TT}\n"
+        "4: targets = {foo}\n"
+        "5: targets = {vector}\n"
+        "6: targets = {foo}\n"
+        "7: targets = {TP}\n"},
+       // Non-type template parameters with declarations.
+       {R"cpp(
             int func();
             template <int(*)()> struct wrapper {};
 
@@ -1333,12 +1350,12 @@
               $3^FuncParam();
             }
         )cpp",
-           "0: targets = {wrapper<&func>}\n"
-           "1: targets = {func}\n"
-           "2: targets = {w}, decl\n"
-           "3: targets = {FuncParam}\n"},
-          // declaration references.
-          {R"cpp(
+        "0: targets = {wrapper<&func>}\n"
+        "1: targets = {func}\n"
+        "2: targets = {w}, decl\n"
+        "3: targets = {FuncParam}\n"},
+       // declaration references.
+       {R"cpp(
              namespace ns {}
              class S {};
              void foo() {
@@ -1350,19 +1367,19 @@
                namespace $9^NS = $10^ns;
              }
            )cpp",
-           "0: targets = {Foo}, decl\n"
-           "1: targets = {foo()::Foo::Foo}, decl\n"
-           "2: targets = {Foo}\n"
-           "3: targets = {foo()::Foo::field}, decl\n"
-           "4: targets = {Var}, decl\n"
-           "5: targets = {E}, decl\n"
-           "6: targets = {foo()::ABC}, decl\n"
-           "7: targets = {INT}, decl\n"
-           "8: targets = {INT2}, decl\n"
-           "9: targets = {NS}, decl\n"
-           "10: targets = {ns}\n"},
-          // User-defined conversion operator.
-          {R"cpp(
+        "0: targets = {Foo}, decl\n"
+        "1: targets = {foo()::Foo::Foo}, decl\n"
+        "2: targets = {Foo}\n"
+        "3: targets = {foo()::Foo::field}, decl\n"
+        "4: targets = {Var}, decl\n"
+        "5: targets = {E}, decl\n"
+        "6: targets = {foo()::ABC}, decl\n"
+        "7: targets = {INT}, decl\n"
+        "8: targets = {INT2}, decl\n"
+        "9: targets = {NS}, decl\n"
+        "10: targets = {ns}\n"},
+       // User-defined conversion operator.
+       {R"cpp(
             void foo() {
                class $0^Bar {};
                class $1^Foo {
@@ -1375,18 +1392,18 @@
                $7^f.$8^operator $9^Bar();
             }
         )cpp",
-           "0: targets = {Bar}, decl\n"
-           "1: targets = {Foo}, decl\n"
-           "2: targets = {foo()::Foo::operator Bar}, decl\n"
-           "3: targets = {Bar}\n"
-           "4: targets = {Bar}\n"
-           "5: targets = {Foo}\n"
-           "6: targets = {f}, decl\n"
-           "7: targets = {f}\n"
-           "8: targets = {foo()::Foo::operator Bar}\n"
-           "9: targets = {Bar}\n"},
-          // Destructor.
-          {R"cpp(
+        "0: targets = {Bar}, decl\n"
+        "1: targets = {Foo}, decl\n"
+        "2: targets = {foo()::Foo::operator Bar}, decl\n"
+        "3: targets = {Bar}\n"
+        "4: targets = {Bar}\n"
+        "5: targets = {Foo}\n"
+        "6: targets = {f}, decl\n"
+        "7: targets = {f}\n"
+        "8: targets = {foo()::Foo::operator Bar}\n"
+        "9: targets = {Bar}\n"},
+       // Destructor.
+       {R"cpp(
              void foo() {
                class $0^Foo {
                public:
@@ -1401,18 +1418,18 @@
                $6^f.~ /*...*/ $7^Foo();
              }
            )cpp",
-           "0: targets = {Foo}, decl\n"
-           // FIXME: It's better to target destructor's FunctionDecl instead of
-           // the type itself (similar to constructor).
-           "1: targets = {Foo}\n"
-           "2: targets = {foo()::Foo::destructMe}, decl\n"
-           "3: targets = {Foo}\n"
-           "4: targets = {Foo}\n"
-           "5: targets = {f}, decl\n"
-           "6: targets = {f}\n"
-           "7: targets = {Foo}\n"},
-          // cxx constructor initializer.
-          {R"cpp(
+        "0: targets = {Foo}, decl\n"
+        // FIXME: It's better to target destructor's FunctionDecl instead of
+        // the type itself (similar to constructor).
+        "1: targets = {Foo}\n"
+        "2: targets = {foo()::Foo::destructMe}, decl\n"
+        "3: targets = {Foo}\n"
+        "4: targets = {Foo}\n"
+        "5: targets = {f}, decl\n"
+        "6: targets = {f}\n"
+        "7: targets = {Foo}\n"},
+       // cxx constructor initializer.
+       {R"cpp(
              class Base {};
              void foo() {
                // member initializer
@@ -1432,34 +1449,34 @@
                };
              }
            )cpp",
-           "0: targets = {X}, decl\n"
-           "1: targets = {foo()::X::abc}, decl\n"
-           "2: targets = {foo()::X::X}, decl\n"
-           "3: targets = {foo()::X::abc}\n"
-           "4: targets = {Derived}, decl\n"
-           "5: targets = {Base}\n"
-           "6: targets = {Base}\n"
-           "7: targets = {foo()::Derived::B}, decl\n"
-           "8: targets = {foo()::Derived::Derived}, decl\n"
-           "9: targets = {Base}\n"
-           "10: targets = {Foo}, decl\n"
-           "11: targets = {foo()::Foo::Foo}, decl\n"
-           "12: targets = {foo()::Foo::Foo}, decl\n"
-           "13: targets = {Foo}\n"},
-          // Anonymous entities should not be reported.
-          {
-              R"cpp(
+        "0: targets = {X}, decl\n"
+        "1: targets = {foo()::X::abc}, decl\n"
+        "2: targets = {foo()::X::X}, decl\n"
+        "3: targets = {foo()::X::abc}\n"
+        "4: targets = {Derived}, decl\n"
+        "5: targets = {Base}\n"
+        "6: targets = {Base}\n"
+        "7: targets = {foo()::Derived::B}, decl\n"
+        "8: targets = {foo()::Derived::Derived}, decl\n"
+        "9: targets = {Base}\n"
+        "10: targets = {Foo}, decl\n"
+        "11: targets = {foo()::Foo::Foo}, decl\n"
+        "12: targets = {foo()::Foo::Foo}, decl\n"
+        "13: targets = {Foo}\n"},
+       // Anonymous entities should not be reported.
+       {
+           R"cpp(
              void foo() {
               class {} $0^x;
               int (*$1^fptr)(int $2^a, int) = nullptr;
              }
            )cpp",
-              "0: targets = {x}, decl\n"
-              "1: targets = {fptr}, decl\n"
-              "2: targets = {a}, decl\n"},
-          // Namespace aliases should be handled properly.
-          {
-              R"cpp(
+           "0: targets = {x}, decl\n"
+           "1: targets = {fptr}, decl\n"
+           "2: targets = {a}, decl\n"},
+       // Namespace aliases should be handled properly.
+       {
+           R"cpp(
                 namespace ns { struct Type {}; }
                 namespace alias = ns;
                 namespace rec_alias = alias;
@@ -1470,28 +1487,28 @@
                   $6^rec_alias::$7^Type $8^c;
                 }
            )cpp",
-              "0: targets = {ns}\n"
-              "1: targets = {ns::Type}, qualifier = 'ns::'\n"
-              "2: targets = {a}, decl\n"
-              "3: targets = {alias}\n"
-              "4: targets = {ns::Type}, qualifier = 'alias::'\n"
-              "5: targets = {b}, decl\n"
-              "6: targets = {rec_alias}\n"
-              "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
-              "8: targets = {c}, decl\n"},
-          // Handle SizeOfPackExpr.
-          {
-              R"cpp(
+           "0: targets = {ns}\n"
+           "1: targets = {ns::Type}, qualifier = 'ns::'\n"
+           "2: targets = {a}, decl\n"
+           "3: targets = {alias}\n"
+           "4: targets = {ns::Type}, qualifier = 'alias::'\n"
+           "5: targets = {b}, decl\n"
+           "6: targets = {rec_alias}\n"
+           "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
+           "8: targets = {c}, decl\n"},
+       // Handle SizeOfPackExpr.
+       {
+           R"cpp(
                 template <typename... E>
                 void foo() {
                   constexpr int $0^size = sizeof...($1^E);
                 };
             )cpp",
-              "0: targets = {size}, decl\n"
-              "1: targets = {E}\n"},
-          // Class template argument deduction
-          {
-              R"cpp(
+           "0: targets = {size}, decl\n"
+           "1: targets = {E}\n"},
+       // Class template argument deduction
+       {
+           R"cpp(
                 template <typename T>
                 struct Test {
                 Test(T);
@@ -1500,51 +1517,51 @@
                 $0^Test $1^a(5);
               }
             )cpp",
-              "0: targets = {Test}\n"
-              "1: targets = {a}, decl\n"},
-          // Templates
-          {R"cpp(
+           "0: targets = {Test}\n"
+           "1: targets = {a}, decl\n"},
+       // Templates
+       {R"cpp(
             namespace foo {
               template <typename $0^T>
               class $1^Bar {};
             }
           )cpp",
-           "0: targets = {foo::Bar::T}, decl\n"
-           "1: targets = {foo::Bar}, decl\n"},
-          // Templates
-          {R"cpp(
+        "0: targets = {foo::Bar::T}, decl\n"
+        "1: targets = {foo::Bar}, decl\n"},
+       // Templates
+       {R"cpp(
             namespace foo {
               template <typename $0^T>
               void $1^func();
             }
           )cpp",
-           "0: targets = {T}, decl\n"
-           "1: targets = {foo::func}, decl\n"},
-          // Templates
-          {R"cpp(
+        "0: targets = {T}, decl\n"
+        "1: targets = {foo::func}, decl\n"},
+       // Templates
+       {R"cpp(
             namespace foo {
               template <typename $0^T>
               $1^T $2^x;
             }
           )cpp",
-           "0: targets = {foo::T}, decl\n"
-           "1: targets = {foo::T}\n"
-           "2: targets = {foo::x}, decl\n"},
-          // Templates
-          {R"cpp(
+        "0: targets = {foo::T}, decl\n"
+        "1: targets = {foo::T}\n"
+        "2: targets = {foo::x}, decl\n"},
+       // Templates
+       {R"cpp(
             template<typename T> class vector {};
             namespace foo {
               template <typename $0^T>
               using $1^V = $2^vector<$3^T>;
             }
           )cpp",
-           "0: targets = {foo::T}, decl\n"
-           "1: targets = {foo::V}, decl\n"
-           "2: targets = {vector}\n"
-           "3: targets = {foo::T}\n"},
-          // Concept
-          {
-              R"cpp(
+        "0: targets = {foo::T}, decl\n"
+        "1: targets = {foo::V}, decl\n"
+        "2: targets = {vector}\n"
+        "3: targets = {foo::T}\n"},
+       // Concept
+       {
+           R"cpp(
               template <typename T>
               concept Drawable = requires (T t) { t.draw(); };
 
@@ -1555,17 +1572,17 @@
                 }
               }
           )cpp",
-              "0: targets = {T}, decl\n"
-              "1: targets = {Drawable}\n"
-              "2: targets = {T}\n"
-              "3: targets = {foo::bar}, decl\n"
-              "4: targets = {T}\n"
-              "5: targets = {t}, decl\n"
-              "6: targets = {t}\n"
-              "7: targets = {}\n"},
-          // Objective-C: properties
-          {
-              R"cpp(
+           "0: targets = {T}, decl\n"
+           "1: targets = {Drawable}\n"
+           "2: targets = {T}\n"
+           "3: targets = {foo::bar}, decl\n"
+           "4: targets = {T}\n"
+           "5: targets = {t}, decl\n"
+           "6: targets = {t}\n"
+           "7: targets = {}\n"},
+       // Objective-C: properties
+       {
+           R"cpp(
             @interface I {}
             @property(retain) I* x;
             @property(retain) I* y;
@@ -1575,12 +1592,12 @@
               $0^f.$1^x.$2^y = 0;
             }
           )cpp",
-              "0: targets = {f}\n"
-              "1: targets = {I::x}\n"
-              "2: targets = {I::y}\n"},
-          // Objective-C: implicit properties
-          {
-              R"cpp(
+           "0: targets = {f}\n"
+           "1: targets = {I::x}\n"
+           "2: targets = {I::y}\n"},
+       // Objective-C: implicit properties
+       {
+           R"cpp(
             @interface I {}
             -(I*)x;
             -(void)setY:(I*)y;
@@ -1590,12 +1607,11 @@
               $0^f.$1^x.$2^y = 0;
             }
           )cpp",
-              "0: targets = {f}\n"
-              "1: targets = {I::x}\n"
-              "2: targets = {I::setY:}\n"},
-          {
-          // Objective-C: methods
-              R"cpp(
+           "0: targets = {f}\n"
+           "1: targets = {I::x}\n"
+           "2: targets = {I::setY:}\n"},
+       {// Objective-C: methods
+        R"cpp(
             @interface I
               -(void) a:(int)x b:(int)y;
             @end
@@ -1603,27 +1619,24 @@
               [$0^i $1^a:1 b:2];
             }
           )cpp",
-              "0: targets = {i}\n"
-              "1: targets = {I::a:b:}\n"
-          },
-          {
-          // Objective-C: protocols
-              R"cpp(
+        "0: targets = {i}\n"
+        "1: targets = {I::a:b:}\n"},
+       {// Objective-C: protocols
+        R"cpp(
             @interface I
             @end
             @protocol P
             @end
             void foo() {
-              // FIXME: should reference P
-              $0^I<P> *$1^x;
+              $0^I<$1^P> *$2^x;
             }
           )cpp",
-              "0: targets = {I}\n"
-              "1: targets = {x}, decl\n"
-          },
+        "0: targets = {I}\n"
+        "1: targets = {P}\n"
+        "2: targets = {x}, decl\n"},
 
-          // Designated initializers.
-          {R"cpp(
+       // Designated initializers.
+       {R"cpp(
             void foo() {
               struct $0^Foo {
                 int $1^Bar;
@@ -1631,12 +1644,12 @@
               $2^Foo $3^f { .$4^Bar = 42 };
             }
         )cpp",
-           "0: targets = {Foo}, decl\n"
-           "1: targets = {foo()::Foo::Bar}, decl\n"
-           "2: targets = {Foo}\n"
-           "3: targets = {f}, decl\n"
-           "4: targets = {foo()::Foo::Bar}\n"},
-          {R"cpp(
+        "0: targets = {Foo}, decl\n"
+        "1: targets = {foo()::Foo::Bar}, decl\n"
+        "2: targets = {Foo}\n"
+        "3: targets = {f}, decl\n"
+        "4: targets = {foo()::Foo::Bar}\n"},
+       {R"cpp(
             void foo() {
               struct $0^Baz {
                 int $1^Field;
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -432,10 +432,13 @@
         Outer.add(OIT->getDecl(), Flags);
       }
       void VisitObjCObjectType(const ObjCObjectType *OOT) {
-        // FIXME: ObjCObjectTypeLoc has no children for the protocol list, so
-        // there is no node in id<Foo> that refers to ObjCProtocolDecl Foo.
-        if (OOT->isObjCQualifiedId() && OOT->getNumProtocols() == 1)
-          Outer.add(OOT->getProtocol(0), Flags);
+        // Make all of the protocols targets since there's no child nodes for
+        // protocols. This isn't needed for the base type, which *does* have a
+        // child `ObjCInterfaceTypeLoc`. This structure is a hack, but it works
+        // well for go-to-definition.
+        unsigned NumProtocols = OOT->getNumProtocols();
+        for (unsigned I = 0; I < NumProtocols; I++)
+          Outer.add(OOT->getProtocol(I), Flags);
       }
     };
     Visitor(*this, Flags).Visit(T.getTypePtr());
@@ -813,30 +816,34 @@
     Visitor(const HeuristicResolver *Resolver) : Resolver(Resolver) {}
 
     const HeuristicResolver *Resolver;
-    llvm::Optional<ReferenceLoc> Ref;
+    llvm::SmallVector<ReferenceLoc> Refs;
 
     void VisitElaboratedTypeLoc(ElaboratedTypeLoc L) {
       // We only know about qualifier, rest if filled by inner locations.
+      size_t InitialSize = Refs.size();
       Visit(L.getNamedTypeLoc().getUnqualifiedLoc());
-      // Fill in the qualifier.
-      if (!Ref)
-        return;
-      assert(!Ref->Qualifier.hasQualifier() && "qualifier already set");
-      Ref->Qualifier = L.getQualifierLoc();
+      size_t NewSize = Refs.size();
+      // Add qualifier for the newly-added refs.
+      for (unsigned I = InitialSize; I < NewSize; ++I) {
+        ReferenceLoc *Ref = &Refs[I];
+        // Fill in the qualifier.
+        assert(!Ref->Qualifier.hasQualifier() && "qualifier already set");
+        Ref->Qualifier = L.getQualifierLoc();
+      }
     }
 
     void VisitTagTypeLoc(TagTypeLoc L) {
-      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
-                         L.getNameLoc(),
-                         /*IsDecl=*/false,
-                         {L.getDecl()}};
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  L.getNameLoc(),
+                                  /*IsDecl=*/false,
+                                  {L.getDecl()}});
     }
 
     void VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc L) {
-      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
-                         L.getNameLoc(),
-                         /*IsDecl=*/false,
-                         {L.getDecl()}};
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  L.getNameLoc(),
+                                  /*IsDecl=*/false,
+                                  {L.getDecl()}});
     }
 
     void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc L) {
@@ -848,63 +855,71 @@
       //    1. valias with mask 'Alias'.
       //    2. 'vector<int>' with mask 'Underlying'.
       //  we want to return only #1 in this case.
-      Ref = ReferenceLoc{
+      Refs.push_back(ReferenceLoc{
           NestedNameSpecifierLoc(), L.getTemplateNameLoc(), /*IsDecl=*/false,
           explicitReferenceTargets(DynTypedNode::create(L.getType()),
-                                   DeclRelation::Alias, Resolver)};
+                                   DeclRelation::Alias, Resolver)});
     }
     void VisitDeducedTemplateSpecializationTypeLoc(
         DeducedTemplateSpecializationTypeLoc L) {
-      Ref = ReferenceLoc{
+      Refs.push_back(ReferenceLoc{
           NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
           explicitReferenceTargets(DynTypedNode::create(L.getType()),
-                                   DeclRelation::Alias, Resolver)};
+                                   DeclRelation::Alias, Resolver)});
     }
 
     void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
-      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
-                         TL.getNameLoc(),
-                         /*IsDecl=*/false,
-                         {TL.getDecl()}};
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  TL.getNameLoc(),
+                                  /*IsDecl=*/false,
+                                  {TL.getDecl()}});
     }
 
     void VisitDependentTemplateSpecializationTypeLoc(
         DependentTemplateSpecializationTypeLoc L) {
-      Ref = ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(),
-                         /*IsDecl=*/false,
-                         explicitReferenceTargets(
-                             DynTypedNode::create(L.getType()), {}, Resolver)};
+      Refs.push_back(
+          ReferenceLoc{L.getQualifierLoc(), L.getTemplateNameLoc(),
+                       /*IsDecl=*/false,
+                       explicitReferenceTargets(
+                           DynTypedNode::create(L.getType()), {}, Resolver)});
     }
 
     void VisitDependentNameTypeLoc(DependentNameTypeLoc L) {
-      Ref = ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(), /*IsDecl=*/false,
-                         explicitReferenceTargets(
-                             DynTypedNode::create(L.getType()), {}, Resolver)};
+      Refs.push_back(
+          ReferenceLoc{L.getQualifierLoc(), L.getNameLoc(),
+                       /*IsDecl=*/false,
+                       explicitReferenceTargets(
+                           DynTypedNode::create(L.getType()), {}, Resolver)});
     }
 
     void VisitTypedefTypeLoc(TypedefTypeLoc L) {
-      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
-                         L.getNameLoc(),
-                         /*IsDecl=*/false,
-                         {L.getTypedefNameDecl()}};
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  L.getNameLoc(),
+                                  /*IsDecl=*/false,
+                                  {L.getTypedefNameDecl()}});
     }
 
     void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc L) {
-      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
-                         L.getNameLoc(),
-                         /*IsDecl=*/false,
-                         {L.getIFaceDecl()}};
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  L.getNameLoc(),
+                                  /*IsDecl=*/false,
+                                  {L.getIFaceDecl()}});
     }
 
-    // FIXME: add references to protocols in ObjCObjectTypeLoc and maybe
-    // ObjCObjectPointerTypeLoc.
+    void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc L) {
+      unsigned NumProtocols = L.getNumProtocols();
+      for (unsigned I = 0; I < NumProtocols; I++) {
+        Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                    L.getProtocolLoc(I),
+                                    /*IsDecl=*/false,
+                                    {L.getProtocol(I)}});
+      }
+    }
   };
 
   Visitor V{Resolver};
   V.Visit(L.getUnqualifiedLoc());
-  if (!V.Ref)
-    return {};
-  return {*V.Ref};
+  return V.Refs;
 }
 
 class ExplicitReferenceCollector
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to