diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 576f14915d9462fb086eae5a1ec88597300eb736..16a1d46b13563e243852c86dd5410de01925a640 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -3134,14 +3134,17 @@ public: 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 @@ public: /// \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/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 79e432d611447a8e3f074fb9c6804ceafeaab72f..68473a551d1ab1489598d6c98acf3661b022e29b 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -856,6 +856,20 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, 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 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, ConsumeCodeCompletionToken(); Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(), mType == tok::minus, + /*AtParameterName=*/false, ReturnType, KeyIdents.data(), KeyIdents.size()); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index f4f873df2f3d27c330e63a5deae3072dcdf1f7b3..1f948b6624371ec67063a92f0d64729ada9fbcfb 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -4574,6 +4574,7 @@ public: DeclPtrTy IDecl); virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, + bool AtParameterName, TypeTy *ReturnType, IdentifierInfo **SelIdents, unsigned NumSelIdents); diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 8df9eace276d1e041a7160c24c1274be630ec0fe..6a706dfefe59a9dd76a5c8b805d54f4259547fae 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -4147,6 +4147,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, bool IsInstanceMethod, + bool AtParameterName, TypeTy *ReturnTy, IdentifierInfo **SelIdents, unsigned NumSelIdents) { @@ -4185,6 +4186,20 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, 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/clang/test/Index/complete-method-decls.m b/clang/test/Index/complete-method-decls.m index 802b360f0049ae8b2eeaeda5201764356feb54fd..a30874b8a28e24b35aa3f58377c55879e03ba809 100644 --- a/clang/test/Index/complete-method-decls.m +++ b/clang/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)