Chromium Code Reviews| Index: tools/gn/parse_tree.cc |
| diff --git a/tools/gn/parse_tree.cc b/tools/gn/parse_tree.cc |
| index 74f493b601741f7a36e970674118b79635a4ca55..ecfd5d4831c040ee9faffde147f0c80060d0f2ae 100644 |
| --- a/tools/gn/parse_tree.cc |
| +++ b/tools/gn/parse_tree.cc |
| @@ -194,6 +194,12 @@ Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const { |
| return *result; |
| } |
| +void AccessorNode::SetNewLocation(int line_number) { |
| + Location old = base_.location(); |
| + base_.set_location( |
| + Location(old.file(), line_number, old.char_offset(), old.byte())); |
| +} |
| + |
| // BinaryOpNode --------------------------------------------------------------- |
| BinaryOpNode::BinaryOpNode() { |
| @@ -436,6 +442,12 @@ void IdentifierNode::Print(std::ostream& out, int indent) const { |
| PrintComments(out, indent); |
| } |
| +void IdentifierNode::SetNewLocation(int line_number) { |
| + Location old = value_.location(); |
| + value_.set_location( |
| + Location(old.file(), line_number, old.char_offset(), old.byte())); |
| +} |
| + |
| // ListNode ------------------------------------------------------------------- |
| ListNode::ListNode() : prefer_multiline_(false) { |
| @@ -490,6 +502,106 @@ void ListNode::Print(std::ostream& out, int indent) const { |
| end_->Print(out, indent + 1); |
| } |
| +using Range = std::pair<std::vector<const ParseNode*>::iterator, |
| + std::vector<const ParseNode*>::iterator>; |
| + |
| +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.
|
| + // If it's a block comment, or has an attached comment with a blank line |
| + // before it, then we break the range at this point. |
| + return node->AsBlockComment() != nullptr || |
| + (prev && node->comments() && !node->comments()->before().empty() && |
| + (node->GetRange().begin().line_number() > |
| + prev->GetRange().end().line_number() + |
| + static_cast<int>(node->comments()->before().size() + 1))); |
| +} |
| + |
| +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.
|
| + std::vector<Range> ranges; |
| + auto begin = contents.begin(); |
| + const ParseNode* prev = nullptr; |
| + 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
|
| + if (IsSeparatorComment(*it, prev)) { |
| + if (it > begin) { |
| + ranges.push_back(std::make_pair(begin, it)); |
| + if (!(*it)->AsBlockComment()) |
| + begin = it; |
| + else |
| + begin = it + 1; |
| + } else { |
| + begin = it + 1; |
| + } |
| + 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.
|
| + break; |
| + } |
| + } |
| + if (begin != contents.end()) |
| + ranges.push_back(std::make_pair(begin, contents.end())); |
| + return ranges; |
| +} |
| + |
| +base::StringPiece GetStringRepresentation(const ParseNode* node) { |
| + DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor()); |
| + if (node->AsLiteral()) |
| + return node->AsLiteral()->value().value(); |
| + else if (node->AsIdentifier()) |
| + return node->AsIdentifier()->value().value(); |
| + else if (node->AsAccessor()) |
| + return node->AsAccessor()->base().value(); |
| + return base::StringPiece(); |
| +} |
| + |
| +void ListNode::SortAsStringsList() { |
| + // Sorts alphabetically. Partitions first on BlockCommentNodes and sorts each |
| + // partition separately. |
| + std::vector<Range> ranges = GetSortRanges(contents_); |
| + 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.
|
| + // Save the original line number so that we can re-assign ranges. We assume |
| + // they're contiguous lines because GetSortRanges() does so above. We need |
| + // to re-assign these line numbers primiarily because `gn format` uses them |
| + // to determine whether two nodes were initially separated by a blank line |
| + // or not. |
| + int start_line = (*range.first)->GetRange().begin().line_number(); |
| + const ParseNode* original_first = *range.first; |
| + std::sort(range.first, range.second, |
| + [](const ParseNode* a, const ParseNode* b) { |
| + base::StringPiece astr = GetStringRepresentation(a); |
| + base::StringPiece bstr = GetStringRepresentation(b); |
| + return astr < bstr; |
| + }); |
| + // If the beginning of the range had before comments, and the first node |
| + // moved during the sort, then move its comments to the new head of the |
| + // range. |
| + if (original_first->comments() && *range.first != original_first) { |
| + for (const auto& hc : original_first->comments()->before()) { |
| + const_cast<ParseNode*>(*range.first) |
| + ->comments_mutable() |
| + ->append_before(hc); |
| + } |
| + const_cast<ParseNode*>(original_first) |
| + ->comments_mutable() |
| + ->clear_before(); |
| + } |
| + const ParseNode* prev = nullptr; |
| + for (auto it = range.first; it != range.second; ++it) { |
| + const ParseNode* node = *it; |
| + DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor()); |
| + int line_number = |
| + prev ? prev->GetRange().end().line_number() + 1 : start_line; |
| + if (node->AsLiteral()) { |
| + const_cast<LiteralNode*>(node->AsLiteral()) |
| + ->SetNewLocation(line_number); |
| + } else if (node->AsIdentifier()) { |
| + const_cast<IdentifierNode*>(node->AsIdentifier()) |
| + ->SetNewLocation(line_number); |
| + } else if (node->AsAccessor()) { |
| + const_cast<AccessorNode*>(node->AsAccessor()) |
| + ->SetNewLocation(line_number); |
| + } |
| + prev = node; |
| + } |
| + } |
| +} |
| + |
| // LiteralNode ----------------------------------------------------------------- |
| LiteralNode::LiteralNode() { |
| @@ -544,6 +656,12 @@ void LiteralNode::Print(std::ostream& out, int indent) const { |
| PrintComments(out, indent); |
| } |
| +void LiteralNode::SetNewLocation(int line_number) { |
| + Location old = value_.location(); |
| + value_.set_location( |
| + Location(old.file(), line_number, old.char_offset(), old.byte())); |
| +} |
| + |
| // UnaryOpNode ---------------------------------------------------------------- |
| UnaryOpNode::UnaryOpNode() { |
| @@ -608,7 +726,6 @@ void BlockCommentNode::Print(std::ostream& out, int indent) const { |
| PrintComments(out, indent); |
| } |
| - |
| // EndNode --------------------------------------------------------------------- |
| EndNode::EndNode(const Token& token) : value_(token) { |