aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-09-15 16:23:04 +0000
committerDouglas Gregor <dgregor@apple.com>2010-09-15 16:23:04 +0000
commit78edf515544f0b9dddf69d6c1678fd83e94d8352 (patch)
treeebbc3d8638d96124c58b1136d6541d5932efe3c8
parent5f81d8aa26ad4de6568772c4768b272af96c18be (diff)
Improve code completion for Objective-C message sends when the opening
'[' is missing. Prior commits improving recovery also improved code completion beyond the first selector, e.g., at or after the "to" in calculator add:x to:y but not after "calculator". We now provide the same completions for calculator <CC> that we would for [calculator <CC> if "calculator" is an expression whose type is something that can receive Objective-C messages. This code completion works for instance and super message sends, but not class message sends. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113976 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h13
-rw-r--r--lib/Parse/ParseExpr.cpp19
-rw-r--r--lib/Sema/SemaCodeComplete.cpp23
-rw-r--r--test/Index/complete-objc-message.m11
-rw-r--r--test/Index/complete-super.m6
5 files changed, 44 insertions, 28 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index abdd083779..8b8f2d82c0 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4313,6 +4313,7 @@ public:
void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
SourceLocation OpLoc,
bool IsArrow);
+ void CodeCompletePostfixExpression(Scope *S, Expr *LHS);
void CodeCompleteTag(Scope *S, unsigned TagSpec);
void CodeCompleteTypeQualifiers(DeclSpec &DS);
void CodeCompleteCase(Scope *S);
@@ -4351,18 +4352,12 @@ public:
unsigned NumSelIdents);
void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- void CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
- IdentifierInfo **SelIdents,
unsigned NumSelIdents,
- bool IsSuper);
+ bool IsSuper = false);
void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
IdentifierInfo **SelIdents,
- unsigned NumSelIdents);
- void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
- IdentifierInfo **SelIdents,
- unsigned NumSelIdents,
- bool IsSuper);
+ unsigned NumSelIdents,
+ bool IsSuper = false);
void CodeCompleteObjCForCollection(Scope *S,
DeclGroupPtrTy IterationVar);
void CodeCompleteObjCSelector(Scope *S,
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 0f9154827e..26563de2b2 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -664,12 +664,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
}
// In an Objective-C method, if we have "super" followed by an identifier,
- // the token sequence is ill-fomed. However, if there's a ':' or ']' after
+ // the token sequence is ill-formed. However, if there's a ':' or ']' after
// that identifier, this is probably a message send with a missing open
- // bracket. Treat it as such.
- if (getLang().ObjC1 && &II == Ident_super && Tok.is(tok::identifier) &&
+ // bracket. Treat it as such.
+ if (getLang().ObjC1 && &II == Ident_super && !InMessageExpression &&
getCurScope()->isInObjcMethodScope() &&
- (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
+ ((Tok.is(tok::identifier) &&
+ (NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
+ Tok.is(tok::code_completion))) {
Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
0);
break;
@@ -991,6 +993,15 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
SourceLocation Loc;
while (1) {
switch (Tok.getKind()) {
+ case tok::code_completion:
+ if (InMessageExpression)
+ return move(LHS);
+
+ Actions.CodeCompletePostfixExpression(getCurScope(), LHS.take());
+ ConsumeCodeCompletionToken();
+ LHS = ExprError();
+ break;
+
case tok::identifier:
// If we see identifier: after an expression, and we're not already in a
// message send, then this is probably a message send with a missing
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 7dc2cb3609..fd6b5518d7 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -2728,6 +2728,10 @@ void Sema::CodeCompleteExpression(Scope *S,
Results.data(),Results.size());
}
+void Sema::CodeCompletePostfixExpression(Scope *S, Expr *E) {
+ if (getLangOptions().ObjC1)
+ CodeCompleteObjCInstanceMessage(S, E, 0, 0, false);
+}
static void AddObjCProperties(ObjCContainerDecl *Container,
bool AllowCategories,
@@ -4014,7 +4018,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) {
/// common uses of Objective-C. This routine returns that class type,
/// or NULL if no better result could be determined.
static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
- ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E);
+ ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
if (!Msg)
return 0;
@@ -4280,12 +4284,6 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
IdentifierInfo **SelIdents,
- unsigned NumSelIdents) {
- CodeCompleteObjCClassMessage(S, Receiver, SelIdents, NumSelIdents, false);
-}
-
-void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
- IdentifierInfo **SelIdents,
unsigned NumSelIdents,
bool IsSuper) {
typedef CodeCompletionResult Result;
@@ -4364,12 +4362,6 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
IdentifierInfo **SelIdents,
- unsigned NumSelIdents) {
- CodeCompleteObjCInstanceMessage(S, Receiver, SelIdents, NumSelIdents, false);
-}
-
-void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
- IdentifierInfo **SelIdents,
unsigned NumSelIdents,
bool IsSuper) {
typedef CodeCompletionResult Result;
@@ -4378,8 +4370,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
// If necessary, apply function/array conversion to the receiver.
// C99 6.7.5.3p[7,8].
- DefaultFunctionArrayLvalueConversion(RecExpr);
- QualType ReceiverType = RecExpr->getType();
+ if (RecExpr)
+ DefaultFunctionArrayLvalueConversion(RecExpr);
+ QualType ReceiverType = RecExpr? RecExpr->getType() : Context.getObjCIdType();
// Build the set of methods we can see.
ResultBuilder Results(*this);
diff --git a/test/Index/complete-objc-message.m b/test/Index/complete-objc-message.m
index f9d671037b..d6abd4bd83 100644
--- a/test/Index/complete-objc-message.m
+++ b/test/Index/complete-objc-message.m
@@ -132,6 +132,11 @@ void msg_id(id x) {
void test_ranking(B *b) {
[b method1];
+ b method1];
+}
+
+void test_overload_2(Overload *ovl) {
+ ovl Method:1 Arg1:1 OtherArg:ovl];
}
// RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
@@ -234,3 +239,9 @@ void test_ranking(B *b) {
// RUN: c-index-test -code-completion-at=%s:134:6 %s | FileCheck -check-prefix=CHECK-CCI %s
// CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method1} (22)
// CHECK-CCI: ObjCInstanceMethodDecl:{ResultType void}{TypedText method2} (20)
+
+// Test code completion with a missing opening bracket:
+// RUN: c-index-test -code-completion-at=%s:135:5 %s | FileCheck -check-prefix=CHECK-CCI %s
+// RUN: c-index-test -code-completion-at=%s:139:7 %s | FileCheck -check-prefix=CHECK-CC7 %s
+// RUN: c-index-test -code-completion-at=%s:139:16 %s | FileCheck -check-prefix=CHECK-CC8 %s
+// RUN: c-index-test -code-completion-at=%s:139:23 %s | FileCheck -check-prefix=CHECK-CC9 %s
diff --git a/test/Index/complete-super.m b/test/Index/complete-super.m
index fc60c6c42d..62267fa74f 100644
--- a/test/Index/complete-super.m
+++ b/test/Index/complete-super.m
@@ -22,6 +22,7 @@ typedef int Bool;
+ (void)select:(Bool)condition first:(int)a second:(int)b {
[super selector:condition first:a second:b];
+ super selector:condition first:a second:b];
}
@end
@@ -53,3 +54,8 @@ typedef int Bool;
// Check "super" completion at the third identifier
// RUN: c-index-test -code-completion-at=%s:24:37 %s | FileCheck -check-prefix=CHECK-SELECTOR-SECOND %s
// CHECK-SELECTOR-SECOND: ObjCClassMethodDecl:{ResultType void}{Informative select:}{Informative first:}{TypedText second:}{Placeholder b} (8)
+
+// Check "super" completion with missing '['.
+// RUN: c-index-test -code-completion-at=%s:25:10 %s | FileCheck -check-prefix=CHECK-SELECTOR-SELECTOR %s
+// RUN: c-index-test -code-completion-at=%s:25:28 %s | FileCheck -check-prefix=CHECK-SELECTOR-FIRST %s
+// RUN: c-index-test -code-completion-at=%s:25:37 %s | FileCheck -check-prefix=CHECK-SELECTOR-SECOND %s