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 |