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 "tools/gn/commands.h" | 8 #include "tools/gn/commands.h" |
9 #include "tools/gn/input_file.h" | 9 #include "tools/gn/input_file.h" |
10 #include "tools/gn/parser.h" | 10 #include "tools/gn/parser.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 void Block(const ParseNode* file); | 43 void Block(const ParseNode* file); |
44 | 44 |
45 std::string String() const { return output_; } | 45 std::string String() const { return output_; } |
46 | 46 |
47 private: | 47 private: |
48 // Format a list of values using the given style. | 48 // Format a list of values using the given style. |
49 enum SequenceStyle { | 49 enum SequenceStyle { |
50 kSequenceStyleFunctionCall, | 50 kSequenceStyleFunctionCall, |
51 kSequenceStyleList, | 51 kSequenceStyleList, |
52 kSequenceStyleBlock, | 52 kSequenceStyleBlock, |
| 53 kSequenceStyleBracedBlock, |
53 }; | 54 }; |
54 | 55 |
55 enum ExprStyle { | 56 enum ExprStyle { |
56 kExprStyleRegular, | 57 kExprStyleRegular, |
57 kExprStyleComment, | 58 kExprStyleComment, |
58 }; | 59 }; |
59 | 60 |
60 // Add to output. | 61 // Add to output. |
61 void Print(base::StringPiece str); | 62 void Print(base::StringPiece str); |
62 | 63 |
63 // Add the current margin (as spaces) to the output. | 64 // Add the current margin (as spaces) to the output. |
64 void PrintMargin(); | 65 void PrintMargin(); |
65 | 66 |
66 void TrimAndPrintToken(const Token& token); | 67 void TrimAndPrintToken(const Token& token); |
67 | 68 |
68 // End the current line, flushing end of line comments. | 69 // End the current line, flushing end of line comments. |
69 void Newline(); | 70 void Newline(); |
70 | 71 |
71 // Remove trailing spaces from the current line. | 72 // Remove trailing spaces from the current line. |
72 void Trim(); | 73 void Trim(); |
73 | 74 |
74 // Get the 0-based x position on the current line. | 75 // Get the 0-based x position on the current line. |
75 int CurrentColumn(); | 76 int CurrentColumn(); |
76 | 77 |
77 // Print the expression to the output buffer. Returns the type of element | 78 // Print the expression to the output buffer. Returns the type of element |
78 // added to the output. | 79 // added to the output. |
79 ExprStyle Expr(const ParseNode* root); | 80 ExprStyle Expr(const ParseNode* root); |
80 | 81 |
| 82 // Format a list of values using the given style. |
| 83 // |end| holds any trailing comments to be printed just before the closing |
| 84 // bracket. |
81 template <class PARSENODE> // Just for const covariance. | 85 template <class PARSENODE> // Just for const covariance. |
82 void Sequence(SequenceStyle style, const std::vector<PARSENODE*>& list); | 86 void Sequence(SequenceStyle style, |
| 87 const std::vector<PARSENODE*>& list, |
| 88 const ParseNode* end); |
83 | 89 |
84 std::string output_; // Output buffer. | 90 std::string output_; // Output buffer. |
85 std::vector<Token> comments_; // Pending end-of-line comments. | 91 std::vector<Token> comments_; // Pending end-of-line comments. |
86 int margin_; // Left margin (number of spaces). | 92 int margin_; // Left margin (number of spaces). |
87 | 93 |
88 DISALLOW_COPY_AND_ASSIGN(Printer); | 94 DISALLOW_COPY_AND_ASSIGN(Printer); |
89 }; | 95 }; |
90 | 96 |
91 Printer::Printer() : margin_(0) { | 97 Printer::Printer() : margin_(0) { |
92 output_.reserve(100 << 10); | 98 output_.reserve(100 << 10); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 Print("TODO(scottmg): AccessorNode"); | 209 Print("TODO(scottmg): AccessorNode"); |
204 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { | 210 } else if (const BinaryOpNode* binop = root->AsBinaryOp()) { |
205 // TODO(scottmg): Lots to do here for complex if expressions: reflowing, | 211 // TODO(scottmg): Lots to do here for complex if expressions: reflowing, |
206 // parenthesizing, etc. | 212 // parenthesizing, etc. |
207 Expr(binop->left()); | 213 Expr(binop->left()); |
208 Print(" "); | 214 Print(" "); |
209 Print(binop->op().value()); | 215 Print(binop->op().value()); |
210 Print(" "); | 216 Print(" "); |
211 Expr(binop->right()); | 217 Expr(binop->right()); |
212 } else if (const BlockNode* block = root->AsBlock()) { | 218 } else if (const BlockNode* block = root->AsBlock()) { |
213 Sequence(kSequenceStyleBlock, block->statements()); | 219 Sequence(kSequenceStyleBracedBlock, block->statements(), block->End()); |
214 } else if (const ConditionNode* condition = root->AsConditionNode()) { | 220 } else if (const ConditionNode* condition = root->AsConditionNode()) { |
215 Print("if ("); | 221 Print("if ("); |
216 Expr(condition->condition()); | 222 Expr(condition->condition()); |
217 Print(") {"); | 223 Print(") "); |
218 margin_ += kIndentSize; | 224 Sequence(kSequenceStyleBracedBlock, |
219 Newline(); | 225 condition->if_true()->statements(), |
220 Block(condition->if_true()); | 226 condition->if_true()->End()); |
221 margin_ -= kIndentSize; | |
222 Trim(); | |
223 PrintMargin(); | |
224 Print("}"); | |
225 if (condition->if_false()) { | 227 if (condition->if_false()) { |
226 Print(" else "); | 228 Print(" else "); |
227 // If it's a block it's a bare 'else', otherwise it's an 'else if'. See | 229 // If it's a block it's a bare 'else', otherwise it's an 'else if'. See |
228 // ConditionNode::Execute. | 230 // ConditionNode::Execute. |
229 bool is_else_if = condition->if_false()->AsBlock() == NULL; | 231 bool is_else_if = condition->if_false()->AsBlock() == NULL; |
230 if (is_else_if) { | 232 if (is_else_if) { |
231 Expr(condition->if_false()); | 233 Expr(condition->if_false()); |
232 } else { | 234 } else { |
233 Print("{"); | 235 Sequence(kSequenceStyleBracedBlock, |
234 margin_ += kIndentSize; | 236 condition->if_false()->AsBlock()->statements(), |
235 Newline(); | 237 condition->if_false()->AsBlock()->End()); |
236 Block(condition->if_false()); | |
237 margin_ -= kIndentSize; | |
238 Trim(); | |
239 PrintMargin(); | |
240 Print("}"); | |
241 } | 238 } |
242 } | 239 } |
243 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { | 240 } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) { |
244 Print(func_call->function().value()); | 241 Print(func_call->function().value()); |
245 Sequence(kSequenceStyleFunctionCall, func_call->args()->contents()); | 242 Sequence(kSequenceStyleFunctionCall, |
246 Print(" {"); | 243 func_call->args()->contents(), |
247 margin_ += kIndentSize; | 244 func_call->args()->End()); |
248 Newline(); | 245 Print(" "); |
249 Block(func_call->block()); | 246 Sequence(kSequenceStyleBracedBlock, |
250 margin_ -= kIndentSize; | 247 func_call->block()->statements(), |
251 Trim(); | 248 func_call->block()->End()); |
252 PrintMargin(); | |
253 Print("}"); | |
254 } else if (const IdentifierNode* identifier = root->AsIdentifier()) { | 249 } else if (const IdentifierNode* identifier = root->AsIdentifier()) { |
255 Print(identifier->value().value()); | 250 Print(identifier->value().value()); |
256 } else if (const ListNode* list = root->AsList()) { | 251 } else if (const ListNode* list = root->AsList()) { |
257 Sequence(kSequenceStyleList, list->contents()); | 252 Sequence(kSequenceStyleList, list->contents(), list->End()); |
258 } else if (const LiteralNode* literal = root->AsLiteral()) { | 253 } else if (const LiteralNode* literal = root->AsLiteral()) { |
259 // TODO(scottmg): Quoting? | 254 // TODO(scottmg): Quoting? |
260 Print(literal->value().value()); | 255 Print(literal->value().value()); |
261 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { | 256 } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) { |
262 Print(unaryop->op().value()); | 257 Print(unaryop->op().value()); |
263 Expr(unaryop->operand()); | 258 Expr(unaryop->operand()); |
264 } else if (const BlockCommentNode* block_comment = root->AsBlockComment()) { | 259 } else if (const BlockCommentNode* block_comment = root->AsBlockComment()) { |
265 Print(block_comment->comment().value()); | 260 Print(block_comment->comment().value()); |
266 result = kExprStyleComment; | 261 result = kExprStyleComment; |
| 262 } else if (const EndNode* end = root->AsEnd()) { |
| 263 Print(end->value().value()); |
267 } else { | 264 } else { |
268 CHECK(false) << "Unhandled case in Expr."; | 265 CHECK(false) << "Unhandled case in Expr."; |
269 } | 266 } |
270 | 267 |
271 // Defer any end of line comment until we reach the newline. | 268 // Defer any end of line comment until we reach the newline. |
272 if (root->comments() && !root->comments()->suffix().empty()) { | 269 if (root->comments() && !root->comments()->suffix().empty()) { |
273 std::copy(root->comments()->suffix().begin(), | 270 std::copy(root->comments()->suffix().begin(), |
274 root->comments()->suffix().end(), | 271 root->comments()->suffix().end(), |
275 std::back_inserter(comments_)); | 272 std::back_inserter(comments_)); |
276 } | 273 } |
277 | 274 |
278 return result; | 275 return result; |
279 } | 276 } |
280 | 277 |
281 template <class PARSENODE> | 278 template <class PARSENODE> |
282 void Printer::Sequence(SequenceStyle style, | 279 void Printer::Sequence(SequenceStyle style, |
283 const std::vector<PARSENODE*>& list) { | 280 const std::vector<PARSENODE*>& list, |
| 281 const ParseNode* end) { |
284 bool force_multiline = false; | 282 bool force_multiline = false; |
285 if (style == kSequenceStyleFunctionCall) | 283 if (style == kSequenceStyleFunctionCall) |
286 Print("("); | 284 Print("("); |
287 else if (style == kSequenceStyleList) | 285 else if (style == kSequenceStyleList) |
288 Print("["); | 286 Print("["); |
| 287 else if (style == kSequenceStyleBracedBlock) |
| 288 Print("{"); |
289 | 289 |
290 if (style == kSequenceStyleBlock) | 290 if (style == kSequenceStyleBlock || style == kSequenceStyleBracedBlock) |
| 291 force_multiline = true; |
| 292 |
| 293 if (end && end->comments() && !end->comments()->before().empty()) |
291 force_multiline = true; | 294 force_multiline = true; |
292 | 295 |
293 // If there's before line comments, make sure we have a place to put them. | 296 // If there's before line comments, make sure we have a place to put them. |
294 for (const auto& i : list) { | 297 for (const auto& i : list) { |
295 if (i->comments() && !i->comments()->before().empty()) | 298 if (i->comments() && !i->comments()->before().empty()) |
296 force_multiline = true; | 299 force_multiline = true; |
297 } | 300 } |
298 | 301 |
299 if (list.size() == 0 && !force_multiline) { | 302 if (list.size() == 0 && !force_multiline) { |
300 // No elements, and not forcing newlines, print nothing. | 303 // No elements, and not forcing newlines, print nothing. |
301 } else if (list.size() == 1 && !force_multiline) { | 304 } else if (list.size() == 1 && !force_multiline) { |
302 if (style != kSequenceStyleFunctionCall) | 305 if (style != kSequenceStyleFunctionCall) |
303 Print(" "); | 306 Print(" "); |
304 Expr(list[0]); | 307 Expr(list[0]); |
305 CHECK(list[0]->comments()->after().empty()); | 308 CHECK(!list[0]->comments() || list[0]->comments()->after().empty()); |
306 if (style != kSequenceStyleFunctionCall) | 309 if (style != kSequenceStyleFunctionCall) |
307 Print(" "); | 310 Print(" "); |
308 } else { | 311 } else { |
309 margin_ += kIndentSize; | 312 margin_ += kIndentSize; |
310 size_t i = 0; | 313 size_t i = 0; |
311 for (const auto& x : list) { | 314 for (const auto& x : list) { |
312 Newline(); | 315 Newline(); |
313 ExprStyle expr_style = Expr(x); | 316 ExprStyle expr_style = Expr(x); |
314 CHECK(x->comments()->after().empty()); | 317 CHECK(!x->comments() || x->comments()->after().empty()); |
315 if (i < list.size() - 1 || style == kSequenceStyleList) { | 318 if (i < list.size() - 1 || style == kSequenceStyleList) { |
316 if (expr_style == kExprStyleRegular) | 319 if ((style == kSequenceStyleList || kSequenceStyleFunctionCall) && |
| 320 expr_style == kExprStyleRegular) { |
317 Print(","); | 321 Print(","); |
318 else | 322 } else { |
319 Newline(); | 323 Newline(); |
| 324 } |
320 } | 325 } |
321 ++i; | 326 ++i; |
322 } | 327 } |
323 | 328 |
| 329 // Trailing comments. |
| 330 if (end->comments()) { |
| 331 if (!list.empty()) |
| 332 Newline(); |
| 333 for (const auto& c : end->comments()->before()) { |
| 334 Newline(); |
| 335 TrimAndPrintToken(c); |
| 336 } |
| 337 } |
| 338 |
324 margin_ -= kIndentSize; | 339 margin_ -= kIndentSize; |
325 Newline(); | 340 Newline(); |
326 } | 341 } |
327 | 342 |
328 if (style == kSequenceStyleFunctionCall) | 343 if (style == kSequenceStyleFunctionCall) |
329 Print(")"); | 344 Print(")"); |
330 else if (style == kSequenceStyleList) | 345 else if (style == kSequenceStyleList) |
331 Print("]"); | 346 Print("]"); |
| 347 else if (style == kSequenceStyleBracedBlock) |
| 348 Print("}"); |
332 } | 349 } |
333 | 350 |
334 } // namespace | 351 } // namespace |
335 | 352 |
336 bool FormatFileToString(const std::string& input_filename, | 353 bool FormatFileToString(const std::string& input_filename, |
337 bool dump_tree, | 354 bool dump_tree, |
338 std::string* output) { | 355 std::string* output) { |
339 Setup setup; | 356 Setup setup; |
340 Err err; | 357 Err err; |
341 SourceFile input_file(input_filename); | 358 SourceFile input_file(input_filename); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 } | 399 } |
383 std::string output_string; | 400 std::string output_string; |
384 if (FormatFileToString(input_name, dump_tree, &output_string)) { | 401 if (FormatFileToString(input_name, dump_tree, &output_string)) { |
385 printf("%s", output_string.c_str()); | 402 printf("%s", output_string.c_str()); |
386 } | 403 } |
387 | 404 |
388 return 0; | 405 return 0; |
389 } | 406 } |
390 | 407 |
391 } // namespace commands | 408 } // namespace commands |
OLD | NEW |