]> granicus.if.org Git - clang/commitdiff
[completion] complete ObjC interface names in an expression
authorAlex Lorenz <arphaman@gmail.com>
Tue, 14 Nov 2017 01:46:24 +0000 (01:46 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 14 Nov 2017 01:46:24 +0000 (01:46 +0000)
Objective-C interfaces can be used in a class property expression.

rdar://26982192

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

lib/Frontend/ASTUnit.cpp
lib/Sema/SemaCodeComplete.cpp
test/Index/complete-interfaces.m

index 9eeec37a758f7a85daea02a69ef72baf4e6b9180..c69d3676de68b04952a611de68d0bf76c5957e54 100644 (file)
@@ -264,8 +264,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND,
       Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver);
     
     // In Objective-C, you can only be a subclass of another Objective-C class
-    if (isa<ObjCInterfaceDecl>(ND))
+    if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
+      // Objective-C interfaces can be used in a class property expression.
+      if (ID->getDefinition())
+        Contexts |= (1LL << CodeCompletionContext::CCC_Expression);
       Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName);
+    }
 
     // Deal with tag names.
     if (isa<EnumDecl>(ND)) {
index 26004cf3c36e1c0fa0318f0ff72dc84ea524f729..7ee24b114cc1166e084a0375383927f254a8a20e 100644 (file)
@@ -1082,9 +1082,16 @@ bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
 /// ordinary name lookup but is not a type name.
 bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
   ND = cast<NamedDecl>(ND->getUnderlyingDecl());
-  if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
+  if (isa<TypeDecl>(ND))
     return false;
-  
+  // Objective-C interfaces names are not filtered by this method because they
+  // can be used in a class property expression. We can still filter out
+  // @class declarations though.
+  if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
+    if (!ID->getDefinition())
+      return false;
+  }
+
   unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
   if (SemaRef.getLangOpts().CPlusPlus)
     IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
index 2f86c3d8f43cf47acaa7d5cc10ad721b56787287..3e90407c78d7c7c383447a35d8c2f24c2c64d797 100644 (file)
 
 
 // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:11:12 %s | FileCheck -check-prefix=CHECK-CC2 %s
+
+
+void useClasses() {
+  int i = 0;
+  [Int3 message:1];
+}
+
+// RUN: c-index-test -code-completion-at=%s:51:11 %s | FileCheck -check-prefix=CHECK-USE %s
+// RUN: c-index-test -code-completion-at=%s:52:17 %s | FileCheck -check-prefix=CHECK-USE %s
+// CHECK-USE: ObjCInterfaceDecl:{TypedText Int2} (50)
+// CHECK-USE: ObjCInterfaceDecl:{TypedText Int3} (50)
+// CHECK-USE-NOT: Int1
+// CHECK-USE-NOT: Int4
+
+// Caching should work too:
+// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:51:11 %s | FileCheck -check-prefix=CHECK-USE %s