aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2013-01-10 18:45:26 +0000
committerManuel Klimek <klimek@google.com>2013-01-10 18:45:26 +0000
commit3f8c7f3a07df65580a9ca0fe3e956b8a40956a79 (patch)
treedbe66addd091b3af502f01a0b40df516d7f4a1ac
parentc8c8a478639f1474f4c53d12befc405934083633 (diff)
Pulling formatFirstToken one level up.
This prepares the code for single line optimizations and changes the dependencies between single-line-formats to the indent of the first token. Conceptually, the first token is "between" the lines anyway, as the whitespace for the first token includes the previous end-of-line, which needs to be escaped when inside a preprocessor directive. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172083 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Format/Format.cpp176
1 files changed, 91 insertions, 85 deletions
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index de92b75b0b..d2ea7ec301 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -123,17 +123,52 @@ struct OptimizationParameters {
unsigned PenaltyExcessCharacter;
};
+/// \brief Replaces the whitespace in front of \p Tok. Only call once for
+/// each \c FormatToken.
+static void replaceWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
+ unsigned Spaces, const FormatStyle &Style,
+ SourceManager &SourceMgr,
+ tooling::Replacements &Replaces) {
+ Replaces.insert(tooling::Replacement(
+ SourceMgr, Tok.FormatTok.WhiteSpaceStart, Tok.FormatTok.WhiteSpaceLength,
+ std::string(NewLines, '\n') + std::string(Spaces, ' ')));
+}
+
+/// \brief Like \c replaceWhitespace, but additionally adds right-aligned
+/// backslashes to escape newlines inside a preprocessor directive.
+///
+/// This function and \c replaceWhitespace have the same behavior if
+/// \c Newlines == 0.
+static void replacePPWhitespace(
+ const AnnotatedToken &Tok, unsigned NewLines, unsigned Spaces,
+ unsigned WhitespaceStartColumn, const FormatStyle &Style,
+ SourceManager &SourceMgr, tooling::Replacements &Replaces) {
+ std::string NewLineText;
+ if (NewLines > 0) {
+ unsigned Offset = std::min<int>(Style.ColumnLimit - 1,
+ WhitespaceStartColumn);
+ for (unsigned i = 0; i < NewLines; ++i) {
+ NewLineText += std::string(Style.ColumnLimit - Offset - 1, ' ');
+ NewLineText += "\\\n";
+ Offset = 0;
+ }
+ }
+ Replaces.insert(tooling::Replacement(SourceMgr, Tok.FormatTok.WhiteSpaceStart,
+ Tok.FormatTok.WhiteSpaceLength,
+ NewLineText + std::string(Spaces, ' ')));
+}
+
class UnwrappedLineFormatter {
public:
UnwrappedLineFormatter(
const FormatStyle &Style, SourceManager &SourceMgr,
- const UnwrappedLine &Line, unsigned PreviousEndOfLineColumn,
+ const UnwrappedLine &Line, unsigned FirstIndent,
LineType CurrentLineType, const AnnotatedToken &RootToken,
tooling::Replacements &Replaces, bool StructuralError)
: Style(Style), SourceMgr(SourceMgr), Line(Line),
- PreviousEndOfLineColumn(PreviousEndOfLineColumn),
+ FirstIndent(FirstIndent),
CurrentLineType(CurrentLineType), RootToken(RootToken),
- Replaces(Replaces), StructuralError(StructuralError) {
+ Replaces(Replaces) {
Parameters.PenaltyIndentLevel = 15;
Parameters.PenaltyLevelDecrease = 30;
Parameters.PenaltyExcessCharacter = 1000000;
@@ -144,15 +179,12 @@ public:
/// \returns The column after the last token in the last line of the
/// \c UnwrappedLine.
unsigned format() {
- // Format first token and initialize indent.
- unsigned Indent = formatFirstToken();
-
// Initialize state dependent on indent.
IndentState State;
- State.Column = Indent;
+ State.Column = FirstIndent;
State.NextToken = &RootToken;
- State.Indent.push_back(Indent + 4);
- State.LastSpace.push_back(Indent);
+ State.Indent.push_back(FirstIndent + 4);
+ State.LastSpace.push_back(FirstIndent);
State.FirstLessLess.push_back(0);
State.BreakBeforeClosingBrace.push_back(false);
State.ForLoopVariablePos = 0;
@@ -325,10 +357,12 @@ private:
if (!DryRun) {
if (!Line.InPPDirective)
- replaceWhitespace(Current.FormatTok, 1, State.Column);
+ replaceWhitespace(Current.FormatTok, 1, State.Column, Style,
+ SourceMgr, Replaces);
else
replacePPWhitespace(Current.FormatTok, 1, State.Column,
- WhitespaceStartColumn);
+ WhitespaceStartColumn, Style, SourceMgr,
+ Replaces);
}
State.LastSpace[ParenLevel] = State.Column;
@@ -345,7 +379,7 @@ private:
Spaces = Style.SpacesBeforeTrailingComments;
if (!DryRun)
- replaceWhitespace(Current, 0, Spaces);
+ replaceWhitespace(Current, 0, Spaces, Style, SourceMgr, Replaces);
// FIXME: Do we need to do this for assignments nested in other
// expressions?
@@ -528,82 +562,13 @@ private:
return Result == UINT_MAX ? UINT_MAX : Result + CurrentPenalty;
}
- /// \brief Replaces the whitespace in front of \p Tok. Only call once for
- /// each \c FormatToken.
- void replaceWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
- unsigned Spaces) {
- Replaces.insert(tooling::Replacement(
- SourceMgr, Tok.FormatTok.WhiteSpaceStart,
- Tok.FormatTok.WhiteSpaceLength,
- std::string(NewLines, '\n') + std::string(Spaces, ' ')));
- }
-
- /// \brief Like \c replaceWhitespace, but additionally adds right-aligned
- /// backslashes to escape newlines inside a preprocessor directive.
- ///
- /// This function and \c replaceWhitespace have the same behavior if
- /// \c Newlines == 0.
- void replacePPWhitespace(const AnnotatedToken &Tok, unsigned NewLines,
- unsigned Spaces, unsigned WhitespaceStartColumn) {
- std::string NewLineText;
- if (NewLines > 0) {
- unsigned Offset = std::min<int>(Style.ColumnLimit - 1,
- WhitespaceStartColumn);
- for (unsigned i = 0; i < NewLines; ++i) {
- NewLineText += std::string(Style.ColumnLimit - Offset - 1, ' ');
- NewLineText += "\\\n";
- Offset = 0;
- }
- }
- Replaces.insert(
- tooling::Replacement(SourceMgr, Tok.FormatTok.WhiteSpaceStart,
- Tok.FormatTok.WhiteSpaceLength,
- NewLineText + std::string(Spaces, ' ')));
- }
-
- /// \brief Add a new line and the required indent before the first Token
- /// of the \c UnwrappedLine if there was no structural parsing error.
- /// Returns the indent level of the \c UnwrappedLine.
- unsigned formatFirstToken() {
- const FormatToken &Tok = RootToken.FormatTok;
- if (!Tok.WhiteSpaceStart.isValid() || StructuralError)
- return SourceMgr.getSpellingColumnNumber(Tok.Tok.getLocation()) - 1;
-
- unsigned Newlines = std::min(Tok.NewlinesBefore,
- Style.MaxEmptyLinesToKeep + 1);
- if (Newlines == 0 && !Tok.IsFirst)
- Newlines = 1;
- unsigned Indent = Line.Level * 2;
-
- bool IsAccessModifier = false;
- if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) ||
- RootToken.is(tok::kw_private))
- IsAccessModifier = true;
- else if (RootToken.is(tok::at) && !RootToken.Children.empty() &&
- (RootToken.Children[0].isObjCAtKeyword(tok::objc_public) ||
- RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) ||
- RootToken.Children[0].isObjCAtKeyword(tok::objc_package) ||
- RootToken.Children[0].isObjCAtKeyword(tok::objc_private)))
- IsAccessModifier = true;
-
- if (IsAccessModifier &&
- static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
- Indent += Style.AccessModifierOffset;
- if (!Line.InPPDirective || Tok.HasUnescapedNewline)
- replaceWhitespace(Tok, Newlines, Indent);
- else
- replacePPWhitespace(Tok, Newlines, Indent, PreviousEndOfLineColumn);
- return Indent;
- }
-
FormatStyle Style;
SourceManager &SourceMgr;
const UnwrappedLine &Line;
- const unsigned PreviousEndOfLineColumn;
+ const unsigned FirstIndent;
const LineType CurrentLineType;
const AnnotatedToken &RootToken;
tooling::Replacements &Replaces;
- bool StructuralError;
// A map from an indent state to a pair (Result, Used-StopAt).
typedef std::map<IndentState, std::pair<unsigned, unsigned> > StateMap;
@@ -1245,8 +1210,7 @@ public:
Lexer &Lex, SourceManager &SourceMgr,
const std::vector<CharSourceRange> &Ranges)
: Diag(Diag), Style(Style), Lex(Lex), SourceMgr(SourceMgr),
- Ranges(Ranges), StructuralError(false) {
- }
+ Ranges(Ranges) {}
virtual ~Formatter() {
}
@@ -1289,8 +1253,11 @@ private:
TokenAnnotator Annotator(TheLine, Style, SourceMgr, Lex);
if (!Annotator.annotate())
break;
+ unsigned Indent = formatFirstToken(Annotator.getRootToken(),
+ TheLine.Level, TheLine.InPPDirective,
+ PreviousEndOfLineColumn);
UnwrappedLineFormatter Formatter(
- Style, SourceMgr, TheLine, PreviousEndOfLineColumn,
+ Style, SourceMgr, TheLine, Indent,
Annotator.getLineType(), Annotator.getRootToken(), Replaces,
StructuralError);
return Formatter.format();
@@ -1304,6 +1271,45 @@ private:
1;
}
+ /// \brief Add a new line and the required indent before the first Token
+ /// of the \c UnwrappedLine if there was no structural parsing error.
+ /// Returns the indent level of the \c UnwrappedLine.
+ unsigned formatFirstToken(const AnnotatedToken &RootToken, unsigned Level,
+ bool InPPDirective,
+ unsigned PreviousEndOfLineColumn) {
+ const FormatToken& Tok = RootToken.FormatTok;
+ if (!Tok.WhiteSpaceStart.isValid() || StructuralError)
+ return SourceMgr.getSpellingColumnNumber(Tok.Tok.getLocation()) - 1;
+
+ unsigned Newlines = std::min(Tok.NewlinesBefore,
+ Style.MaxEmptyLinesToKeep + 1);
+ if (Newlines == 0 && !Tok.IsFirst)
+ Newlines = 1;
+ unsigned Indent = Level * 2;
+
+ bool IsAccessModifier = false;
+ if (RootToken.is(tok::kw_public) || RootToken.is(tok::kw_protected) ||
+ RootToken.is(tok::kw_private))
+ IsAccessModifier = true;
+ else if (RootToken.is(tok::at) && !RootToken.Children.empty() &&
+ (RootToken.Children[0].isObjCAtKeyword(tok::objc_public) ||
+ RootToken.Children[0].isObjCAtKeyword(tok::objc_protected) ||
+ RootToken.Children[0].isObjCAtKeyword(tok::objc_package) ||
+ RootToken.Children[0].isObjCAtKeyword(tok::objc_private)))
+ IsAccessModifier = true;
+
+ if (IsAccessModifier &&
+ static_cast<int>(Indent) + Style.AccessModifierOffset >= 0)
+ Indent += Style.AccessModifierOffset;
+ if (!InPPDirective || Tok.HasUnescapedNewline) {
+ replaceWhitespace(Tok, Newlines, Indent, Style, SourceMgr, Replaces);
+ } else {
+ replacePPWhitespace(Tok, Newlines, Indent, PreviousEndOfLineColumn, Style,
+ SourceMgr, Replaces);
+ }
+ return Indent;
+ }
+
clang::DiagnosticsEngine &Diag;
FormatStyle Style;
Lexer &Lex;