[cfe-commits] r111918 - in /cfe/trunk: lib/Sema/SemaCodeComplete.cpp test/Index/complete-blocks.m

Douglas Gregor dgregor at apple.com
Tue Aug 24 09:15:59 PDT 2010


Author: dgregor
Date: Tue Aug 24 11:15:59 2010
New Revision: 111918

URL: http://llvm.org/viewvc/llvm-project?rev=111918&view=rev
Log:
When providing completions for a function or method argument that
corresponds to a block pointer, provide the skeleton of a block
literal.

Added:
    cfe/trunk/test/Index/complete-blocks.m
Modified:
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=111918&r1=111917&r2=111918&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Aug 24 11:15:59 2010
@@ -1690,6 +1690,102 @@
     }
 }
 
+static std::string FormatFunctionParameter(ASTContext &Context,
+                                           ParmVarDecl *Param) {
+  bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
+  if (Param->getType()->isDependentType() ||
+      !Param->getType()->isBlockPointerType()) {
+    // The argument for a dependent or non-block parameter is a placeholder 
+    // containing that parameter's type.
+    std::string Result;
+    
+    if (Param->getIdentifier() && !ObjCMethodParam)
+      Result = Param->getIdentifier()->getName();
+    
+    Param->getType().getAsStringInternal(Result, 
+                                         Context.PrintingPolicy);
+    
+    if (ObjCMethodParam) {
+      Result = "(" + Result;
+      Result += ")";
+      if (Param->getIdentifier())
+        Result += Param->getIdentifier()->getName();
+    }
+    return Result;
+  }
+  
+  // The argument for a block pointer parameter is a block literal with
+  // the appropriate type.
+  FunctionProtoTypeLoc *Block = 0;
+  TypeLoc TL;
+  if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
+    TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
+    while (true) {
+      // Look through typedefs.
+      if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
+        if (TypeSourceInfo *InnerTSInfo
+            = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
+          TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
+          continue;
+        }
+      }
+      
+      // Look through qualified types
+      if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
+        TL = QualifiedTL->getUnqualifiedLoc();
+        continue;
+      }
+      
+      // Try to get the function prototype behind the block pointer type,
+      // then we're done.
+      if (BlockPointerTypeLoc *BlockPtr
+          = dyn_cast<BlockPointerTypeLoc>(&TL)) {
+        TL = BlockPtr->getPointeeLoc();
+        Block = dyn_cast<FunctionProtoTypeLoc>(&TL);
+      }
+      break;
+    }
+  }
+
+  if (!Block) {
+    // We were unable to find a FunctionProtoTypeLoc with parameter names
+    // for the block; just use the parameter type as a placeholder.
+    std::string Result;
+    Param->getType().getUnqualifiedType().
+                            getAsStringInternal(Result, Context.PrintingPolicy);
+    
+    if (ObjCMethodParam) {
+      Result = "(" + Result;
+      Result += ")";
+      if (Param->getIdentifier())
+        Result += Param->getIdentifier()->getName();
+    }
+      
+    return Result;
+  }
+  
+  // We have the function prototype behind the block pointer type, as it was
+  // written in the source.
+  std::string Result = "(^)(";
+  for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
+    if (I)
+      Result += ", ";
+    Result += FormatFunctionParameter(Context, Block->getArg(I));
+  }
+  if (Block->getTypePtr()->isVariadic()) {
+    if (Block->getNumArgs() > 0)
+      Result += ", ...";
+    else
+      Result += "...";
+  } else if (Block->getNumArgs() == 0 && !Context.getLangOptions().CPlusPlus)
+    Result += "void";
+             
+  Result += ")";
+  Block->getTypePtr()->getResultType().getAsStringInternal(Result, 
+                                                        Context.PrintingPolicy);
+  return Result;
+}
+
 /// \brief Add function parameter chunks to the given code completion string.
 static void AddFunctionParameterChunks(ASTContext &Context,
                                        FunctionDecl *Function,
@@ -1713,13 +1809,8 @@
       CCStr->AddChunk(Chunk(CodeCompletionString::CK_Comma));
     
     // Format the placeholder string.
-    std::string PlaceholderStr;
-    if (Param->getIdentifier())
-      PlaceholderStr = Param->getIdentifier()->getName();
-    
-    Param->getType().getAsStringInternal(PlaceholderStr, 
-                                         Context.PrintingPolicy);
-    
+    std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
+        
     // Add the placeholder string.
     CCStr->AddPlaceholderChunk(PlaceholderStr);
   }
@@ -2028,10 +2119,16 @@
         continue;
 
       std::string Arg;
-      (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
-      Arg = "(" + Arg + ")";
-      if (IdentifierInfo *II = (*P)->getIdentifier())
-        Arg += II->getName().str();
+      
+      if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
+        Arg = FormatFunctionParameter(S.Context, *P);
+      else {
+        (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
+        Arg = "(" + Arg + ")";
+        if (IdentifierInfo *II = (*P)->getIdentifier())
+          Arg += II->getName().str();
+      }
+      
       if (DeclaringEntity)
         Result->AddTextChunk(Arg);
       else if (AllParametersAreInformative)

Added: cfe/trunk/test/Index/complete-blocks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-blocks.m?rev=111918&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-blocks.m (added)
+++ cfe/trunk/test/Index/complete-blocks.m Tue Aug 24 11:15:59 2010
@@ -0,0 +1,24 @@
+// The line and column layout of this test is significant. Run lines
+// are at the end.
+typedef void (^block_t)(float f, double d);
+void f(int (^block)(int x, int y));
+void g(block_t b);
+
+void test_f() {
+
+}
+
+ at interface A
+- method:(int (^)(int x, int y))b;
+- method2:(block_t)b;
+ at end
+
+void test_A(A *a) {
+  [a method:0];
+}
+// RUN: c-index-test -code-completion-at=%s:8:1 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText f}{LeftParen (}{Placeholder int (^)(int x, int y)}{RightParen )} (50)
+// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{Placeholder void (^)(float f, double d)}{RightParen )} (50)
+// RUN: c-index-test -code-completion-at=%s:17:6 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType id}{TypedText method2:}{Placeholder void (^)(float f, double d)} (20)
+// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType id}{TypedText method:}{Placeholder int (^)(int x, int y)} (20)





More information about the cfe-commits mailing list