Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Unified Diff: tools/gn/command_format.cc

Issue 748863003: gn format: penalty-based scheme for line breaking (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gn-more-disabled
Patch Set: x64 Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/gn/command_format_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/gn/command_format.cc
diff --git a/tools/gn/command_format.cc b/tools/gn/command_format.cc
index 8162698861d8d522fba405f8ada0dbe54e339f56..593c150139016949dbe4722d17d7ebde6fb92985 100644
--- a/tools/gn/command_format.cc
+++ b/tools/gn/command_format.cc
@@ -56,6 +56,11 @@ namespace {
const int kIndentSize = 2;
const int kMaximumWidth = 80;
+const int kPenaltyLineBreak = 500;
+const int kPenaltyHorizontalSeparation = 100;
+const int kPenaltyExcess = 10000;
+const int kPenaltyBrokenLineOnOneLiner = 1000;
+
enum Precedence {
kPrecedenceLowest,
kPrecedenceAssign,
@@ -84,11 +89,6 @@ class Printer {
kSequenceStyleBracedBlock,
};
- enum ExprStyle {
- kExprStyleRegular,
- kExprStyleComment,
- };
-
struct Metrics {
Metrics() : first_length(-1), longest_length(-1), multiline(false) {}
int first_length;
@@ -113,7 +113,8 @@ class Printer {
// Whether there's a blank separator line at the current position.
bool HaveBlankLine();
- bool IsAssignment(const ParseNode* node);
+ // Flag assignments to sources, deps, etc. to make their RHSs multiline.
+ void AnnotatePreferedMultilineAssignment(const BinaryOpNode* binop);
// Heuristics to decide if there should be a blank line added between two
// items. For various "small" items, it doesn't look nice if there's too much
@@ -121,7 +122,10 @@ class Printer {
bool ShouldAddBlankLineInBetween(const ParseNode* a, const ParseNode* b);
// Get the 0-based x position on the current line.
- int CurrentColumn();
+ int CurrentColumn() const;
+
+ // Get the current line in the output;
+ int CurrentLine() const;
// Adds an opening ( if prec is less than the outers (to maintain evalution
// order for a subexpression). If an opening paren is emitted, *parenthesized
@@ -132,11 +136,10 @@ class Printer {
// added to the output. The value of outer_prec gives the precedence of the
// operator outside this Expr. If that operator binds tighter than root's,
// Expr must introduce parentheses.
- ExprStyle Expr(const ParseNode* root, int outer_prec);
+ int Expr(const ParseNode* root, int outer_prec, const std::string& suffix);
- // Use a sub-Printer recursively to figure out the size that an expression
- // would be before actually adding it to the output.
- Metrics GetLengthOfExpr(const ParseNode* expr, int outer_prec);
+ // Generic penalties for exceeding maximum width, adding more lines, etc.
+ int AssessPenalty(const std::string& output);
// Format a list of values using the given style.
// |end| holds any trailing comments to be printed just before the closing
@@ -144,13 +147,38 @@ class Printer {
template <class PARSENODE> // Just for const covariance.
void Sequence(SequenceStyle style,
const std::vector<PARSENODE*>& list,
- const ParseNode* end);
+ const ParseNode* end,
+ bool force_multiline);
- void FunctionCall(const FunctionCallNode* func_call);
+ // Returns the penalty.
+ int FunctionCall(const FunctionCallNode* func_call);
+
+ // Create a clone of this Printer in a similar state (other than the output,
+ // but including margins, etc.) to be used for dry run measurements.
+ void InitializeSub(Printer* sub);
std::string output_; // Output buffer.
std::vector<Token> comments_; // Pending end-of-line comments.
- int margin_; // Left margin (number of spaces).
+ int margin() const { return stack_.back().margin; }
+
+ int penalty_depth_;
+ int GetPenaltyForLineBreak() const {
+ return penalty_depth_ * kPenaltyLineBreak;
+ }
+
+ struct IndentState {
+ IndentState() : margin(0), continuation_requires_indent(false) {}
+ IndentState(int margin, bool continuation_requires_indent)
+ : margin(margin),
+ continuation_requires_indent(continuation_requires_indent) {}
+
+ // The left margin (number of spaces).
+ int margin;
+
+ bool continuation_requires_indent;
+ };
+ // Stack used to track
+ std::vector<IndentState> stack_;
// Gives the precedence for operators in a BinaryOpNode.
std::map<base::StringPiece, Precedence> precedence_;
@@ -158,7 +186,7 @@ class Printer {
DISALLOW_COPY_AND_ASSIGN(Printer);
};
-Printer::Printer() : margin_(0) {
+Printer::Printer() : penalty_depth_(0) {
output_.reserve(100 << 10);
precedence_["="] = kPrecedenceAssign;
precedence_["+="] = kPrecedenceAssign;
@@ -174,6 +202,7 @@ Printer::Printer() : margin_(0) {
precedence_["+"] = kPrecedenceAdd;
precedence_["-"] = kPrecedenceAdd;
precedence_["!"] = kPrecedenceUnary;
+ stack_.push_back(IndentState());
}
Printer::~Printer() {
@@ -184,7 +213,7 @@ void Printer::Print(base::StringPiece str) {
}
void Printer::PrintMargin() {
- output_ += std::string(margin_, ' ');
+ output_ += std::string(margin(), ' ');
}
void Printer::TrimAndPrintToken(const Token& token) {
@@ -196,15 +225,13 @@ void Printer::TrimAndPrintToken(const Token& token) {
void Printer::Newline() {
if (!comments_.empty()) {
Print(" ");
- int i = 0;
// Save the margin, and temporarily set it to where the first comment
// starts so that multiple suffix comments are vertically aligned. This
// will need to be fancier once we enforce 80 col.
- int old_margin = margin_;
+ stack_.push_back(IndentState(CurrentColumn(), false));
+ int i = 0;
for (const auto& c : comments_) {
- if (i == 0)
- margin_ = CurrentColumn();
- else {
+ if (i > 0) {
Trim();
Print("\n");
PrintMargin();
@@ -212,7 +239,7 @@ void Printer::Newline() {
TrimAndPrintToken(c);
++i;
}
- margin_ = old_margin;
+ stack_.pop_back();
comments_.clear();
}
Trim();
@@ -234,10 +261,20 @@ bool Printer::HaveBlankLine() {
return n > 2 && output_[n - 1] == '\n' && output_[n - 2] == '\n';
}
-bool Printer::IsAssignment(const ParseNode* node) {
- return node->AsBinaryOp() && (node->AsBinaryOp()->op().value() == "=" ||
- node->AsBinaryOp()->op().value() == "+=" ||
- node->AsBinaryOp()->op().value() == "-=");
+void Printer::AnnotatePreferedMultilineAssignment(const BinaryOpNode* binop) {
+ const IdentifierNode* ident = binop->left()->AsIdentifier();
+ const ListNode* list = binop->right()->AsList();
+ // This is somewhat arbitrary, but we include the 'deps'- and 'sources'-like
+ // things, but not flags things.
+ if (binop->op().value() == "=" && ident && list &&
+ (ident->value().value() == "data" ||
+ ident->value().value() == "datadeps" ||
+ ident->value().value() == "deps" || ident->value().value() == "inputs" ||
+ ident->value().value() == "public" ||
+ ident->value().value() == "public_deps" ||
+ ident->value().value() == "sources")) {
+ const_cast<ListNode*>(list)->set_prefer_multiline(true);
+ }
}
bool Printer::ShouldAddBlankLineInBetween(const ParseNode* a,
@@ -249,7 +286,7 @@ bool Printer::ShouldAddBlankLineInBetween(const ParseNode* a,
return b_range.begin().line_number() > a_range.end().line_number() + 1;
}
-int Printer::CurrentColumn() {
+int Printer::CurrentColumn() const {
int n = 0;
while (n < static_cast<int>(output_.size()) &&
output_[output_.size() - 1 - n] != '\n') {
@@ -258,6 +295,15 @@ int Printer::CurrentColumn() {
return n;
}
+int Printer::CurrentLine() const {
+ int count = 1;
+ for (const char* p = output_.c_str(); (p = strchr(p, '\n')) != NULL;) {
+ ++count;
+ ++p;
+ }
+ return count;
+}
+
void Printer::Block(const ParseNode* root) {
const BlockNode* block = root->AsBlock();
@@ -270,7 +316,7 @@ void Printer::Block(const ParseNode* root) {
size_t i = 0;
for (const auto& stmt : block->statements()) {
- Expr(stmt, kPrecedenceLowest);
+ Expr(stmt, kPrecedenceLowest, std::string());
Newline();
if (stmt->comments()) {
// Why are before() not printed here too? before() are handled inside
@@ -299,20 +345,16 @@ void Printer::Block(const ParseNode* root) {
}
}
-Printer::Metrics Printer::GetLengthOfExpr(const ParseNode* expr,
- int outer_prec) {
- Metrics result;
- Printer sub;
- sub.Expr(expr, outer_prec);
+int Printer::AssessPenalty(const std::string& output) {
+ int penalty = 0;
std::vector<std::string> lines;
- base::SplitStringDontTrim(sub.String(), '\n', &lines);
- result.multiline = lines.size() > 1;
- result.first_length = static_cast<int>(lines[0].size());
+ base::SplitStringDontTrim(output, '\n', &lines);
+ penalty += static_cast<int>(lines.size() - 1) * GetPenaltyForLineBreak();
for (const auto& line : lines) {
- result.longest_length =
- std::max(result.longest_length, static_cast<int>(line.size()));
+ if (line.size() > kMaximumWidth)
+ penalty += static_cast<int>(line.size() - kMaximumWidth) * kPenaltyExcess;
}
- return result;
+ return penalty;
}
void Printer::AddParen(int prec, int outer_prec, bool* parenthesized) {
@@ -322,8 +364,12 @@ void Printer::AddParen(int prec, int outer_prec, bool* parenthesized) {
}
}
-Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) {
- ExprStyle result = kExprStyleRegular;
+int Printer::Expr(const ParseNode* root,
+ int outer_prec,
+ const std::string& suffix) {
+ int penalty = 0;
+ penalty_depth_++;
+
if (root->comments()) {
if (!root->comments()->before().empty()) {
Trim();
@@ -346,73 +392,103 @@ Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) {
Print(accessor->base().value());
if (accessor->member()) {
Print(".");
- Expr(accessor->member(), kPrecedenceLowest);
+ Expr(accessor->member(), kPrecedenceLowest, std::string());
} else {
CHECK(accessor->index());
Print("[");
- Expr(accessor->index(), kPrecedenceLowest);
- Print("]");
+ Expr(accessor->index(), kPrecedenceLowest, "]");
}
} else if (const BinaryOpNode* binop = root->AsBinaryOp()) {
CHECK(precedence_.find(binop->op().value()) != precedence_.end());
+ AnnotatePreferedMultilineAssignment(binop);
Precedence prec = precedence_[binop->op().value()];
AddParen(prec, outer_prec, &parenthesized);
- Metrics right = GetLengthOfExpr(binop->right(), prec + 1);
- int op_length = static_cast<int>(binop->op().value().size()) + 2;
- Expr(binop->left(), prec);
- if (CurrentColumn() + op_length + right.first_length <= kMaximumWidth) {
- // If it just fits normally, put it here.
- Print(" ");
- Print(binop->op().value());
+ int start_line = CurrentLine();
+ int start_column = CurrentColumn();
+ int indent_column =
+ (binop->op().value() == "=" || binop->op().value() == "+=" ||
+ binop->op().value() == "-=")
+ ? margin() + kIndentSize * 2
+ : start_column;
+ if (stack_.back().continuation_requires_indent)
+ indent_column += kIndentSize * 2;
+
+ Expr(binop->left(),
+ prec,
+ std::string(" ") + binop->op().value().as_string());
+
+ // Single line.
+ Printer sub1;
+ InitializeSub(&sub1);
+ sub1.stack_.push_back(IndentState(indent_column, false));
+ sub1.Print(" ");
+ int penalty_current_line =
+ sub1.Expr(binop->right(), prec + 1, std::string());
+ sub1.Print(suffix);
+ penalty_current_line += AssessPenalty(sub1.String());
+
+ // Break after operator.
+ Printer sub2;
+ InitializeSub(&sub2);
+ sub2.stack_.push_back(IndentState(indent_column, false));
+ sub2.Newline();
+ int penalty_next_line = sub2.Expr(binop->right(), prec + 1, std::string());
+ sub2.Print(suffix);
+ penalty_next_line += AssessPenalty(sub2.String());
+
+ if (penalty_current_line < penalty_next_line) {
Print(" ");
- Expr(binop->right(), prec + 1);
+ Expr(binop->right(), prec + 1, std::string());
} else {
// Otherwise, put first argument and op, and indent next.
- Print(" ");
- Print(binop->op().value());
- int old_margin = margin_;
- margin_ += kIndentSize * 2;
+ stack_.push_back(IndentState(indent_column, false));
Newline();
- Expr(binop->right(), prec + 1);
- margin_ = old_margin;
+ penalty += std::abs(CurrentColumn() - start_column) *
+ kPenaltyHorizontalSeparation;
+ Expr(binop->right(), prec + 1, std::string());
+ stack_.pop_back();
}
+ penalty += (CurrentLine() - start_line) * GetPenaltyForLineBreak();
} else if (const BlockNode* block = root->AsBlock()) {
- Sequence(kSequenceStyleBracedBlock, block->statements(), block->End());
+ Sequence(
+ kSequenceStyleBracedBlock, block->statements(), block->End(), false);
} else if (const ConditionNode* condition = root->AsConditionNode()) {
Print("if (");
- Expr(condition->condition(), kPrecedenceLowest);
- Print(") ");
+ // TODO(scottmg): The { needs to be included in the suffix here.
+ Expr(condition->condition(), kPrecedenceLowest, ") ");
Sequence(kSequenceStyleBracedBlock,
condition->if_true()->statements(),
- condition->if_true()->End());
+ condition->if_true()->End(),
+ false);
if (condition->if_false()) {
Print(" else ");
// If it's a block it's a bare 'else', otherwise it's an 'else if'. See
// ConditionNode::Execute.
bool is_else_if = condition->if_false()->AsBlock() == NULL;
if (is_else_if) {
- Expr(condition->if_false(), kPrecedenceLowest);
+ Expr(condition->if_false(), kPrecedenceLowest, std::string());
} else {
Sequence(kSequenceStyleBracedBlock,
condition->if_false()->AsBlock()->statements(),
- condition->if_false()->AsBlock()->End());
+ condition->if_false()->AsBlock()->End(), false);
}
}
} else if (const FunctionCallNode* func_call = root->AsFunctionCall()) {
- FunctionCall(func_call);
+ penalty += FunctionCall(func_call);
} else if (const IdentifierNode* identifier = root->AsIdentifier()) {
Print(identifier->value().value());
} else if (const ListNode* list = root->AsList()) {
- Sequence(kSequenceStyleList, list->contents(), list->End());
+ bool force_multiline =
+ list->prefer_multiline() && !list->contents().empty();
+ Sequence(
+ kSequenceStyleList, list->contents(), list->End(), force_multiline);
} else if (const LiteralNode* literal = root->AsLiteral()) {
- // TODO(scottmg): Quoting?
Print(literal->value().value());
} else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) {
Print(unaryop->op().value());
- Expr(unaryop->operand(), kPrecedenceUnary);
+ Expr(unaryop->operand(), kPrecedenceUnary, std::string());
} else if (const BlockCommentNode* block_comment = root->AsBlockComment()) {
Print(block_comment->comment().value());
- result = kExprStyleComment;
} else if (const EndNode* end = root->AsEnd()) {
Print(end->value().value());
} else {
@@ -429,14 +505,17 @@ Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) {
std::back_inserter(comments_));
}
- return result;
+ Print(suffix);
+
+ penalty_depth_--;
+ return penalty;
}
template <class PARSENODE>
void Printer::Sequence(SequenceStyle style,
const std::vector<PARSENODE*>& list,
- const ParseNode* end) {
- bool force_multiline = false;
+ const ParseNode* end,
+ bool force_multiline) {
if (style == kSequenceStyleList)
Print("[");
else if (style == kSequenceStyleBracedBlock)
@@ -458,11 +537,12 @@ void Printer::Sequence(SequenceStyle style,
// No elements, and not forcing newlines, print nothing.
} else if (list.size() == 1 && !force_multiline) {
Print(" ");
- Expr(list[0], kPrecedenceLowest);
+ Expr(list[0], kPrecedenceLowest, std::string());
CHECK(!list[0]->comments() || list[0]->comments()->after().empty());
Print(" ");
} else {
- margin_ += kIndentSize;
+ stack_.push_back(
+ IndentState(margin() + kIndentSize, style == kSequenceStyleList));
size_t i = 0;
for (const auto& x : list) {
Newline();
@@ -475,12 +555,13 @@ void Printer::Sequence(SequenceStyle style,
!HaveBlankLine()) {
Newline();
}
- ExprStyle expr_style = Expr(x, kPrecedenceLowest);
+ bool body_of_list = i < list.size() - 1 || style == kSequenceStyleList;
+ bool want_comma =
+ body_of_list && (style == kSequenceStyleList && !x->AsBlockComment());
+ Expr(x, kPrecedenceLowest, want_comma ? "," : std::string());
CHECK(!x->comments() || x->comments()->after().empty());
- if (i < list.size() - 1 || style == kSequenceStyleList) {
- if (style == kSequenceStyleList && expr_style == kExprStyleRegular) {
- Print(",");
- } else {
+ if (body_of_list) {
+ if (!want_comma) {
if (i < list.size() - 1 &&
ShouldAddBlankLineInBetween(list[i], list[i + 1]))
Newline();
@@ -499,7 +580,7 @@ void Printer::Sequence(SequenceStyle style,
}
}
- margin_ -= kIndentSize;
+ stack_.pop_back();
Newline();
// Defer any end of line comment until we reach the newline.
@@ -516,11 +597,12 @@ void Printer::Sequence(SequenceStyle style,
Print("}");
}
-void Printer::FunctionCall(const FunctionCallNode* func_call) {
+int Printer::FunctionCall(const FunctionCallNode* func_call) {
+ int start_line = CurrentLine();
+ int start_column = CurrentColumn();
Print(func_call->function().value());
Print("(");
- int old_margin = margin_;
bool have_block = func_call->block() != nullptr;
bool force_multiline = false;
@@ -536,107 +618,146 @@ void Printer::FunctionCall(const FunctionCallNode* func_call) {
force_multiline = true;
}
- // Calculate the length of the items for function calls so we can decide to
- // compress them in various nicer ways.
- std::vector<int> natural_lengths;
- bool fits_on_current_line = true;
- int max_item_width = 0;
- int total_length = 0;
- natural_lengths.reserve(list.size());
+ // Calculate the penalties for 3 possible layouts:
+ // 1. all on same line;
+ // 2. starting on same line, broken at each comma but paren aligned;
+ // 3. broken to next line + 4, broken at each comma.
std::string terminator = ")";
if (have_block)
terminator += " {";
+
+ // 1: Same line.
+ Printer sub1;
+ InitializeSub(&sub1);
+ sub1.stack_.push_back(IndentState(CurrentColumn(), true));
+ int penalty_one_line = 0;
for (size_t i = 0; i < list.size(); ++i) {
- Metrics sub = GetLengthOfExpr(list[i], kPrecedenceLowest);
- if (sub.multiline)
- fits_on_current_line = false;
- natural_lengths.push_back(sub.longest_length);
- total_length += sub.longest_length;
+ penalty_one_line += sub1.Expr(list[i], kPrecedenceLowest,
+ i < list.size() - 1 ? ", " : std::string());
+ }
+ sub1.Print(terminator);
+ penalty_one_line += AssessPenalty(sub1.String());
+ std::vector<std::string> lines;
+ base::SplitStringDontTrim(sub1.String(), '\n', &lines);
+ // This extra penalty prevents a short second argument from being squeezed in
+ // after a first argument that went multiline (and instead preferring a
+ // variant below).
+ if (lines.size() > 1)
+ penalty_one_line += kPenaltyBrokenLineOnOneLiner;
+
+ // 2: Starting on same line, broken at commas.
+ Printer sub2;
+ InitializeSub(&sub2);
+ sub2.stack_.push_back(IndentState(CurrentColumn(), true));
+ int penalty_multiline_start_same_line = 0;
+ for (size_t i = 0; i < list.size(); ++i) {
+ penalty_multiline_start_same_line += sub2.Expr(
+ list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string());
if (i < list.size() - 1) {
- total_length += static_cast<int>(strlen(", "));
+ sub2.Newline();
}
}
- fits_on_current_line =
- fits_on_current_line &&
- CurrentColumn() + total_length + terminator.size() <= kMaximumWidth;
- if (natural_lengths.size() > 0) {
- max_item_width =
- *std::max_element(natural_lengths.begin(), natural_lengths.end());
+ sub2.Print(terminator);
+ penalty_multiline_start_same_line += AssessPenalty(sub2.String());
+
+ // 3: Starting on next line, broken at commas.
+ Printer sub3;
+ InitializeSub(&sub3);
+ sub3.stack_.push_back(IndentState(margin() + kIndentSize * 2, true));
+ sub3.Newline();
+ int penalty_multiline_start_next_line = 0;
+ for (size_t i = 0; i < list.size(); ++i) {
+ if (i == 0) {
+ penalty_multiline_start_next_line +=
+ std::abs(sub3.CurrentColumn() - start_column) *
+ kPenaltyHorizontalSeparation;
+ }
+ penalty_multiline_start_next_line += sub3.Expr(
+ list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string());
+ if (i < list.size() - 1) {
+ sub3.Newline();
+ }
+ }
+ sub3.Print(terminator);
+ penalty_multiline_start_next_line += AssessPenalty(sub3.String());
+
+ int penalty = penalty_multiline_start_next_line;
+ bool fits_on_current_line = false;
+ if (penalty_one_line < penalty_multiline_start_next_line ||
+ penalty_multiline_start_same_line < penalty_multiline_start_next_line) {
+ fits_on_current_line = true;
+ penalty = penalty_one_line;
+ if (penalty_multiline_start_same_line < penalty_one_line) {
+ penalty = penalty_multiline_start_same_line;
+ force_multiline = true;
+ }
+ } else {
+ force_multiline = true;
}
if (list.size() == 0 && !force_multiline) {
// No elements, and not forcing newlines, print nothing.
- } else if (list.size() == 1 && !force_multiline && fits_on_current_line) {
- Expr(list[0], kPrecedenceLowest);
- CHECK(!list[0]->comments() || list[0]->comments()->after().empty());
} else {
- // Function calls get to be single line even with multiple arguments, if
- // they fit inside the maximum width.
- if (!force_multiline && fits_on_current_line) {
- for (size_t i = 0; i < list.size(); ++i) {
- Expr(list[i], kPrecedenceLowest);
- if (i < list.size() - 1)
- Print(", ");
- }
+ if (penalty_multiline_start_next_line < penalty_multiline_start_same_line) {
+ stack_.push_back(IndentState(margin() + kIndentSize * 2, true));
+ Newline();
} else {
- bool should_break_to_next_line = true;
- int indent = kIndentSize * 2;
- if (CurrentColumn() + max_item_width + terminator.size() <=
- kMaximumWidth ||
- CurrentColumn() < margin_ + indent) {
- should_break_to_next_line = false;
- margin_ = CurrentColumn();
- } else {
- margin_ += indent;
+ stack_.push_back(IndentState(CurrentColumn(), true));
+ }
+
+ for (size_t i = 0; i < list.size(); ++i) {
+ const auto& x = list[i];
+ if (i > 0) {
+ if (fits_on_current_line && !force_multiline)
+ Print(" ");
+ else
+ Newline();
}
- size_t i = 0;
- for (const auto& x : list) {
- // Function calls where all the arguments would fit at the current
- // position should do that instead of going back to margin+4.
- if (i > 0 || should_break_to_next_line)
+ bool want_comma = i < list.size() - 1 && !x->AsBlockComment();
+ Expr(x, kPrecedenceLowest, want_comma ? "," : std::string());
+ CHECK(!x->comments() || x->comments()->after().empty());
+ if (i < list.size() - 1) {
+ if (!want_comma)
Newline();
- ExprStyle expr_style = Expr(x, kPrecedenceLowest);
- CHECK(!x->comments() || x->comments()->after().empty());
- if (i < list.size() - 1) {
- if (expr_style == kExprStyleRegular) {
- Print(",");
- } else {
- Newline();
- }
- }
- ++i;
}
+ }
- // Trailing comments.
- if (end->comments()) {
- if (!list.empty())
- Newline();
- for (const auto& c : end->comments()->before()) {
- Newline();
- TrimAndPrintToken(c);
- }
- if (!end->comments()->before().empty())
- Newline();
+ // Trailing comments.
+ if (end->comments() && !end->comments()->before().empty()) {
+ if (!list.empty())
+ Newline();
+ for (const auto& c : end->comments()->before()) {
+ Newline();
+ TrimAndPrintToken(c);
}
+ Newline();
}
+ stack_.pop_back();
}
// Defer any end of line comment until we reach the newline.
if (end->comments() && !end->comments()->suffix().empty()) {
std::copy(end->comments()->suffix().begin(),
- end->comments()->suffix().end(),
- std::back_inserter(comments_));
+ end->comments()->suffix().end(), std::back_inserter(comments_));
}
Print(")");
- margin_ = old_margin;
if (have_block) {
Print(" ");
Sequence(kSequenceStyleBracedBlock,
func_call->block()->statements(),
- func_call->block()->End());
+ func_call->block()->End(),
+ false);
}
+ return penalty + (CurrentLine() - start_line) * GetPenaltyForLineBreak();
+}
+
+void Printer::InitializeSub(Printer* sub) {
+ sub->stack_ = stack_;
+ sub->comments_ = comments_;
+ sub->penalty_depth_ = penalty_depth_;
+ sub->Print(std::string(CurrentColumn(), 'x'));
}
void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) {
« no previous file with comments | « no previous file | tools/gn/command_format_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698