[cfe-commits] r89223 - in /cfe/trunk: include/clang/AST/DeclObjC.h include/clang/Parse/Action.h lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaCodeComplete.cpp test/Index/complete-categories.m
Douglas Gregor
dgregor at apple.com
Wed Nov 18 11:08:43 PST 2009
Author: dgregor
Date: Wed Nov 18 13:08:43 2009
New Revision: 89223
URL: http://llvm.org/viewvc/llvm-project?rev=89223&view=rev
Log:
Implement code completion for Objective-C category names in @interface
and @implementation declarations.
Added:
cfe/trunk/test/Index/complete-categories.m
Modified:
cfe/trunk/include/clang/AST/DeclObjC.h
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/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=89223&r1=89222&r2=89223&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Wed Nov 18 13:08:43 2009
@@ -808,7 +808,7 @@
/// - myMethod;
/// @end
///
-/// Cateogries also allow you to split the implementation of a class across
+/// Categories also allow you to split the implementation of a class across
/// several files (a feature more naturally supported in C++).
///
/// Categories were originally inspired by dynamic languages such as Common
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=89223&r1=89222&r2=89223&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Wed Nov 18 13:08:43 2009
@@ -2389,6 +2389,25 @@
/// \brief Code completion for an Objective-C implementation, after the
/// @implementation but before any identifier.
virtual void CodeCompleteObjCImplementationDecl(Scope *S) { }
+
+ /// \brief Code completion for the category name in an Objective-C interface
+ /// declaration.
+ ///
+ /// This code completion action is invoked after the '(' that indicates
+ /// a category name within an Objective-C interface declaration.
+ virtual void CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName) {
+ }
+
+ /// \brief Code completion for the category name in an Objective-C category
+ /// implementation.
+ ///
+ /// This code completion action is invoked after the '(' that indicates
+ /// the category name within an Objective-C category implementation.
+ virtual void CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName) {
+ }
+
//@}
};
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=89223&r1=89222&r2=89223&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Wed Nov 18 13:08:43 2009
@@ -143,6 +143,11 @@
SourceLocation categoryLoc, rparenLoc;
IdentifierInfo *categoryId = 0;
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCInterfaceCategory(CurScope, nameId);
+ ConsumeToken();
+ }
+
// For ObjC2, the category name is optional (not an error).
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
@@ -1111,6 +1116,11 @@
SourceLocation categoryLoc, rparenLoc;
IdentifierInfo *categoryId = 0;
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCImplementationCategory(CurScope, nameId);
+ ConsumeToken();
+ }
+
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89223&r1=89222&r2=89223&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 18 13:08:43 2009
@@ -3649,6 +3649,10 @@
virtual void CodeCompleteObjCSuperclass(Scope *S,
IdentifierInfo *ClassName);
virtual void CodeCompleteObjCImplementationDecl(Scope *S);
+ virtual void CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName);
+ virtual void CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName);
//@}
//===--------------------------------------------------------------------===//
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=89223&r1=89222&r2=89223&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Wed Nov 18 13:08:43 2009
@@ -1933,7 +1933,7 @@
// Make sure that we ignore the class we're currently defining.
NamedDecl *CurClass
= LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
- if (isa<ObjCInterfaceDecl>(CurClass))
+ if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Results.Ignore(CurClass);
// Add all classes.
@@ -1955,3 +1955,69 @@
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
+
+void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
+ IdentifierInfo *ClassName) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ ResultBuilder Results(*this);
+
+ // Ignore any categories we find that have already been implemented by this
+ // interface.
+ llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+ if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ CategoryNames.insert(Category->getIdentifier());
+
+ // Add all of the categories we know about.
+ Results.EnterNewScope();
+ TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
+ for (DeclContext::decl_iterator D = TU->decls_begin(),
+ DEnd = TU->decls_end();
+ D != DEnd; ++D)
+ if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
+ if (CategoryNames.insert(Category->getIdentifier()))
+ Results.MaybeAddResult(Result(Category, 0), CurContext);
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
+
+void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
+ IdentifierInfo *ClassName) {
+ typedef CodeCompleteConsumer::Result Result;
+
+ // Find the corresponding interface. If we couldn't find the interface, the
+ // program itself is ill-formed. However, we'll try to be helpful still by
+ // providing the list of all of the categories we know about.
+ NamedDecl *CurClass
+ = LookupSingleName(TUScope, ClassName, LookupOrdinaryName);
+ ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
+ if (!Class)
+ return CodeCompleteObjCInterfaceCategory(S, ClassName);
+
+ ResultBuilder Results(*this);
+
+ // Add all of the categories that have have corresponding interface
+ // declarations in this class and any of its superclasses, except for
+ // already-implemented categories in the class itself.
+ llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
+ Results.EnterNewScope();
+ bool IgnoreImplemented = true;
+ while (Class) {
+ for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
+ Category = Category->getNextClassCategory())
+ if ((!IgnoreImplemented || !Category->getImplementation()) &&
+ CategoryNames.insert(Category->getIdentifier()))
+ Results.MaybeAddResult(Result(Category, 0), CurContext);
+
+ Class = Class->getSuperClass();
+ IgnoreImplemented = false;
+ }
+ Results.ExitScope();
+
+ HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
+}
Added: cfe/trunk/test/Index/complete-categories.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-categories.m?rev=89223&view=auto
==============================================================================
--- cfe/trunk/test/Index/complete-categories.m (added)
+++ cfe/trunk/test/Index/complete-categories.m Wed Nov 18 13:08:43 2009
@@ -0,0 +1,39 @@
+/* Note: the RUN lines are near the end of the file, since line/column
+ matter for this test. */
+
+ at interface I1 @end
+ at interface I2 @end
+ at interface I3 : I2 @end
+
+ at interface I1(Cat1) @end
+ at interface I1(Cat2) @end
+ at interface I1(Cat3) @end
+
+ at interface I2 (Cat2) @end
+ at interface I2 (Cat3) @end
+ at interface I2 (Cat2) @end
+ at interface I3 (Cat1) @end
+ at interface I3 (Cat2) @end
+
+ at implementation I1(Cat2) @end
+ at implementation I1(Cat3) @end
+ at implementation I3(Cat2) @end
+
+// RUN: c-index-test -code-completion-at=%s:12:16 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: ObjCCategoryDecl:{TypedText Cat1}
+// CHECK-CC1: ObjCCategoryDecl:{TypedText Cat2}
+// CHECK-CC1: ObjCCategoryDecl:{TypedText Cat3}
+// RUN: c-index-test -code-completion-at=%s:13:16 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: ObjCCategoryDecl:{TypedText Cat1}
+// CHECK-CC2-NEXT: ObjCCategoryDecl:{TypedText Cat3}
+// RUN: c-index-test -code-completion-at=%s:18:20 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// CHECK-CC3: ObjCCategoryDecl:{TypedText Cat1}
+// CHECK-CC3: ObjCCategoryDecl:{TypedText Cat2}
+// CHECK-CC3: ObjCCategoryDecl:{TypedText Cat3}
+// RUN: c-index-test -code-completion-at=%s:19:20 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: ObjCCategoryDecl:{TypedText Cat1}
+// CHECK-CC4-NEXT: ObjCCategoryDecl:{TypedText Cat3}
+// RUN: c-index-test -code-completion-at=%s:20:20 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: ObjCCategoryDecl:{TypedText Cat1}
+// CHECK-CC5-NEXT: ObjCCategoryDecl:{TypedText Cat2}
+// CHECK-CC5-NEXT: ObjCCategoryDecl:{TypedText Cat3}
More information about the cfe-commits
mailing list