Formatter: Add space before '(' in @implemenation, @interface, @protocol lines
authorNico Weber <nicolasweber@gmx.de>
Thu, 10 Jan 2013 19:19:14 +0000 (19:19 +0000)
committerNico Weber <nicolasweber@gmx.de>
Thu, 10 Jan 2013 19:19:14 +0000 (19:19 +0000)
The first token in @implementation, @interface, and @protocol lines is now
marked TT_ObjCDecl, and lines starting with a TT_ObjCDecl token are now marked
LT_ObjCMethodDecl.

llvm-svn: 172093

clang/lib/Format/Format.cpp
clang/test/Index/comment-objc-decls.m
clang/unittests/Format/FormatTest.cpp

index a167834..406daac 100644 (file)
@@ -37,6 +37,7 @@ enum TokenType {
   TT_DirectorySeparator,
   TT_LineComment,
   TT_ObjCBlockLParen,
+  TT_ObjCDecl,
   TT_ObjCMethodSpecifier,
   TT_OverloadedOperator,
   TT_PointerOrReference,
@@ -53,6 +54,7 @@ enum LineType {
   LT_Other,
   LT_PreprocessorDirective,
   LT_VirtualFunctionDecl,
+  LT_ObjCDecl, // An @interface, @implementation, or @protocol line.
   LT_ObjCMethodDecl
 };
 
@@ -835,6 +837,8 @@ public:
 
     if (RootToken.Type == TT_ObjCMethodSpecifier)
       CurrentLineType = LT_ObjCMethodDecl;
+    else if (RootToken.Type == TT_ObjCDecl)
+      CurrentLineType = LT_ObjCDecl;
 
     if (!RootToken.Children.empty())
       calculateExtraInformation(RootToken.Children[0]);
@@ -879,6 +883,15 @@ private:
                   Current.Parent->Type == TT_TemplateCloser)) {
         // FIXME: We need to get smarter and understand more cases of casts.
         Current.Type = TT_CastRParen;
+      } else if (Current.is(tok::at) && Current.Children.size()) {
+        switch (Current.Children[0].FormatTok.Tok.getObjCKeywordID()) {
+        case tok::objc_interface:
+        case tok::objc_implementation:
+        case tok::objc_protocol:
+          Current.Type = TT_ObjCDecl;
+        default:
+          break;
+        }
       }
     }
 
@@ -997,8 +1010,9 @@ private:
     if (Left.is(tok::l_paren))
       return false;
     if (Right.is(tok::l_paren)) {
-      return Left.is(tok::kw_if) || Left.is(tok::kw_for) ||
-             Left.is(tok::kw_while) || Left.is(tok::kw_switch) ||
+      return CurrentLineType == LT_ObjCDecl || Left.is(tok::kw_if) ||
+             Left.is(tok::kw_for) || Left.is(tok::kw_while) ||
+             Left.is(tok::kw_switch) ||
              Left.is(tok::kw_return) || Left.is(tok::kw_catch);
     }
     if (Left.is(tok::at) &&
index 0e3c072..9b9805f 100644 (file)
@@ -90,7 +90,7 @@
   id IvarMyClassExtension;
 }
 @end
-// CHECK: <Declaration>@interface MyClass() {\n  id IvarMyClassExtension;\n}\n@end</Declaration>
+// CHECK: <Declaration>@interface MyClass () {\n  id IvarMyClassExtension;\n}\n@end</Declaration>
 // CHECK: <Declaration>id IvarMyClassExtension</Declaration>
 
 
 */
 @property (copy) id PropertyMyClassCategory;
 @end
-// CHECK: <Declaration>@interface MyClass(Category)\n@end</Declaration>
+// CHECK: <Declaration>@interface MyClass (Category)\n@end</Declaration>
 // CHECK: <Declaration>- (void)MethodMyClassCategory;</Declaration>
 // CHECK: <Declaration>@property(readwrite, copy, atomic) id PropertyMyClassCategory;</Declaration>
 // CHECK: <Declaration>- (id)PropertyMyClassCategory;</Declaration>
 */
 - (void) setPropertyMyClassCategory : (id) arg {}
 @end
-// CHECK: <Declaration>@implementation MyClass(Category)\n@end</Declaration>
+// CHECK: <Declaration>@implementation MyClass (Category)\n@end</Declaration>
 // CHECK: <Declaration>- (void)MethodMyClassCategory;</Declaration>
 // CHECK: <Declaration>- (id)PropertyMyClassCategory;</Declaration>
 // CHECK: <Declaration>- (void)setPropertyMyClassCategory:(id)arg;</Declaration>
index 1d9363d..077c358 100644 (file)
@@ -1232,16 +1232,15 @@ TEST_F(FormatTest, FormatObjCInterface) {
                "+ (id)init;\n"
                "@end");
 
-  // FIXME: there should be a space before '(' for categories.
-  verifyFormat("@interface Foo(HackStuff)\n"
+  verifyFormat("@interface Foo (HackStuff)\n"
                "+ (id)init;\n"
                "@end");
 
-  verifyFormat("@interface Foo()\n"
+  verifyFormat("@interface Foo ()\n"
                "+ (id)init;\n"
                "@end");
 
-  verifyFormat("@interface Foo(HackStuff)<MyProtocol>\n"
+  verifyFormat("@interface Foo (HackStuff)<MyProtocol>\n"
                "+ (id)init;\n"
                "@end");
 
@@ -1263,19 +1262,19 @@ TEST_F(FormatTest, FormatObjCInterface) {
                "+ (id)init;\n"
                "@end");
 
-  verifyFormat("@interface Foo(HackStuff) {\n"
+  verifyFormat("@interface Foo (HackStuff) {\n"
                "  int _i;\n"
                "}\n"
                "+ (id)init;\n"
                "@end");
 
-  verifyFormat("@interface Foo() {\n"
+  verifyFormat("@interface Foo () {\n"
                "  int _i;\n"
                "}\n"
                "+ (id)init;\n"
                "@end");
 
-  verifyFormat("@interface Foo(HackStuff)<MyProtocol> {\n"
+  verifyFormat("@interface Foo (HackStuff)<MyProtocol> {\n"
                "  int _i;\n"
                "}\n"
                "+ (id)init;\n"
@@ -1341,8 +1340,7 @@ TEST_F(FormatTest, FormatObjCImplementation) {
                "+ (id)init {}\n"
                "@end");
 
-  // FIXME: there should be a space before '(' for categories.
-  verifyFormat("@implementation Foo(HackStuff)\n"
+  verifyFormat("@implementation Foo (HackStuff)\n"
                "+ (id)init {}\n"
                "@end");
 }