Don't format the code completion for parameters of block literal

arguments as block literal arguments; the block literal argument code
completion should only go one level deep. Fixes <rdar://problem/10291294>.

llvm-svn: 142335
This commit is contained in:
Douglas Gregor 2011-10-18 04:23:19 +00:00
parent bab66789d5
commit d793e7c3f7
2 changed files with 60 additions and 27 deletions

View File

@ -1966,7 +1966,8 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
static std::string FormatFunctionParameter(ASTContext &Context,
const PrintingPolicy &Policy,
ParmVarDecl *Param,
bool SuppressName = false) {
bool SuppressName = false,
bool SuppressBlock = false) {
bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
if (Param->getType()->isDependentType() ||
!Param->getType()->isBlockPointerType()) {
@ -1997,20 +1998,22 @@ static std::string FormatFunctionParameter(ASTContext &Context,
TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
while (true) {
// Look through typedefs.
if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
if (TypeSourceInfo *InnerTSInfo
= TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
if (!SuppressBlock) {
if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
if (TypeSourceInfo *InnerTSInfo
= TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
continue;
}
}
// Look through qualified types
if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
TL = QualifiedTL->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
@ -2027,6 +2030,9 @@ static std::string FormatFunctionParameter(ASTContext &Context,
// We were unable to find a FunctionProtoTypeLoc with parameter names
// for the block; just use the parameter type as a placeholder.
std::string Result;
if (!ObjCMethodParam && Param->getIdentifier())
Result = Param->getIdentifier()->getName();
Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
if (ObjCMethodParam) {
@ -2038,36 +2044,52 @@ static std::string FormatFunctionParameter(ASTContext &Context,
return Result;
}
// We have the function prototype behind the block pointer type, as it was
// written in the source.
std::string Result;
QualType ResultType = Block->getTypePtr()->getResultType();
if (!ResultType->isVoidType())
if (!ResultType->isVoidType() || SuppressBlock)
ResultType.getAsStringInternal(Result, Policy);
Result = '^' + Result;
// Format the parameter list.
std::string Params;
if (!BlockProto || Block->getNumArgs() == 0) {
if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Result += "(...)";
Params = "(...)";
else
Result += "(void)";
Params = "(void)";
} else {
Result += "(";
Params += "(";
for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
if (I)
Result += ", ";
Result += FormatFunctionParameter(Context, Policy, Block->getArg(I));
Params += ", ";
Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
/*SuppressName=*/false,
/*SuppressBlock=*/true);
if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Result += ", ...";
Params += ", ...";
}
Result += ")";
Params += ")";
}
if (SuppressBlock) {
// Format as a parameter.
Result = Result + " (^";
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
Result += ")";
Result += Params;
} else {
// Format as a block literal argument.
Result = '^' + Result;
Result += Params;
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
}
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
return Result;
}

View File

@ -26,14 +26,22 @@ void test_B(B *b) {
}
@interface C
- method4:(void(^)(void))arg { };
- method5:(void(^)())arg5 { };
- method4:(void(^)(void))arg;
- method5:(void(^)())arg5;
@end
void test_C(C *c) {
[c method4:^{}];
}
@interface D
- method6:(void(^)(block_t block))arg;
@end
void test_D(D *d) {
[d method6: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)block}{RightParen )} (50)
// CHECK-CC1: FunctionDecl:{ResultType void}{TypedText g}{LeftParen (}{Placeholder ^(float f, double d)b}{RightParen )} (50)
@ -51,3 +59,6 @@ void test_C(C *c) {
// CHECK-CC5-NOT: test_A
// CHECK-CC5: {TypedText union} (50)
// RUN: c-index-test -code-completion-at=%s:42:6 %s | FileCheck -check-prefix=CHECK-CC6 %s
// CHECK-CC6: ObjCInstanceMethodDecl:{ResultType id}{TypedText method6:}{Placeholder ^(block_t block)arg} (35)