[cfe-commits] r89182 - in /cfe/trunk: lib/Sema/SemaCodeComplete.cpp test/Index/complete-member-access.m
Douglas Gregor
dgregor at apple.com
Tue Nov 17 17:29:26 PST 2009
Author: dgregor
Date: Tue Nov 17 19:29:26 2009
New Revision: 89182
URL: http://llvm.org/viewvc/llvm-project?rev=89182&view=rev
Log:
Code completion for member accesses that involve Objective-C properties and instance variables
Added:
cfe/trunk/test/Index/complete-member-access.m
Modified:
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=89182&r1=89181&r2=89182&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Nov 17 19:29:26 2009
@@ -1128,6 +1128,49 @@
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+static void AddObjCProperties(ObjCContainerDecl *Container,
+ DeclContext *CurContext,
+ ResultBuilder &Results) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ // Add properties in this container.
+ for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
+ PEnd = Container->prop_end();
+ P != PEnd;
+ ++P)
+ Results.MaybeAddResult(Result(*P, 0), 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, CurContext, Results);
+ } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
+ // Look through categories.
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ AddObjCProperties(Category, CurContext, Results);
+
+ // Look through protocols.
+ for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
+ E = IFace->protocol_end();
+ I != E; ++I)
+ AddObjCProperties(*I, CurContext, Results);
+
+ // Look in the superclass.
+ if (IFace->getSuperClass())
+ AddObjCProperties(IFace->getSuperClass(), CurContext, Results);
+ } else if (const ObjCCategoryDecl *Category
+ = dyn_cast<ObjCCategoryDecl>(Container)) {
+ // Look through protocols.
+ for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
+ PEnd = Category->protocol_end();
+ P != PEnd; ++P)
+ AddObjCProperties(*P, CurContext, Results);
+ }
+}
+
void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
SourceLocation OpLoc,
bool IsArrow) {
@@ -1151,38 +1194,75 @@
ResultBuilder Results(*this, &ResultBuilder::IsMember);
unsigned NextRank = 0;
- // If this isn't a record type, we are done.
- const RecordType *Record = BaseType->getAs<RecordType>();
- if (!Record)
- return;
-
- NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
- Record->getDecl(), Results);
+ Results.EnterNewScope();
+ if (const RecordType *Record = BaseType->getAs<RecordType>()) {
+ // Access to a C/C++ class, struct, or union.
+ NextRank = CollectMemberLookupResults(Record->getDecl(), NextRank,
+ Record->getDecl(), Results);
+
+ if (getLangOptions().CPlusPlus) {
+ if (!Results.empty()) {
+ // The "template" keyword can follow "->" or "." in the grammar.
+ // However, we only want to suggest the template keyword if something
+ // is dependent.
+ bool IsDependent = BaseType->isDependentType();
+ if (!IsDependent) {
+ for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
+ if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
+ IsDependent = Ctx->isDependentContext();
+ break;
+ }
+ }
- if (getLangOptions().CPlusPlus) {
- if (!Results.empty()) {
- // The "template" keyword can follow "->" or "." in the grammar.
- // However, we only want to suggest the template keyword if something
- // is dependent.
- bool IsDependent = BaseType->isDependentType();
- if (!IsDependent) {
- for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
- if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
- IsDependent = Ctx->isDependentContext();
- break;
- }
+ if (IsDependent)
+ Results.MaybeAddResult(Result("template", NextRank++));
}
- if (IsDependent)
- Results.MaybeAddResult(Result("template", NextRank++));
+ // We could have the start of a nested-name-specifier. Add those
+ // results as well.
+ Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
+ CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
+ CurContext, Results);
+ }
+ } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
+ // Objective-C property reference.
+
+ // Add property results based on our interface.
+ const ObjCObjectPointerType *ObjCPtr
+ = BaseType->getAsObjCInterfacePointerType();
+ assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
+ AddObjCProperties(ObjCPtr->getInterfaceDecl(), CurContext, 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, CurContext, Results);
+
+ // FIXME: We could (should?) also look for "implicit" properties, identified
+ // only by the presence of nullary and unary selectors.
+ } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
+ (!IsArrow && BaseType->isObjCInterfaceType())) {
+ // Objective-C instance variable access.
+ ObjCInterfaceDecl *Class = 0;
+ if (const ObjCObjectPointerType *ObjCPtr
+ = BaseType->getAs<ObjCObjectPointerType>())
+ Class = ObjCPtr->getInterfaceDecl();
+ else
+ Class = BaseType->getAs<ObjCInterfaceType>()->getDecl();
+
+ // Add all ivars from this class and its superclasses.
+ for (; Class; Class = Class->getSuperClass()) {
+ for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
+ IVarEnd = Class->ivar_end();
+ IVar != IVarEnd; ++IVar)
+ Results.MaybeAddResult(Result(*IVar, 0), CurContext);
}
-
- // We could have the start of a nested-name-specifier. Add those
- // results as well.
- Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
- CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank,
- CurContext, Results);
}
+
+ // FIXME: How do we cope with isa?
+
+ Results.ExitScope();
// Add macros
if (CodeCompleter->includeMacros())
Added: cfe/trunk/test/Index/complete-member-access.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-member-access.m?rev=89182&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-member-access.m (added)
+++ cfe/trunk/test/Index/complete-member-access.m Tue Nov 17 19:29:26 2009
@@ -0,0 +1,30 @@
+// Note: the RUN lines are near the end of the file, since line/column
+// matter for this test.
+
+ at protocol MyProtocol
+ at property float ProtoProp;
+ at end
+
+ at interface Super {
+ int SuperIVar;
+}
+ at end
+ at interface Int : Super<MyProtocol>
+{
+ int IVar;
+}
+
+ at property int prop1;
+ at end
+
+void test_props(Int* ptr) {
+ ptr.prop1 = 0;
+ ptr->IVar = 0;
+}
+
+// RUN: c-index-test -code-completion-at=%s:21:7 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCPropertyDecl:{TypedText prop1}
+// CHECK-CC1: ObjCPropertyDecl:{TypedText ProtoProp}
+// RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCIvarDecl:{TypedText IVar}
+// CHECK-CC2: ObjCIvarDecl:{TypedText SuperIVar}
More information about the cfe-commits
mailing list