Index: tools/gn/command_format.cc |
diff --git a/tools/gn/command_format.cc b/tools/gn/command_format.cc |
index 8162698861d8d522fba405f8ada0dbe54e339f56..c3396474fc7759a1c469b58f4aa310009b934f02 100644 |
--- a/tools/gn/command_format.cc |
+++ b/tools/gn/command_format.cc |
@@ -113,7 +113,7 @@ class Printer { |
// Whether there's a blank separator line at the current position. |
bool HaveBlankLine(); |
- bool IsAssignment(const ParseNode* node); |
+ bool IsAlwaysMultilineAssignment(const ParseNode* node); |
// 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 |
@@ -131,12 +131,17 @@ class Printer { |
// Print the expression to the output buffer. Returns the type of element |
// 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); |
+ // Expr must introduce parentheses. |prefer_multiline| is used to cause |
+ // the RHS of certain special assignments to be caused to be multiline. |
+ ExprStyle Expr(const ParseNode* root, |
+ int outer_prec, |
+ bool prefer_multiline); |
// 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); |
+ Metrics GetLengthOfExpr(const ParseNode* expr, |
+ int outer_prec, |
+ bool prefer_multiline); |
// Format a list of values using the given style. |
// |end| holds any trailing comments to be printed just before the closing |
@@ -144,7 +149,8 @@ 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); |
@@ -234,10 +240,21 @@ 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() == "-="); |
+bool Printer::IsAlwaysMultilineAssignment(const ParseNode* node) { |
+ if (node->AsBinaryOp() && node->AsBinaryOp()->op().value() == "=") { |
+ const IdentifierNode* ident = node->AsBinaryOp()->left()->AsIdentifier(); |
+ return ident && |
+ // TODO(scottmg): This is somewhat arbitrary, but we include the |
+ // 'deps'- and 'sources'-like things, but not flags things. |
+ (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"); |
+ } |
+ return false; |
} |
bool Printer::ShouldAddBlankLineInBetween(const ParseNode* a, |
@@ -270,7 +287,7 @@ void Printer::Block(const ParseNode* root) { |
size_t i = 0; |
for (const auto& stmt : block->statements()) { |
- Expr(stmt, kPrecedenceLowest); |
+ Expr(stmt, kPrecedenceLowest, false); |
Newline(); |
if (stmt->comments()) { |
// Why are before() not printed here too? before() are handled inside |
@@ -300,10 +317,11 @@ void Printer::Block(const ParseNode* root) { |
} |
Printer::Metrics Printer::GetLengthOfExpr(const ParseNode* expr, |
- int outer_prec) { |
+ int outer_prec, |
+ bool prefer_multiline) { |
Metrics result; |
Printer sub; |
- sub.Expr(expr, outer_prec); |
+ sub.Expr(expr, outer_prec, prefer_multiline); |
std::vector<std::string> lines; |
base::SplitStringDontTrim(sub.String(), '\n', &lines); |
result.multiline = lines.size() > 1; |
@@ -322,7 +340,9 @@ void Printer::AddParen(int prec, int outer_prec, bool* parenthesized) { |
} |
} |
-Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) { |
+Printer::ExprStyle Printer::Expr(const ParseNode* root, |
+ int outer_prec, |
+ bool prefer_multiline) { |
ExprStyle result = kExprStyleRegular; |
if (root->comments()) { |
if (!root->comments()->before().empty()) { |
@@ -346,26 +366,27 @@ 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, false); |
} else { |
CHECK(accessor->index()); |
Print("["); |
- Expr(accessor->index(), kPrecedenceLowest); |
+ Expr(accessor->index(), kPrecedenceLowest, false); |
Print("]"); |
} |
} else if (const BinaryOpNode* binop = root->AsBinaryOp()) { |
CHECK(precedence_.find(binop->op().value()) != precedence_.end()); |
Precedence prec = precedence_[binop->op().value()]; |
AddParen(prec, outer_prec, &parenthesized); |
- Metrics right = GetLengthOfExpr(binop->right(), prec + 1); |
+ Metrics right = GetLengthOfExpr( |
+ binop->right(), prec + 1, IsAlwaysMultilineAssignment(binop)); |
int op_length = static_cast<int>(binop->op().value().size()) + 2; |
- Expr(binop->left(), prec); |
+ Expr(binop->left(), prec, false); |
if (CurrentColumn() + op_length + right.first_length <= kMaximumWidth) { |
// If it just fits normally, put it here. |
Print(" "); |
Print(binop->op().value()); |
Print(" "); |
- Expr(binop->right(), prec + 1); |
+ Expr(binop->right(), prec + 1, IsAlwaysMultilineAssignment(binop)); |
} else { |
// Otherwise, put first argument and op, and indent next. |
Print(" "); |
@@ -373,29 +394,32 @@ Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) { |
int old_margin = margin_; |
margin_ += kIndentSize * 2; |
Newline(); |
- Expr(binop->right(), prec + 1); |
+ Expr(binop->right(), prec + 1, IsAlwaysMultilineAssignment(binop)); |
margin_ = old_margin; |
} |
} 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); |
+ Expr(condition->condition(), kPrecedenceLowest, false); |
Print(") "); |
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, false); |
} 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()) { |
@@ -403,13 +427,15 @@ Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) { |
} 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 = 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, false); |
} else if (const BlockCommentNode* block_comment = root->AsBlockComment()) { |
Print(block_comment->comment().value()); |
result = kExprStyleComment; |
@@ -435,8 +461,8 @@ Printer::ExprStyle Printer::Expr(const ParseNode* root, int outer_prec) { |
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,7 +484,7 @@ 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, false); |
CHECK(!list[0]->comments() || list[0]->comments()->after().empty()); |
Print(" "); |
} else { |
@@ -475,7 +501,7 @@ void Printer::Sequence(SequenceStyle style, |
!HaveBlankLine()) { |
Newline(); |
} |
- ExprStyle expr_style = Expr(x, kPrecedenceLowest); |
+ ExprStyle expr_style = Expr(x, kPrecedenceLowest, false); |
CHECK(!x->comments() || x->comments()->after().empty()); |
if (i < list.size() - 1 || style == kSequenceStyleList) { |
if (style == kSequenceStyleList && expr_style == kExprStyleRegular) { |
@@ -547,7 +573,7 @@ void Printer::FunctionCall(const FunctionCallNode* func_call) { |
if (have_block) |
terminator += " {"; |
for (size_t i = 0; i < list.size(); ++i) { |
- Metrics sub = GetLengthOfExpr(list[i], kPrecedenceLowest); |
+ Metrics sub = GetLengthOfExpr(list[i], kPrecedenceLowest, false); |
if (sub.multiline) |
fits_on_current_line = false; |
natural_lengths.push_back(sub.longest_length); |
@@ -567,14 +593,14 @@ void Printer::FunctionCall(const FunctionCallNode* func_call) { |
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); |
+ Expr(list[0], kPrecedenceLowest, false); |
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); |
+ Expr(list[i], kPrecedenceLowest, false); |
if (i < list.size() - 1) |
Print(", "); |
} |
@@ -595,7 +621,7 @@ void Printer::FunctionCall(const FunctionCallNode* func_call) { |
// position should do that instead of going back to margin+4. |
if (i > 0 || should_break_to_next_line) |
Newline(); |
- ExprStyle expr_style = Expr(x, kPrecedenceLowest); |
+ ExprStyle expr_style = Expr(x, kPrecedenceLowest, false); |
CHECK(!x->comments() || x->comments()->after().empty()); |
if (i < list.size() - 1) { |
if (expr_style == kExprStyleRegular) { |
@@ -635,7 +661,8 @@ void Printer::FunctionCall(const FunctionCallNode* func_call) { |
Print(" "); |
Sequence(kSequenceStyleBracedBlock, |
func_call->block()->statements(), |
- func_call->block()->End()); |
+ func_call->block()->End(), |
+ false); |
} |
} |