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 |