| 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 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 Printer sub_left; |
| 417 prec, | 438 InitializeSub(&sub_left); |
| 418 std::string(" ") + binop->op().value().as_string()); | 439 sub_left.Expr(binop->left(), |
| 440 prec, |
| 441 std::string(" ") + binop->op().value().as_string()); |
| 442 bool left_is_multiline = CountLines(sub_left.String()) > 1; |
| 443 // Avoid walking the whole left redundantly times (see timing of Format.046) |
| 444 // so pull the output and comments from subprinter. |
| 445 Print(sub_left.String().substr(start_column)); |
| 446 std::copy(sub_left.comments_.begin(), |
| 447 sub_left.comments_.end(), |
| 448 std::back_inserter(comments_)); |
| 419 | 449 |
| 420 // Single line. | 450 // Single line. |
| 421 Printer sub1; | 451 Printer sub1; |
| 422 InitializeSub(&sub1); | 452 InitializeSub(&sub1); |
| 423 sub1.stack_.push_back(IndentState(indent_column, false)); | 453 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)); | 469 sub2.stack_.push_back(IndentState(indent_column, false)); |
| 434 sub2.Newline(); | 470 sub2.Newline(); |
| 435 int penalty_next_line = sub2.Expr(binop->right(), prec + 1, std::string()); | 471 int penalty_next_line = sub2.Expr(binop->right(), prec + 1, std::string()); |
| 436 sub2.Print(suffix); | 472 sub2.Print(suffix); |
| 437 penalty_next_line += AssessPenalty(sub2.String()); | 473 penalty_next_line += AssessPenalty(sub2.String()); |
| 438 | 474 |
| 475 stack_.push_back(IndentState(indent_column, false)); |
| 439 if (penalty_current_line < penalty_next_line) { | 476 if (penalty_current_line < penalty_next_line) { |
| 440 Print(" "); | 477 Print(" "); |
| 441 Expr(binop->right(), prec + 1, std::string()); | 478 Expr(binop->right(), prec + 1, std::string()); |
| 442 } else { | 479 } else { |
| 443 // Otherwise, put first argument and op, and indent next. | 480 // Otherwise, put first argument and op, and indent next. |
| 444 stack_.push_back(IndentState(indent_column, false)); | |
| 445 Newline(); | 481 Newline(); |
| 446 penalty += std::abs(CurrentColumn() - start_column) * | 482 penalty += std::abs(CurrentColumn() - start_column) * |
| 447 kPenaltyHorizontalSeparation; | 483 kPenaltyHorizontalSeparation; |
| 448 Expr(binop->right(), prec + 1, std::string()); | 484 Expr(binop->right(), prec + 1, std::string()); |
| 449 stack_.pop_back(); | |
| 450 } | 485 } |
| 486 stack_.pop_back(); |
| 451 penalty += (CurrentLine() - start_line) * GetPenaltyForLineBreak(); | 487 penalty += (CurrentLine() - start_line) * GetPenaltyForLineBreak(); |
| 452 } else if (const BlockNode* block = root->AsBlock()) { | 488 } else if (const BlockNode* block = root->AsBlock()) { |
| 453 Sequence( | 489 Sequence( |
| 454 kSequenceStyleBracedBlock, block->statements(), block->End(), false); | 490 kSequenceStyleBracedBlock, block->statements(), block->End(), false); |
| 455 } else if (const ConditionNode* condition = root->AsConditionNode()) { | 491 } else if (const ConditionNode* condition = root->AsConditionNode()) { |
| 456 Print("if ("); | 492 Print("if ("); |
| 457 // TODO(scottmg): The { needs to be included in the suffix here. | 493 // TODO(scottmg): The { needs to be included in the suffix here. |
| 458 Expr(condition->condition(), kPrecedenceLowest, ") "); | 494 Expr(condition->condition(), kPrecedenceLowest, ") "); |
| 459 Sequence(kSequenceStyleBracedBlock, | 495 Sequence(kSequenceStyleBracedBlock, |
| 460 condition->if_true()->statements(), | 496 condition->if_true()->statements(), |
| 461 condition->if_true()->End(), | 497 condition->if_true()->End(), |
| 462 false); | 498 false); |
| 463 if (condition->if_false()) { | 499 if (condition->if_false()) { |
| 464 Print(" else "); | 500 Print(" else "); |
| 465 // If it's a block it's a bare 'else', otherwise it's an 'else if'. See | 501 // If it's a block it's a bare 'else', otherwise it's an 'else if'. See |
| 466 // ConditionNode::Execute. | 502 // ConditionNode::Execute. |
| 467 bool is_else_if = condition->if_false()->AsBlock() == NULL; | 503 bool is_else_if = condition->if_false()->AsBlock() == NULL; |
| 468 if (is_else_if) { | 504 if (is_else_if) { |
| 469 Expr(condition->if_false(), kPrecedenceLowest, std::string()); | 505 Expr(condition->if_false(), kPrecedenceLowest, std::string()); |
| 470 } else { | 506 } else { |
| 471 Sequence(kSequenceStyleBracedBlock, | 507 Sequence(kSequenceStyleBracedBlock, |
| 472 condition->if_false()->AsBlock()->statements(), | 508 condition->if_false()->AsBlock()->statements(), |
| 473 condition->if_false()->AsBlock()->End(), false); | 509 condition->if_false()->AsBlock()->End(), |
| 510 false); |
| 474 } | 511 } |
| 475 } | 512 } |
| 476 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { | 513 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { |
| 477 penalty += FunctionCall(func_call); | 514 penalty += FunctionCall(func_call, at_end); |
| 515 at_end = ""; |
| 478 } else if (const IdentifierNode* identifier = root->AsIdentifier()) { | 516 } else if (const IdentifierNode* identifier = root->AsIdentifier()) { |
| 479 Print(identifier->value().value()); | 517 Print(identifier->value().value()); |
| 480 } else if (const ListNode* list = root->AsList()) { | 518 } else if (const ListNode* list = root->AsList()) { |
| 481 bool force_multiline = | 519 bool force_multiline = |
| 482 list->prefer_multiline() && !list->contents().empty(); | 520 list->prefer_multiline() && !list->contents().empty(); |
| 483 Sequence( | 521 Sequence( |
| 484 kSequenceStyleList, list->contents(), list->End(), force_multiline); | 522 kSequenceStyleList, list->contents(), list->End(), force_multiline); |
| 485 } else if (const LiteralNode* literal = root->AsLiteral()) { | 523 } else if (const LiteralNode* literal = root->AsLiteral()) { |
| 486 Print(literal->value().value()); | 524 Print(literal->value().value()); |
| 487 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { | 525 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 498 if (parenthesized) | 536 if (parenthesized) |
| 499 Print(")"); | 537 Print(")"); |
| 500 | 538 |
| 501 // Defer any end of line comment until we reach the newline. | 539 // Defer any end of line comment until we reach the newline. |
| 502 if (root->comments() && !root->comments()->suffix().empty()) { | 540 if (root->comments() && !root->comments()->suffix().empty()) { |
| 503 std::copy(root->comments()->suffix().begin(), | 541 std::copy(root->comments()->suffix().begin(), |
| 504 root->comments()->suffix().end(), | 542 root->comments()->suffix().end(), |
| 505 std::back_inserter(comments_)); | 543 std::back_inserter(comments_)); |
| 506 } | 544 } |
| 507 | 545 |
| 508 Print(suffix); | 546 Print(at_end); |
| 509 | 547 |
| 510 penalty_depth_--; | 548 penalty_depth_--; |
| 511 return penalty; | 549 return penalty; |
| 512 } | 550 } |
| 513 | 551 |
| 514 template <class PARSENODE> | 552 template <class PARSENODE> |
| 515 void Printer::Sequence(SequenceStyle style, | 553 void Printer::Sequence(SequenceStyle style, |
| 516 const std::vector<PARSENODE*>& list, | 554 const std::vector<PARSENODE*>& list, |
| 517 const ParseNode* end, | 555 const ParseNode* end, |
| 518 bool force_multiline) { | 556 bool force_multiline) { |
| 519 if (style == kSequenceStyleList) | 557 if (style == kSequenceStyleList) |
| 520 Print("["); | 558 Print("["); |
| 521 else if (style == kSequenceStyleBracedBlock) | 559 else if (style == kSequenceStyleBracedBlock) |
| 522 Print("{"); | 560 Print("{"); |
| 523 | 561 |
| 524 if (style == kSequenceStyleBlock || style == kSequenceStyleBracedBlock) | 562 if (style == kSequenceStyleBlock || style == kSequenceStyleBracedBlock) |
| 525 force_multiline = true; | 563 force_multiline = true; |
| 526 | 564 |
| 527 if (end && end->comments() && !end->comments()->before().empty()) | 565 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 | 566 |
| 536 if (list.size() == 0 && !force_multiline) { | 567 if (list.size() == 0 && !force_multiline) { |
| 537 // No elements, and not forcing newlines, print nothing. | 568 // No elements, and not forcing newlines, print nothing. |
| 538 } else if (list.size() == 1 && !force_multiline) { | 569 } else if (list.size() == 1 && !force_multiline) { |
| 539 Print(" "); | 570 Print(" "); |
| 540 Expr(list[0], kPrecedenceLowest, std::string()); | 571 Expr(list[0], kPrecedenceLowest, std::string()); |
| 541 CHECK(!list[0]->comments() || list[0]->comments()->after().empty()); | 572 CHECK(!list[0]->comments() || list[0]->comments()->after().empty()); |
| 542 Print(" "); | 573 Print(" "); |
| 543 } else { | 574 } else { |
| 544 stack_.push_back( | 575 stack_.push_back( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 564 if (!want_comma) { | 595 if (!want_comma) { |
| 565 if (i < list.size() - 1 && | 596 if (i < list.size() - 1 && |
| 566 ShouldAddBlankLineInBetween(list[i], list[i + 1])) | 597 ShouldAddBlankLineInBetween(list[i], list[i + 1])) |
| 567 Newline(); | 598 Newline(); |
| 568 } | 599 } |
| 569 } | 600 } |
| 570 ++i; | 601 ++i; |
| 571 } | 602 } |
| 572 | 603 |
| 573 // Trailing comments. | 604 // Trailing comments. |
| 574 if (end->comments()) { | 605 if (end->comments() && !end->comments()->before().empty()) { |
| 575 if (list.size() >= 2) | 606 if (list.size() >= 2) |
| 576 Newline(); | 607 Newline(); |
| 577 for (const auto& c : end->comments()->before()) { | 608 for (const auto& c : end->comments()->before()) { |
| 578 Newline(); | 609 Newline(); |
| 579 TrimAndPrintToken(c); | 610 TrimAndPrintToken(c); |
| 580 } | 611 } |
| 581 } | 612 } |
| 582 | 613 |
| 583 stack_.pop_back(); | 614 stack_.pop_back(); |
| 584 Newline(); | 615 Newline(); |
| 585 | 616 |
| 586 // Defer any end of line comment until we reach the newline. | 617 // Defer any end of line comment until we reach the newline. |
| 587 if (end->comments() && !end->comments()->suffix().empty()) { | 618 if (end->comments() && !end->comments()->suffix().empty()) { |
| 588 std::copy(end->comments()->suffix().begin(), | 619 std::copy(end->comments()->suffix().begin(), |
| 589 end->comments()->suffix().end(), | 620 end->comments()->suffix().end(), |
| 590 std::back_inserter(comments_)); | 621 std::back_inserter(comments_)); |
| 591 } | 622 } |
| 592 } | 623 } |
| 593 | 624 |
| 594 if (style == kSequenceStyleList) | 625 if (style == kSequenceStyleList) |
| 595 Print("]"); | 626 Print("]"); |
| 596 else if (style == kSequenceStyleBracedBlock) | 627 else if (style == kSequenceStyleBracedBlock) |
| 597 Print("}"); | 628 Print("}"); |
| 598 } | 629 } |
| 599 | 630 |
| 600 int Printer::FunctionCall(const FunctionCallNode* func_call) { | 631 int Printer::FunctionCall(const FunctionCallNode* func_call, |
| 632 const std::string& suffix) { |
| 601 int start_line = CurrentLine(); | 633 int start_line = CurrentLine(); |
| 602 int start_column = CurrentColumn(); | 634 int start_column = CurrentColumn(); |
| 603 Print(func_call->function().value()); | 635 Print(func_call->function().value()); |
| 604 Print("("); | 636 Print("("); |
| 605 | 637 |
| 606 bool have_block = func_call->block() != nullptr; | 638 bool have_block = func_call->block() != nullptr; |
| 607 bool force_multiline = false; | 639 bool force_multiline = false; |
| 608 | 640 |
| 609 const std::vector<const ParseNode*>& list = func_call->args()->contents(); | 641 const std::vector<const ParseNode*>& list = func_call->args()->contents(); |
| 610 const ParseNode* end = func_call->args()->End(); | 642 const ParseNode* end = func_call->args()->End(); |
| 611 | 643 |
| 612 if (end && end->comments() && !end->comments()->before().empty()) | 644 if (end && end->comments() && !end->comments()->before().empty()) |
| 613 force_multiline = true; | 645 force_multiline = true; |
| 614 | 646 |
| 615 // If there's before line comments, make sure we have a place to put them. | 647 // If there's before line comments, make sure we have a place to put them. |
| 616 for (const auto& i : list) { | 648 for (const auto& i : list) { |
| 617 if (i->comments() && !i->comments()->before().empty()) | 649 if (i->comments() && !i->comments()->before().empty()) |
| 618 force_multiline = true; | 650 force_multiline = true; |
| 619 } | 651 } |
| 620 | 652 |
| 621 // Calculate the penalties for 3 possible layouts: | 653 // Calculate the penalties for 3 possible layouts: |
| 622 // 1. all on same line; | 654 // 1. all on same line; |
| 623 // 2. starting on same line, broken at each comma but paren aligned; | 655 // 2. starting on same line, broken at each comma but paren aligned; |
| 624 // 3. broken to next line + 4, broken at each comma. | 656 // 3. broken to next line + 4, broken at each comma. |
| 625 std::string terminator = ")"; | 657 std::string terminator = ")"; |
| 626 if (have_block) | 658 if (have_block) |
| 627 terminator += " {"; | 659 terminator += " {"; |
| 660 terminator += suffix; |
| 628 | 661 |
| 629 // 1: Same line. | 662 // 1: Same line. |
| 630 Printer sub1; | 663 Printer sub1; |
| 631 InitializeSub(&sub1); | 664 InitializeSub(&sub1); |
| 632 sub1.stack_.push_back(IndentState(CurrentColumn(), true)); | 665 sub1.stack_.push_back(IndentState(CurrentColumn(), true)); |
| 633 int penalty_one_line = 0; | 666 int penalty_one_line = 0; |
| 634 for (size_t i = 0; i < list.size(); ++i) { | 667 for (size_t i = 0; i < list.size(); ++i) { |
| 635 penalty_one_line += sub1.Expr(list[i], kPrecedenceLowest, | 668 penalty_one_line += sub1.Expr(list[i], kPrecedenceLowest, |
| 636 i < list.size() - 1 ? ", " : std::string()); | 669 i < list.size() - 1 ? ", " : std::string()); |
| 637 } | 670 } |
| 638 sub1.Print(terminator); | 671 sub1.Print(terminator); |
| 639 penalty_one_line += AssessPenalty(sub1.String()); | 672 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 | 673 // This extra penalty prevents a short second argument from being squeezed in |
| 643 // after a first argument that went multiline (and instead preferring a | 674 // after a first argument that went multiline (and instead preferring a |
| 644 // variant below). | 675 // variant below). |
| 645 if (lines.size() > 1) | 676 penalty_one_line += |
| 646 penalty_one_line += kPenaltyBrokenLineOnOneLiner; | 677 (CountLines(sub1.String()) - 1) * kPenaltyBrokenLineOnOneLiner; |
| 647 | 678 |
| 648 // 2: Starting on same line, broken at commas. | 679 // 2: Starting on same line, broken at commas. |
| 649 Printer sub2; | 680 Printer sub2; |
| 650 InitializeSub(&sub2); | 681 InitializeSub(&sub2); |
| 651 sub2.stack_.push_back(IndentState(CurrentColumn(), true)); | 682 sub2.stack_.push_back(IndentState(CurrentColumn(), true)); |
| 652 int penalty_multiline_start_same_line = 0; | 683 int penalty_multiline_start_same_line = 0; |
| 653 for (size_t i = 0; i < list.size(); ++i) { | 684 for (size_t i = 0; i < list.size(); ++i) { |
| 654 penalty_multiline_start_same_line += sub2.Expr( | 685 penalty_multiline_start_same_line += sub2.Expr( |
| 655 list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string()); | 686 list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string()); |
| 656 if (i < list.size() - 1) { | 687 if (i < list.size() - 1) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 stack_.pop_back(); | 766 stack_.pop_back(); |
| 736 } | 767 } |
| 737 | 768 |
| 738 // Defer any end of line comment until we reach the newline. | 769 // Defer any end of line comment until we reach the newline. |
| 739 if (end->comments() && !end->comments()->suffix().empty()) { | 770 if (end->comments() && !end->comments()->suffix().empty()) { |
| 740 std::copy(end->comments()->suffix().begin(), | 771 std::copy(end->comments()->suffix().begin(), |
| 741 end->comments()->suffix().end(), std::back_inserter(comments_)); | 772 end->comments()->suffix().end(), std::back_inserter(comments_)); |
| 742 } | 773 } |
| 743 | 774 |
| 744 Print(")"); | 775 Print(")"); |
| 776 Print(suffix); |
| 745 | 777 |
| 746 if (have_block) { | 778 if (have_block) { |
| 747 Print(" "); | 779 Print(" "); |
| 748 Sequence(kSequenceStyleBracedBlock, | 780 Sequence(kSequenceStyleBracedBlock, |
| 749 func_call->block()->statements(), | 781 func_call->block()->statements(), |
| 750 func_call->block()->End(), | 782 func_call->block()->End(), |
| 751 false); | 783 false); |
| 752 } | 784 } |
| 753 return penalty + (CurrentLine() - start_line) * GetPenaltyForLineBreak(); | 785 return penalty + (CurrentLine() - start_line) * GetPenaltyForLineBreak(); |
| 754 } | 786 } |
| 755 | 787 |
| 756 void Printer::InitializeSub(Printer* sub) { | 788 void Printer::InitializeSub(Printer* sub) { |
| 757 sub->stack_ = stack_; | 789 sub->stack_ = stack_; |
| 758 sub->comments_ = comments_; | 790 sub->comments_ = comments_; |
| 759 sub->penalty_depth_ = penalty_depth_; | 791 sub->penalty_depth_ = penalty_depth_; |
| 760 sub->Print(std::string(CurrentColumn(), 'x')); | 792 sub->Print(std::string(CurrentColumn(), 'x')); |
| 761 } | 793 } |
| 762 | 794 |
| 795 template <class PARSENODE> |
| 796 bool Printer::ListWillBeMultiline(const std::vector<PARSENODE*>& list, |
| 797 const ParseNode* end) { |
| 798 if (list.size() > 1) |
| 799 return true; |
| 800 |
| 801 if (end && end->comments() && !end->comments()->before().empty()) |
| 802 return true; |
| 803 |
| 804 // If there's before line comments, make sure we have a place to put them. |
| 805 for (const auto& i : list) { |
| 806 if (i->comments() && !i->comments()->before().empty()) |
| 807 return true; |
| 808 } |
| 809 |
| 810 return false; |
| 811 } |
| 812 |
| 763 void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) { | 813 void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) { |
| 764 if (dump_tree) { | 814 if (dump_tree) { |
| 765 std::ostringstream os; | 815 std::ostringstream os; |
| 766 root->Print(os, 0); | 816 root->Print(os, 0); |
| 767 printf("----------------------\n"); | 817 printf("----------------------\n"); |
| 768 printf("-- PARSE TREE --------\n"); | 818 printf("-- PARSE TREE --------\n"); |
| 769 printf("----------------------\n"); | 819 printf("----------------------\n"); |
| 770 printf("%s", os.str().c_str()); | 820 printf("%s", os.str().c_str()); |
| 771 printf("----------------------\n"); | 821 printf("----------------------\n"); |
| 772 } | 822 } |
| (...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()); | 937 printf("Wrote formatted to '%s'.\n", to_write.AsUTF8Unsafe().c_str()); |
| 888 } else { | 938 } else { |
| 889 printf("%s", output_string.c_str()); | 939 printf("%s", output_string.c_str()); |
| 890 } | 940 } |
| 891 } | 941 } |
| 892 | 942 |
| 893 return 0; | 943 return 0; |
| 894 } | 944 } |
| 895 | 945 |
| 896 } // namespace commands | 946 } // namespace commands |
| OLD | NEW |