diff options
-rw-r--r-- | include/clang/Sema/CodeCompleteConsumer.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 74 | ||||
-rw-r--r-- | test/Index/complete-member-access.m | 17 |
3 files changed, 82 insertions, 14 deletions
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 882440b78c..d3221809b9 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -88,7 +88,10 @@ enum { /// \brief Adjustment for KVC code pattern priorities when it doesn't look /// like the - CCD_ProbablyNotObjCCollection = 15 + CCD_ProbablyNotObjCCollection = 15, + + /// \brief An Objective-C method being used as a property. + CCD_MethodAsProperty = 2 }; /// \brief Priority value factors by which we will divide or multiply the diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3673139acc..4989b2b414 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3078,6 +3078,7 @@ typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet; static void AddObjCProperties(ObjCContainerDecl *Container, bool AllowCategories, + bool AllowNullaryMethods, DeclContext *CurContext, AddedPropertiesSet &AddedProperties, ResultBuilder &Results) { @@ -3092,32 +3093,75 @@ static void AddObjCProperties(ObjCContainerDecl *Container, Results.MaybeAddResult(Result(*P, 0), CurContext); } + // Add nullary methods + if (AllowNullaryMethods) { + ASTContext &Context = Container->getASTContext(); + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if (M->getSelector().isUnarySelector()) + if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0)) + if (AddedProperties.insert(Name)) { + CodeCompletionBuilder Builder(Results.getAllocator()); + AddResultTypeChunk(Context, *M, Builder); + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString(Name->getName())); + + CXAvailabilityKind Availability = CXAvailability_Available; + switch (M->getAvailability()) { + case AR_Available: + case AR_NotYetIntroduced: + Availability = CXAvailability_Available; + break; + + case AR_Deprecated: + Availability = CXAvailability_Deprecated; + break; + + case AR_Unavailable: + Availability = CXAvailability_NotAvailable; + break; + } + + Results.MaybeAddResult(Result(Builder.TakeString(), + CCP_MemberDeclaration + CCD_MethodAsProperty, + M->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl, + Availability), + CurContext); + } + } + } + + // Add properties in referenced protocols. if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), PEnd = Protocol->protocol_end(); P != PEnd; ++P) - AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties, - Results); + AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ if (AllowCategories) { // Look through categories. for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category; Category = Category->getNextClassCategory()) - AddObjCProperties(Category, AllowCategories, CurContext, - AddedProperties, Results); + AddObjCProperties(Category, AllowCategories, AllowNullaryMethods, + CurContext, AddedProperties, Results); } // Look through protocols. for (ObjCInterfaceDecl::all_protocol_iterator I = IFace->all_referenced_protocol_begin(), E = IFace->all_referenced_protocol_end(); I != E; ++I) - AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties, - Results); + AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); // Look in the superclass. if (IFace->getSuperClass()) - AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext, + AddObjCProperties(IFace->getSuperClass(), AllowCategories, + AllowNullaryMethods, CurContext, AddedProperties, Results); } else if (const ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { @@ -3125,8 +3169,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container, for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), PEnd = Category->protocol_end(); P != PEnd; ++P) - AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties, - Results); + AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); } } @@ -3192,14 +3236,16 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, const ObjCObjectPointerType *ObjCPtr = BaseType->getAsObjCInterfacePointerType(); assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); - AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext, + AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, + /*AllowNullaryMethods=*/true, CurContext, AddedProperties, Results); // Add properties from the protocols in a qualified interface. for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(), E = ObjCPtr->qual_end(); I != E; ++I) - AddObjCProperties(*I, true, CurContext, AddedProperties, Results); + AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext, + AddedProperties, Results); } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || (!IsArrow && BaseType->isObjCObjectType())) { // Objective-C instance variable access. @@ -5334,11 +5380,13 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) { Results.EnterNewScope(); if (ObjCImplementationDecl *ClassImpl = dyn_cast<ObjCImplementationDecl>(Container)) - AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext, + AddObjCProperties(ClassImpl->getClassInterface(), false, + /*AllowNullaryMethods=*/false, CurContext, AddedProperties, Results); else AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(), - false, CurContext, AddedProperties, Results); + false, /*AllowNullaryMethods=*/false, CurContext, + AddedProperties, Results); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, diff --git a/test/Index/complete-member-access.m b/test/Index/complete-member-access.m index ad2998cbf1..bd68deb5d1 100644 --- a/test/Index/complete-member-access.m +++ b/test/Index/complete-member-access.m @@ -22,9 +22,26 @@ void test_props(Int* ptr) { ptr->IVar = 0; } +@interface Sub : Int +@property int myProp; + +- (int)myProp; +- (int)myOtherPropLikeThing; +- (int)myOtherNonPropThing:(int)value; +@end + +int test_more_props(Sub *s) { + return s.myOtherPropLikeThing; +} + // RUN: c-index-test -code-completion-at=%s:21:7 %s | FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText prop1} // CHECK-CC1: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} // RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CC2 %s // CHECK-CC2: ObjCIvarDecl:{ResultType int}{TypedText IVar} (35) // CHECK-CC2: ObjCIvarDecl:{ResultType int}{TypedText SuperIVar} (37) +// RUN: c-index-test -code-completion-at=%s:34:12 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37) +// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35) +// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35) +// CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35) |