Support code completion for parameter names in Objective-C method
declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107933 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 576f149..16a1d46 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -3134,14 +3134,17 @@
DeclPtrTy IDecl) {
}
- /// \brief Code completion for a selector identifier within an Objective-C
- /// method declaration.
+ /// \brief Code completion for a selector identifier or argument name within
+ /// an Objective-C method declaration.
///
/// \param S The scope in which this code completion occurs.
///
/// \param IsInstanceMethod Whether we are parsing an instance method (or,
/// if false, a class method).
///
+ /// \param AtParameterName Whether the actual code completion point is at the
+ /// argument name.
+ ///
/// \param ReturnType If non-NULL, the specified return type of the method
/// being declared or defined.
///
@@ -3151,6 +3154,7 @@
/// \param NumSelIdents The number of identifiers provided by SelIdents.
virtual void CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
+ bool AtParameterName,
TypeTy *ReturnType,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) { }
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 79e432d..68473a5 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -856,6 +856,20 @@
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
ArgInfo.ArgAttrs = ParseGNUAttributes();
+ // Code completion for the next piece of the selector.
+ if (Tok.is(tok::code_completion)) {
+ ConsumeCodeCompletionToken();
+ KeyIdents.push_back(SelIdent);
+ Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
+ mType == tok::minus,
+ /*AtParameterName=*/true,
+ ReturnType,
+ KeyIdents.data(),
+ KeyIdents.size());
+ KeyIdents.pop_back();
+ break;
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing argument name.
break;
@@ -873,6 +887,7 @@
ConsumeCodeCompletionToken();
Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
mType == tok::minus,
+ /*AtParameterName=*/false,
ReturnType,
KeyIdents.data(),
KeyIdents.size());
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index f4f873d..1f948b6 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -4574,6 +4574,7 @@
DeclPtrTy IDecl);
virtual void CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
+ bool AtParameterName,
TypeTy *ReturnType,
IdentifierInfo **SelIdents,
unsigned NumSelIdents);
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 8df9eac..6a706df 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -4147,6 +4147,7 @@
void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
bool IsInstanceMethod,
+ bool AtParameterName,
TypeTy *ReturnTy,
IdentifierInfo **SelIdents,
unsigned NumSelIdents) {
@@ -4185,6 +4186,20 @@
NumSelIdents))
continue;
+ if (AtParameterName) {
+ // Suggest parameter names we've seen before.
+ if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
+ ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
+ if (Param->getIdentifier()) {
+ CodeCompletionString *Pattern = new CodeCompletionString;
+ Pattern->AddTypedTextChunk(Param->getIdentifier()->getName());
+ Results.AddResult(Pattern);
+ }
+ }
+
+ continue;
+ }
+
Result R(MethList->Method, 0);
R.StartParameter = NumSelIdents;
R.AllParametersAreInformative = false;
diff --git a/test/Index/complete-method-decls.m b/test/Index/complete-method-decls.m
index 802b360..a30874b 100644
--- a/test/Index/complete-method-decls.m
+++ b/test/Index/complete-method-decls.m
@@ -44,12 +44,12 @@
@interface C
- (int)first:(int)x second:(float)y third:(double)z;
-- (id)first:(int)x second2:(float)y third:(double)z;
-- (void*)first:(int)x second3:(float)y third:(double)z;
+- (id)first:(int)xx second2:(float)y2 third:(double)z;
+- (void*)first:(int)xxx second3:(float)y3 third:(double)z;
@end
@interface D
-- (int)first:(int)x second4:(float)y third:(double)z;
+- (int)first:(int)x second2:(float)y third:(double)z;
@end
// RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
@@ -90,8 +90,14 @@
// RUN: c-index-test -code-completion-at=%s:42:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC7 %s
// CHECK-CC7: NotImplemented:{LeftParen (}{Text id}{RightParen )}{TypedText categoryFunction}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
// RUN: c-index-test -code-completion-at=%s:52:21 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC8 %s
-// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y}{HorizontalSpace }{Text third:}{Text (double)z} (20)
-// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType void *}{Informative first:}{TypedText second3:}{Text (float)y}{HorizontalSpace }{Text third:}{Text (double)z} (20)
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{TypedText second2:}{Text (float)y2}{HorizontalSpace }{Text third:}{Text (double)z} (20)
+// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType void *}{Informative first:}{TypedText second3:}{Text (float)y3}{HorizontalSpace }{Text third:}{Text (double)z} (20)
// CHECK-CC8: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{TypedText second:}{Text (float)y}{HorizontalSpace }{Text third:}{Text (double)z} (5)
+// RUN: c-index-test -code-completion-at=%s:52:19 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC9 %s
+// CHECK-CC9: NotImplemented:{TypedText x} (30)
+// CHECK-CC9: NotImplemented:{TypedText xx} (30)
+// CHECK-CC9: NotImplemented:{TypedText xxx} (30)
+// RUN: c-index-test -code-completion-at=%s:52:36 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CCA %s
+// CHECK-CCA: NotImplemented:{TypedText y2} (30)