| 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);
|
| }
|
| }
|
|
|
|
|