Skip to content

Commit

Permalink
When code completion walks the members of a protocol or interface,
Browse files Browse the repository at this point in the history
make sure that we walk the definition. Fixes <rdar://problem/11427742>.

llvm-svn: 158357
  • Loading branch information
DougGregor committed Jun 12, 2012
1 parent 2ae781f commit 9b4f370
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 14 deletions.
58 changes: 45 additions & 13 deletions clang/lib/Sema/SemaCodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3334,14 +3334,35 @@ void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
/// property name.
typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;

static void AddObjCProperties(ObjCContainerDecl *Container,
/// \brief Retrieve the container definition, if any?
static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
if (Interface->hasDefinition())
return Interface->getDefinition();

return Interface;
}

if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition())
return Protocol->getDefinition();

return Protocol;
}
return Container;
}

static void AddObjCProperties(ObjCContainerDecl *Container,
bool AllowCategories,
bool AllowNullaryMethods,
DeclContext *CurContext,
AddedPropertiesSet &AddedProperties,
ResultBuilder &Results) {
typedef CodeCompletionResult Result;

// Retrieve the definition.
Container = getContainerDef(Container);

// Add properties in this container.
for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
PEnd = Container->prop_end();
Expand Down Expand Up @@ -3617,6 +3638,8 @@ void Sema::CodeCompleteCase(Scope *S) {
// Code-complete the cases of a switch statement over an enumeration type
// by providing the list of
EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
if (EnumDecl *Def = Enum->getDefinition())
Enum = Def;

// Determine which enumerators we have already seen in the switch statement.
// FIXME: Ideally, we would also be able to look *past* the code-completion
Expand Down Expand Up @@ -4695,6 +4718,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container,
ResultBuilder &Results,
bool InOriginalClass = true) {
typedef CodeCompletionResult Result;
Container = getContainerDef(Container);
for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
MEnd = Container->meth_end();
M != MEnd; ++M) {
Expand Down Expand Up @@ -5826,7 +5850,8 @@ void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
return;

// Ignore any properties that have already been implemented.
for (DeclContext::decl_iterator D = Container->decls_begin(),
Container = getContainerDef(Container);
for (DeclContext::decl_iterator D = Container->decls_begin(),
DEnd = Container->decls_end();
D != DEnd; ++D)
if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
Expand Down Expand Up @@ -5959,9 +5984,12 @@ static void FindImplementableMethods(ASTContext &Context,
KnownMethodsMap &KnownMethods,
bool InOriginalClass = true) {
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
// Recurse into protocols.
// Make sure we have a definition; that's what we'll walk.
if (!IFace->hasDefinition())
return;

IFace = IFace->getDefinition();
Container = IFace;

const ObjCList<ObjCProtocolDecl> &Protocols
= IFace->getReferencedProtocols();
Expand Down Expand Up @@ -6003,16 +6031,20 @@ static void FindImplementableMethods(ASTContext &Context,
}

if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
if (Protocol->hasDefinition()) {
// Recurse into protocols.
const ObjCList<ObjCProtocolDecl> &Protocols
= Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, false);
}
// Make sure we have a definition; that's what we'll walk.
if (!Protocol->hasDefinition())
return;
Protocol = Protocol->getDefinition();
Container = Protocol;

// Recurse into protocols.
const ObjCList<ObjCProtocolDecl> &Protocols
= Protocol->getReferencedProtocols();
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end();
I != E; ++I)
FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
KnownMethods, false);
}

// Add methods in this container. This operation occurs last because
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Index/complete-method-decls.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ - (id)initWithTwoInts:(inout int)x second:(int)y;
- (int)getInt;
- (id)getSelf;
@end

@protocol P1;
@protocol P2<P1>
+ (id)alloc;
@end
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Index/complete-properties.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ @implementation I4 {
@synthesize Prop2 = Prop2_;
@end

@protocol P1
@property int Prop5;
@end

@class P1;

@interface I5<P1>
@end
@implementation I5
@synthesize Prop5;
@end
// RUN: c-index-test -code-completion-at=%s:20:13 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText Prop0}
// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText Prop1}
Expand Down Expand Up @@ -80,3 +91,6 @@ @implementation I4 {
// CHECK-CC7-NOT: ObjCIvarDecl:{ResultType id}{TypedText _Prop2}
// CHECK-CC7: ObjCIvarDecl:{ResultType I4 *}{TypedText Prop1} (17)
// CHECK-CC7: ObjCIvarDecl:{ResultType id}{TypedText Prop2_} (7)

// RUN: c-index-test -code-completion-at=%s:57:13 -fobjc-nonfragile-abi %s | FileCheck -check-prefix=CHECK-CC8 %s
// CHECK-CC8: ObjCPropertyDecl:{ResultType int}{TypedText Prop5} (35)

0 comments on commit 9b4f370

Please sign in to comment.