r286363 - [CodeCompletion] Show block invocation results for block property setters

Alex Lorenz via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 9 05:43:19 PST 2016


Author: arphaman
Date: Wed Nov  9 07:43:18 2016
New Revision: 286363

URL: http://llvm.org/viewvc/llvm-project?rev=286363&view=rev
Log:
[CodeCompletion] Show block invocation results for block property setters

This commit changes the code completion results for block property setters:
The default block property result is now a block invocation rather than a simple
property reference.

rdar://28846196

Differential Revision: https://reviews.llvm.org/D26071

Added:
    cfe/trunk/test/Index/complete-block-properties.m
Modified:
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-block-property-assignment.m

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=286363&r1=286362&r2=286363&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Nov  9 07:43:18 2016
@@ -3612,6 +3612,44 @@ static ObjCContainerDecl *getContainerDe
   return Container;
 }
 
+/// \brief Adds a block invocation code completion result for the given block
+/// declaration \p BD.
+static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
+                             CodeCompletionBuilder &Builder,
+                             const NamedDecl *BD,
+                             const FunctionTypeLoc &BlockLoc,
+                             const FunctionProtoTypeLoc &BlockProtoLoc) {
+  Builder.AddResultTypeChunk(
+      GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
+                              Policy, Builder.getAllocator()));
+
+  AddTypedNameChunk(Context, Policy, BD, Builder);
+  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
+
+  if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
+    Builder.AddPlaceholderChunk("...");
+  } else {
+    for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
+      if (I)
+        Builder.AddChunk(CodeCompletionString::CK_Comma);
+
+      // Format the placeholder string.
+      std::string PlaceholderStr =
+          FormatFunctionParameter(Policy, BlockLoc.getParam(I));
+
+      if (I == N - 1 && BlockProtoLoc &&
+          BlockProtoLoc.getTypePtr()->isVariadic())
+        PlaceholderStr += ", ...";
+
+      // Add the placeholder string.
+      Builder.AddPlaceholderChunk(
+          Builder.getAllocator().CopyString(PlaceholderStr));
+    }
+  }
+
+  Builder.AddChunk(CodeCompletionString::CK_RightParen);
+}
+
 static void AddObjCProperties(const CodeCompletionContext &CCContext,
                               ObjCContainerDecl *Container,
                               bool AllowCategories, bool AllowNullaryMethods,
@@ -3629,42 +3667,61 @@ static void AddObjCProperties(const Code
     if (!AddedProperties.insert(P->getIdentifier()).second)
       continue;
 
-    Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
-                           CurContext);
+    // FIXME: Provide block invocation completion for non-statement
+    // expressions.
+    if (!P->getType().getTypePtr()->isBlockPointerType() ||
+        !IsBaseExprStatement) {
+      Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
+                             CurContext);
+      continue;
+    }
+
+    // Block setter and invocation completion is provided only when we are able
+    // to find the FunctionProtoTypeLoc with parameter names for the block.
+    FunctionTypeLoc BlockLoc;
+    FunctionProtoTypeLoc BlockProtoLoc;
+    findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
+                                 BlockProtoLoc);
+    if (!BlockLoc) {
+      Results.MaybeAddResult(Result(P, Results.getBasePriority(P), nullptr),
+                             CurContext);
+      continue;
+    }
+
+    // The default completion result for block properties should be the block
+    // invocation completion when the base expression is a statement.
+    CodeCompletionBuilder Builder(Results.getAllocator(),
+                                  Results.getCodeCompletionTUInfo());
+    AddObjCBlockCall(Container->getASTContext(),
+                     getCompletionPrintingPolicy(Results.getSema()), Builder, P,
+                     BlockLoc, BlockProtoLoc);
+    Results.MaybeAddResult(
+        Result(Builder.TakeString(), P, Results.getBasePriority(P)),
+        CurContext);
 
     // Provide additional block setter completion iff the base expression is a
