diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index a167834a4ea2..406daac7a62f 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -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) && diff --git a/clang/test/Index/comment-objc-decls.m b/clang/test/Index/comment-objc-decls.m index 0e3c0721211b..9b9805fb8407 100644 --- a/clang/test/Index/comment-objc-decls.m +++ b/clang/test/Index/comment-objc-decls.m @@ -90,7 +90,7 @@ id IvarMyClassExtension; } @end -// CHECK: @interface MyClass() {\n id IvarMyClassExtension;\n}\n@end +// CHECK: @interface MyClass () {\n id IvarMyClassExtension;\n}\n@end // CHECK: id IvarMyClassExtension @@ -108,7 +108,7 @@ */ @property (copy) id PropertyMyClassCategory; @end -// CHECK: @interface MyClass(Category)\n@end +// CHECK: @interface MyClass (Category)\n@end // CHECK: - (void)MethodMyClassCategory; // CHECK: @property(readwrite, copy, atomic) id PropertyMyClassCategory; // CHECK: - (id)PropertyMyClassCategory; @@ -162,7 +162,7 @@ */ - (void) setPropertyMyClassCategory : (id) arg {} @end -// CHECK: @implementation MyClass(Category)\n@end +// CHECK: @implementation MyClass (Category)\n@end // CHECK: - (void)MethodMyClassCategory; // CHECK: - (id)PropertyMyClassCategory; // CHECK: - (void)setPropertyMyClassCategory:(id)arg; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 1d9363dc2e4b..077c358c22b1 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -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)\n" + verifyFormat("@interface Foo (HackStuff)\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) {\n" + verifyFormat("@interface Foo (HackStuff) {\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"); }