From 8696a8d9e38e3f4fc267db9d1c5c47415e335316 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Wed, 9 Jan 2013 21:15:03 +0000 Subject: [PATCH] Formatting: Add support for @protocol. Pull pieces of the @interface code into reusable methods. llvm-svn: 172001 --- clang/lib/Format/UnwrappedLineParser.cpp | 56 +++++++++++++++++------- clang/lib/Format/UnwrappedLineParser.h | 3 ++ clang/test/Index/comment-objc-decls.m | 2 +- clang/unittests/Format/FormatTest.cpp | 15 +++++++ 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 131d982906b6..688937c1e6aa 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -210,6 +210,8 @@ void UnwrappedLineParser::parseStructuralElement() { return parseAccessSpecifier(); case tok::objc_interface: return parseObjCInterface(); + case tok::objc_protocol: + return parseObjCProtocol(); default: break; } @@ -496,6 +498,25 @@ void UnwrappedLineParser::parseStructOrClass() { } while (!eof()); } +void UnwrappedLineParser::parseObjCProtocolList() { + assert(FormatTok.Tok.is(tok::less) && "'<' expected."); + do + nextToken(); + while (!eof() && FormatTok.Tok.isNot(tok::greater)); + nextToken(); // Skip '>'. +} + +void UnwrappedLineParser::parseObjCUntilAtEnd() { + do { + if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) { + nextToken(); + addUnwrappedLine(); + break; + } + parseStructuralElement(); + } while (!eof()); +} + void UnwrappedLineParser::parseObjCInterface() { nextToken(); nextToken(); // interface name @@ -508,13 +529,8 @@ void UnwrappedLineParser::parseObjCInterface() { // 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 (FormatTok.Tok.is(tok::less)) + parseObjCProtocolList(); // If instance variables are present, keep the '{' on the first line too. if (FormatTok.Tok.is(tok::l_brace)) @@ -524,16 +540,24 @@ void UnwrappedLineParser::parseObjCInterface() { // variables, this ends the @interface line. addUnwrappedLine(); - // Read everything up to the @end. - do { - if (FormatTok.Tok.isObjCAtKeyword(tok::objc_end)) { - nextToken(); - addUnwrappedLine(); - break; - } + parseObjCUntilAtEnd(); +} - parseStructuralElement(); - } while (!eof()); +void UnwrappedLineParser::parseObjCProtocol() { + nextToken(); + nextToken(); // protocol name + + if (FormatTok.Tok.is(tok::less)) + parseObjCProtocolList(); + + // Check for protocol declaration. + if (FormatTok.Tok.is(tok::semi)) { + nextToken(); + return addUnwrappedLine(); + } + + addUnwrappedLine(); + parseObjCUntilAtEnd(); } void UnwrappedLineParser::addUnwrappedLine() { diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 28ef23519001..303afc2d98da 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -142,7 +142,10 @@ private: void parseAccessSpecifier(); void parseEnum(); void parseStructOrClass(); + void parseObjCProtocolList(); + void parseObjCUntilAtEnd(); void parseObjCInterface(); + void parseObjCProtocol(); void addUnwrappedLine(); bool eof() const; void nextToken(); diff --git a/clang/test/Index/comment-objc-decls.m b/clang/test/Index/comment-objc-decls.m index 4b9a4bcaba03..4c9f878c3564 100644 --- a/clang/test/Index/comment-objc-decls.m +++ b/clang/test/Index/comment-objc-decls.m @@ -30,7 +30,7 @@ */ + ClassMethodMyProto; @end -// CHECK: @protocol MyProto @end +// CHECK: @protocol MyProto\n@end // CHECK: - (unsigned int)MethodMyProto:(id)anObject inRange:(unsigned int)range; // CHECK: @optional\n @property(readwrite, copy, atomic) id PropertyMyProto; // CHECK: + (id)ClassMethodMyProto; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 4decf94c766f..e06544a95f20 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -1249,6 +1249,21 @@ TEST_F(FormatTest, FormatObjCInterface) { "@end"); } +TEST_F(FormatTest, FormatObjCProtocol) { + verifyFormat("@protocol Foo\n" + "@property(weak) id delegate;\n" + "- (NSUInteger)numberOfThings;\n" + "@end"); + + // FIXME: In LLVM style, there should be a space before '<' for protocols. + verifyFormat("@protocol MyProtocol\n" + "- (NSUInteger)numberOfThings;\n" + "@end"); + + verifyFormat("@protocol Foo;\n" + "@protocol Bar;\n"); +} + TEST_F(FormatTest, ObjCAt) { verifyFormat("@autoreleasepool"); verifyFormat("@catch");