From 416b575edcdb9287fdf7c9cbcdc7ec520aa610d4 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 25 Aug 2010 01:08:01 +0000 Subject: [PATCH] When performing completions involving Objective-C method declarations (e.g., for message sends or method declaration/definition completions), adjust methods that come from a base class. llvm-svn: 112013 --- clang/lib/Sema/SemaCodeComplete.cpp | 49 ++++++++++++++++-------- clang/test/Index/complete-method-decls.m | 4 +- clang/test/Index/complete-objc-message.m | 15 ++++++++ 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 9ed73dc8c844..b3948dba1e92 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3506,7 +3506,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container, IdentifierInfo **SelIdents, unsigned NumSelIdents, DeclContext *CurContext, - ResultBuilder &Results) { + ResultBuilder &Results, + bool InOriginalClass = true) { typedef CodeCompleteConsumer::Result Result; for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), MEnd = Container->meth_end(); @@ -3520,6 +3521,8 @@ static void AddObjCMethods(ObjCContainerDecl *Container, Result R = Result(*M, 0); R.StartParameter = NumSelIdents; R.AllParametersAreInformative = (WantKind != MK_Any); + if (!InOriginalClass) + R.Priority += CCD_InBaseClass; Results.MaybeAddResult(R, CurContext); } } @@ -3534,13 +3537,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container, E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, - CurContext, Results); + CurContext, Results, false); // Add methods in categories. for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; CatDecl = CatDecl->getNextClassCategory()) { AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, InOriginalClass); // Add a categories protocol methods. const ObjCList &Protocols @@ -3549,23 +3552,23 @@ static void AddObjCMethods(ObjCContainerDecl *Container, E = Protocols.end(); I != E; ++I) AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, false); // Add methods in category implementations. if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, InOriginalClass); } // Add methods in superclass. if (IFace->getSuperClass()) AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, - SelIdents, NumSelIdents, CurContext, Results); + SelIdents, NumSelIdents, CurContext, Results, false); // Add methods in our implementation, if any. if (ObjCImplementationDecl *Impl = IFace->getImplementation()) AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, - NumSelIdents, CurContext, Results); + NumSelIdents, CurContext, Results, InOriginalClass); } @@ -4326,7 +4329,10 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, Results.data(),Results.size()); } -typedef llvm::DenseMap KnownMethodsMap; +// Mapping from selectors to the methods that implement that selector, along +// with the "in original class" flag. +typedef llvm::DenseMap > + KnownMethodsMap; /// \brief Find all of the methods that reside in the given container /// (and its superclasses, protocols, etc.) that meet the given @@ -4337,7 +4343,8 @@ static void FindImplementableMethods(ASTContext &Context, bool WantInstanceMethods, QualType ReturnType, bool IsInImplementation, - KnownMethodsMap &KnownMethods) { + KnownMethodsMap &KnownMethods, + bool InOriginalClass = true) { if (ObjCInterfaceDecl *IFace = dyn_cast(Container)) { // Recurse into protocols. const ObjCList &Protocols @@ -4346,14 +4353,16 @@ static void FindImplementableMethods(ASTContext &Context, E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + InOriginalClass); // If we're not in the implementation of a class, also visit the // superclass. if (!IsInImplementation && IFace->getSuperClass()) FindImplementableMethods(Context, IFace->getSuperClass(), WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + false); // Add methods from any class extensions (but not from categories; // those should go into category implementations). @@ -4361,7 +4370,8 @@ static void FindImplementableMethods(ASTContext &Context, Cat = Cat->getNextClassExtension()) FindImplementableMethods(Context, const_cast(Cat), WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + InOriginalClass); } if (ObjCCategoryDecl *Category = dyn_cast(Container)) { @@ -4372,7 +4382,8 @@ static void FindImplementableMethods(ASTContext &Context, E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, + InOriginalClass); } if (ObjCProtocolDecl *Protocol = dyn_cast(Container)) { @@ -4383,7 +4394,7 @@ static void FindImplementableMethods(ASTContext &Context, E = Protocols.end(); I != E; ++I) FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, - IsInImplementation, KnownMethods); + IsInImplementation, KnownMethods, false); } // Add methods in this container. This operation occurs last because @@ -4397,7 +4408,7 @@ static void FindImplementableMethods(ASTContext &Context, !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType())) continue; - KnownMethods[(*M)->getSelector()] = *M; + KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass); } } } @@ -4470,7 +4481,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, for (KnownMethodsMap::iterator M = KnownMethods.begin(), MEnd = KnownMethods.end(); M != MEnd; ++M) { - ObjCMethodDecl *Method = M->second; + ObjCMethodDecl *Method = M->second.first; CodeCompletionString *Pattern = new CodeCompletionString; // If the result type was not already provided, add it to the @@ -4538,7 +4549,11 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Pattern->AddChunk(CodeCompletionString::CK_RightBrace); } - Results.AddResult(Result(Pattern, CCP_CodePattern, + unsigned Priority = CCP_CodePattern; + if (!M->second.second) + Priority += CCD_InBaseClass; + + Results.AddResult(Result(Pattern, Priority, Method->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl)); diff --git a/clang/test/Index/complete-method-decls.m b/clang/test/Index/complete-method-decls.m index 5a5ee6963ab6..1324ae4a6970 100644 --- a/clang/test/Index/complete-method-decls.m +++ b/clang/test/Index/complete-method-decls.m @@ -78,10 +78,10 @@ // CHECK-CC3: ObjCInstanceMethodDecl:{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x} // CHECK-CC3: ObjCInstanceMethodDecl:{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y} // RUN: c-index-test -code-completion-at=%s:33:3 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s -// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc} +// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Text return}{HorizontalSpace }{Placeholder expression}{SemiColon ;}{VerticalSpace }{RightBrace }} (32) // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace -// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}{HorizontalSpace }{LeftBrace {}{VerticalSpace +// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Text return}{HorizontalSpace }{Placeholder expression}{SemiColon ;}{VerticalSpace }{RightBrace }} (30) // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{Text second}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace }{LeftBrace {}{VerticalSpace // CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText setValue}{Colon :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace diff --git a/clang/test/Index/complete-objc-message.m b/clang/test/Index/complete-objc-message.m index 450ad0491bd0..54f62a045db3 100644 --- a/clang/test/Index/complete-objc-message.m +++ b/clang/test/Index/complete-objc-message.m @@ -122,6 +122,18 @@ void msg_id(id x) { [id Method:1 Arg1:1 OtherArg:ovl]; } +@interface A +- (void)method1; +@end + +@interface B : A +- (void)method2; +@end + +void test_ranking(B *b) { + [b method1]; +} + // RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: {TypedText categoryClassMethod} // CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)a}{HorizontalSpace }{Text withKeyword:}{Placeholder (int)b} @@ -228,3 +240,6 @@ void msg_id(id x) { // CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText new} // CHECK-CCH: ObjCClassMethodDecl:{ResultType int}{TypedText OtherMethod:}{Placeholder (float)f}{HorizontalSpace }{Text Arg1:}{Placeholder (int)i1}{HorizontalSpace }{Text Arg2:}{Placeholder (int)i2} // CHECK-CCH: ObjCClassMethodDecl:{ResultType id}{TypedText protocolClassMethod} +// 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) -- GitLab