}
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
- llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", T=" << Line.Type
- << ", C=" << Line.IsContinuation << "):\n";
+ llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
+ << ", T=" << Line.Type << ", C=" << Line.IsContinuation
+ << "):\n";
const FormatToken *Tok = Line.First;
while (Tok) {
llvm::errs() << " M=" << Tok->MustBreakBefore
public:
AnnotatedLine(const UnwrappedLine &Line)
: First(Line.Tokens.front().Tok), Level(Line.Level),
+ PPLevel(Line.PPLevel),
MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
InPPDirective(Line.InPPDirective),
LineType Type;
unsigned Level;
+ unsigned PPLevel;
size_t MatchingOpeningBlockLineIndex;
size_t MatchingClosingBlockLineIndex;
bool InPPDirective;
// Update the indent level cache size so that we can rely on it
// having the right size in adjustToUnmodifiedline.
skipLine(Line, /*UnknownIndent=*/true);
- if (Line.InPPDirective ||
- (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
- Line.Type == LT_CommentAbovePPDirective)) {
- unsigned IndentWidth =
+ if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
+ (Line.InPPDirective ||
+ (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
+ Line.Type == LT_CommentAbovePPDirective))) {
+ unsigned PPIndentWidth =
(Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
- Indent = Line.Level * IndentWidth + AdditionalIndent;
+ Indent = Line.InMacroBody
+ ? Line.PPLevel * PPIndentWidth +
+ (Line.Level - Line.PPLevel) * Style.IndentWidth
+ : Line.Level * PPIndentWidth;
+ Indent += AdditionalIndent;
} else {
Indent = getIndent(Line.Level);
}
PreBlockLine = std::move(Parser.Line);
Parser.Line = std::make_unique<UnwrappedLine>();
Parser.Line->Level = PreBlockLine->Level;
+ Parser.Line->PPLevel = PreBlockLine->PPLevel;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
}
delete SavedToken.Tok;
}
+ // If these change PPLevel needs to be used for get correct indentation.
+ assert(!Line.InMacroBody);
+ assert(!Line.InPPDirective);
return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
}
Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
++Line->Level;
+
+ Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
+ assert((int)Line->PPLevel >= 0);
Line->InMacroBody = true;
// Errors during a preprocessor directive can only affect the layout of the
/// The indent level of the \c UnwrappedLine.
unsigned Level;
+ /// The \c PPBranchLevel (adjusted for header guards) if this line is a
+ /// \c InMacroBody line, and 0 otherwise.
+ unsigned PPLevel;
+
/// Whether this \c UnwrappedLine is part of a preprocessor directive.
bool InPPDirective;
/// Whether this \c UnwrappedLine is part of a pramga directive.
};
inline UnwrappedLine::UnwrappedLine()
- : Level(0), InPPDirective(false), InPragmaDirective(false),
+ : Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
InMacroBody(false), MustBeDeclaration(false),
MatchingOpeningBlockLineIndex(kInvalidIndex) {}
" int y = 0;\n"
"}",
style);
+
+ style.IndentPPDirectives = FormatStyle::PPDIS_None;
+ verifyFormat("#ifdef foo\n"
+ "#define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ "#endif",
+ style);
+ verifyFormat("if (emacs) {\n"
+ "#ifdef is\n"
+ "#define lit \\\n"
+ " if (af) { \\\n"
+ " return duh(); \\\n"
+ " }\n"
+ "#endif\n"
+ "}",
+ style);
+ verifyFormat("#if abc\n"
+ "#ifdef foo\n"
+ "#define bar() \\\n"
+ " if (A) { \\\n"
+ " if (B) { \\\n"
+ " C(); \\\n"
+ " } \\\n"
+ " } \\\n"
+ " D();\n"
+ "#endif\n"
+ "#endif",
+ style);
+ verifyFormat("#ifndef foo\n"
+ "#define foo\n"
+ "if (emacs) {\n"
+ "#ifdef is\n"
+ "#define lit \\\n"
+ " if (af) { \\\n"
+ " return duh(); \\\n"
+ " }\n"
+ "#endif\n"
+ "}\n"
+ "#endif",
+ style);
+ verifyFormat("#if 1\n"
+ "#define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }\n"
+ "#endif",
+ style);
+ verifyFormat("#define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }",
+ style);
+
+ style.PPIndentWidth = 2;
+ verifyFormat("#ifdef foo\n"
+ "#define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ "#endif",
+ style);
+ style.IndentWidth = 8;
+ verifyFormat("#ifdef foo\n"
+ "#define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ "#endif",
+ style);
+
+ style.IndentWidth = 1;
+ style.PPIndentWidth = 4;
+ verifyFormat("#if 1\n"
+ "#define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }\n"
+ "#endif",
+ style);
+ verifyFormat("#define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }",
+ style);
+
+ style.IndentWidth = 4;
+ style.PPIndentWidth = 1;
+ style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash;
+ verifyFormat("#ifdef foo\n"
+ "# define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ "#endif",
+ style);
+ verifyFormat("#if abc\n"
+ "# ifdef foo\n"
+ "# define bar() \\\n"
+ " if (A) { \\\n"
+ " if (B) { \\\n"
+ " C(); \\\n"
+ " } \\\n"
+ " } \\\n"
+ " D();\n"
+ "# endif\n"
+ "#endif",
+ style);
+ verifyFormat("#ifndef foo\n"
+ "#define foo\n"
+ "if (emacs) {\n"
+ "#ifdef is\n"
+ "# define lit \\\n"
+ " if (af) { \\\n"
+ " return duh(); \\\n"
+ " }\n"
+ "#endif\n"
+ "}\n"
+ "#endif",
+ style);
+ verifyFormat("#define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }",
+ style);
+
+ style.PPIndentWidth = 2;
+ style.IndentWidth = 8;
+ verifyFormat("#ifdef foo\n"
+ "# define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ "#endif",
+ style);
+
+ style.PPIndentWidth = 4;
+ style.IndentWidth = 1;
+ verifyFormat("#define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }",
+ style);
+
+ style.IndentWidth = 4;
+ style.PPIndentWidth = 1;
+ style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash;
+ verifyFormat("if (emacs) {\n"
+ "#ifdef is\n"
+ " #define lit \\\n"
+ " if (af) { \\\n"
+ " return duh(); \\\n"
+ " }\n"
+ "#endif\n"
+ "}",
+ style);
+ verifyFormat("#if abc\n"
+ " #ifdef foo\n"
+ " #define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ " #endif\n"
+ "#endif",
+ style);
+ verifyFormat("#if 1\n"
+ " #define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }\n"
+ "#endif",
+ style);
+
+ style.PPIndentWidth = 2;
+ verifyFormat("#ifdef foo\n"
+ " #define bar() \\\n"
+ " if (A) { \\\n"
+ " B(); \\\n"
+ " } \\\n"
+ " C();\n"
+ "#endif",
+ style);
+
+ style.PPIndentWidth = 4;
+ style.IndentWidth = 1;
+ verifyFormat("#if 1\n"
+ " #define X \\\n"
+ " { \\\n"
+ " x; \\\n"
+ " x; \\\n"
+ " }\n"
+ "#endif",
+ style);
}
TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) {