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

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

Issue 742003002: gn format: penalty-based line breaking WIP XXX Base URL: https://chromium.googlesource.com/chromium/src.git@gn-more-disabled
Patch Set: futzing Created 6 years 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/line_breaker.h ('k') | tools/gn/line_breaker_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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "tools/gn/line_breaker.h"
6
7 #include "tools/gn/parse_tree.h"
8
9 namespace commands {
10
11 const int kExcessCharacterPenalty = 1000000;
12
13 Precedence GetPrecedence(const base::StringPiece op) {
14 if (op == "=" || op == "+=" || op == "-=")
15 return kPrecedenceAssign;
16 if (op == "||")
17 return kPrecedenceOr;
18 if (op == "&&")
19 return kPrecedenceAnd;
20 if (op == "<" || op == ">" || op == "==" || op == "!=" || op == "<=" ||
21 op == ">=") {
22 return kPrecedenceCompare;
23 }
24 if (op == "+" || op == "-")
25 return kPrecedenceAdd;
26 if (op == "!")
27 return kPrecedenceUnary;
28 DCHECK(false);
29 return kPrecedenceLowest;
30 }
31
32 AnnotatedToken::AnnotatedToken(const Token& token, Type type)
33 : token_(token), type_(type) {
34 }
35
36 AnnotatedToken::~AnnotatedToken() {
37 }
38
39 void AddParen(int prec,
40 int outer_prec,
41 bool* parenthesized,
42 std::vector<AnnotatedToken>* result) {
43 if (prec < outer_prec) {
44 result->push_back(AnnotatedToken(Token(Location(), Token::LEFT_PAREN, "("),
45 AnnotatedToken::LEFT_PAREN_GROUPING));
46 *parenthesized = true;
47 }
48 }
49
50 void FlattenUntilNextChunk(const ParseNode* root,
51 int outer_prec,
52 std::vector<AnnotatedToken>* result) {
53 if (root) {
54 bool parenthesized = false;
55 if (const AccessorNode* accessor = root->AsAccessor()) {
56 AddParen(kPrecedenceSuffix, outer_prec, &parenthesized, result);
57 if (accessor->member()) {
58 result->push_back(AnnotatedToken(Token(Location(), Token::DOT, "."),
59 AnnotatedToken::UNDERLYING));
60 FlattenUntilNextChunk(accessor->member(), kPrecedenceLowest, result);
61 } else {
62 result->push_back(
63 AnnotatedToken(Token(Location(), Token::LEFT_BRACKET, "["),
64 AnnotatedToken::LEFT_BRACKET_ACCESSOR));
65 FlattenUntilNextChunk(accessor->index(), kPrecedenceLowest, result);
66 result->push_back(
67 AnnotatedToken(Token(Location(), Token::RIGHT_BRACKET, "]"),
68 AnnotatedToken::UNDERLYING));
69 }
70 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) {
71 Precedence prec = GetPrecedence(binop->op().value());
72 AddParen(prec, outer_prec, &parenthesized, result);
73 FlattenUntilNextChunk(binop->left(), prec, result);
74 result->push_back(
75 AnnotatedToken(binop->op(), AnnotatedToken::UNDERLYING));
76 FlattenUntilNextChunk(binop->right(), prec + 1, result);
77 } else if (const BlockNode* block = root->AsBlock()) {
78 if (block->begin_token().type() != Token::INVALID) {
79 result->push_back(
80 AnnotatedToken(block->begin_token(), AnnotatedToken::UNDERLYING));
81 }
82 // Don't walk rest after first.
83 for (const auto& statement : block->statements()) {
84 FlattenUntilNextChunk(statement, kPrecedenceLowest, result);
85 break;
86 }
87 } else if (const ConditionNode* condition = root->AsConditionNode()) {
88 FlattenUntilNextChunk(condition->condition(), kPrecedenceLowest, result);
89 // Don't traverse into true/false as those count as breaks.
90 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) {
91 result->push_back(
92 AnnotatedToken(func_call->function(), AnnotatedToken::UNDERLYING));
93 result->push_back(
94 AnnotatedToken(func_call->args()->begin_token(),
95 AnnotatedToken::LEFT_PAREN_FUNCTION_CALL));
96 size_t i = 0;
97 for (const auto& node : func_call->args()->contents()) {
98 FlattenUntilNextChunk(node, kPrecedenceLowest, result);
99 if (i < func_call->args()->contents().size() - 1) {
100 result->push_back(AnnotatedToken(Token(Location(), Token::COMMA, ","),
101 AnnotatedToken::UNDERLYING));
102 }
103 ++i;
104 }
105 FlattenUntilNextChunk(func_call->args()->End(), kPrecedenceLowest,
106 result);
107 } else if (const IdentifierNode* identifier = root->AsIdentifier()) {
108 result->push_back(
109 AnnotatedToken(identifier->value(), AnnotatedToken::UNDERLYING));
110 } else if (const ListNode* list = root->AsList()) {
111 result->push_back(AnnotatedToken(
112 list->begin_token(), AnnotatedToken::LEFT_BRACKET_LIST_LITERAL));
113 size_t i = 0;
114 for (const auto& node : list->contents()) {
115 FlattenUntilNextChunk(node, kPrecedenceLowest, result);
116 if (i < list->contents().size() - 1) {
117 result->push_back(AnnotatedToken(Token(Location(), Token::COMMA, ","),
118 AnnotatedToken::UNDERLYING));
119 }
120 ++i;
121 }
122 FlattenUntilNextChunk(list->End(), kPrecedenceLowest, result);
123 } else if (const LiteralNode* literal = root->AsLiteral()) {
124 result->push_back(
125 AnnotatedToken(literal->value(), AnnotatedToken::UNDERLYING));
126 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) {
127 FlattenUntilNextChunk(unaryop->operand(), kPrecedenceUnary, result);
128 } else if (const BlockCommentNode* comment = root->AsBlockComment()) {
129 result->push_back(
130 AnnotatedToken(comment->comment(), AnnotatedToken::UNDERLYING));
131 } else if (const EndNode* end = root->AsEnd()) {
132 result->push_back(
133 AnnotatedToken(end->value(), AnnotatedToken::UNDERLYING));
134 } else {
135 CHECK(false) << "Unhandled case in FlattenUntilNextChunk.";
136 }
137
138 if (parenthesized) {
139 result->push_back(
140 AnnotatedToken(Token(Location(), Token::RIGHT_PAREN, ")"),
141 AnnotatedToken::UNDERLYING));
142 }
143 }
144 }
145
146 std::vector<AnnotatedToken> BuildAnnotatedTokenList(
147 const ParseNode* statement) {
148 std::vector<AnnotatedToken> result;
149 FlattenUntilNextChunk(statement, kPrecedenceLowest, &result);
150 return result;
151 }
152
153 LineBreaker::LineBreaker(const std::vector<AnnotatedToken>& annotated_tokens,
154 int initial_column)
155 : annotated_tokens_(annotated_tokens),
156 initial_column_(initial_column),
157 end_(static_cast<int>(annotated_tokens.size())) {
158 }
159
160 LineBreaker::~LineBreaker() {
161 }
162
163 std::string LineBreaker::GetBestLayout() {
164 Format(0, initial_column_);
165 return std::string();
166 }
167
168 void LineBreaker::Format(int index, int start_column) {
169 LineState state;
170 state.column = start_column;
171 state.next = index + 1;
172
173 // todo move past first, it's already in place
174
175 while (state.next < end_) {
176
177 }
178 }
179
180 int LineBreaker::CalculatePenalty(LineState state, bool newline) {
181 if (state.next == end_)
182 return 0;
183
184 int penalty = 0;
185
186 AddTokenToState(newline, &state);
187
188 // Assign penalty for being too long.
189 if (state.column > kMaximumWidth) {
190 int excess_characters = state.column - kMaximumWidth;
191 penalty += excess_characters * kExcessCharacterPenalty;
192 }
193
194 int no_break = CalculatePenalty(state, false);
195 int with_break = CalculatePenalty(state, true);
196 int result = std::min(no_break, with_break);
197 //penalty_cache_[state] = result;
198 return result + penalty;
199 }
200
201 void LineBreaker::AddTokenToState(bool newline, LineState* state) {
202 }
203
204 } // namespace commands
OLDNEW
« no previous file with comments | « tools/gn/line_breaker.h ('k') | tools/gn/line_breaker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698