[cfe-commits] r86323 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/objc-message.m
Steve Naroff
snaroff at apple.com
Fri Nov 6 18:08:14 PST 2009
Author: snaroff
Date: Fri Nov 6 20:08:14 2009
New Revision: 86323
URL: http://llvm.org/viewvc/llvm-project?rev=86323&view=rev
Log:
Add basic code completion support for ObjC messages.
Still a work in progress...
Added:
cfe/trunk/test/CodeCompletion/objc-message.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=86323&r1=86322&r2=86323&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri Nov 6 20:08:14 2009
@@ -2329,6 +2329,26 @@
///
/// \param S the scope in which the operator keyword occurs.
virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { }
+
+ /// \brief Code completion for an ObjC factory method (from within a message
+ /// expression).
+ ///
+ /// This code completion action is invoked when the code-completion token is
+ /// found after the class name.
+ ///
+ /// \param S the scope in which the message expression occurs.
+ /// \param FName the factory name.
+ virtual void CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName){ }
+
+ /// \brief Code completion for an ObjC instance method (from within a message
+ /// expression).
+ ///
+ /// This code completion action is invoked when the code-completion token is
+ /// found after the receiver expression.
+ ///
+ /// \param S the scope in which the operator keyword occurs.
+ /// \param Receiver an expression for the receiver of the message.
+ virtual void CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver) { }
//@}
};
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=86323&r1=86322&r2=86323&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Nov 6 20:08:14 2009
@@ -1549,6 +1549,13 @@
SourceLocation NameLoc,
IdentifierInfo *ReceiverName,
ExprArg ReceiverExpr) {
+ if (Tok.is(tok::code_completion)) {
+ if (ReceiverName)
+ Actions.CodeCompleteObjCFactoryMethod(CurScope, ReceiverName);
+ else
+ Actions.CodeCompleteObjCInstanceMethod(CurScope, ReceiverExpr.release());
+ ConsumeToken();
+ }
// Parse objc-selector
SourceLocation Loc;
IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86323&r1=86322&r2=86323&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Nov 6 20:08:14 2009
@@ -3764,6 +3764,8 @@
virtual void CodeCompleteOperatorName(Scope *S);
virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS);
+ virtual void CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName);
+ virtual void CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver);
//@}
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=86323&r1=86322&r2=86323&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Nov 6 20:08:14 2009
@@ -1518,3 +1518,114 @@
Results.ExitScope();
HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
}
+
+void Sema::CodeCompleteObjCFactoryMethod(Scope *S, IdentifierInfo *FName) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ ObjCInterfaceDecl *CDecl = getObjCInterfaceDecl(FName);
+
+ while (CDecl != NULL) {
+ for (ObjCInterfaceDecl::classmeth_iterator I = CDecl->classmeth_begin(),
+ E = CDecl->classmeth_end();
+ I != E; ++I) {
+ Results.MaybeAddResult(Result(*I, 0), CurContext);
+ }
+ // Add class methods in protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols=CDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I) {
+ for (ObjCProtocolDecl::classmeth_iterator I2 = (*I)->classmeth_begin(),
+ E2 = (*I)->classmeth_end();
+ I2 != E2; ++I2) {
+ Results.MaybeAddResult(Result(*I2, 0), CurContext);
+ }
+ }
+ // Add class methods in categories.
+ ObjCCategoryDecl *CatDecl = CDecl->getCategoryList();
+ while (CatDecl) {
+ for (ObjCCategoryDecl::classmeth_iterator I = CatDecl->classmeth_begin(),
+ E = CatDecl->classmeth_end();
+ I != E; ++I) {
+ Results.MaybeAddResult(Result(*I, 0), CurContext);
+ }
+ // Add a categories protocol methods.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I) {
+ for (ObjCProtocolDecl::classmeth_iterator I2 = (*I)->classmeth_begin(),
+ E2 = (*I)->classmeth_end();
+ I2 != E2; ++I2) {
+ Results.MaybeAddResult(Result(*I2, 0), CurContext);
+ }
+ }
+ CatDecl = CatDecl->getNextClassCategory();
+ }
+ CDecl = CDecl->getSuperClass();
+ }
+ Results.ExitScope();
+ // This also suppresses remaining diagnostics.
+ HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+}
+
+void Sema::CodeCompleteObjCInstanceMethod(Scope *S, ExprTy *Receiver) {
+ typedef CodeCompleteConsumer::Result Result;
+ ResultBuilder Results(*this);
+ Results.EnterNewScope();
+
+ Expr *RecExpr = static_cast<Expr *>(Receiver);
+ QualType RecType = RecExpr->getType();
+
+ const ObjCObjectPointerType* OCOPT = RecType->getAs<ObjCObjectPointerType>();
+
+ if (!OCOPT)
+ return;
+
+ // FIXME: handle 'id', 'Class', and qualified types.
+ ObjCInterfaceDecl *CDecl = OCOPT->getInterfaceDecl();
+
+ while (CDecl != NULL) {
+ for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(),
+ E = CDecl->instmeth_end();
+ I != E; ++I) {
+ Results.MaybeAddResult(Result(*I, 0), CurContext);
+ }
+ // Add class methods in protocols.
+ const ObjCList<ObjCProtocolDecl> &Protocols=CDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I) {
+ for (ObjCProtocolDecl::instmeth_iterator I2 = (*I)->instmeth_begin(),
+ E2 = (*I)->instmeth_end();
+ I2 != E2; ++I2) {
+ Results.MaybeAddResult(Result(*I2, 0), CurContext);
+ }
+ }
+ // Add class methods in categories.
+ ObjCCategoryDecl *CatDecl = CDecl->getCategoryList();
+ while (CatDecl) {
+ for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(),
+ E = CatDecl->instmeth_end();
+ I != E; ++I) {
+ Results.MaybeAddResult(Result(*I, 0), CurContext);
+ }
+ // Add a categories protocol methods.
+ const ObjCList<ObjCProtocolDecl> &Protocols =
+ CatDecl->getReferencedProtocols();
+ for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
+ E = Protocols.end(); I != E; ++I) {
+ for (ObjCProtocolDecl::instmeth_iterator I2 = (*I)->instmeth_begin(),
+ E2 = (*I)->instmeth_end();
+ I2 != E2; ++I2) {
+ Results.MaybeAddResult(Result(*I2, 0), CurContext);
+ }
+ }
+ CatDecl = CatDecl->getNextClassCategory();
+ }
+ CDecl = CDecl->getSuperClass();
+ }
+ Results.ExitScope();
+ // This also suppresses remaining diagnostics.
+ HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+}
Added: cfe/trunk/test/CodeCompletion/objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/objc-message.m?rev=86323&view=auto
==============================================================================
--- cfe/trunk/test/CodeCompletion/objc-message.m (added)
+++ cfe/trunk/test/CodeCompletion/objc-message.m Fri Nov 6 20:08:14 2009
@@ -0,0 +1,35 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+ at protocol FooTestProtocol
++ protocolClassMethod;
+- protocolInstanceMethod;
+ at end
+ at interface Foo <FooTestProtocol> {
+ void *isa;
+}
++ (int)classMethod1:a withKeyword:b;
++ (void)classMethod2;
++ new;
+- instanceMethod1;
+ at end
+
+ at interface Foo (FooTestCategory)
++ categoryClassMethod;
+- categoryInstanceMethod;
+ at end
+
+void func() {
+ Foo *obj = [Foo new];
+ [obj xx];
+}
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:23:19 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s &&
+// CHECK-CC1: categoryClassMethod : 0
+// CHECK-CC1: classMethod2 : 0
+// CHECK-CC1: new : 0
+// CHECK-CC1: protocolClassMethod : 0
+// CHECK-CC1: classMethod1:withKeyword: : 0
+// RUN: clang-cc -fsyntax-only -code-completion-at=%s:24:8 %s -o - | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: categoryInstanceMethod : 0
+// CHECK-CC2: instanceMethod1 : 0
+// CHECK-CC2: protocolInstanceMethod : 0
More information about the cfe-commits
mailing list