[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
llvm-svn: 286363
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 445b8b4..9f770ce 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -3612,6 +3612,44 @@
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 @@
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);
+ // 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);
- // 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));
- 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);
- }
+ Results.MaybeAddResult(
+ Result(Builder.TakeString(), P,
+ Results.getBasePriority(P) + CCD_BlockPropertySetter),
+ CurContext);
}
}