Formatter: Add support for @interface.

Previously:
@interface Foo + (id)init; @end

Now:
@interface Foo
+ (id)init;
@end

Some tweaking remains, but this is a good first step.

llvm-svn: 171995
This commit is contained in:
Nico Weber 2013-01-09 20:25:35 +00:00
parent 46e432fb8a
commit 7eecf4b6e3
3 changed files with 140 additions and 28 deletions

View File

@ -208,6 +208,8 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::objc_package:
case tok::objc_private:
return parseAccessSpecifier();
case tok::objc_interface:
return parseObjCInterface();
default:
break;
}
@ -494,6 +496,46 @@ void UnwrappedLineParser::parseStructOrClass() {
} while (!eof());
}
void UnwrappedLineParser::parseObjCInterface() {
nextToken();
nextToken(); // interface name
// @interface can be followed by either a base class, or a category.
if (FormatTok.Tok.is(tok::colon)) {
nextToken();
nextToken(); // base class name
} else if (FormatTok.Tok.is(tok::l_paren))
// Skip category, if present.
parseParens();
// Skip protocol list, if present.
if (FormatTok.Tok.is(tok::less)) {
do
nextToken();
while (!eof() && FormatTok.Tok.isNot(tok::greater));
nextToken(); // Skip '>'.
}
// If instance variables are present, keep the '{' on the first line too.
if (FormatTok.Tok.is(tok::l_brace))
parseBlock();
// With instance variables, this puts '}' on its own line. Without instance
// variables, this ends the @interface line.
addUnwrappedLine();
// Read everything up to the @end.
do {
if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) {
nextToken();
addUnwrappedLine();
break;
}
parseStructuralElement();
} while (!eof());
}
void UnwrappedLineParser::addUnwrappedLine() {
if (!RootTokenInitialized)
return;

View File

@ -142,6 +142,7 @@ private:
void parseAccessSpecifier();
void parseEnum();
void parseStructOrClass();
void parseObjCInterface();
void addUnwrappedLine();
bool eof() const;
void nextToken();

View File

@ -443,34 +443,6 @@ TEST_F(FormatTest, FormatObjCTryCatch) {
"}");
}
TEST_F(FormatTest, FormatObjCInterface) {
verifyFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
"@public\n"
" int field1;\n"
"@protected\n"
" int field2;\n"
"@private\n"
" int field3;\n"
"@package\n"
" int field4;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyGoogleFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
" @public\n"
" int field1;\n"
" @protected\n"
" int field2;\n"
" @private\n"
" int field3;\n"
" @package\n"
" int field4;\n"
"}\n"
"+ (id)init;\n"
"@end");
}
TEST_F(FormatTest, StaticInitializers) {
verifyFormat("static SomeClass SC = { 1, 'a' };");
@ -1180,6 +1152,103 @@ TEST_F(FormatTest, FormatObjCBlocks) {
verifyFormat("int (^Block1) (int, int) = ^(int i, int j)");
}
TEST_F(FormatTest, FormatObjCInterface) {
// FIXME: Handle comments like in "@interface /* wait for it */ Foo", PR14875
// FIXME: In google style, it's "+(id) init", not "+ (id)init".
verifyFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
"@public\n"
" int field1;\n"
"@protected\n"
" int field2;\n"
"@private\n"
" int field3;\n"
"@package\n"
" int field4;\n"
"}\n"
"+ (id)init;\n"
"@end");
// FIXME: In LLVM style, there should be a space before '<' for protocols.
verifyGoogleFormat("@interface Foo : NSObject<NSSomeDelegate> {\n"
" @public\n"
" int field1;\n"
" @protected\n"
" int field2;\n"
" @private\n"
" int field3;\n"
" @package\n"
" int field4;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo\n"
"+ (id)init;\n"
"// Look, a comment!\n"
"- (int)answerWith:(int)i;\n"
"@end");
verifyFormat("@interface Foo\n"
"@end");
verifyFormat("@interface Foo : Bar\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo : Bar<Baz, Quux>\n"
"+ (id)init;\n"
"@end");
// FIXME: there should be a space before '(' for categories.
verifyFormat("@interface Foo(HackStuff)\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo()\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo(HackStuff)<MyProtocol>\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo {\n"
" int _i;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo : Bar {\n"
" int _i;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo : Bar<Baz, Quux> {\n"
" int _i;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo(HackStuff) {\n"
" int _i;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo() {\n"
" int _i;\n"
"}\n"
"+ (id)init;\n"
"@end");
verifyFormat("@interface Foo(HackStuff)<MyProtocol> {\n"
" int _i;\n"
"}\n"
"+ (id)init;\n"
"@end");
}
TEST_F(FormatTest, ObjCAt) {
verifyFormat("@autoreleasepool");
verifyFormat("@catch");