-    // statement.
-    if (!P->isReadOnly() && IsBaseExprStatement &&
-        P->getType().getTypePtr()->isBlockPointerType()) {
-      FunctionTypeLoc BlockLoc;
-      FunctionProtoTypeLoc BlockProtoLoc;
-      findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
-                                   BlockProtoLoc);
-
-      // Provide block setter completion only when we are able to find
-      // the FunctionProtoTypeLoc with parameter names for the block.
-      if (BlockLoc) {
-        CodeCompletionBuilder Builder(Results.getAllocator(),
-                                      Results.getCodeCompletionTUInfo());
-        AddResultTypeChunk(Container->getASTContext(),
-                           getCompletionPrintingPolicy(Results.getSema()), P,
-                           CCContext.getBaseType(), Builder);
-        Builder.AddTypedTextChunk(
-            Results.getAllocator().CopyString(P->getName()));
-        Builder.AddChunk(CodeCompletionString::CK_Equal);
-
-        std::string PlaceholderStr = formatBlockPlaceholder(
-            getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
-            BlockProtoLoc, /*SuppressBlockName=*/true);
-        // Add the placeholder string.
-        Builder.AddPlaceholderChunk(
-            Builder.getAllocator().CopyString(PlaceholderStr));
-
-        Results.MaybeAddResult(
-            Result(Builder.TakeString(), P,
-                   Results.getBasePriority(P) + CCD_BlockPropertySetter),
-            CurContext);
-      }
+    // statement and the block property is mutable.
+    if (!P->isReadOnly()) {
+      CodeCompletionBuilder Builder(Results.getAllocator(),
+                                    Results.getCodeCompletionTUInfo());
+      AddResultTypeChunk(Container->getASTContext(),
+                         getCompletionPrintingPolicy(Results.getSema()), P,
+                         CCContext.getBaseType(), Builder);
+      Builder.AddTypedTextChunk(
+          Results.getAllocator().CopyString(P->getName()));
+      Builder.AddChunk(CodeCompletionString::CK_Equal);
+
+      std::string PlaceholderStr = formatBlockPlaceholder(
+          getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
+          BlockProtoLoc, /*SuppressBlockName=*/true);
+      // Add the placeholder string.
+      Builder.AddPlaceholderChunk(
+          Builder.getAllocator().CopyString(PlaceholderStr));
+
+      Results.MaybeAddResult(
+          Result(Builder.TakeString(), P,
+                 Results.getBasePriority(P) + CCD_BlockPropertySetter),
+          CurContext);
     }
   }
 

Added: cfe/trunk/test/Index/complete-block-properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-block-properties.m?rev=286363&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-block-properties.m (added)
+++ cfe/trunk/test/Index/complete-block-properties.m Wed Nov  9 07:43:18 2016
@@ -0,0 +1,53 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+// Block invocations should be presented when completing properties in
+// standalone statements.
+// rdar://28846196
+
+typedef int Foo;
+typedef void (^FooBlock)(Foo *someParameter);
+typedef int (^BarBlock)(int *);
+
+ at interface Obj
+
+ at property (readwrite, nonatomic, copy) void (^block)();
+ at property (readonly, nonatomic, copy) int (^performA)();
+ at property (readonly, nonatomic, copy) int (^performB)(int x, int y);
+ at property (readwrite, nonatomic, copy) Foo (^blocker)(int x, Foo y, FooBlock foo);
+
+ at end
+
+
+ at interface Test : Obj
+
+ at property (readonly, nonatomic, copy) FooBlock fooBlock;
+ at property (readonly, nonatomic, copy) BarBlock barBlock;
+ at property (readonly, nonatomic, copy) Test * (^getObject)(int index);
+ at property (readwrite, nonatomic) int foo;
+
+ at end
+
+ at implementation Test
+
+- (void)test {
+  self.foo = 2;
+  int x = self.performA(); self.foo = 2;
+  self.getObject(0).foo = 2;
+}
+
+// RUN: c-index-test -code-completion-at=%s:34:8 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:35:33 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// RUN: c-index-test -code-completion-at=%s:36:21 %s | FileCheck -check-prefix=CHECK-CC1 %s
+//CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText barBlock}{LeftParen (}{Placeholder int *}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText block}{LeftParen (}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)()}{TypedText block}{Equal  = }{Placeholder ^(void)} (38)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo}{TypedText blocker}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder Foo y}{Comma , }{Placeholder ^(Foo *someParameter)foo}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Foo (^)(int, Foo, FooBlock)}{TypedText blocker}{Equal  = }{Placeholder ^Foo(int x, Foo y, FooBlock foo)} (38)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText fooBlock}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Test *}{TypedText getObject}{LeftParen (}{Placeholder int index}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performA}{LeftParen (}{RightParen )} (35)
+//CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType int}{TypedText performB}{LeftParen (}{Placeholder int x}{Comma , }{Placeholder int y}{RightParen )} (35)
+
+ at end

Modified: cfe/trunk/test/Index/complete-block-property-assignment.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-block-property-assignment.m?rev=286363&r1=286362&r2=286363&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-block-property-assignment.m (original)
+++ cfe/trunk/test/Index/complete-block-property-assignment.m Wed Nov  9 07:43:18 2016
@@ -35,11 +35,11 @@ typedef void (^FooBlock)(Foo *someParame
 // RUN: c-index-test -code-completion-at=%s:29:9 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText foo} (35)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType Obj *}{TypedText obj} (35)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onAction}{LeftParen (}{Placeholder Obj *object}{RightParen )} (35)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(Obj *)}{TypedText onAction}{Equal  = }{Placeholder ^(Obj *object)} (38)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onEventHandler}{LeftParen (}{Placeholder Foo *someParameter}{RightParen )} (35)
 // CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType FooBlock}{TypedText onEventHandler}{Equal  = }{Placeholder ^(Foo *someParameter)} (38)
-// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void (^)(int *)}{TypedText onReadonly} (35)
+// CHECK-CC1-NEXT: ObjCPropertyDecl:{ResultType void}{TypedText onReadonly}{LeftParen (}{Placeholder int *someParameter}{RightParen )} (35)
 
 - (void) takeInt:(int)x { }
 




More information about the cfe-commits mailing list