]> granicus.if.org Git - clang/commitdiff
[libclang] Implement proper code-completion in an ObjC type parameter position.
authorDouglas Gregor <dgregor@apple.com>
Tue, 7 Jul 2015 06:20:36 +0000 (06:20 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 7 Jul 2015 06:20:36 +0000 (06:20 +0000)
rdar://19670303

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@241561 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Type.h
lib/AST/Type.cpp
lib/Parse/ParseObjc.cpp
test/Index/complete-parameterized-classes.m

index 18d054733da14e9ed69df09ce60a94b608d805fe..632d4b95e3761656e581133505847413c29fd38e 100644 (file)
@@ -1942,6 +1942,10 @@ public:
   Optional<ArrayRef<QualType>>
   getObjCSubstitutions(const DeclContext *dc) const;
 
+  /// Determines if this is an ObjC interface type that may accept type
+  /// parameters.
+  bool acceptsObjCTypeParams() const;
+
   const char *getTypeClassName() const;
 
   QualType getCanonicalTypeInternal() const {
index 5a60655bf4846504b0aa5f61f14fe07e219c4e32..cee5fee83913e95de7efb52365a10cf1e5b0740b 100644 (file)
@@ -1339,6 +1339,17 @@ Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
   return objectType->getTypeArgs();
 }
 
+bool Type::acceptsObjCTypeParams() const {
+  if (auto *IfaceT = getAsObjCInterfaceType()) {
+    if (auto *ID = IfaceT->getInterface()) {
+      if (ID->getTypeParamList())
+        return true;
+    }
+  }
+
+  return false;
+}
+
 void ObjCObjectType::computeSuperClassTypeSlow() const {
   // Retrieve the class declaration for this type. If there isn't one
   // (e.g., this is some variant of "id" or "Class"), then there is no
index 4f16d47dfa758fb02160a74fca8f55b9ba762dd0..ed6090453daa954791129cd4357e2386b3e2220e 100644 (file)
@@ -1658,8 +1658,13 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers(
                                                        identifierLocs[i]));
       }
 
-      Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs.data(),
-                                                 identifierLocPairs.size());
+      QualType BaseT = Actions.GetTypeFromParser(baseType);
+      if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
+        Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
+      } else {
+        Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs.data(),
+                                                   identifierLocPairs.size());
+      }
       cutOffParsing();
       return;
     }
index c7d273ac1ef799d885c716dc46f56635e7a673fc..70d85885e3b7e0588e4dd83485c4715bce59bacf 100644 (file)
@@ -37,6 +37,11 @@ void test2(Test *obj) {
 -(id)getit:(id)val {}
 @end
 
+void test3() {
+  Test<> t;
+  NSObject<> n;
+}
+
 // RUN: c-index-test -code-completion-at=%s:25:8 %s | FileCheck -check-prefix=CHECK-CC0 %s
 // CHECK-CC0: ObjCInstanceMethodDecl:{ResultType void}{TypedText apply2:}{Placeholder ^(MyClsA *, MyClsB *)block} (35)
 // CHECK-CC0: ObjCInstanceMethodDecl:{ResultType void}{TypedText apply:}{Placeholder ^(MyClsA *, MyClsB *)block} (35)
@@ -64,3 +69,11 @@ void test2(Test *obj) {
 // CHECK-CC6: ObjCInstanceMethodDecl:{LeftParen (}{Text void}{RightParen )}{TypedText apply}{TypedText :}{LeftParen (}{Text void (^)(id, NSObject *)}{RightParen )}{Text block} (40)
 // CHECK-CC6: ObjCInstanceMethodDecl:{LeftParen (}{Text NSObject *}{RightParen )}{TypedText getit}{TypedText :}{LeftParen (}{Text id}{RightParen )}{Text val} (40)
 // CHECK-CC6: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText prop} (40)
+
+// RUN: c-index-test -code-completion-at=%s:41:8 %s | FileCheck -check-prefix=CHECK-CC7 %s
+// CHECK-CC7: ObjCInterfaceDecl:{TypedText MyClsA}
+// RUN: c-index-test -code-completion-at=%s:42:12 %s > %t.out
+// RUN: FileCheck -input-file=%t.out -check-prefix=CHECK-CC8 %s
+// RUN: FileCheck -input-file=%t.out -check-prefix=CHECK-CC9 %s
+// CHECK-CC8: ObjCProtocolDecl:{TypedText NSObject}
+// CHECK-CC9-NOT: ObjCInterfaceDecl:{TypedText MyClsA}