Fix formatting of preprocessor directives (incluces, warnings & errors).

Treat tokens inside <> for includes and everything from the second token
of a warning / error on as an implicit string literal, e.g. do not
change its whitespace at all.

Now correctly formats:
 #include < path with space >
 #error Leave     all         white!!!!! space* alone!

Note that for #error and #warning we still format the space up to the
first token of the text, so:
   #  error   Text
will become
 #error Text

llvm-svn: 172536
This commit is contained in:
Manuel Klimek 2013-01-15 15:50:27 +00:00
parent f71e7ad3cc
commit 99c7baa3cf
2 changed files with 39 additions and 7 deletions

View File

@ -34,7 +34,7 @@ enum TokenType {
TT_CastRParen,
TT_ConditionalExpr,
TT_CtorInitializerColon,
TT_IncludePath,
TT_ImplicitStringLiteral,
TT_LineComment,
TT_ObjCBlockLParen,
TT_ObjCDecl,
@ -374,6 +374,11 @@ private:
assert(State.Stack.size());
unsigned ParenLevel = State.Stack.size() - 1;
if (Current.Type == TT_ImplicitStringLiteral) {
moveStateToNextToken(State);
return;
}
if (Newline) {
unsigned WhitespaceStartColumn = State.Column;
if (Current.is(tok::r_brace)) {
@ -862,8 +867,27 @@ public:
}
void parseIncludeDirective() {
next();
if (CurrentToken != NULL && CurrentToken->is(tok::less)) {
next();
while (CurrentToken != NULL) {
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
} else {
while (CurrentToken != NULL) {
next();
}
}
}
void parseWarningOrError() {
next();
// We still want to format the whitespace left of the first token of the
// warning or error.
next();
while (CurrentToken != NULL) {
CurrentToken->Type = TT_IncludePath;
CurrentToken->Type = TT_ImplicitStringLiteral;
next();
}
}
@ -882,6 +906,10 @@ public:
case tok::pp_import:
parseIncludeDirective();
break;
case tok::pp_error:
case tok::pp_warning:
parseWarningOrError();
break;
default:
break;
}
@ -1213,8 +1241,6 @@ private:
if (Tok.Parent->is(tok::comma))
return true;
if (Tok.Type == TT_IncludePath)
return Tok.is(tok::less) || Tok.is(tok::string_literal);
if (Tok.Type == TT_CtorInitializerColon || Tok.Type == TT_ObjCBlockLParen)
return true;
if (Tok.Type == TT_OverloadedOperator)
@ -1264,8 +1290,6 @@ private:
// Don't break at ':' if identifier before it can beak.
return false;
}
if (Right.Type == TT_IncludePath)
return false;
if (Right.is(tok::colon) && Right.Type == TT_ObjCMethodExpr)
return false;
if (Left.is(tok::colon) && Left.Type == TT_ObjCMethodExpr)

View File

@ -1184,7 +1184,8 @@ TEST_F(FormatTest, HandlesIncludeDirectives) {
"#include \"a/b/string\"\n"
"#include \"string.h\"\n"
"#include \"string.h\"\n"
"#include <a-a>");
"#include <a-a>\n"
"#include < path with space >\n");
verifyFormat("#import <string>");
verifyFormat("#import <a/b/c.h>");
@ -1334,6 +1335,13 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
" f();\n");
}
TEST_F(FormatTest, DoNotInterfereWithErrorAndWarning) {
verifyFormat("#error Leave all white!!!!! space* alone!\n");
verifyFormat("#warning Leave all white!!!!! space* alone!\n");
EXPECT_EQ("#error 1", format(" # error 1"));
EXPECT_EQ("#warning 1", format(" # warning 1"));
}
// FIXME: This breaks the order of the unwrapped lines:
// TEST_F(FormatTest, OrderUnwrappedLines) {
// verifyFormat("{\n"