Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 } | 187 } |
| 188 | 188 |
| 189 if (!result) { | 189 if (!result) { |
| 190 *err = Err(member_.get(), "No value named \"" + | 190 *err = Err(member_.get(), "No value named \"" + |
| 191 member_->value().value() + "\" in scope \"" + base_.value() + "\""); | 191 member_->value().value() + "\" in scope \"" + base_.value() + "\""); |
| 192 return Value(); | 192 return Value(); |
| 193 } | 193 } |
| 194 return *result; | 194 return *result; |
| 195 } | 195 } |
| 196 | 196 |
| 197 void AccessorNode::SetNewLocation(int line_number) { | |
| 198 Location old = base_.location(); | |
| 199 base_.set_location( | |
| 200 Location(old.file(), line_number, old.char_offset(), old.byte())); | |
| 201 } | |
| 202 | |
| 197 // BinaryOpNode --------------------------------------------------------------- | 203 // BinaryOpNode --------------------------------------------------------------- |
| 198 | 204 |
| 199 BinaryOpNode::BinaryOpNode() { | 205 BinaryOpNode::BinaryOpNode() { |
| 200 } | 206 } |
| 201 | 207 |
| 202 BinaryOpNode::~BinaryOpNode() { | 208 BinaryOpNode::~BinaryOpNode() { |
| 203 } | 209 } |
| 204 | 210 |
| 205 const BinaryOpNode* BinaryOpNode::AsBinaryOp() const { | 211 const BinaryOpNode* BinaryOpNode::AsBinaryOp() const { |
| 206 return this; | 212 return this; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 429 Err IdentifierNode::MakeErrorDescribing(const std::string& msg, | 435 Err IdentifierNode::MakeErrorDescribing(const std::string& msg, |
| 430 const std::string& help) const { | 436 const std::string& help) const { |
| 431 return Err(value_, msg, help); | 437 return Err(value_, msg, help); |
| 432 } | 438 } |
| 433 | 439 |
| 434 void IdentifierNode::Print(std::ostream& out, int indent) const { | 440 void IdentifierNode::Print(std::ostream& out, int indent) const { |
| 435 out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n"; | 441 out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n"; |
| 436 PrintComments(out, indent); | 442 PrintComments(out, indent); |
| 437 } | 443 } |
| 438 | 444 |
| 445 void IdentifierNode::SetNewLocation(int line_number) { | |
| 446 Location old = value_.location(); | |
| 447 value_.set_location( | |
| 448 Location(old.file(), line_number, old.char_offset(), old.byte())); | |
| 449 } | |
| 450 | |
| 439 // ListNode ------------------------------------------------------------------- | 451 // ListNode ------------------------------------------------------------------- |
| 440 | 452 |
| 441 ListNode::ListNode() : prefer_multiline_(false) { | 453 ListNode::ListNode() : prefer_multiline_(false) { |
| 442 } | 454 } |
| 443 | 455 |
| 444 ListNode::~ListNode() { | 456 ListNode::~ListNode() { |
| 445 STLDeleteContainerPointers(contents_.begin(), contents_.end()); | 457 STLDeleteContainerPointers(contents_.begin(), contents_.end()); |
| 446 } | 458 } |
| 447 | 459 |
| 448 const ListNode* ListNode::AsList() const { | 460 const ListNode* ListNode::AsList() const { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 483 void ListNode::Print(std::ostream& out, int indent) const { | 495 void ListNode::Print(std::ostream& out, int indent) const { |
| 484 out << IndentFor(indent) << "LIST" << (prefer_multiline_ ? " multiline" : "") | 496 out << IndentFor(indent) << "LIST" << (prefer_multiline_ ? " multiline" : "") |
| 485 << "\n"; | 497 << "\n"; |
| 486 PrintComments(out, indent); | 498 PrintComments(out, indent); |
| 487 for (const auto& cur : contents_) | 499 for (const auto& cur : contents_) |
| 488 cur->Print(out, indent + 1); | 500 cur->Print(out, indent + 1); |
| 489 if (end_ && end_->comments()) | 501 if (end_ && end_->comments()) |
| 490 end_->Print(out, indent + 1); | 502 end_->Print(out, indent + 1); |
| 491 } | 503 } |
| 492 | 504 |
| 505 using Range = std::pair<std::vector<const ParseNode*>::iterator, | |
| 506 std::vector<const ParseNode*>::iterator>; | |
| 507 | |
| 508 bool IsSeparatorComment(const ParseNode* node, const ParseNode* prev) { | |
|
brettw
2015/02/27 22:27:27
Seems like these standalone functions should be in
scottmg
2015/02/27 23:17:44
Done.
| |
| 509 // If it's a block comment, or has an attached comment with a blank line | |
| 510 // before it, then we break the range at this point. | |
| 511 return node->AsBlockComment() != nullptr || | |
| 512 (prev && node->comments() && !node->comments()->before().empty() && | |
| 513 (node->GetRange().begin().line_number() > | |
| 514 prev->GetRange().end().line_number() + | |
| 515 static_cast<int>(node->comments()->before().size() + 1))); | |
| 516 } | |
| 517 | |
| 518 std::vector<Range> GetSortRanges(std::vector<const ParseNode*>& contents) { | |
|
brettw
2015/02/27 22:27:27
Can you provide a function level comment of what t
scottmg
2015/02/27 23:17:44
Done.
| |
| 519 std::vector<Range> ranges; | |
| 520 auto begin = contents.begin(); | |
| 521 const ParseNode* prev = nullptr; | |
| 522 for (auto it = begin; it != contents.end(); prev = *(it++)) { | |
|
brettw
2015/02/27 22:27:27
This is pretty hard to wrap one's head around. Wou
scottmg
2015/02/27 23:17:44
Switched to size_ts. Not sure it helps, I think it
| |
| 523 if (IsSeparatorComment(*it, prev)) { | |
| 524 if (it > begin) { | |
| 525 ranges.push_back(std::make_pair(begin, it)); | |
| 526 if (!(*it)->AsBlockComment()) | |
| 527 begin = it; | |
| 528 else | |
| 529 begin = it + 1; | |
| 530 } else { | |
| 531 begin = it + 1; | |
| 532 } | |
| 533 if (it == contents.end()) | |
|
brettw
2015/02/27 22:27:27
This could also go away if you used ints
scottmg
2015/02/27 23:17:44
Might not have been necessary either way I think.
| |
| 534 break; | |
| 535 } | |
| 536 } | |
| 537 if (begin != contents.end()) | |
| 538 ranges.push_back(std::make_pair(begin, contents.end())); | |
| 539 return ranges; | |
| 540 } | |
| 541 | |
| 542 base::StringPiece GetStringRepresentation(const ParseNode* node) { | |
| 543 DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor()); | |
| 544 if (node->AsLiteral()) | |
| 545 return node->AsLiteral()->value().value(); | |
| 546 else if (node->AsIdentifier()) | |
| 547 return node->AsIdentifier()->value().value(); | |
| 548 else if (node->AsAccessor()) | |
| 549 return node->AsAccessor()->base().value(); | |
| 550 return base::StringPiece(); | |
| 551 } | |
| 552 | |
| 553 void ListNode::SortAsStringsList() { | |
| 554 // Sorts alphabetically. Partitions first on BlockCommentNodes and sorts each | |
| 555 // partition separately. | |
| 556 std::vector<Range> ranges = GetSortRanges(contents_); | |
| 557 for (auto range : ranges) { | |
|
brettw
2015/02/27 22:27:27
You couldn't do for (auto range : GetSortRanges(co
scottmg
2015/02/27 23:17:44
Done.
| |
| 558 // Save the original line number so that we can re-assign ranges. We assume | |
| 559 // they're contiguous lines because GetSortRanges() does so above. We need | |
| 560 // to re-assign these line numbers primiarily because `gn format` uses them | |
| 561 // to determine whether two nodes were initially separated by a blank line | |
| 562 // or not. | |
| 563 int start_line = (*range.first)->GetRange().begin().line_number(); | |
| 564 const ParseNode* original_first = *range.first; | |
| 565 std::sort(range.first, range.second, | |
| 566 [](const ParseNode* a, const ParseNode* b) { | |
| 567 base::StringPiece astr = GetStringRepresentation(a); | |
| 568 base::StringPiece bstr = GetStringRepresentation(b); | |
| 569 return astr < bstr; | |
| 570 }); | |
| 571 // If the beginning of the range had before comments, and the first node | |
| 572 // moved during the sort, then move its comments to the new head of the | |
| 573 // range. | |
| 574 if (original_first->comments() && *range.first != original_first) { | |
| 575 for (const auto& hc : original_first->comments()->before()) { | |
| 576 const_cast<ParseNode*>(*range.first) | |
| 577 ->comments_mutable() | |
| 578 ->append_before(hc); | |
| 579 } | |
| 580 const_cast<ParseNode*>(original_first) | |
| 581 ->comments_mutable() | |
| 582 ->clear_before(); | |
| 583 } | |
| 584 const ParseNode* prev = nullptr; | |
| 585 for (auto it = range.first; it != range.second; ++it) { | |
| 586 const ParseNode* node = *it; | |
| 587 DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor()); | |
| 588 int line_number = | |
| 589 prev ? prev->GetRange().end().line_number() + 1 : start_line; | |
| 590 if (node->AsLiteral()) { | |
| 591 const_cast<LiteralNode*>(node->AsLiteral()) | |
| 592 ->SetNewLocation(line_number); | |
| 593 } else if (node->AsIdentifier()) { | |
| 594 const_cast<IdentifierNode*>(node->AsIdentifier()) | |
| 595 ->SetNewLocation(line_number); | |
| 596 } else if (node->AsAccessor()) { | |
| 597 const_cast<AccessorNode*>(node->AsAccessor()) | |
| 598 ->SetNewLocation(line_number); | |
| 599 } | |
| 600 prev = node; | |
| 601 } | |
| 602 } | |
| 603 } | |
| 604 | |
| 493 // LiteralNode ----------------------------------------------------------------- | 605 // LiteralNode ----------------------------------------------------------------- |
| 494 | 606 |
| 495 LiteralNode::LiteralNode() { | 607 LiteralNode::LiteralNode() { |
| 496 } | 608 } |
| 497 | 609 |
| 498 LiteralNode::LiteralNode(const Token& token) : value_(token) { | 610 LiteralNode::LiteralNode(const Token& token) : value_(token) { |
| 499 } | 611 } |
| 500 | 612 |
| 501 LiteralNode::~LiteralNode() { | 613 LiteralNode::~LiteralNode() { |
| 502 } | 614 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 537 Err LiteralNode::MakeErrorDescribing(const std::string& msg, | 649 Err LiteralNode::MakeErrorDescribing(const std::string& msg, |
| 538 const std::string& help) const { | 650 const std::string& help) const { |
| 539 return Err(value_, msg, help); | 651 return Err(value_, msg, help); |
| 540 } | 652 } |
| 541 | 653 |
| 542 void LiteralNode::Print(std::ostream& out, int indent) const { | 654 void LiteralNode::Print(std::ostream& out, int indent) const { |
| 543 out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n"; | 655 out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n"; |
| 544 PrintComments(out, indent); | 656 PrintComments(out, indent); |
| 545 } | 657 } |
| 546 | 658 |
| 659 void LiteralNode::SetNewLocation(int line_number) { | |
| 660 Location old = value_.location(); | |
| 661 value_.set_location( | |
| 662 Location(old.file(), line_number, old.char_offset(), old.byte())); | |
| 663 } | |
| 664 | |
| 547 // UnaryOpNode ---------------------------------------------------------------- | 665 // UnaryOpNode ---------------------------------------------------------------- |
| 548 | 666 |
| 549 UnaryOpNode::UnaryOpNode() { | 667 UnaryOpNode::UnaryOpNode() { |
| 550 } | 668 } |
| 551 | 669 |
| 552 UnaryOpNode::~UnaryOpNode() { | 670 UnaryOpNode::~UnaryOpNode() { |
| 553 } | 671 } |
| 554 | 672 |
| 555 const UnaryOpNode* UnaryOpNode::AsUnaryOp() const { | 673 const UnaryOpNode* UnaryOpNode::AsUnaryOp() const { |
| 556 return this; | 674 return this; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 Err BlockCommentNode::MakeErrorDescribing(const std::string& msg, | 719 Err BlockCommentNode::MakeErrorDescribing(const std::string& msg, |
| 602 const std::string& help) const { | 720 const std::string& help) const { |
| 603 return Err(comment_, msg, help); | 721 return Err(comment_, msg, help); |
| 604 } | 722 } |
| 605 | 723 |
| 606 void BlockCommentNode::Print(std::ostream& out, int indent) const { | 724 void BlockCommentNode::Print(std::ostream& out, int indent) const { |
| 607 out << IndentFor(indent) << "BLOCK_COMMENT(" << comment_.value() << ")\n"; | 725 out << IndentFor(indent) << "BLOCK_COMMENT(" << comment_.value() << ")\n"; |
| 608 PrintComments(out, indent); | 726 PrintComments(out, indent); |
| 609 } | 727 } |
| 610 | 728 |
| 611 | |
| 612 // EndNode --------------------------------------------------------------------- | 729 // EndNode --------------------------------------------------------------------- |
| 613 | 730 |
| 614 EndNode::EndNode(const Token& token) : value_(token) { | 731 EndNode::EndNode(const Token& token) : value_(token) { |
| 615 } | 732 } |
| 616 | 733 |
| 617 EndNode::~EndNode() { | 734 EndNode::~EndNode() { |
| 618 } | 735 } |
| 619 | 736 |
| 620 const EndNode* EndNode::AsEnd() const { | 737 const EndNode* EndNode::AsEnd() const { |
| 621 return this; | 738 return this; |
| 622 } | 739 } |
| 623 | 740 |
| 624 Value EndNode::Execute(Scope* scope, Err* err) const { | 741 Value EndNode::Execute(Scope* scope, Err* err) const { |
| 625 return Value(); | 742 return Value(); |
| 626 } | 743 } |
| 627 | 744 |
| 628 LocationRange EndNode::GetRange() const { | 745 LocationRange EndNode::GetRange() const { |
| 629 return value_.range(); | 746 return value_.range(); |
| 630 } | 747 } |
| 631 | 748 |
| 632 Err EndNode::MakeErrorDescribing(const std::string& msg, | 749 Err EndNode::MakeErrorDescribing(const std::string& msg, |
| 633 const std::string& help) const { | 750 const std::string& help) const { |
| 634 return Err(value_, msg, help); | 751 return Err(value_, msg, help); |
| 635 } | 752 } |
| 636 | 753 |
| 637 void EndNode::Print(std::ostream& out, int indent) const { | 754 void EndNode::Print(std::ostream& out, int indent) const { |
| 638 out << IndentFor(indent) << "END(" << value_.value() << ")\n"; | 755 out << IndentFor(indent) << "END(" << value_.value() << ")\n"; |
| 639 PrintComments(out, indent); | 756 PrintComments(out, indent); |
| 640 } | 757 } |
| OLD | NEW |