forked from OSchip/llvm-project
When code completion walks the members of a protocol or interface,
make sure that we walk the definition. Fixes <rdar://problem/11427742>. llvm-svn: 158357
This commit is contained in:
parent
2ae781f9e3
commit
9b4f370095
clang
|
@ -3334,7 +3334,25 @@ 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,
|
||||
|
@ -3342,6 +3360,9 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
|
|||
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();
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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))
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
- (int)getInt;
|
||||
- (id)getSelf;
|
||||
@end
|
||||
|
||||
@protocol P1;
|
||||
@protocol P2<P1>
|
||||
+ (id)alloc;
|
||||
@end
|
||||
|
|
|
@ -45,6 +45,17 @@ id test(I3 *i3) {
|
|||
@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}
|
||||
|
@ -80,3 +91,6 @@ id test(I3 *i3) {
|
|||
// 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)
|
||||
|
|
Loading…
Reference in New Issue