| 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 |