| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library formatter_impl; | 5 library formatter_impl; |
| 6 | 6 |
| 7 import 'dart:math'; | 7 import 'dart:math'; |
| 8 | 8 |
| 9 import 'package:analyzer_experimental/analyzer.dart'; | 9 import 'package:analyzer_experimental/analyzer.dart'; |
| 10 import 'package:analyzer_experimental/src/generated/parser.dart'; | 10 import 'package:analyzer_experimental/src/generated/parser.dart'; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 | 143 |
| 144 /// The writer to which the source is to be written. | 144 /// The writer to which the source is to be written. |
| 145 final SourceWriter writer; | 145 final SourceWriter writer; |
| 146 | 146 |
| 147 /// Cached line info for calculating blank lines. | 147 /// Cached line info for calculating blank lines. |
| 148 LineInfo lineInfo; | 148 LineInfo lineInfo; |
| 149 | 149 |
| 150 /// Cached previous token for calculating preceding whitespace. | 150 /// Cached previous token for calculating preceding whitespace. |
| 151 Token previousToken; | 151 Token previousToken; |
| 152 | 152 |
| 153 /// A flag to indicate that a newline should be emitted before the next token. |
| 154 bool needsNewline = false; |
| 155 |
| 156 /// A flag to indicate that user introduced newlines should be emitted before |
| 157 /// the next token. |
| 158 bool preservePrecedingNewlines = false; |
| 159 |
| 153 /// Initialize a newly created visitor to write source code representing | 160 /// Initialize a newly created visitor to write source code representing |
| 154 /// the visited nodes to the given [writer]. | 161 /// the visited nodes to the given [writer]. |
| 155 SourceVisitor(FormatterOptions options, this.lineInfo) : | 162 SourceVisitor(FormatterOptions options, this.lineInfo) : |
| 156 writer = new SourceWriter(indentCount: options.initialIndentationLevel, | 163 writer = new SourceWriter(indentCount: options.initialIndentationLevel, |
| 157 lineSeparator: options.lineSeparator); | 164 lineSeparator: options.lineSeparator); |
| 158 | 165 |
| 159 visitAdjacentStrings(AdjacentStrings node) { | 166 visitAdjacentStrings(AdjacentStrings node) { |
| 160 visitList(node.strings, ' '); | 167 visitList(node.strings, ' '); |
| 161 } | 168 } |
| 162 | 169 |
| 163 visitAnnotation(Annotation node) { | 170 visitAnnotation(Annotation node) { |
| 164 emitToken(node.atSign); | 171 token(node.atSign); |
| 165 visit(node.name); | 172 visit(node.name); |
| 166 visitPrefixed('.', node.constructorName); | 173 visitPrefixed('.', node.constructorName); |
| 167 visit(node.arguments); | 174 visit(node.arguments); |
| 168 } | 175 } |
| 169 | 176 |
| 170 visitArgumentDefinitionTest(ArgumentDefinitionTest node) { | 177 visitArgumentDefinitionTest(ArgumentDefinitionTest node) { |
| 171 emitToken(node.question); | 178 token(node.question); |
| 172 visit(node.identifier); | 179 visit(node.identifier); |
| 173 } | 180 } |
| 174 | 181 |
| 175 visitArgumentList(ArgumentList node) { | 182 visitArgumentList(ArgumentList node) { |
| 176 emitToken(node.leftParenthesis); | 183 token(node.leftParenthesis); |
| 177 visitList(node.arguments, ', '); | 184 visitList(node.arguments, ', '); |
| 178 emitToken(node.rightParenthesis); | 185 token(node.rightParenthesis); |
| 179 } | 186 } |
| 180 | 187 |
| 181 visitAsExpression(AsExpression node) { | 188 visitAsExpression(AsExpression node) { |
| 182 visit(node.expression); | 189 visit(node.expression); |
| 183 emitToken(node.asOperator, prefix: ' ', suffix: ' '); | 190 space(); |
| 191 token(node.asOperator); |
| 192 space(); |
| 184 visit(node.type); | 193 visit(node.type); |
| 185 } | 194 } |
| 186 | 195 |
| 187 visitAssertStatement(AssertStatement node) { | 196 visitAssertStatement(AssertStatement node) { |
| 188 emitToken(node.keyword, suffix: ' ('); | 197 token(node.keyword); |
| 198 space(); |
| 199 token(node.leftParenthesis); |
| 189 visit(node.condition); | 200 visit(node.condition); |
| 190 emitToken(node.semicolon, prefix: ')'); | 201 token(node.rightParenthesis); |
| 202 token(node.semicolon); |
| 191 } | 203 } |
| 192 | 204 |
| 193 visitAssignmentExpression(AssignmentExpression node) { | 205 visitAssignmentExpression(AssignmentExpression node) { |
| 194 visit(node.leftHandSide); | 206 visit(node.leftHandSide); |
| 195 emitToken(node.operator, prefix: ' ', suffix: ' '); | 207 space(); |
| 208 token(node.operator); |
| 209 space(); |
| 196 visit(node.rightHandSide); | 210 visit(node.rightHandSide); |
| 197 } | 211 } |
| 198 | 212 |
| 199 visitBinaryExpression(BinaryExpression node) { | 213 visitBinaryExpression(BinaryExpression node) { |
| 200 visit(node.leftOperand); | 214 visit(node.leftOperand); |
| 201 emitToken(node.operator, prefix: ' ', suffix: ' '); | 215 space(); |
| 216 token(node.operator); |
| 217 space(); |
| 202 visit(node.rightOperand); | 218 visit(node.rightOperand); |
| 203 } | 219 } |
| 204 | 220 |
| 205 visitBlock(Block node) { | 221 visitBlock(Block node) { |
| 206 emitToken(node.leftBracket); | 222 token(node.leftBracket); |
| 223 needsNewline = true; |
| 207 indent(); | 224 indent(); |
| 208 | 225 |
| 209 for (var stmt in node.statements) { | 226 for (var stmt in node.statements) { |
| 210 visit(stmt); | 227 visit(stmt); |
| 211 } | 228 } |
| 212 | 229 |
| 213 unindent(); | 230 unindent(); |
| 214 newline(); | 231 preservePrecedingNewlines = true; |
| 215 print('}'); | 232 needsNewline = true; |
| 216 //TODO(pquitslund): make this work | 233 token(node.rightBracket); |
| 217 // emitToken(node.rightBracket); | |
| 218 previousToken = node.rightBracket; | |
| 219 } | 234 } |
| 220 | 235 |
| 221 visitBlockFunctionBody(BlockFunctionBody node) { | 236 visitBlockFunctionBody(BlockFunctionBody node) { |
| 222 visit(node.block); | 237 visit(node.block); |
| 223 } | 238 } |
| 224 | 239 |
| 225 visitBooleanLiteral(BooleanLiteral node) { | 240 visitBooleanLiteral(BooleanLiteral node) { |
| 226 emitToken(node.literal); | 241 token(node.literal); |
| 227 } | 242 } |
| 228 | 243 |
| 229 visitBreakStatement(BreakStatement node) { | 244 visitBreakStatement(BreakStatement node) { |
| 230 emitToken(node.keyword); | 245 preservePrecedingNewlines = true; |
| 246 token(node.keyword); |
| 231 visitPrefixed(' ', node.label); | 247 visitPrefixed(' ', node.label); |
| 232 emitToken(node.semicolon); | 248 token(node.semicolon); |
| 249 needsNewline = true; |
| 233 } | 250 } |
| 234 | 251 |
| 235 visitCascadeExpression(CascadeExpression node) { | 252 visitCascadeExpression(CascadeExpression node) { |
| 236 visit(node.target); | 253 visit(node.target); |
| 237 visitList(node.cascadeSections); | 254 visitList(node.cascadeSections); |
| 238 } | 255 } |
| 239 | 256 |
| 240 visitCatchClause(CatchClause node) { | 257 visitCatchClause(CatchClause node) { |
| 241 visitPrefixed('on ', node.exceptionType); | 258 visitPrefixed('on ', node.exceptionType); |
| 242 if (node.catchKeyword != null) { | 259 if (node.catchKeyword != null) { |
| 243 if (node.exceptionType != null) { | 260 if (node.exceptionType != null) { |
| 244 print(' '); | 261 space(); |
| 245 } | 262 } |
| 246 print('catch ('); | 263 token(node.catchKeyword); |
| 264 space(); |
| 265 token(node.leftParenthesis); |
| 247 visit(node.exceptionParameter); | 266 visit(node.exceptionParameter); |
| 248 visitPrefixed(', ', node.stackTraceParameter); | 267 visitPrefixed(', ', node.stackTraceParameter); |
| 249 print(') '); | 268 token(node.rightParenthesis); |
| 269 space(); |
| 250 } else { | 270 } else { |
| 251 print(' '); | 271 space(); |
| 252 } | 272 } |
| 253 visit(node.body); | 273 visit(node.body); |
| 254 newline(); | 274 needsNewline = true; |
| 255 } | 275 } |
| 256 | 276 |
| 257 visitClassDeclaration(ClassDeclaration node) { | 277 visitClassDeclaration(ClassDeclaration node) { |
| 258 emitToken(node.abstractKeyword, suffix: ' '); | 278 preservePrecedingNewlines = true; |
| 259 emitToken(node.classKeyword, suffix: ' '); | 279 modifier(node.abstractKeyword); |
| 280 token(node.classKeyword); |
| 281 space(); |
| 260 visit(node.name); | 282 visit(node.name); |
| 261 visit(node.typeParameters); | 283 visit(node.typeParameters); |
| 262 visitPrefixed(' ', node.extendsClause); | 284 visitPrefixed(' ', node.extendsClause); |
| 263 visitPrefixed(' ', node.withClause); | 285 visitPrefixed(' ', node.withClause); |
| 264 visitPrefixed(' ', node.implementsClause); | 286 visitPrefixed(' ', node.implementsClause); |
| 265 emitToken(node.leftBracket, prefix: ' '); | 287 space(); |
| 288 token(node.leftBracket); |
| 266 indent(); | 289 indent(); |
| 267 | 290 |
| 268 for (var i = 0; i < node.members.length; i++) { | 291 for (var i = 0; i < node.members.length; i++) { |
| 269 visit(node.members[i]); | 292 visit(node.members[i]); |
| 270 } | 293 } |
| 271 | 294 |
| 272 unindent(); | 295 unindent(); |
| 273 | 296 |
| 274 emitToken(node.rightBracket, minNewlines: 1); | 297 emitPrecedingNewlines(node.rightBracket, min: 1); |
| 298 token(node.rightBracket); |
| 275 } | 299 } |
| 276 | 300 |
| 277 visitClassTypeAlias(ClassTypeAlias node) { | 301 visitClassTypeAlias(ClassTypeAlias node) { |
| 278 emitToken(node.keyword, suffix: ' '); | 302 token(node.keyword); |
| 303 space(); |
| 279 visit(node.name); | 304 visit(node.name); |
| 280 visit(node.typeParameters); | 305 visit(node.typeParameters); |
| 281 print(' = '); | 306 space(); |
| 307 token(node.equals); |
| 308 space(); |
| 282 if (node.abstractKeyword != null) { | 309 if (node.abstractKeyword != null) { |
| 283 print('abstract '); | 310 token(node.abstractKeyword); |
| 311 space(); |
| 284 } | 312 } |
| 285 visit(node.superclass); | 313 visit(node.superclass); |
| 286 visitPrefixed(' ', node.withClause); | 314 visitPrefixed(' ', node.withClause); |
| 287 visitPrefixed(' ', node.implementsClause); | 315 visitPrefixed(' ', node.implementsClause); |
| 288 emitToken(node.semicolon); | 316 token(node.semicolon); |
| 289 } | 317 } |
| 290 | 318 |
| 291 visitComment(Comment node) => null; | 319 visitComment(Comment node) => null; |
| 292 | 320 |
| 293 visitCommentReference(CommentReference node) => null; | 321 visitCommentReference(CommentReference node) => null; |
| 294 | 322 |
| 295 visitCompilationUnit(CompilationUnit node) { | 323 visitCompilationUnit(CompilationUnit node) { |
| 324 |
| 325 // Cache EOF for leading whitespace calculation |
| 326 var start = node.beginToken.previous; |
| 327 if (start != null && start.type is TokenType_EOF) { |
| 328 previousToken = start; |
| 329 } |
| 330 |
| 296 var scriptTag = node.scriptTag; | 331 var scriptTag = node.scriptTag; |
| 297 var directives = node.directives; | 332 var directives = node.directives; |
| 298 visit(scriptTag); | 333 visit(scriptTag); |
| 299 var prefix = scriptTag == null ? '' : ' '; | 334 visitList(directives); |
| 300 visitPrefixedList(prefix, directives, ' '); | 335 visitList(node.declarations); |
| 301 //prefix = scriptTag == null && directives.isEmpty ? '' : ' '; | |
| 302 prefix = ''; | |
| 303 visitPrefixedList(prefix, node.declarations); | |
| 304 | 336 |
| 305 //TODO(pquitslund): move this? | 337 // Handle trailing whitespace |
| 306 newline(); | 338 preservePrecedingNewlines = true; |
| 339 token(node.endToken /* EOF */); |
| 307 } | 340 } |
| 308 | 341 |
| 309 visitConditionalExpression(ConditionalExpression node) { | 342 visitConditionalExpression(ConditionalExpression node) { |
| 310 visit(node.condition); | 343 visit(node.condition); |
| 311 print(' ? '); | 344 space(); |
| 345 token(node.question); |
| 346 space(); |
| 312 visit(node.thenExpression); | 347 visit(node.thenExpression); |
| 313 print(' : '); | 348 space(); |
| 349 token(node.colon); |
| 350 space(); |
| 314 visit(node.elseExpression); | 351 visit(node.elseExpression); |
| 315 } | 352 } |
| 316 | 353 |
| 317 visitConstructorDeclaration(ConstructorDeclaration node) { | 354 visitConstructorDeclaration(ConstructorDeclaration node) { |
| 318 emitToken(node.externalKeyword, suffix: ' '); | 355 modifier(node.externalKeyword); |
| 319 emitToken(node.constKeyword, suffix: ' '); | 356 modifier(node.constKeyword); |
| 320 emitToken(node.factoryKeyword, suffix: ' '); | 357 modifier(node.factoryKeyword); |
| 321 visit(node.returnType); | 358 visit(node.returnType); |
| 322 visitPrefixed('.', node.name); | 359 visitPrefixed('.', node.name); |
| 323 visit(node.parameters); | 360 visit(node.parameters); |
| 324 visitPrefixedList(' : ', node.initializers, ', '); | 361 visitPrefixedList(' : ', node.initializers, ', '); |
| 325 visitPrefixed(' = ', node.redirectedConstructor); | 362 visitPrefixed(' = ', node.redirectedConstructor); |
| 326 visitPrefixedBody(' ', node.body); | 363 visitPrefixedBody(' ', node.body); |
| 327 } | 364 } |
| 328 | 365 |
| 329 visitConstructorFieldInitializer(ConstructorFieldInitializer node) { | 366 visitConstructorFieldInitializer(ConstructorFieldInitializer node) { |
| 330 emitToken(node.keyword, suffix: '.'); | 367 token(node.keyword); |
| 368 token(node.period); |
| 331 visit(node.fieldName); | 369 visit(node.fieldName); |
| 332 print(' = '); | 370 space(); |
| 371 token(node.equals); |
| 372 space(); |
| 333 visit(node.expression); | 373 visit(node.expression); |
| 334 } | 374 } |
| 335 | 375 |
| 336 visitConstructorName(ConstructorName node) { | 376 visitConstructorName(ConstructorName node) { |
| 337 visit(node.type); | 377 visit(node.type); |
| 338 visitPrefixed('.', node.name); | 378 visitPrefixed('.', node.name); |
| 339 } | 379 } |
| 340 | 380 |
| 341 visitContinueStatement(ContinueStatement node) { | 381 visitContinueStatement(ContinueStatement node) { |
| 342 emitToken(node.keyword); | 382 token(node.keyword); |
| 343 visitPrefixed(' ', node.label); | 383 visitPrefixed(' ', node.label); |
| 344 emitToken(node.semicolon); | 384 token(node.semicolon); |
| 345 } | 385 } |
| 346 | 386 |
| 347 visitDeclaredIdentifier(DeclaredIdentifier node) { | 387 visitDeclaredIdentifier(DeclaredIdentifier node) { |
| 348 emitToken(node.keyword, suffix: ' '); | 388 token(node.keyword); |
| 389 space(); |
| 349 visitSuffixed(node.type, ' '); | 390 visitSuffixed(node.type, ' '); |
| 350 visit(node.identifier); | 391 visit(node.identifier); |
| 351 } | 392 } |
| 352 | 393 |
| 353 visitDefaultFormalParameter(DefaultFormalParameter node) { | 394 visitDefaultFormalParameter(DefaultFormalParameter node) { |
| 354 visit(node.parameter); | 395 visit(node.parameter); |
| 355 if (node.separator != null) { | 396 if (node.separator != null) { |
| 356 print(' '); | 397 space(); |
| 357 print(node.separator.lexeme); | 398 token(node.separator); |
| 358 visitPrefixed(' ', node.defaultValue); | 399 visitPrefixed(' ', node.defaultValue); |
| 359 } | 400 } |
| 360 } | 401 } |
| 361 | 402 |
| 362 visitDoStatement(DoStatement node) { | 403 visitDoStatement(DoStatement node) { |
| 363 emitToken(node.doKeyword, suffix: ' '); | 404 token(node.doKeyword); |
| 405 space(); |
| 364 visit(node.body); | 406 visit(node.body); |
| 365 emitToken(node.whileKeyword, prefix: ' ', suffix: ' ('); | 407 space(); |
| 408 token(node.whileKeyword); |
| 409 space(); |
| 410 token(node.leftParenthesis); |
| 366 visit(node.condition); | 411 visit(node.condition); |
| 367 emitToken(node.semicolon, prefix: ')'); | 412 token(node.rightParenthesis); |
| 413 token(node.semicolon); |
| 368 } | 414 } |
| 369 | 415 |
| 370 visitDoubleLiteral(DoubleLiteral node) { | 416 visitDoubleLiteral(DoubleLiteral node) { |
| 371 print(node.literal.lexeme); | 417 token(node.literal); |
| 372 } | 418 } |
| 373 | 419 |
| 374 visitEmptyFunctionBody(EmptyFunctionBody node) { | 420 visitEmptyFunctionBody(EmptyFunctionBody node) { |
| 375 emitToken(node.semicolon); | 421 token(node.semicolon); |
| 376 } | 422 } |
| 377 | 423 |
| 378 visitEmptyStatement(EmptyStatement node) { | 424 visitEmptyStatement(EmptyStatement node) { |
| 379 emitToken(node.semicolon); | 425 token(node.semicolon); |
| 380 } | 426 } |
| 381 | 427 |
| 382 visitExportDirective(ExportDirective node) { | 428 visitExportDirective(ExportDirective node) { |
| 383 emitToken(node.keyword, suffix: ' '); | 429 token(node.keyword); |
| 430 space(); |
| 384 visit(node.uri); | 431 visit(node.uri); |
| 385 visitPrefixedList(' ', node.combinators, ' '); | 432 visitPrefixedList(' ', node.combinators, ' '); |
| 386 emitToken(node.semicolon); | 433 token(node.semicolon); |
| 387 } | 434 } |
| 388 | 435 |
| 389 visitExpressionFunctionBody(ExpressionFunctionBody node) { | 436 visitExpressionFunctionBody(ExpressionFunctionBody node) { |
| 390 emitToken(node.functionDefinition, suffix: ' '); | 437 token(node.functionDefinition); |
| 438 space(); |
| 391 visit(node.expression); | 439 visit(node.expression); |
| 392 emitToken(node.semicolon); | 440 token(node.semicolon); |
| 393 } | 441 } |
| 394 | 442 |
| 395 visitExpressionStatement(ExpressionStatement node) { | 443 visitExpressionStatement(ExpressionStatement node) { |
| 396 visit(node.expression); | 444 visit(node.expression); |
| 397 emitToken(node.semicolon); | 445 token(node.semicolon); |
| 398 } | 446 } |
| 399 | 447 |
| 400 visitExtendsClause(ExtendsClause node) { | 448 visitExtendsClause(ExtendsClause node) { |
| 401 emitToken(node.keyword, suffix: ' '); | 449 token(node.keyword); |
| 450 space(); |
| 402 visit(node.superclass); | 451 visit(node.superclass); |
| 403 } | 452 } |
| 404 | 453 |
| 405 visitFieldDeclaration(FieldDeclaration node) { | 454 visitFieldDeclaration(FieldDeclaration node) { |
| 406 emitToken(node.keyword, suffix: ' '); | 455 token(node.keyword); |
| 456 space(); |
| 407 visit(node.fields); | 457 visit(node.fields); |
| 408 emitToken(node.semicolon); | 458 token(node.semicolon); |
| 409 } | 459 } |
| 410 | 460 |
| 411 visitFieldFormalParameter(FieldFormalParameter node) { | 461 visitFieldFormalParameter(FieldFormalParameter node) { |
| 412 emitToken(node.keyword, suffix: ' '); | 462 token(node.keyword); |
| 463 space(); |
| 413 visitSuffixed(node.type, ' '); | 464 visitSuffixed(node.type, ' '); |
| 414 print('this.'); | 465 token(node.thisToken); |
| 466 token(node.period); |
| 415 visit(node.identifier); | 467 visit(node.identifier); |
| 416 visit(node.parameters); | 468 visit(node.parameters); |
| 417 } | 469 } |
| 418 | 470 |
| 419 visitForEachStatement(ForEachStatement node) { | 471 visitForEachStatement(ForEachStatement node) { |
| 420 print('for ('); | 472 token(node.forKeyword); |
| 473 space(); |
| 474 token(node.leftParenthesis); |
| 421 visit(node.loopVariable); | 475 visit(node.loopVariable); |
| 422 print(' in '); | 476 space(); |
| 477 token(node.inKeyword); |
| 478 space(); |
| 423 visit(node.iterator); | 479 visit(node.iterator); |
| 424 print(') '); | 480 token(node.leftParenthesis); |
| 481 space(); |
| 425 visit(node.body); | 482 visit(node.body); |
| 426 } | 483 } |
| 427 | 484 |
| 428 visitFormalParameterList(FormalParameterList node) { | 485 visitFormalParameterList(FormalParameterList node) { |
| 429 var groupEnd = null; | 486 var groupEnd = null; |
| 430 print('('); | 487 token(node.leftParenthesis); |
| 431 var parameters = node.parameters; | 488 var parameters = node.parameters; |
| 432 var size = parameters.length; | 489 var size = parameters.length; |
| 433 for (var i = 0; i < size; i++) { | 490 for (var i = 0; i < size; i++) { |
| 434 var parameter = parameters[i]; | 491 var parameter = parameters[i]; |
| 435 if (i > 0) { | 492 if (i > 0) { |
| 436 print(', '); | 493 append(', '); |
| 437 } | 494 } |
| 438 if (groupEnd == null && parameter is DefaultFormalParameter) { | 495 if (groupEnd == null && parameter is DefaultFormalParameter) { |
| 439 if (identical(parameter.kind, ParameterKind.NAMED)) { | 496 if (identical(parameter.kind, ParameterKind.NAMED)) { |
| 440 groupEnd = '}'; | 497 groupEnd = '}'; |
| 441 print('{'); | 498 append('{'); |
| 442 } else { | 499 } else { |
| 443 groupEnd = ']'; | 500 groupEnd = ']'; |
| 444 print('['); | 501 append('['); |
| 445 } | 502 } |
| 446 } | 503 } |
| 447 parameter.accept(this); | 504 parameter.accept(this); |
| 448 } | 505 } |
| 449 if (groupEnd != null) { | 506 if (groupEnd != null) { |
| 450 print(groupEnd); | 507 append(groupEnd); |
| 451 } | 508 } |
| 452 print(')'); | 509 token(node.rightParenthesis); |
| 453 } | 510 } |
| 454 | 511 |
| 455 visitForStatement(ForStatement node) { | 512 visitForStatement(ForStatement node) { |
| 513 token(node.forKeyword); |
| 514 space(); |
| 515 token(node.leftParenthesis); |
| 456 var initialization = node.initialization; | 516 var initialization = node.initialization; |
| 457 print('for ('); | |
| 458 if (initialization != null) { | 517 if (initialization != null) { |
| 459 visit(initialization); | 518 visit(initialization); |
| 460 } else { | 519 } else { |
| 461 visit(node.variables); | 520 visit(node.variables); |
| 462 } | 521 } |
| 463 print(';'); | 522 token(node.leftSeparator); |
| 464 visitPrefixed(' ', node.condition); | 523 visitPrefixed(' ', node.condition); |
| 465 print(';'); | 524 token(node.rightSeparator); |
| 466 visitPrefixedList(' ', node.updaters, ', '); | 525 visitPrefixedList(' ', node.updaters, ', '); |
| 467 print(') '); | 526 token(node.leftParenthesis); |
| 527 space(); |
| 468 visit(node.body); | 528 visit(node.body); |
| 469 } | 529 } |
| 470 | 530 |
| 471 visitFunctionDeclaration(FunctionDeclaration node) { | 531 visitFunctionDeclaration(FunctionDeclaration node) { |
| 532 needsNewline = true; |
| 533 preservePrecedingNewlines = true; |
| 472 visitSuffixed(node.returnType, ' '); | 534 visitSuffixed(node.returnType, ' '); |
| 473 emitToken(node.propertyKeyword, suffix: ' '); | 535 token(node.propertyKeyword, followedBy: space); |
| 474 visit(node.name); | 536 visit(node.name); |
| 475 visit(node.functionExpression); | 537 visit(node.functionExpression); |
| 476 } | 538 } |
| 477 | 539 |
| 478 visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { | 540 visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { |
| 479 visit(node.functionDeclaration); | 541 visit(node.functionDeclaration); |
| 480 print(';'); | 542 // TODO(pquitslund): fix and handle in function body |
| 543 append(';'); |
| 481 } | 544 } |
| 482 | 545 |
| 483 visitFunctionExpression(FunctionExpression node) { | 546 visitFunctionExpression(FunctionExpression node) { |
| 484 visit(node.parameters); | 547 visit(node.parameters); |
| 485 print(' '); | 548 space(); |
| 486 visit(node.body); | 549 visit(node.body); |
| 487 } | 550 } |
| 488 | 551 |
| 489 visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | 552 visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 490 visit(node.function); | 553 visit(node.function); |
| 491 visit(node.argumentList); | 554 visit(node.argumentList); |
| 492 } | 555 } |
| 493 | 556 |
| 494 visitFunctionTypeAlias(FunctionTypeAlias node) { | 557 visitFunctionTypeAlias(FunctionTypeAlias node) { |
| 495 emitToken(node.keyword, suffix: ' '); | 558 token(node.keyword); |
| 559 space(); |
| 496 visitSuffixed(node.returnType, ' '); | 560 visitSuffixed(node.returnType, ' '); |
| 497 visit(node.name); | 561 visit(node.name); |
| 498 visit(node.typeParameters); | 562 visit(node.typeParameters); |
| 499 visit(node.parameters); | 563 visit(node.parameters); |
| 500 emitToken(node.semicolon); | 564 token(node.semicolon); |
| 501 } | 565 } |
| 502 | 566 |
| 503 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { | 567 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { |
| 504 visitSuffixed(node.returnType, ' '); | 568 visitSuffixed(node.returnType, ' '); |
| 505 visit(node.identifier); | 569 visit(node.identifier); |
| 506 visit(node.parameters); | 570 visit(node.parameters); |
| 507 } | 571 } |
| 508 | 572 |
| 509 visitHideCombinator(HideCombinator node) { | 573 visitHideCombinator(HideCombinator node) { |
| 510 emitToken(node.keyword, suffix: ' '); | 574 token(node.keyword); |
| 575 space(); |
| 511 visitList(node.hiddenNames, ', '); | 576 visitList(node.hiddenNames, ', '); |
| 512 } | 577 } |
| 513 | 578 |
| 514 visitIfStatement(IfStatement node) { | 579 visitIfStatement(IfStatement node) { |
| 515 emitToken(node.ifKeyword); | 580 preservePrecedingNewlines = true; |
| 516 print(' ('); | 581 token(node.ifKeyword); |
| 582 space(); |
| 583 token(node.leftParenthesis); |
| 517 visit(node.condition); | 584 visit(node.condition); |
| 518 print(') '); | 585 token(node.rightParenthesis); |
| 586 space(); |
| 519 visit(node.thenStatement); | 587 visit(node.thenStatement); |
| 520 visitPrefixed(' else ', node.elseStatement); | 588 //visitPrefixed(' else ', node.elseStatement); |
| 589 if (node.elseStatement != null) { |
| 590 space(); |
| 591 token(node.elseKeyword); |
| 592 space(); |
| 593 visit(node.elseStatement); |
| 594 } |
| 595 needsNewline = true; |
| 521 } | 596 } |
| 522 | 597 |
| 523 visitImplementsClause(ImplementsClause node) { | 598 visitImplementsClause(ImplementsClause node) { |
| 524 emitToken(node.keyword, suffix: ' '); | 599 token(node.keyword); |
| 600 space(); |
| 525 visitList(node.interfaces, ', '); | 601 visitList(node.interfaces, ', '); |
| 526 } | 602 } |
| 527 | 603 |
| 528 visitImportDirective(ImportDirective node) { | 604 visitImportDirective(ImportDirective node) { |
| 529 emitToken(node.keyword, suffix: ' '); | 605 preservePrecedingNewlines = true; |
| 606 token(node.keyword); |
| 607 space(); |
| 530 visit(node.uri); | 608 visit(node.uri); |
| 531 visitPrefixed(' as ', node.prefix); | 609 visitPrefixed(' as ', node.prefix); |
| 532 visitPrefixedList(' ', node.combinators, ' '); | 610 visitPrefixedList(' ', node.combinators, ' '); |
| 533 emitToken(node.semicolon); | 611 token(node.semicolon); |
| 612 needsNewline = true; |
| 534 } | 613 } |
| 535 | 614 |
| 536 visitIndexExpression(IndexExpression node) { | 615 visitIndexExpression(IndexExpression node) { |
| 537 if (node.isCascaded) { | 616 if (node.isCascaded) { |
| 538 print('..'); | 617 token(node.period); |
| 539 } else { | 618 } else { |
| 540 visit(node.target); | 619 visit(node.target); |
| 541 } | 620 } |
| 542 print('['); | 621 token(node.leftBracket); |
| 543 visit(node.index); | 622 visit(node.index); |
| 544 print(']'); | 623 token(node.rightBracket); |
| 545 } | 624 } |
| 546 | 625 |
| 547 visitInstanceCreationExpression(InstanceCreationExpression node) { | 626 visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 548 emitToken(node.keyword, suffix: ' '); | 627 token(node.keyword); |
| 628 space(); |
| 549 visit(node.constructorName); | 629 visit(node.constructorName); |
| 550 visit(node.argumentList); | 630 visit(node.argumentList); |
| 551 } | 631 } |
| 552 | 632 |
| 553 visitIntegerLiteral(IntegerLiteral node) { | 633 visitIntegerLiteral(IntegerLiteral node) { |
| 554 print(node.literal.lexeme); | 634 token(node.literal); |
| 555 } | 635 } |
| 556 | 636 |
| 557 visitInterpolationExpression(InterpolationExpression node) { | 637 visitInterpolationExpression(InterpolationExpression node) { |
| 558 if (node.rightBracket != null) { | 638 if (node.rightBracket != null) { |
| 559 print('\${'); | 639 token(node.leftBracket); |
| 560 visit(node.expression); | 640 visit(node.expression); |
| 561 print('}'); | 641 token(node.rightBracket); |
| 562 } else { | 642 } else { |
| 563 print('\$'); | 643 token(node.leftBracket); |
| 564 visit(node.expression); | 644 visit(node.expression); |
| 565 } | 645 } |
| 566 } | 646 } |
| 567 | 647 |
| 568 visitInterpolationString(InterpolationString node) { | 648 visitInterpolationString(InterpolationString node) { |
| 569 print(node.contents.lexeme); | 649 token(node.contents); |
| 570 } | 650 } |
| 571 | 651 |
| 572 visitIsExpression(IsExpression node) { | 652 visitIsExpression(IsExpression node) { |
| 573 visit(node.expression); | 653 visit(node.expression); |
| 574 if (node.notOperator == null) { | 654 space(); |
| 575 print(' is '); | 655 token(node.isOperator); |
| 576 } else { | 656 token(node.notOperator); |
| 577 print(' is! '); | 657 space(); |
| 578 } | |
| 579 visit(node.type); | 658 visit(node.type); |
| 580 } | 659 } |
| 581 | 660 |
| 582 visitLabel(Label node) { | 661 visitLabel(Label node) { |
| 583 visit(node.label); | 662 visit(node.label); |
| 584 print(':'); | 663 token(node.colon); |
| 585 } | 664 } |
| 586 | 665 |
| 587 visitLabeledStatement(LabeledStatement node) { | 666 visitLabeledStatement(LabeledStatement node) { |
| 588 visitSuffixedList(node.labels, ' ', ' '); | 667 visitSuffixedList(node.labels, ' ', ' '); |
| 589 visit(node.statement); | 668 visit(node.statement); |
| 590 } | 669 } |
| 591 | 670 |
| 592 visitLibraryDirective(LibraryDirective node) { | 671 visitLibraryDirective(LibraryDirective node) { |
| 593 emitToken(node.keyword, suffix: ' '); | 672 token(node.keyword); |
| 673 space(); |
| 594 visit(node.name); | 674 visit(node.name); |
| 595 emitToken(node.semicolon); | 675 token(node.semicolon); |
| 596 } | 676 } |
| 597 | 677 |
| 598 visitLibraryIdentifier(LibraryIdentifier node) { | 678 visitLibraryIdentifier(LibraryIdentifier node) { |
| 599 print(node.name); | 679 append(node.name); |
| 600 } | 680 } |
| 601 | 681 |
| 602 visitListLiteral(ListLiteral node) { | 682 visitListLiteral(ListLiteral node) { |
| 603 if (node.modifier != null) { | 683 if (node.modifier != null) { |
| 604 print(node.modifier.lexeme); | 684 token(node.modifier); |
| 605 print(' '); | 685 space(); |
| 606 } | 686 } |
| 607 visit(node.typeArguments); | 687 visit(node.typeArguments); |
| 608 print('['); | 688 token(node.leftBracket); |
| 609 visitList(node.elements, ', '); | 689 visitList(node.elements, ', '); |
| 610 print(']'); | 690 token(node.rightBracket); |
| 611 } | 691 } |
| 612 | 692 |
| 613 visitMapLiteral(MapLiteral node) { | 693 visitMapLiteral(MapLiteral node) { |
| 614 if (node.modifier != null) { | 694 modifier(node.modifier); |
| 615 print(node.modifier.lexeme); | |
| 616 print(' '); | |
| 617 } | |
| 618 visitSuffixed(node.typeArguments, ' '); | 695 visitSuffixed(node.typeArguments, ' '); |
| 619 print('{'); | 696 token(node.leftBracket); |
| 620 visitList(node.entries, ', '); | 697 visitList(node.entries, ', '); |
| 621 print('}'); | 698 token(node.rightBracket); |
| 622 } | 699 } |
| 623 | 700 |
| 624 visitMapLiteralEntry(MapLiteralEntry node) { | 701 visitMapLiteralEntry(MapLiteralEntry node) { |
| 625 visit(node.key); | 702 visit(node.key); |
| 626 print(' : '); | 703 space(); |
| 704 token(node.separator); |
| 705 space(); |
| 627 visit(node.value); | 706 visit(node.value); |
| 628 } | 707 } |
| 629 | 708 |
| 630 visitMethodDeclaration(MethodDeclaration node) { | 709 visitMethodDeclaration(MethodDeclaration node) { |
| 631 emitToken(node.externalKeyword, suffix: ' '); | 710 needsNewline = true; |
| 632 emitToken(node.modifierKeyword, suffix: ' '); | 711 preservePrecedingNewlines = true; |
| 712 modifier(node.externalKeyword); |
| 713 modifier(node.modifierKeyword); |
| 633 visitSuffixed(node.returnType, ' '); | 714 visitSuffixed(node.returnType, ' '); |
| 634 emitToken(node.propertyKeyword, suffix: ' '); | 715 modifier(node.propertyKeyword); |
| 635 emitToken(node.operatorKeyword, suffix: ' '); | 716 modifier(node.operatorKeyword); |
| 636 visit(node.name); | 717 visit(node.name); |
| 637 if (!node.isGetter) { | 718 if (!node.isGetter) { |
| 638 visit(node.parameters); | 719 visit(node.parameters); |
| 639 } | 720 } |
| 640 visitPrefixedBody(' ', node.body); | 721 visitPrefixedBody(' ', node.body); |
| 641 } | 722 } |
| 642 | 723 |
| 643 visitMethodInvocation(MethodInvocation node) { | 724 visitMethodInvocation(MethodInvocation node) { |
| 644 if (node.isCascaded) { | 725 if (node.isCascaded) { |
| 645 print('..'); | 726 token(node.period); |
| 646 } else { | 727 } else { |
| 647 visitSuffixed(node.target, '.'); | 728 visitSuffixed(node.target, '.'); |
| 648 } | 729 } |
| 649 visit(node.methodName); | 730 visit(node.methodName); |
| 650 visit(node.argumentList); | 731 visit(node.argumentList); |
| 651 } | 732 } |
| 652 | 733 |
| 653 visitNamedExpression(NamedExpression node) { | 734 visitNamedExpression(NamedExpression node) { |
| 654 visit(node.name); | 735 visit(node.name); |
| 655 visitPrefixed(' ', node.expression); | 736 visitPrefixed(' ', node.expression); |
| 656 } | 737 } |
| 657 | 738 |
| 658 visitNativeClause(NativeClause node) { | 739 visitNativeClause(NativeClause node) { |
| 659 emitToken(node.keyword, suffix: ' '); | 740 token(node.keyword); |
| 741 space(); |
| 660 visit(node.name); | 742 visit(node.name); |
| 661 } | 743 } |
| 662 | 744 |
| 663 visitNativeFunctionBody(NativeFunctionBody node) { | 745 visitNativeFunctionBody(NativeFunctionBody node) { |
| 664 emitToken(node.nativeToken, suffix: ' '); | 746 token(node.nativeToken); |
| 747 space(); |
| 665 visit(node.stringLiteral); | 748 visit(node.stringLiteral); |
| 666 emitToken(node.semicolon); | 749 token(node.semicolon); |
| 667 } | 750 } |
| 668 | 751 |
| 669 visitNullLiteral(NullLiteral node) { | 752 visitNullLiteral(NullLiteral node) { |
| 670 emitToken(node.literal); | 753 token(node.literal); |
| 671 } | 754 } |
| 672 | 755 |
| 673 visitParenthesizedExpression(ParenthesizedExpression node) { | 756 visitParenthesizedExpression(ParenthesizedExpression node) { |
| 674 emitToken(node.leftParenthesis); | 757 token(node.leftParenthesis); |
| 675 visit(node.expression); | 758 visit(node.expression); |
| 676 emitToken(node.rightParenthesis); | 759 token(node.rightParenthesis); |
| 677 } | 760 } |
| 678 | 761 |
| 679 visitPartDirective(PartDirective node) { | 762 visitPartDirective(PartDirective node) { |
| 680 emitToken(node.keyword, suffix: ' '); | 763 token(node.keyword); |
| 764 space(); |
| 681 visit(node.uri); | 765 visit(node.uri); |
| 682 emitToken(node.semicolon); | 766 token(node.semicolon); |
| 683 } | 767 } |
| 684 | 768 |
| 685 visitPartOfDirective(PartOfDirective node) { | 769 visitPartOfDirective(PartOfDirective node) { |
| 686 emitToken(node.keyword, suffix: ' '); | 770 token(node.keyword); |
| 771 space(); |
| 687 visit(node.libraryName); | 772 visit(node.libraryName); |
| 688 emitToken(node.semicolon); | 773 token(node.semicolon); |
| 689 } | 774 } |
| 690 | 775 |
| 691 visitPostfixExpression(PostfixExpression node) { | 776 visitPostfixExpression(PostfixExpression node) { |
| 692 visit(node.operand); | 777 visit(node.operand); |
| 693 print(node.operator.lexeme); | 778 token(node.operator); |
| 694 } | 779 } |
| 695 | 780 |
| 696 visitPrefixedIdentifier(PrefixedIdentifier node) { | 781 visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 697 visit(node.prefix); | 782 visit(node.prefix); |
| 698 print('.'); | 783 token(node.period); |
| 699 visit(node.identifier); | 784 visit(node.identifier); |
| 700 } | 785 } |
| 701 | 786 |
| 702 visitPrefixExpression(PrefixExpression node) { | 787 visitPrefixExpression(PrefixExpression node) { |
| 703 emitToken(node.operator); | 788 token(node.operator); |
| 704 visit(node.operand); | 789 visit(node.operand); |
| 705 } | 790 } |
| 706 | 791 |
| 707 visitPropertyAccess(PropertyAccess node) { | 792 visitPropertyAccess(PropertyAccess node) { |
| 708 if (node.isCascaded) { | 793 if (node.isCascaded) { |
| 709 print('..'); | 794 token(node.operator); |
| 710 } else { | 795 } else { |
| 711 visit(node.target); | 796 visit(node.target); |
| 712 print('.'); | 797 token(node.operator); |
| 713 } | 798 } |
| 714 visit(node.propertyName); | 799 visit(node.propertyName); |
| 715 } | 800 } |
| 716 | 801 |
| 717 visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { | 802 visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { |
| 718 emitToken(node.keyword); | 803 token(node.keyword); |
| 719 visitPrefixed('.', node.constructorName); | 804 visitPrefixed('.', node.constructorName); |
| 720 visit(node.argumentList); | 805 visit(node.argumentList); |
| 721 } | 806 } |
| 722 | 807 |
| 723 visitRethrowExpression(RethrowExpression node) { | 808 visitRethrowExpression(RethrowExpression node) { |
| 724 emitToken(node.keyword); | 809 token(node.keyword); |
| 725 } | 810 } |
| 726 | 811 |
| 727 visitReturnStatement(ReturnStatement node) { | 812 visitReturnStatement(ReturnStatement node) { |
| 813 preservePrecedingNewlines = true; |
| 728 var expression = node.expression; | 814 var expression = node.expression; |
| 729 if (expression == null) { | 815 if (expression == null) { |
| 730 emitToken(node.keyword, minNewlines: 1); | 816 token(node.keyword); |
| 731 emitToken(node.semicolon); | 817 token(node.semicolon); |
| 732 } else { | 818 } else { |
| 733 emitToken(node.keyword, suffix: ' ', minNewlines: 1); | 819 token(node.keyword); |
| 820 space(); |
| 734 expression.accept(this); | 821 expression.accept(this); |
| 735 emitToken(node.semicolon); | 822 token(node.semicolon); |
| 736 } | 823 } |
| 737 } | 824 } |
| 738 | 825 |
| 739 visitScriptTag(ScriptTag node) { | 826 visitScriptTag(ScriptTag node) { |
| 740 print(node.scriptTag.lexeme); | 827 token(node.scriptTag); |
| 741 } | 828 } |
| 742 | 829 |
| 743 visitShowCombinator(ShowCombinator node) { | 830 visitShowCombinator(ShowCombinator node) { |
| 744 emitToken(node.keyword, suffix: ' '); | 831 token(node.keyword); |
| 832 space(); |
| 745 visitList(node.shownNames, ', '); | 833 visitList(node.shownNames, ', '); |
| 746 } | 834 } |
| 747 | 835 |
| 748 visitSimpleFormalParameter(SimpleFormalParameter node) { | 836 visitSimpleFormalParameter(SimpleFormalParameter node) { |
| 749 emitToken(node.keyword, suffix: ' '); | 837 token(node.keyword); |
| 838 space(); |
| 750 visitSuffixed(node.type, ' '); | 839 visitSuffixed(node.type, ' '); |
| 751 visit(node.identifier); | 840 visit(node.identifier); |
| 752 } | 841 } |
| 753 | 842 |
| 754 visitSimpleIdentifier(SimpleIdentifier node) { | 843 visitSimpleIdentifier(SimpleIdentifier node) { |
| 755 emitToken(node.token); | 844 token(node.token); |
| 756 } | 845 } |
| 757 | 846 |
| 758 visitSimpleStringLiteral(SimpleStringLiteral node) { | 847 visitSimpleStringLiteral(SimpleStringLiteral node) { |
| 759 emitToken(node.literal); | 848 token(node.literal); |
| 760 } | 849 } |
| 761 | 850 |
| 762 visitStringInterpolation(StringInterpolation node) { | 851 visitStringInterpolation(StringInterpolation node) { |
| 763 visitList(node.elements); | 852 visitList(node.elements); |
| 764 } | 853 } |
| 765 | 854 |
| 766 visitSuperConstructorInvocation(SuperConstructorInvocation node) { | 855 visitSuperConstructorInvocation(SuperConstructorInvocation node) { |
| 767 emitToken(node.keyword); | 856 token(node.keyword); |
| 768 visitPrefixed('.', node.constructorName); | 857 visitPrefixed('.', node.constructorName); |
| 769 visit(node.argumentList); | 858 visit(node.argumentList); |
| 770 } | 859 } |
| 771 | 860 |
| 772 visitSuperExpression(SuperExpression node) { | 861 visitSuperExpression(SuperExpression node) { |
| 773 emitToken(node.keyword); | 862 token(node.keyword); |
| 774 } | 863 } |
| 775 | 864 |
| 776 visitSwitchCase(SwitchCase node) { | 865 visitSwitchCase(SwitchCase node) { |
| 866 preservePrecedingNewlines = true; |
| 777 visitSuffixedList(node.labels, ' ', ' '); | 867 visitSuffixedList(node.labels, ' ', ' '); |
| 778 emitToken(node.keyword, suffix: ' '); | 868 token(node.keyword); |
| 869 space(); |
| 779 visit(node.expression); | 870 visit(node.expression); |
| 780 print(':'); | 871 token(node.colon); |
| 781 indent(); | 872 indent(); |
| 873 needsNewline = true; |
| 782 visitList(node.statements); | 874 visitList(node.statements); |
| 783 unindent(); | 875 unindent(); |
| 784 } | 876 } |
| 785 | 877 |
| 786 visitSwitchDefault(SwitchDefault node) { | 878 visitSwitchDefault(SwitchDefault node) { |
| 879 preservePrecedingNewlines = true; |
| 787 visitSuffixedList(node.labels, ' ', ' '); | 880 visitSuffixedList(node.labels, ' ', ' '); |
| 788 emitToken(node.keyword, suffix: ': '); | 881 token(node.keyword); |
| 882 token(node.colon); |
| 883 space(); |
| 789 visitList(node.statements, ' '); | 884 visitList(node.statements, ' '); |
| 790 } | 885 } |
| 791 | 886 |
| 792 visitSwitchStatement(SwitchStatement node) { | 887 visitSwitchStatement(SwitchStatement node) { |
| 793 emitToken(node.keyword); | 888 token(node.keyword); |
| 794 print(' ('); | 889 space(); |
| 890 token(node.leftParenthesis); |
| 795 visit(node.expression); | 891 visit(node.expression); |
| 796 print(') '); | 892 token(node.rightParenthesis); |
| 797 emitToken(node.leftBracket); | 893 space(); |
| 894 token(node.leftBracket); |
| 798 indent(); | 895 indent(); |
| 799 visitList(node.members); | 896 visitList(node.members); |
| 800 unindent(); | 897 unindent(); |
| 801 emitToken(node.rightBracket); | 898 token(node.rightBracket); |
| 802 newline(); | 899 needsNewline = true; |
| 803 } | 900 } |
| 804 | 901 |
| 805 visitSymbolLiteral(SymbolLiteral node) { | 902 visitSymbolLiteral(SymbolLiteral node) { |
| 806 // No-op ? | 903 // No-op ? |
| 807 } | 904 } |
| 808 | 905 |
| 809 visitThisExpression(ThisExpression node) { | 906 visitThisExpression(ThisExpression node) { |
| 810 emitToken(node.keyword); | 907 token(node.keyword); |
| 811 } | 908 } |
| 812 | 909 |
| 813 visitThrowExpression(ThrowExpression node) { | 910 visitThrowExpression(ThrowExpression node) { |
| 814 emitToken(node.keyword, suffix: ' '); | 911 token(node.keyword); |
| 912 space(); |
| 815 visit(node.expression); | 913 visit(node.expression); |
| 816 } | 914 } |
| 817 | 915 |
| 818 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { | 916 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { |
| 819 visitSuffixed(node.variables, ';'); | 917 visitSuffixed(node.variables, ';'); |
| 820 } | 918 } |
| 821 | 919 |
| 822 visitTryStatement(TryStatement node) { | 920 visitTryStatement(TryStatement node) { |
| 823 emitToken(node.tryKeyword, suffix: ' '); | 921 preservePrecedingNewlines = true; |
| 922 token(node.tryKeyword); |
| 923 space(); |
| 824 visit(node.body); | 924 visit(node.body); |
| 825 visitPrefixedList(' ', node.catchClauses, ' '); | 925 visitPrefixedList(' ', node.catchClauses, ' '); |
| 826 visitPrefixed(' finally ', node.finallyClause); | 926 visitPrefixed(' finally ', node.finallyClause); |
| 827 } | 927 } |
| 828 | 928 |
| 829 visitTypeArgumentList(TypeArgumentList node) { | 929 visitTypeArgumentList(TypeArgumentList node) { |
| 830 emitToken(node.leftBracket); | 930 token(node.leftBracket); |
| 831 visitList(node.arguments, ', '); | 931 visitList(node.arguments, ', '); |
| 832 emitToken(node.rightBracket); | 932 token(node.rightBracket); |
| 833 } | 933 } |
| 834 | 934 |
| 835 visitTypeName(TypeName node) { | 935 visitTypeName(TypeName node) { |
| 836 visit(node.name); | 936 visit(node.name); |
| 837 visit(node.typeArguments); | 937 visit(node.typeArguments); |
| 838 } | 938 } |
| 839 | 939 |
| 840 visitTypeParameter(TypeParameter node) { | 940 visitTypeParameter(TypeParameter node) { |
| 841 visit(node.name); | 941 visit(node.name); |
| 842 visitPrefixed(' extends ', node.bound); | 942 visitPrefixed(' extends ', node.bound); |
| 843 } | 943 } |
| 844 | 944 |
| 845 visitTypeParameterList(TypeParameterList node) { | 945 visitTypeParameterList(TypeParameterList node) { |
| 846 emitToken(node.leftBracket); | 946 token(node.leftBracket); |
| 847 visitList(node.typeParameters, ', '); | 947 visitList(node.typeParameters, ', '); |
| 848 emitToken(node.rightBracket); | 948 token(node.rightBracket); |
| 849 } | 949 } |
| 850 | 950 |
| 851 visitVariableDeclaration(VariableDeclaration node) { | 951 visitVariableDeclaration(VariableDeclaration node) { |
| 852 visit(node.name); | 952 visit(node.name); |
| 853 visitPrefixed(' = ', node.initializer); | 953 visitPrefixed(' = ', node.initializer); |
| 854 } | 954 } |
| 855 | 955 |
| 856 visitVariableDeclarationList(VariableDeclarationList node) { | 956 visitVariableDeclarationList(VariableDeclarationList node) { |
| 857 emitToken(node.keyword, suffix: ' '); | 957 token(node.keyword); |
| 958 space(); |
| 858 visitSuffixed(node.type, ' '); | 959 visitSuffixed(node.type, ' '); |
| 859 visitList(node.variables, ', '); | 960 visitList(node.variables, ', '); |
| 860 } | 961 } |
| 861 | 962 |
| 862 visitVariableDeclarationStatement(VariableDeclarationStatement node) { | 963 visitVariableDeclarationStatement(VariableDeclarationStatement node) { |
| 863 visit(node.variables); | 964 visit(node.variables); |
| 864 emitToken(node.semicolon); | 965 token(node.semicolon); |
| 865 } | 966 } |
| 866 | 967 |
| 867 visitWhileStatement(WhileStatement node) { | 968 visitWhileStatement(WhileStatement node) { |
| 868 emitToken(node.keyword, suffix: ' ('); | 969 token(node.keyword); |
| 970 space(); |
| 971 token(node.leftParenthesis); |
| 869 visit(node.condition); | 972 visit(node.condition); |
| 870 print(') '); | 973 token(node.rightParenthesis); |
| 974 space(); |
| 871 visit(node.body); | 975 visit(node.body); |
| 872 } | 976 } |
| 873 | 977 |
| 874 visitWithClause(WithClause node) { | 978 visitWithClause(WithClause node) { |
| 875 emitToken(node.withKeyword, suffix: ' '); | 979 token(node.withKeyword); |
| 980 space(); |
| 876 visitList(node.mixinTypes, ', '); | 981 visitList(node.mixinTypes, ', '); |
| 877 } | 982 } |
| 878 | 983 |
| 879 /// Safely visit the given [node]. | 984 /// Safely visit the given [node]. |
| 880 visit(ASTNode node) { | 985 visit(ASTNode node) { |
| 881 if (node != null) { | 986 if (node != null) { |
| 882 node.accept(this); | 987 node.accept(this); |
| 883 } | 988 } |
| 884 } | 989 } |
| 885 | 990 |
| 886 /// Safely visit the given [node], printing the [suffix] after the node if it | 991 /// Safely visit the given [node], printing the [suffix] after the node if it |
| 887 /// is non-null. | 992 /// is non-null. |
| 888 visitSuffixed(ASTNode node, String suffix) { | 993 visitSuffixed(ASTNode node, String suffix) { |
| 889 if (node != null) { | 994 if (node != null) { |
| 890 node.accept(this); | 995 node.accept(this); |
| 891 print(suffix); | 996 append(suffix); |
| 892 } | 997 } |
| 893 } | 998 } |
| 894 | 999 |
| 895 /// Safely visit the given [node], printing the [prefix] before the node if | 1000 /// Safely visit the given [node], printing the [prefix] before the node if |
| 896 /// it is non-null. | 1001 /// it is non-null. |
| 897 visitPrefixed(String prefix, ASTNode node) { | 1002 visitPrefixed(String prefix, ASTNode node) { |
| 898 if (node != null) { | 1003 if (node != null) { |
| 899 print(prefix); | 1004 append(prefix); |
| 900 node.accept(this); | 1005 node.accept(this); |
| 901 } | 1006 } |
| 902 } | 1007 } |
| 903 | 1008 |
| 904 /// Visit the given function [body], printing the [prefix] before if given | 1009 /// Visit the given function [body], printing the [prefix] before if given |
| 905 /// body is not empty. | 1010 /// body is not empty. |
| 906 visitPrefixedBody(String prefix, FunctionBody body) { | 1011 visitPrefixedBody(String prefix, FunctionBody body) { |
| 907 if (body is! EmptyFunctionBody) { | 1012 if (body is! EmptyFunctionBody) { |
| 908 print(prefix); | 1013 append(prefix); |
| 909 } | 1014 } |
| 910 visit(body); | 1015 visit(body); |
| 911 } | 1016 } |
| 912 | 1017 |
| 913 /// Print a list of [nodes], optionally separated by the given [separator]. | 1018 /// Print a list of [nodes], optionally separated by the given [separator]. |
| 914 visitList(NodeList<ASTNode> nodes, [String separator = '']) { | 1019 visitList(NodeList<ASTNode> nodes, [String separator = '']) { |
| 915 if (nodes != null) { | 1020 if (nodes != null) { |
| 916 var size = nodes.length; | 1021 var size = nodes.length; |
| 917 for (var i = 0; i < size; i++) { | 1022 for (var i = 0; i < size; i++) { |
| 918 if (i > 0) { | 1023 if (i > 0) { |
| 919 print(separator); | 1024 append(separator); |
| 920 } | 1025 } |
| 921 nodes[i].accept(this); | 1026 nodes[i].accept(this); |
| 922 } | 1027 } |
| 923 } | 1028 } |
| 924 } | 1029 } |
| 925 | 1030 |
| 926 /// Print a list of [nodes], separated by the given [separator]. | 1031 /// Print a list of [nodes], separated by the given [separator]. |
| 927 visitSuffixedList(NodeList<ASTNode> nodes, String separator, String suffix) { | 1032 visitSuffixedList(NodeList<ASTNode> nodes, String separator, String suffix) { |
| 928 if (nodes != null) { | 1033 if (nodes != null) { |
| 929 var size = nodes.length; | 1034 var size = nodes.length; |
| 930 if (size > 0) { | 1035 if (size > 0) { |
| 931 for (var i = 0; i < size; i++) { | 1036 for (var i = 0; i < size; i++) { |
| 932 if (i > 0) { | 1037 if (i > 0) { |
| 933 print(separator); | 1038 append(separator); |
| 934 } | 1039 } |
| 935 nodes[i].accept(this); | 1040 nodes[i].accept(this); |
| 936 } | 1041 } |
| 937 print(suffix); | 1042 append(suffix); |
| 938 } | 1043 } |
| 939 } | 1044 } |
| 940 } | 1045 } |
| 941 | 1046 |
| 942 /// Print a list of [nodes], separated by the given [separator]. | 1047 /// Print a list of [nodes], separated by the given [separator]. |
| 943 visitPrefixedList(String prefix, NodeList<ASTNode> nodes, | 1048 visitPrefixedList(String prefix, NodeList<ASTNode> nodes, |
| 944 [String separator = null]) { | 1049 [String separator = null]) { |
| 945 if (nodes != null) { | 1050 if (nodes != null) { |
| 946 var size = nodes.length; | 1051 var size = nodes.length; |
| 947 if (size > 0) { | 1052 if (size > 0) { |
| 948 print(prefix); | 1053 append(prefix); |
| 949 for (var i = 0; i < size; i++) { | 1054 for (var i = 0; i < size; i++) { |
| 950 if (i > 0 && separator != null) { | 1055 if (i > 0 && separator != null) { |
| 951 print(separator); | 1056 append(separator); |
| 952 } | 1057 } |
| 953 nodes[i].accept(this); | 1058 nodes[i].accept(this); |
| 954 } | 1059 } |
| 955 } | 1060 } |
| 956 } | 1061 } |
| 957 } | 1062 } |
| 958 | 1063 |
| 959 | 1064 /// Emit the given [modifier] if it's non null, followed by non-breaking |
| 960 /// Emit the given [token], if it's non-null, preceded by any detected | 1065 /// whitespace. |
| 961 /// newlines or a minimum as specified by [minNewlines], printing a [prefix] | 1066 modifier(Token modifier) { |
| 962 /// before and a [suffix] after. | 1067 token(modifier, followedBy: space); |
| 963 emitToken(Token token, {String prefix, String suffix, | 1068 } |
| 964 int minNewlines: 0}) { | 1069 |
| 1070 token(Token token, {followedBy(), int minNewlines: 0}) { |
| 965 if (token != null) { | 1071 if (token != null) { |
| 966 print(prefix); | 1072 if (needsNewline) { |
| 967 emitPrecedingNewlines(token, min: minNewlines); | 1073 minNewlines = max(1, minNewlines); |
| 968 print(token.lexeme); | 1074 } |
| 969 print(suffix); | 1075 if (preservePrecedingNewlines || minNewlines > 0) { |
| 970 } | 1076 var emitted = emitPrecedingNewlines(token, min: minNewlines); |
| 1077 preservePrecedingNewlines = false; |
| 1078 if (emitted > 0) { |
| 1079 needsNewline = false; |
| 1080 } |
| 1081 } |
| 1082 append(token.lexeme); |
| 1083 if (followedBy != null) { |
| 1084 followedBy(); |
| 1085 } |
| 1086 previousToken = token; |
| 1087 } |
| 1088 } |
| 1089 |
| 1090 /// Emit a non-breakable space. |
| 1091 space() { |
| 1092 //TODO(pquitslund): replace with a proper space token |
| 1093 append(' '); |
| 971 } | 1094 } |
| 972 | 1095 |
| 973 /// Print the given [string] to the source writer if it's non-null. | 1096 /// Emit a breakable space |
| 974 print(String string) { | 1097 breakableSpace() { |
| 1098 //Implement |
| 1099 } |
| 1100 |
| 1101 /// Append the given [string] to the source writer if it's non-null. |
| 1102 append(String string) { |
| 975 if (string != null) { | 1103 if (string != null) { |
| 976 writer.print(string); | 1104 writer.print(string); |
| 977 } | 1105 } |
| 978 } | 1106 } |
| 979 | 1107 |
| 980 /// Emit a newline. | |
| 981 newline() { | |
| 982 writer.newline(); | |
| 983 } | |
| 984 | |
| 985 /// Emit [n] newlines. | |
| 986 newlines(n) { | |
| 987 writer.newlines(n); | |
| 988 } | |
| 989 | |
| 990 /// Indent. | 1108 /// Indent. |
| 991 indent() { | 1109 indent() { |
| 992 writer.indent(); | 1110 writer.indent(); |
| 993 } | 1111 } |
| 994 | 1112 |
| 995 /// Unindent | 1113 /// Unindent |
| 996 unindent() { | 1114 unindent() { |
| 997 writer.unindent(); | 1115 writer.unindent(); |
| 998 } | 1116 } |
| 999 | 1117 |
| 1000 /// Emit any detected newlines or a minimum as specified by [minNewlines]. | 1118 /// Emit any detected newlines or a minimum as specified by [minNewlines]. |
| 1001 emitPrecedingNewlines(Token token, {min: 0}) { | 1119 int emitPrecedingNewlines(Token token, {min: 0}) { |
| 1002 var comment = token.precedingComments; | 1120 var comment = token.precedingComments; |
| 1003 var currentToken = comment != null ? comment : token; | 1121 var currentToken = comment != null ? comment : token; |
| 1004 var lines = max(min, countNewlinesBetween(previousToken, currentToken)); | 1122 var lines = max(min, countNewlinesBetween(previousToken, currentToken)); |
| 1005 newlines(lines); | 1123 writer.newlines(lines); |
| 1006 while (comment != null) { | 1124 while (comment != null) { |
| 1007 print(comment.toString().trim()); | 1125 append(comment.toString().trim()); |
| 1008 newline(); | 1126 writer.newline(); |
| 1009 comment = comment.next; | 1127 comment = comment.next; |
| 1010 } | 1128 } |
| 1011 | 1129 |
| 1012 previousToken = token; | 1130 previousToken = token; |
| 1131 return lines; |
| 1013 } | 1132 } |
| 1014 | 1133 |
| 1015 /// Count the blanks between these two nodes. | 1134 /// Count the blanks between these two nodes. |
| 1016 int countBlankLinesBetween(ASTNode lastNode, ASTNode currentNode) => | 1135 int countBlankLinesBetween(ASTNode lastNode, ASTNode currentNode) => |
| 1017 countNewlinesBetween(lastNode.endToken, currentNode.beginToken); | 1136 countNewlinesBetween(lastNode.endToken, currentNode.beginToken); |
| 1018 | 1137 |
| 1019 /// Count newlines preceeding this [node]. | 1138 /// Count newlines preceeding this [node]. |
| 1020 int countPrecedingNewlines(ASTNode node) => | 1139 int countPrecedingNewlines(ASTNode node) => |
| 1021 countNewlinesBetween(node.beginToken.previous, node.beginToken); | 1140 countNewlinesBetween(node.beginToken.previous, node.beginToken); |
| 1022 | 1141 |
| 1023 /// Count newlines succeeding this [node]. | 1142 /// Count newlines succeeding this [node]. |
| 1024 int countSucceedingNewlines(ASTNode node) => node == null ? 0 : | 1143 int countSucceedingNewlines(ASTNode node) => node == null ? 0 : |
| 1025 countNewlinesBetween(node.endToken, node.endToken.next); | 1144 countNewlinesBetween(node.endToken, node.endToken.next); |
| 1026 | 1145 |
| 1027 /// Count the blanks between these two nodes. | 1146 /// Count the blanks between these two nodes. |
| 1028 int countNewlinesBetween(Token last, Token current) { | 1147 int countNewlinesBetween(Token last, Token current) { |
| 1029 if (last == null || current == null) { | 1148 if (last == null || current == null) { |
| 1030 return 0; | 1149 return 0; |
| 1031 } | 1150 } |
| 1032 var lastLine = | 1151 var lastLine = |
| 1033 lineInfo.getLocation(last.offset).lineNumber; | 1152 lineInfo.getLocation(last.offset).lineNumber; |
| 1034 var currentLine = | 1153 var currentLine = |
| 1035 lineInfo.getLocation(current.offset).lineNumber; | 1154 lineInfo.getLocation(current.offset).lineNumber; |
| 1036 return currentLine - lastLine; | 1155 return currentLine - lastLine; |
| 1037 } | 1156 } |
| 1038 | 1157 |
| 1039 String toString() => writer.toString(); | 1158 String toString() => writer.toString(); |
| 1040 | 1159 |
| 1041 } | 1160 } |
| OLD | NEW |