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");
}