Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: tools/gn/parse_tree.cc

Issue 962003002: gn format: Have format sort sources (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: unsigned numbers in test Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/gn/parse_tree.h ('k') | tools/gn/parse_tree_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "tools/gn/parse_tree.h" 5 #include "tools/gn/parse_tree.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "tools/gn/functions.h" 11 #include "tools/gn/functions.h"
12 #include "tools/gn/operators.h" 12 #include "tools/gn/operators.h"
13 #include "tools/gn/scope.h" 13 #include "tools/gn/scope.h"
14 #include "tools/gn/string_utils.h" 14 #include "tools/gn/string_utils.h"
15 15
16 namespace { 16 namespace {
17 17
18 std::string IndentFor(int value) { 18 std::string IndentFor(int value) {
19 return std::string(value, ' '); 19 return std::string(value, ' ');
20 } 20 }
21 21
22 bool IsSortRangeSeparator(const ParseNode* node, const ParseNode* prev) {
23 // If it's a block comment, or has an attached comment with a blank line
24 // before it, then we break the range at this point.
25 return node->AsBlockComment() != nullptr ||
26 (prev && node->comments() && !node->comments()->before().empty() &&
27 (node->GetRange().begin().line_number() >
28 prev->GetRange().end().line_number() +
29 static_cast<int>(node->comments()->before().size() + 1)));
30 }
31
32 base::StringPiece GetStringRepresentation(const ParseNode* node) {
33 DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor());
34 if (node->AsLiteral())
35 return node->AsLiteral()->value().value();
36 else if (node->AsIdentifier())
37 return node->AsIdentifier()->value().value();
38 else if (node->AsAccessor())
39 return node->AsAccessor()->base().value();
40 return base::StringPiece();
41 }
42
22 } // namespace 43 } // namespace
23 44
24 Comments::Comments() { 45 Comments::Comments() {
25 } 46 }
26 47
27 Comments::~Comments() { 48 Comments::~Comments() {
28 } 49 }
29 50
30 void Comments::ReverseSuffix() { 51 void Comments::ReverseSuffix() {
31 for (int i = 0, j = static_cast<int>(suffix_.size() - 1); i < j; ++i, --j) 52 for (int i = 0, j = static_cast<int>(suffix_.size() - 1); i < j; ++i, --j)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 } 208 }
188 209
189 if (!result) { 210 if (!result) {
190 *err = Err(member_.get(), "No value named \"" + 211 *err = Err(member_.get(), "No value named \"" +
191 member_->value().value() + "\" in scope \"" + base_.value() + "\""); 212 member_->value().value() + "\" in scope \"" + base_.value() + "\"");
192 return Value(); 213 return Value();
193 } 214 }
194 return *result; 215 return *result;
195 } 216 }
196 217
218 void AccessorNode::SetNewLocation(int line_number) {
219 Location old = base_.location();
220 base_.set_location(
221 Location(old.file(), line_number, old.char_offset(), old.byte()));
222 }
223
197 // BinaryOpNode --------------------------------------------------------------- 224 // BinaryOpNode ---------------------------------------------------------------
198 225
199 BinaryOpNode::BinaryOpNode() { 226 BinaryOpNode::BinaryOpNode() {
200 } 227 }
201 228
202 BinaryOpNode::~BinaryOpNode() { 229 BinaryOpNode::~BinaryOpNode() {
203 } 230 }
204 231
205 const BinaryOpNode* BinaryOpNode::AsBinaryOp() const { 232 const BinaryOpNode* BinaryOpNode::AsBinaryOp() const {
206 return this; 233 return this;
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 Err IdentifierNode::MakeErrorDescribing(const std::string& msg, 456 Err IdentifierNode::MakeErrorDescribing(const std::string& msg,
430 const std::string& help) const { 457 const std::string& help) const {
431 return Err(value_, msg, help); 458 return Err(value_, msg, help);
432 } 459 }
433 460
434 void IdentifierNode::Print(std::ostream& out, int indent) const { 461 void IdentifierNode::Print(std::ostream& out, int indent) const {
435 out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n"; 462 out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n";
436 PrintComments(out, indent); 463 PrintComments(out, indent);
437 } 464 }
438 465
466 void IdentifierNode::SetNewLocation(int line_number) {
467 Location old = value_.location();
468 value_.set_location(
469 Location(old.file(), line_number, old.char_offset(), old.byte()));
470 }
471
439 // ListNode ------------------------------------------------------------------- 472 // ListNode -------------------------------------------------------------------
440 473
441 ListNode::ListNode() : prefer_multiline_(false) { 474 ListNode::ListNode() : prefer_multiline_(false) {
442 } 475 }
443 476
444 ListNode::~ListNode() { 477 ListNode::~ListNode() {
445 STLDeleteContainerPointers(contents_.begin(), contents_.end()); 478 STLDeleteContainerPointers(contents_.begin(), contents_.end());
446 } 479 }
447 480
448 const ListNode* ListNode::AsList() const { 481 const ListNode* ListNode::AsList() const {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 void ListNode::Print(std::ostream& out, int indent) const { 516 void ListNode::Print(std::ostream& out, int indent) const {
484 out << IndentFor(indent) << "LIST" << (prefer_multiline_ ? " multiline" : "") 517 out << IndentFor(indent) << "LIST" << (prefer_multiline_ ? " multiline" : "")
485 << "\n"; 518 << "\n";
486 PrintComments(out, indent); 519 PrintComments(out, indent);
487 for (const auto& cur : contents_) 520 for (const auto& cur : contents_)
488 cur->Print(out, indent + 1); 521 cur->Print(out, indent + 1);
489 if (end_ && end_->comments()) 522 if (end_ && end_->comments())
490 end_->Print(out, indent + 1); 523 end_->Print(out, indent + 1);
491 } 524 }
492 525
526 void ListNode::SortAsStringsList() {
527 // Sorts alphabetically. Partitions first on BlockCommentNodes and sorts each
528 // partition separately.
529 for (auto sr : GetSortRanges()) {
530 // Save the original line number so that we can re-assign ranges. We assume
531 // they're contiguous lines because GetSortRanges() does so above. We need
532 // to re-assign these line numbers primiarily because `gn format` uses them
533 // to determine whether two nodes were initially separated by a blank line
534 // or not.
535 int start_line = contents_[sr.begin]->GetRange().begin().line_number();
536 const ParseNode* original_first = contents_[sr.begin];
537 std::sort(contents_.begin() + sr.begin, contents_.begin() + sr.end,
538 [](const ParseNode* a, const ParseNode* b) {
539 base::StringPiece astr = GetStringRepresentation(a);
540 base::StringPiece bstr = GetStringRepresentation(b);
541 return astr < bstr;
542 });
543 // If the beginning of the range had before comments, and the first node
544 // moved during the sort, then move its comments to the new head of the
545 // range.
546 if (original_first->comments() && contents_[sr.begin] != original_first) {
547 for (const auto& hc : original_first->comments()->before()) {
548 const_cast<ParseNode*>(contents_[sr.begin])
549 ->comments_mutable()
550 ->append_before(hc);
551 }
552 const_cast<ParseNode*>(original_first)
553 ->comments_mutable()
554 ->clear_before();
555 }
556 const ParseNode* prev = nullptr;
557 for (size_t i = sr.begin; i != sr.end; ++i) {
558 const ParseNode* node = contents_[i];
559 DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor());
560 int line_number =
561 prev ? prev->GetRange().end().line_number() + 1 : start_line;
562 if (node->AsLiteral()) {
563 const_cast<LiteralNode*>(node->AsLiteral())
564 ->SetNewLocation(line_number);
565 } else if (node->AsIdentifier()) {
566 const_cast<IdentifierNode*>(node->AsIdentifier())
567 ->SetNewLocation(line_number);
568 } else if (node->AsAccessor()) {
569 const_cast<AccessorNode*>(node->AsAccessor())
570 ->SetNewLocation(line_number);
571 }
572 prev = node;
573 }
574 }
575 }
576
577 // Breaks the ParseNodes of |contents| up by ranges that should be separately
578 // sorted. In particular, we break at a block comment, or an item that has an
579 // attached "before" comment and is separated by a blank line from the item
580 // before it. The assumption is that both of these indicate a separate 'section'
581 // of a sources block across which items should not be inter-sorted.
582 std::vector<ListNode::SortRange> ListNode::GetSortRanges() const {
583 std::vector<SortRange> ranges;
584 const ParseNode* prev = nullptr;
585 size_t begin = 0;
586 for (size_t i = begin; i < contents_.size(); prev = contents_[i++]) {
587 if (IsSortRangeSeparator(contents_[i], prev)) {
588 if (i > begin) {
589 ranges.push_back(SortRange(begin, i));
590 // If |i| is an item with an attached comment, then we start the next
591 // range at that point, because we want to include it in the sort.
592 // Otherwise, it's a block comment which we skip over entirely because
593 // we don't want to move or include it in the sort. The two cases are:
594 //
595 // sources = [
596 // "a",
597 // "b",
598 //
599 // #
600 // # This is a block comment.
601 // #
602 //
603 // "c",
604 // "d",
605 // ]
606 //
607 // which contains 5 elements, and for which the ranges would be { [0,
608 // 2), [3, 5) } (notably excluding 2, the block comment), and:
609 //
610 // sources = [
611 // "a",
612 // "b",
613 //
614 // # This is a header comment.
615 // "c",
616 // "d",
617 // ]
618 //
619 // which contains 4 elements, index 2 containing an attached 'before'
620 // comments, and the ranges should be { [0, 2), [2, 4) }.
621 if (!contents_[i]->AsBlockComment())
622 begin = i;
623 else
624 begin = i + 1;
625 } else {
626 // If it was a one item range, just skip over it.
627 begin = i + 1;
628 }
629 }
630 }
631 if (begin != contents_.size())
632 ranges.push_back(SortRange(begin, contents_.size()));
633 return ranges;
634 }
635
493 // LiteralNode ----------------------------------------------------------------- 636 // LiteralNode -----------------------------------------------------------------
494 637
495 LiteralNode::LiteralNode() { 638 LiteralNode::LiteralNode() {
496 } 639 }
497 640
498 LiteralNode::LiteralNode(const Token& token) : value_(token) { 641 LiteralNode::LiteralNode(const Token& token) : value_(token) {
499 } 642 }
500 643
501 LiteralNode::~LiteralNode() { 644 LiteralNode::~LiteralNode() {
502 } 645 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 Err LiteralNode::MakeErrorDescribing(const std::string& msg, 680 Err LiteralNode::MakeErrorDescribing(const std::string& msg,
538 const std::string& help) const { 681 const std::string& help) const {
539 return Err(value_, msg, help); 682 return Err(value_, msg, help);
540 } 683 }
541 684
542 void LiteralNode::Print(std::ostream& out, int indent) const { 685 void LiteralNode::Print(std::ostream& out, int indent) const {
543 out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n"; 686 out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n";
544 PrintComments(out, indent); 687 PrintComments(out, indent);
545 } 688 }
546 689
690 void LiteralNode::SetNewLocation(int line_number) {
691 Location old = value_.location();
692 value_.set_location(
693 Location(old.file(), line_number, old.char_offset(), old.byte()));
694 }
695
547 // UnaryOpNode ---------------------------------------------------------------- 696 // UnaryOpNode ----------------------------------------------------------------
548 697
549 UnaryOpNode::UnaryOpNode() { 698 UnaryOpNode::UnaryOpNode() {
550 } 699 }
551 700
552 UnaryOpNode::~UnaryOpNode() { 701 UnaryOpNode::~UnaryOpNode() {
553 } 702 }
554 703
555 const UnaryOpNode* UnaryOpNode::AsUnaryOp() const { 704 const UnaryOpNode* UnaryOpNode::AsUnaryOp() const {
556 return this; 705 return this;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 Err BlockCommentNode::MakeErrorDescribing(const std::string& msg, 750 Err BlockCommentNode::MakeErrorDescribing(const std::string& msg,
602 const std::string& help) const { 751 const std::string& help) const {
603 return Err(comment_, msg, help); 752 return Err(comment_, msg, help);
604 } 753 }
605 754
606 void BlockCommentNode::Print(std::ostream& out, int indent) const { 755 void BlockCommentNode::Print(std::ostream& out, int indent) const {
607 out << IndentFor(indent) << "BLOCK_COMMENT(" << comment_.value() << ")\n"; 756 out << IndentFor(indent) << "BLOCK_COMMENT(" << comment_.value() << ")\n";
608 PrintComments(out, indent); 757 PrintComments(out, indent);
609 } 758 }
610 759
611
612 // EndNode --------------------------------------------------------------------- 760 // EndNode ---------------------------------------------------------------------
613 761
614 EndNode::EndNode(const Token& token) : value_(token) { 762 EndNode::EndNode(const Token& token) : value_(token) {
615 } 763 }
616 764
617 EndNode::~EndNode() { 765 EndNode::~EndNode() {
618 } 766 }
619 767
620 const EndNode* EndNode::AsEnd() const { 768 const EndNode* EndNode::AsEnd() const {
621 return this; 769 return this;
622 } 770 }
623 771
624 Value EndNode::Execute(Scope* scope, Err* err) const { 772 Value EndNode::Execute(Scope* scope, Err* err) const {
625 return Value(); 773 return Value();
626 } 774 }
627 775
628 LocationRange EndNode::GetRange() const { 776 LocationRange EndNode::GetRange() const {
629 return value_.range(); 777 return value_.range();
630 } 778 }
631 779
632 Err EndNode::MakeErrorDescribing(const std::string& msg, 780 Err EndNode::MakeErrorDescribing(const std::string& msg,
633 const std::string& help) const { 781 const std::string& help) const {
634 return Err(value_, msg, help); 782 return Err(value_, msg, help);
635 } 783 }
636 784
637 void EndNode::Print(std::ostream& out, int indent) const { 785 void EndNode::Print(std::ostream& out, int indent) const {
638 out << IndentFor(indent) << "END(" << value_.value() << ")\n"; 786 out << IndentFor(indent) << "END(" << value_.value() << ")\n";
639 PrintComments(out, indent); 787 PrintComments(out, indent);
640 } 788 }
OLDNEW
« no previous file with comments | « tools/gn/parse_tree.h ('k') | tools/gn/parse_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698