| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <sstream> | 5 #include <sstream> |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
| 10 #include "tools/gn/commands.h" | 10 #include "tools/gn/commands.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 " gn format --stdin\n"; | 52 " gn format --stdin\n"; |
| 53 | 53 |
| 54 namespace { | 54 namespace { |
| 55 | 55 |
| 56 const int kIndentSize = 2; | 56 const int kIndentSize = 2; |
| 57 const int kMaximumWidth = 80; | 57 const int kMaximumWidth = 80; |
| 58 | 58 |
| 59 const int kPenaltyLineBreak = 500; | 59 const int kPenaltyLineBreak = 500; |
| 60 const int kPenaltyHorizontalSeparation = 100; | 60 const int kPenaltyHorizontalSeparation = 100; |
| 61 const int kPenaltyExcess = 10000; | 61 const int kPenaltyExcess = 10000; |
| 62 const int kPenaltyBrokenLineOnOneLiner = 1000; | 62 const int kPenaltyBrokenLineOnOneLiner = 5000; |
| 63 | 63 |
| 64 enum Precedence { | 64 enum Precedence { |
| 65 kPrecedenceLowest, | 65 kPrecedenceLowest, |
| 66 kPrecedenceAssign, | 66 kPrecedenceAssign, |
| 67 kPrecedenceOr, | 67 kPrecedenceOr, |
| 68 kPrecedenceAnd, | 68 kPrecedenceAnd, |
| 69 kPrecedenceCompare, | 69 kPrecedenceCompare, |
| 70 kPrecedenceAdd, | 70 kPrecedenceAdd, |
| 71 kPrecedenceSuffix, | 71 kPrecedenceSuffix, |
| 72 kPrecedenceUnary, | 72 kPrecedenceUnary, |
| 73 }; | 73 }; |
| 74 | 74 |
| 75 int CountLines(const std::string& str) { |
| 76 std::vector<std::string> lines; |
| 77 base::SplitStringDontTrim(str, '\n', &lines); |
| 78 return static_cast<int>(lines.size()); |
| 79 } |
| 80 |
| 75 class Printer { | 81 class Printer { |
| 76 public: | 82 public: |
| 77 Printer(); | 83 Printer(); |
| 78 ~Printer(); | 84 ~Printer(); |
| 79 | 85 |
| 80 void Block(const ParseNode* file); | 86 void Block(const ParseNode* file); |
| 81 | 87 |
| 82 std::string String() const { return output_; } | 88 std::string String() const { return output_; } |
| 83 | 89 |
| 84 private: | 90 private: |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 // Format a list of values using the given style. | 150 // Format a list of values using the given style. |
| 145 // |end| holds any trailing comments to be printed just before the closing | 151 // |end| holds any trailing comments to be printed just before the closing |
| 146 // bracket. | 152 // bracket. |
| 147 template <class PARSENODE> // Just for const covariance. | 153 template <class PARSENODE> // Just for const covariance. |
| 148 void Sequence(SequenceStyle style, | 154 void Sequence(SequenceStyle style, |
| 149 const std::vector<PARSENODE*>& list, | 155 const std::vector<PARSENODE*>& list, |
| 150 const ParseNode* end, | 156 const ParseNode* end, |
| 151 bool force_multiline); | 157 bool force_multiline); |
| 152 | 158 |
| 153 // Returns the penalty. | 159 // Returns the penalty. |
| 154 int FunctionCall(const FunctionCallNode* func_call); | 160 int FunctionCall(const FunctionCallNode* func_call, |
| 161 const std::string& suffix); |
| 155 | 162 |
| 156 // Create a clone of this Printer in a similar state (other than the output, | 163 // Create a clone of this Printer in a similar state (other than the output, |
| 157 // but including margins, etc.) to be used for dry run measurements. | 164 // but including margins, etc.) to be used for dry run measurements. |
| 158 void InitializeSub(Printer* sub); | 165 void InitializeSub(Printer* sub); |
| 159 | 166 |
| 167 template <class PARSENODE> |
| 168 bool ListWillBeMultiline(const std::vector<PARSENODE*>& list, |
| 169 const ParseNode* end); |
| 170 |
| 160 std::string output_; // Output buffer. | 171 std::string output_; // Output buffer. |
| 161 std::vector<Token> comments_; // Pending end-of-line comments. | 172 std::vector<Token> comments_; // Pending end-of-line comments. |
| 162 int margin() const { return stack_.back().margin; } | 173 int margin() const { return stack_.back().margin; } |
| 163 | 174 |
| 164 int penalty_depth_; | 175 int penalty_depth_; |
| 165 int GetPenaltyForLineBreak() const { | 176 int GetPenaltyForLineBreak() const { |
| 166 return penalty_depth_ * kPenaltyLineBreak; | 177 return penalty_depth_ * kPenaltyLineBreak; |
| 167 } | 178 } |
| 168 | 179 |
| 169 struct IndentState { | 180 struct IndentState { |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 void Printer::AddParen(int prec, int outer_prec, bool* parenthesized) { | 371 void Printer::AddParen(int prec, int outer_prec, bool* parenthesized) { |
| 361 if (prec < outer_prec) { | 372 if (prec < outer_prec) { |
| 362 Print("("); | 373 Print("("); |
| 363 *parenthesized = true; | 374 *parenthesized = true; |
| 364 } | 375 } |
| 365 } | 376 } |
| 366 | 377 |
| 367 int Printer::Expr(const ParseNode* root, | 378 int Printer::Expr(const ParseNode* root, |
| 368 int outer_prec, | 379 int outer_prec, |
| 369 const std::string& suffix) { | 380 const std::string& suffix) { |
| 381 std::string at_end = suffix; |
| 370 int penalty = 0; | 382 int penalty = 0; |
| 371 penalty_depth_++; | 383 penalty_depth_++; |
| 372 | 384 |
| 373 if (root->comments()) { | 385 if (root->comments()) { |
| 374 if (!root->comments()->before().empty()) { | 386 if (!root->comments()->before().empty()) { |
| 375 Trim(); | 387 Trim(); |
| 376 // If there's already other text on the line, start a new line. | 388 // If there's already other text on the line, start a new line. |
| 377 if (CurrentColumn() > 0) | 389 if (CurrentColumn() > 0) |
| 378 Print("\n"); | 390 Print("\n"); |
| 379 // We're printing a line comment, so we need to be at the current margin. | 391 // We're printing a line comment, so we need to be at the current margin. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 398 Print("["); | 410 Print("["); |
| 399 Expr(accessor->index(), kPrecedenceLowest, "]"); | 411 Expr(accessor->index(), kPrecedenceLowest, "]"); |
| 400 } | 412 } |
| 401 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { | 413 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { |
| 402 CHECK(precedence_.find(binop->op().value()) != precedence_.end()); | 414 CHECK(precedence_.find(binop->op().value()) != precedence_.end()); |
| 403 AnnotatePreferedMultilineAssignment(binop); | 415 AnnotatePreferedMultilineAssignment(binop); |
| 404 Precedence prec = precedence_[binop->op().value()]; | 416 Precedence prec = precedence_[binop->op().value()]; |
| 405 AddParen(prec, outer_prec, &parenthesized); | 417 AddParen(prec, outer_prec, &parenthesized); |
| 406 int start_line = CurrentLine(); | 418 int start_line = CurrentLine(); |
| 407 int start_column = CurrentColumn(); | 419 int start_column = CurrentColumn(); |
| 420 bool is_assignment = binop->op().value() == "=" || |
| 421 binop->op().value() == "+=" || |
| 422 binop->op().value() == "-="; |
| 423 // A sort of funny special case for the long lists that are common in .gn |
| 424 // files, don't indent them + 4, even though they're just continuations when |
| 425 // they're simple lists like "x = [ a, b, c, ... ]" |
| 426 const ListNode* right_as_list = binop->right()->AsList(); |
| 408 int indent_column = | 427 int indent_column = |
| 409 (binop->op().value() == "=" || binop->op().value() == "+=" || | 428 (is_assignment && |
| 410 binop->op().value() == "-=") | 429 (!right_as_list || (!right_as_list->prefer_multiline() && |
| 430 !ListWillBeMultiline(right_as_list->contents(), |
| 431 right_as_list->End())))) |
| 411 ? margin() + kIndentSize * 2 | 432 ? margin() + kIndentSize * 2 |
| 412 : start_column; | 433 : start_column; |
| 413 if (stack_.back().continuation_requires_indent) | 434 if (stack_.back().continuation_requires_indent) |
| 414 indent_column += kIndentSize * 2; | 435 indent_column += kIndentSize * 2; |
| 415 | 436 |
| 416 Expr(binop->left(), | 437 stack_.push_back(IndentState(indent_column, false)); |
| 417 prec, | 438 Printer sub_left; |
| 418 std::string(" ") + binop->op().value().as_string()); | 439 InitializeSub(&sub_left); |
| 440 sub_left.Expr(binop->left(), |
| 441 prec, |
| 442 std::string(" ") + binop->op().value().as_string()); |
| 443 bool left_is_multiline = CountLines(sub_left.String()) > 1; |
| 444 // Avoid walking the whole left redundantly times (see timing of Format.046) |
| 445 // so pull the output and comments from subprinter. |
| 446 Print(sub_left.String().substr(start_column)); |
| 447 std::copy(sub_left.comments_.begin(), |
| 448 sub_left.comments_.end(), |
| 449 std::back_inserter(comments_)); |
| 419 | 450 |
| 420 // Single line. | 451 // Single line. |
| 421 Printer sub1; | 452 Printer sub1; |
| 422 InitializeSub(&sub1); | 453 InitializeSub(&sub1); |
| 423 sub1.stack_.push_back(IndentState(indent_column, false)); | |
| 424 sub1.Print(" "); | 454 sub1.Print(" "); |
| 425 int penalty_current_line = | 455 int penalty_current_line = |
| 426 sub1.Expr(binop->right(), prec + 1, std::string()); | 456 sub1.Expr(binop->right(), prec + 1, std::string()); |
| 427 sub1.Print(suffix); | 457 sub1.Print(suffix); |
| 428 penalty_current_line += AssessPenalty(sub1.String()); | 458 penalty_current_line += AssessPenalty(sub1.String()); |
| 459 if (!is_assignment && left_is_multiline) { |
| 460 // In e.g. xxx + yyy, if xxx is already multiline, then we want a penalty |
| 461 // for trying to continue as if this were one line. |
| 462 penalty_current_line += |
| 463 (CountLines(sub1.String()) - 1) * kPenaltyBrokenLineOnOneLiner; |
| 464 } |
| 429 | 465 |
| 430 // Break after operator. | 466 // Break after operator. |
| 431 Printer sub2; | 467 Printer sub2; |
| 432 InitializeSub(&sub2); | 468 InitializeSub(&sub2); |
| 433 sub2.stack_.push_back(IndentState(indent_column, false)); | |
| 434 sub2.Newline(); | 469 sub2.Newline(); |
| 435 int penalty_next_line = sub2.Expr(binop->right(), prec + 1, std::string()); | 470 int penalty_next_line = sub2.Expr(binop->right(), prec + 1, std::string()); |
| 436 sub2.Print(suffix); | 471 sub2.Print(suffix); |
| 437 penalty_next_line += AssessPenalty(sub2.String()); | 472 penalty_next_line += AssessPenalty(sub2.String()); |
| 438 | 473 |
| 439 if (penalty_current_line < penalty_next_line) { | 474 if (penalty_current_line < penalty_next_line) { |
| 440 Print(" "); | 475 Print(" "); |
| 441 Expr(binop->right(), prec + 1, std::string()); | 476 Expr(binop->right(), prec + 1, std::string()); |
| 442 } else { | 477 } else { |
| 443 // Otherwise, put first argument and op, and indent next. | 478 // Otherwise, put first argument and op, and indent next. |
| 444 stack_.push_back(IndentState(indent_column, false)); | |
| 445 Newline(); | 479 Newline(); |
| 446 penalty += std::abs(CurrentColumn() - start_column) * | 480 penalty += std::abs(CurrentColumn() - start_column) * |
| 447 kPenaltyHorizontalSeparation; | 481 kPenaltyHorizontalSeparation; |
| 448 Expr(binop->right(), prec + 1, std::string()); | 482 Expr(binop->right(), prec + 1, std::string()); |
| 449 stack_.pop_back(); | |
| 450 } | 483 } |
| 484 stack_.pop_back(); |
| 451 penalty += (CurrentLine() - start_line) * GetPenaltyForLineBreak(); | 485 penalty += (CurrentLine() - start_line) * GetPenaltyForLineBreak(); |
| 452 } else if (const BlockNode* block = root->AsBlock()) { | 486 } else if (const BlockNode* block = root->AsBlock()) { |
| 453 Sequence( | 487 Sequence( |
| 454 kSequenceStyleBracedBlock, block->statements(), block->End(), false); | 488 kSequenceStyleBracedBlock, block->statements(), block->End(), false); |
| 455 } else if (const ConditionNode* condition = root->AsConditionNode()) { | 489 } else if (const ConditionNode* condition = root->AsConditionNode()) { |
| 456 Print("if ("); | 490 Print("if ("); |
| 457 // TODO(scottmg): The { needs to be included in the suffix here. | 491 // TODO(scottmg): The { needs to be included in the suffix here. |
| 458 Expr(condition->condition(), kPrecedenceLowest, ") "); | 492 Expr(condition->condition(), kPrecedenceLowest, ") "); |
| 459 Sequence(kSequenceStyleBracedBlock, | 493 Sequence(kSequenceStyleBracedBlock, |
| 460 condition->if_true()->statements(), | 494 condition->if_true()->statements(), |
| 461 condition->if_true()->End(), | 495 condition->if_true()->End(), |
| 462 false); | 496 false); |
| 463 if (condition->if_false()) { | 497 if (condition->if_false()) { |
| 464 Print(" else "); | 498 Print(" else "); |
| 465 // If it's a block it's a bare 'else', otherwise it's an 'else if'. See | 499 // If it's a block it's a bare 'else', otherwise it's an 'else if'. See |
| 466 // ConditionNode::Execute. | 500 // ConditionNode::Execute. |
| 467 bool is_else_if = condition->if_false()->AsBlock() == NULL; | 501 bool is_else_if = condition->if_false()->AsBlock() == NULL; |
| 468 if (is_else_if) { | 502 if (is_else_if) { |
| 469 Expr(condition->if_false(), kPrecedenceLowest, std::string()); | 503 Expr(condition->if_false(), kPrecedenceLowest, std::string()); |
| 470 } else { | 504 } else { |
| 471 Sequence(kSequenceStyleBracedBlock, | 505 Sequence(kSequenceStyleBracedBlock, |
| 472 condition->if_false()->AsBlock()->statements(), | 506 condition->if_false()->AsBlock()->statements(), |
| 473 condition->if_false()->AsBlock()->End(), false); | 507 condition->if_false()->AsBlock()->End(), |
| 508 false); |
| 474 } | 509 } |
| 475 } | 510 } |
| 476 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { | 511 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { |
| 477 penalty += FunctionCall(func_call); | 512 penalty += FunctionCall(func_call, at_end); |
| 513 at_end = ""; |
| 478 } else if (const IdentifierNode* identifier = root->AsIdentifier()) { | 514 } else if (const IdentifierNode* identifier = root->AsIdentifier()) { |
| 479 Print(identifier->value().value()); | 515 Print(identifier->value().value()); |
| 480 } else if (const ListNode* list = root->AsList()) { | 516 } else if (const ListNode* list = root->AsList()) { |
| 481 bool force_multiline = | 517 bool force_multiline = |
| 482 list->prefer_multiline() && !list->contents().empty(); | 518 list->prefer_multiline() && !list->contents().empty(); |
| 483 Sequence( | 519 Sequence( |
| 484 kSequenceStyleList, list->contents(), list->End(), force_multiline); | 520 kSequenceStyleList, list->contents(), list->End(), force_multiline); |
| 485 } else if (const LiteralNode* literal = root->AsLiteral()) { | 521 } else if (const LiteralNode* literal = root->AsLiteral()) { |
| 486 Print(literal->value().value()); | 522 Print(literal->value().value()); |
| 487 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { | 523 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 498 if (parenthesized) | 534 if (parenthesized) |
| 499 Print(")"); | 535 Print(")"); |
| 500 | 536 |
| 501 // Defer any end of line comment until we reach the newline. | 537 // Defer any end of line comment until we reach the newline. |
| 502 if (root->comments() && !root->comments()->suffix().empty()) { | 538 if (root->comments() && !root->comments()->suffix().empty()) { |
| 503 std::copy(root->comments()->suffix().begin(), | 539 std::copy(root->comments()->suffix().begin(), |
| 504 root->comments()->suffix().end(), | 540 root->comments()->suffix().end(), |
| 505 std::back_inserter(comments_)); | 541 std::back_inserter(comments_)); |
| 506 } | 542 } |
| 507 | 543 |
| 508 Print(suffix); | 544 Print(at_end); |
| 509 | 545 |
| 510 penalty_depth_--; | 546 penalty_depth_--; |
| 511 return penalty; | 547 return penalty; |
| 512 } | 548 } |
| 513 | 549 |
| 514 template <class PARSENODE> | 550 template <class PARSENODE> |
| 515 void Printer::Sequence(SequenceStyle style, | 551 void Printer::Sequence(SequenceStyle style, |
| 516 const std::vector<PARSENODE*>& list, | 552 const std::vector<PARSENODE*>& list, |
| 517 const ParseNode* end, | 553 const ParseNode* end, |
| 518 bool force_multiline) { | 554 bool force_multiline) { |
| 519 if (style == kSequenceStyleList) | 555 if (style == kSequenceStyleList) |
| 520 Print("["); | 556 Print("["); |
| 521 else if (style == kSequenceStyleBracedBlock) | 557 else if (style == kSequenceStyleBracedBlock) |
| 522 Print("{"); | 558 Print("{"); |
| 523 | 559 |
| 524 if (style == kSequenceStyleBlock || style == kSequenceStyleBracedBlock) | 560 if (style == kSequenceStyleBlock || style == kSequenceStyleBracedBlock) |
| 525 force_multiline = true; | 561 force_multiline = true; |
| 526 | 562 |
| 527 if (end && end->comments() && !end->comments()->before().empty()) | 563 force_multiline |= ListWillBeMultiline(list, end); |
| 528 force_multiline = true; | |
| 529 | |
| 530 // If there's before line comments, make sure we have a place to put them. | |
| 531 for (const auto& i : list) { | |
| 532 if (i->comments() && !i->comments()->before().empty()) | |
| 533 force_multiline = true; | |
| 534 } | |
| 535 | 564 |
| 536 if (list.size() == 0 && !force_multiline) { | 565 if (list.size() == 0 && !force_multiline) { |
| 537 // No elements, and not forcing newlines, print nothing. | 566 // No elements, and not forcing newlines, print nothing. |
| 538 } else if (list.size() == 1 && !force_multiline) { | 567 } else if (list.size() == 1 && !force_multiline) { |
| 539 Print(" "); | 568 Print(" "); |
| 540 Expr(list[0], kPrecedenceLowest, std::string()); | 569 Expr(list[0], kPrecedenceLowest, std::string()); |
| 541 CHECK(!list[0]->comments() || list[0]->comments()->after().empty()); | 570 CHECK(!list[0]->comments() || list[0]->comments()->after().empty()); |
| 542 Print(" "); | 571 Print(" "); |
| 543 } else { | 572 } else { |
| 544 stack_.push_back( | 573 stack_.push_back( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 564 if (!want_comma) { | 593 if (!want_comma) { |
| 565 if (i < list.size() - 1 && | 594 if (i < list.size() - 1 && |
| 566 ShouldAddBlankLineInBetween(list[i], list[i + 1])) | 595 ShouldAddBlankLineInBetween(list[i], list[i + 1])) |
| 567 Newline(); | 596 Newline(); |
| 568 } | 597 } |
| 569 } | 598 } |
| 570 ++i; | 599 ++i; |
| 571 } | 600 } |
| 572 | 601 |
| 573 // Trailing comments. | 602 // Trailing comments. |
| 574 if (end->comments()) { | 603 if (end->comments() && !end->comments()->before().empty()) { |
| 575 if (list.size() >= 2) | 604 if (list.size() >= 2) |
| 576 Newline(); | 605 Newline(); |
| 577 for (const auto& c : end->comments()->before()) { | 606 for (const auto& c : end->comments()->before()) { |
| 578 Newline(); | 607 Newline(); |
| 579 TrimAndPrintToken(c); | 608 TrimAndPrintToken(c); |
| 580 } | 609 } |
| 581 } | 610 } |
| 582 | 611 |
| 583 stack_.pop_back(); | 612 stack_.pop_back(); |
| 584 Newline(); | 613 Newline(); |
| 585 | 614 |
| 586 // Defer any end of line comment until we reach the newline. | 615 // Defer any end of line comment until we reach the newline. |
| 587 if (end->comments() && !end->comments()->suffix().empty()) { | 616 if (end->comments() && !end->comments()->suffix().empty()) { |
| 588 std::copy(end->comments()->suffix().begin(), | 617 std::copy(end->comments()->suffix().begin(), |
| 589 end->comments()->suffix().end(), | 618 end->comments()->suffix().end(), |
| 590 std::back_inserter(comments_)); | 619 std::back_inserter(comments_)); |
| 591 } | 620 } |
| 592 } | 621 } |
| 593 | 622 |
| 594 if (style == kSequenceStyleList) | 623 if (style == kSequenceStyleList) |
| 595 Print("]"); | 624 Print("]"); |
| 596 else if (style == kSequenceStyleBracedBlock) | 625 else if (style == kSequenceStyleBracedBlock) |
| 597 Print("}"); | 626 Print("}"); |
| 598 } | 627 } |
| 599 | 628 |
| 600 int Printer::FunctionCall(const FunctionCallNode* func_call) { | 629 int Printer::FunctionCall(const FunctionCallNode* func_call, |
| 630 const std::string& suffix) { |
| 601 int start_line = CurrentLine(); | 631 int start_line = CurrentLine(); |
| 602 int start_column = CurrentColumn(); | 632 int start_column = CurrentColumn(); |
| 603 Print(func_call->function().value()); | 633 Print(func_call->function().value()); |
| 604 Print("("); | 634 Print("("); |
| 605 | 635 |
| 606 bool have_block = func_call->block() != nullptr; | 636 bool have_block = func_call->block() != nullptr; |
| 607 bool force_multiline = false; | 637 bool force_multiline = false; |
| 608 | 638 |
| 609 const std::vector<const ParseNode*>& list = func_call->args()->contents(); | 639 const std::vector<const ParseNode*>& list = func_call->args()->contents(); |
| 610 const ParseNode* end = func_call->args()->End(); | 640 const ParseNode* end = func_call->args()->End(); |
| 611 | 641 |
| 612 if (end && end->comments() && !end->comments()->before().empty()) | 642 if (end && end->comments() && !end->comments()->before().empty()) |
| 613 force_multiline = true; | 643 force_multiline = true; |
| 614 | 644 |
| 615 // If there's before line comments, make sure we have a place to put them. | 645 // If there's before line comments, make sure we have a place to put them. |
| 616 for (const auto& i : list) { | 646 for (const auto& i : list) { |
| 617 if (i->comments() && !i->comments()->before().empty()) | 647 if (i->comments() && !i->comments()->before().empty()) |
| 618 force_multiline = true; | 648 force_multiline = true; |
| 619 } | 649 } |
| 620 | 650 |
| 621 // Calculate the penalties for 3 possible layouts: | 651 // Calculate the penalties for 3 possible layouts: |
| 622 // 1. all on same line; | 652 // 1. all on same line; |
| 623 // 2. starting on same line, broken at each comma but paren aligned; | 653 // 2. starting on same line, broken at each comma but paren aligned; |
| 624 // 3. broken to next line + 4, broken at each comma. | 654 // 3. broken to next line + 4, broken at each comma. |
| 625 std::string terminator = ")"; | 655 std::string terminator = ")"; |
| 626 if (have_block) | 656 if (have_block) |
| 627 terminator += " {"; | 657 terminator += " {"; |
| 658 terminator += suffix; |
| 628 | 659 |
| 629 // 1: Same line. | 660 // 1: Same line. |
| 630 Printer sub1; | 661 Printer sub1; |
| 631 InitializeSub(&sub1); | 662 InitializeSub(&sub1); |
| 632 sub1.stack_.push_back(IndentState(CurrentColumn(), true)); | 663 sub1.stack_.push_back(IndentState(CurrentColumn(), true)); |
| 633 int penalty_one_line = 0; | 664 int penalty_one_line = 0; |
| 634 for (size_t i = 0; i < list.size(); ++i) { | 665 for (size_t i = 0; i < list.size(); ++i) { |
| 635 penalty_one_line += sub1.Expr(list[i], kPrecedenceLowest, | 666 penalty_one_line += sub1.Expr(list[i], kPrecedenceLowest, |
| 636 i < list.size() - 1 ? ", " : std::string()); | 667 i < list.size() - 1 ? ", " : std::string()); |
| 637 } | 668 } |
| 638 sub1.Print(terminator); | 669 sub1.Print(terminator); |
| 639 penalty_one_line += AssessPenalty(sub1.String()); | 670 penalty_one_line += AssessPenalty(sub1.String()); |
| 640 std::vector<std::string> lines; | |
| 641 base::SplitStringDontTrim(sub1.String(), '\n', &lines); | |
| 642 // This extra penalty prevents a short second argument from being squeezed in | 671 // This extra penalty prevents a short second argument from being squeezed in |
| 643 // after a first argument that went multiline (and instead preferring a | 672 // after a first argument that went multiline (and instead preferring a |
| 644 // variant below). | 673 // variant below). |
| 645 if (lines.size() > 1) | 674 penalty_one_line += |
| 646 penalty_one_line += kPenaltyBrokenLineOnOneLiner; | 675 (CountLines(sub1.String()) - 1) * kPenaltyBrokenLineOnOneLiner; |
| 647 | 676 |
| 648 // 2: Starting on same line, broken at commas. | 677 // 2: Starting on same line, broken at commas. |
| 649 Printer sub2; | 678 Printer sub2; |
| 650 InitializeSub(&sub2); | 679 InitializeSub(&sub2); |
| 651 sub2.stack_.push_back(IndentState(CurrentColumn(), true)); | 680 sub2.stack_.push_back(IndentState(CurrentColumn(), true)); |
| 652 int penalty_multiline_start_same_line = 0; | 681 int penalty_multiline_start_same_line = 0; |
| 653 for (size_t i = 0; i < list.size(); ++i) { | 682 for (size_t i = 0; i < list.size(); ++i) { |
| 654 penalty_multiline_start_same_line += sub2.Expr( | 683 penalty_multiline_start_same_line += sub2.Expr( |
| 655 list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string()); | 684 list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string()); |
| 656 if (i < list.size() - 1) { | 685 if (i < list.size() - 1) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 stack_.pop_back(); | 764 stack_.pop_back(); |
| 736 } | 765 } |
| 737 | 766 |
| 738 // Defer any end of line comment until we reach the newline. | 767 // Defer any end of line comment until we reach the newline. |
| 739 if (end->comments() && !end->comments()->suffix().empty()) { | 768 if (end->comments() && !end->comments()->suffix().empty()) { |
| 740 std::copy(end->comments()->suffix().begin(), | 769 std::copy(end->comments()->suffix().begin(), |
| 741 end->comments()->suffix().end(), std::back_inserter(comments_)); | 770 end->comments()->suffix().end(), std::back_inserter(comments_)); |
| 742 } | 771 } |
| 743 | 772 |
| 744 Print(")"); | 773 Print(")"); |
| 774 Print(suffix); |
| 745 | 775 |
| 746 if (have_block) { | 776 if (have_block) { |
| 747 Print(" "); | 777 Print(" "); |
| 748 Sequence(kSequenceStyleBracedBlock, | 778 Sequence(kSequenceStyleBracedBlock, |
| 749 func_call->block()->statements(), | 779 func_call->block()->statements(), |
| 750 func_call->block()->End(), | 780 func_call->block()->End(), |
| 751 false); | 781 false); |
| 752 } | 782 } |
| 753 return penalty + (CurrentLine() - start_line) * GetPenaltyForLineBreak(); | 783 return penalty + (CurrentLine() - start_line) * GetPenaltyForLineBreak(); |
| 754 } | 784 } |
| 755 | 785 |
| 756 void Printer::InitializeSub(Printer* sub) { | 786 void Printer::InitializeSub(Printer* sub) { |
| 757 sub->stack_ = stack_; | 787 sub->stack_ = stack_; |
| 758 sub->comments_ = comments_; | 788 sub->comments_ = comments_; |
| 759 sub->penalty_depth_ = penalty_depth_; | 789 sub->penalty_depth_ = penalty_depth_; |
| 760 sub->Print(std::string(CurrentColumn(), 'x')); | 790 sub->Print(std::string(CurrentColumn(), 'x')); |
| 761 } | 791 } |
| 762 | 792 |
| 793 template <class PARSENODE> |
| 794 bool Printer::ListWillBeMultiline(const std::vector<PARSENODE*>& list, |
| 795 const ParseNode* end) { |
| 796 if (list.size() > 1) |
| 797 return true; |
| 798 |
| 799 if (end && end->comments() && !end->comments()->before().empty()) |
| 800 return true; |
| 801 |
| 802 // If there's before line comments, make sure we have a place to put them. |
| 803 for (const auto& i : list) { |
| 804 if (i->comments() && !i->comments()->before().empty()) |
| 805 return true; |
| 806 } |
| 807 |
| 808 return false; |
| 809 } |
| 810 |
| 763 void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) { | 811 void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) { |
| 764 if (dump_tree) { | 812 if (dump_tree) { |
| 765 std::ostringstream os; | 813 std::ostringstream os; |
| 766 root->Print(os, 0); | 814 root->Print(os, 0); |
| 767 printf("----------------------\n"); | 815 printf("----------------------\n"); |
| 768 printf("-- PARSE TREE --------\n"); | 816 printf("-- PARSE TREE --------\n"); |
| 769 printf("----------------------\n"); | 817 printf("----------------------\n"); |
| 770 printf("%s", os.str().c_str()); | 818 printf("%s", os.str().c_str()); |
| 771 printf("----------------------\n"); | 819 printf("----------------------\n"); |
| 772 } | 820 } |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 printf("Wrote formatted to '%s'.\n", to_write.AsUTF8Unsafe().c_str()); | 935 printf("Wrote formatted to '%s'.\n", to_write.AsUTF8Unsafe().c_str()); |
| 888 } else { | 936 } else { |
| 889 printf("%s", output_string.c_str()); | 937 printf("%s", output_string.c_str()); |
| 890 } | 938 } |
| 891 } | 939 } |
| 892 | 940 |
| 893 return 0; | 941 return 0; |
| 894 } | 942 } |
| 895 | 943 |
| 896 } // namespace commands | 944 } // namespace commands |
| OLD | NEW |