[cfe-commits] r89259 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-properties.m
Douglas Gregor
dgregor at apple.com
Wed Nov 18 14:32:07 PST 2009
Author: dgregor
Date: Wed Nov 18 16:32:06 2009
New Revision: 89259
URL: http://llvm.org/viewvc/llvm-project?rev=89259&view=rev
Log:
Code completion for Objective-C @synthesized.
Added:
cfe/trunk/test/Index/complete-properties.m
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=89259&r1=89258&r2=89259&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Nov 18 16:32:06 2009
@@ -2408,6 +2408,24 @@
IdentifierInfo *ClassName) {
}
+ /// \brief Code completion for the property names when synthesizing an
+ /// Objective-C property.
+ ///
+ /// This code completion action is invoked after the @synthesized and after
+ /// each "," in an @synthesized definition.
+ virtual void CodeCompleteObjCPropertySynthesize(Scope *S,
+ DeclPtrTy ObjCImpDecl) {
+ }
+
+ /// \brief Code completion for the instance variable name that should
+ /// follow an '=' when synthesizing an Objective-C property.
+ ///
+ /// This code completion action is invoked after each '=' that occurs within
+ /// an @synthesized definition.
+ virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ DeclPtrTy ObjCImpDecl) {
+ }
//@}
};
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=89259&r1=89258&r2=89259&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Wed Nov 18 16:32:06 2009
@@ -1231,12 +1231,13 @@
assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
"ParseObjCPropertyDynamic(): Expected '@synthesize'");
SourceLocation loc = ConsumeToken(); // consume synthesize
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- return DeclPtrTy();
- }
while (true) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPropertySynthesize(CurScope, ObjCImpDecl);
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_synthesized_property_name);
SkipUntil(tok::semi);
@@ -1249,6 +1250,13 @@
if (Tok.is(tok::equal)) {
// property '=' ivar-name
ConsumeToken(); // consume '='
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCPropertySynthesizeIvar(CurScope, propertyId,
+ ObjCImpDecl);
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
break;
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89259&r1=89258&r2=89259&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 18 16:32:06 2009
@@ -3654,6 +3654,11 @@
IdentifierInfo *ClassName);
virtual void CodeCompleteObjCImplementationCategory(Scope *S,
IdentifierInfo *ClassName);
+ virtual void CodeCompleteObjCPropertySynthesize(Scope *S,
+ DeclPtrTy ObjCImpDecl);
+ virtual void CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ DeclPtrTy ObjCImpDecl);
//@}
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=89259&r1=89258&r2=89259&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Nov 18 16:32:06 2009
@@ -1132,6 +1132,7 @@
}
static void AddObjCProperties(ObjCContainerDecl *Container,
+ bool AllowCategories,
DeclContext *CurContext,
ResultBuilder &Results) {
typedef CodeCompleteConsumer::Result Result;
@@ -1148,29 +1149,32 @@
for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
PEnd = Protocol->protocol_end();
P != PEnd; ++P)
- AddObjCProperties(*P, CurContext, Results);
+ AddObjCProperties(*P, AllowCategories, 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);
+ if (AllowCategories) {
+ // Look through categories.
+ for (ObjCCategoryDecl *Category = IFace->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ AddObjCProperties(Category, AllowCategories, CurContext, Results);
+ }
// Look through protocols.
for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
E = IFace->protocol_end();
I != E; ++I)
- AddObjCProperties(*I, CurContext, Results);
+ AddObjCProperties(*I, AllowCategories, CurContext, Results);
// Look in the superclass.
if (IFace->getSuperClass())
- AddObjCProperties(IFace->getSuperClass(), CurContext, Results);
+ AddObjCProperties(IFace->getSuperClass(), AllowCategories, 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);
+ AddObjCProperties(*P, AllowCategories, CurContext, Results);
}
}
@@ -1234,13 +1238,13 @@
const ObjCObjectPointerType *ObjCPtr
= BaseType->getAsObjCInterfacePointerType();
assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
- AddObjCProperties(ObjCPtr->getInterfaceDecl(), CurContext, Results);
+ AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, 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);
+ AddObjCProperties(*I, true, CurContext, Results);
// FIXME: We could (should?) also look for "implicit" properties, identified
// only by the presence of nullary and unary selectors.
@@ -2021,3 +2025,74 @@
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+
+void Sema::CodeCompleteObjCPropertySynthesize(Scope *S, DeclPtrTy ObjCImpDecl) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ // Figure out where this @synthesize lives.
+ ObjCContainerDecl *Container
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
+ return;
+
+ // Ignore any properties that have already been implemented.
+ for (DeclContext::decl_iterator D = Container->decls_begin(),
+ DEnd = Container->decls_end();
+ D != DEnd; ++D)
+ if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
+ Results.Ignore(PropertyImpl->getPropertyDecl());
+
+ // Add any properties that we find.
+ Results.EnterNewScope();
+ if (ObjCImplementationDecl *ClassImpl
+ = dyn_cast<ObjCImplementationDecl>(Container))
+ AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
+ Results);
+ else
+ AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
+ false, CurContext, Results);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
+ IdentifierInfo *PropertyName,
+ DeclPtrTy ObjCImpDecl) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+
+ // Figure out where this @synthesize lives.
+ ObjCContainerDecl *Container
+ = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl.getAs<Decl>());
+ if (!Container ||
+ (!isa<ObjCImplementationDecl>(Container) &&
+ !isa<ObjCCategoryImplDecl>(Container)))
+ return;
+
+ // Figure out which interface we're looking into.
+ ObjCInterfaceDecl *Class = 0;
+ if (ObjCImplementationDecl *ClassImpl
+ = dyn_cast<ObjCImplementationDecl>(Container))
+ Class = ClassImpl->getClassInterface();
+ else
+ Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
+ ->getClassInterface();
+
+ // Add all of the instance variables in this class and its superclasses.
+ Results.EnterNewScope();
+ for(; Class; Class = Class->getSuperClass()) {
+ // FIXME: We could screen the type of each ivar for compatibility with
+ // the property, but is that being too paternal?
+ for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
+ IVarEnd = Class->ivar_end();
+ IVar != IVarEnd; ++IVar)
+ Results.MaybeAddResult(Result(*IVar, 0), CurContext);
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
Added: cfe/trunk/test/Index/complete-properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-properties.m?rev=89259&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-properties.m (added)
+++ cfe/trunk/test/Index/complete-properties.m Wed Nov 18 16:32:06 2009
@@ -0,0 +1,30 @@
+/* Note: the RUN lines are near the end of the file, since line/column
+ matter for this test. */
+
+ at interface I1
+{
+ id StoredProp3;
+ int RandomIVar;
+}
+ at property int Prop1;
+ at property float Prop2;
+ at end
+
+ at interface I2 : I1
+ at property id Prop3;
+ at end
+
+ at implementation I2
+ at synthesize Prop2, Prop1, Prop3 = StoredProp3;
+ at end
+
+// RUN: c-index-test -code-completion-at=%s:18:13 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop1}
+// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop2}
+// CHECK-CC1: ObjCPropertyDecl:{TypedText Prop3}
+// RUN: c-index-test -code-completion-at=%s:18:20 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCPropertyDecl:{TypedText Prop1}
+// CHECK-CC2-NEXT: ObjCPropertyDecl:{TypedText Prop3}
+// RUN: c-index-test -code-completion-at=%s:18:35 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ObjCIvarDecl:{TypedText RandomIVar}
+// CHECK-CC3: ObjCIvarDecl:{TypedText StoredProp3}
More information about the cfe-commits
mailing list