| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; |
| 6 | 6 |
| 7 import 'dart:collection' show HashSet, HashMap; | 7 import 'dart:collection' show HashSet, HashMap; |
| 8 import 'dart:io' show Directory, File; | 8 import 'dart:io' show Directory, File; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 | 280 |
| 281 @override | 281 @override |
| 282 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 282 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
| 283 // If we've already emitted this class, skip it. | 283 // If we've already emitted this class, skip it. |
| 284 var classElem = node.element; | 284 var classElem = node.element; |
| 285 if (_pendingClasses.remove(classElem) == null) return null; | 285 if (_pendingClasses.remove(classElem) == null) return null; |
| 286 if (_getJsNameAnnotation(node) != null) return null; | 286 if (_getJsNameAnnotation(node) != null) return null; |
| 287 | 287 |
| 288 currentClass = node; | 288 currentClass = node; |
| 289 | 289 |
| 290 var name = classElem.name; | |
| 291 | |
| 292 var ctors = <ConstructorDeclaration>[]; | 290 var ctors = <ConstructorDeclaration>[]; |
| 293 var fields = <FieldDeclaration>[]; | 291 var fields = <FieldDeclaration>[]; |
| 294 var staticFields = <FieldDeclaration>[]; | 292 var staticFields = <FieldDeclaration>[]; |
| 295 for (var member in node.members) { | 293 for (var member in node.members) { |
| 296 if (member is ConstructorDeclaration) { | 294 if (member is ConstructorDeclaration) { |
| 297 ctors.add(member); | 295 ctors.add(member); |
| 298 } else if (member is FieldDeclaration) { | 296 } else if (member is FieldDeclaration) { |
| 299 (member.isStatic ? staticFields : fields).add(member); | 297 (member.isStatic ? staticFields : fields).add(member); |
| 300 } | 298 } |
| 301 } | 299 } |
| 302 | 300 |
| 303 var classExpr = new JS.ClassExpression(new JS.Identifier(name), | 301 var classExpr = new JS.ClassExpression(new JS.Identifier(classElem.name), |
| 304 _classHeritage(node), _emitClassMethods(node, ctors, fields)); | 302 _classHeritage(node), _emitClassMethods(node, ctors, fields)); |
| 305 | 303 |
| 306 var body = _finishClassMembers(name, classExpr, ctors, staticFields); | 304 var body = _finishClassMembers(classElem, classExpr, ctors, staticFields); |
| 307 currentClass = null; | 305 currentClass = null; |
| 308 | 306 |
| 309 return _finishClassDef(classElem, body); | 307 return _finishClassDef(classElem, body); |
| 310 } | 308 } |
| 311 | 309 |
| 312 @override | 310 @override |
| 313 JS.Statement visitEnumDeclaration(EnumDeclaration node) => | 311 JS.Statement visitEnumDeclaration(EnumDeclaration node) => |
| 314 _unimplementedCall("Unimplemented enum: $node").toStatement(); | 312 _unimplementedCall("Unimplemented enum: $node").toStatement(); |
| 315 | 313 |
| 316 /// Given a class element and body, complete the class declaration. | 314 /// Given a class element and body, complete the class declaration. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 }; | 537 }; |
| 540 }'''); | 538 }'''); |
| 541 jsMethods.add(new JS.Method(js.call('$_SYMBOL.iterator'), body)); | 539 jsMethods.add(new JS.Method(js.call('$_SYMBOL.iterator'), body)); |
| 542 } | 540 } |
| 543 return jsMethods.where((m) => m != null).toList(growable: false); | 541 return jsMethods.where((m) => m != null).toList(growable: false); |
| 544 } | 542 } |
| 545 | 543 |
| 546 /// Emit class members that need to come after the class declaration, such | 544 /// Emit class members that need to come after the class declaration, such |
| 547 /// as static fields. See [_emitClassMethods] for things that are emitted | 545 /// as static fields. See [_emitClassMethods] for things that are emitted |
| 548 /// insite the ES6 `class { ... }` node. | 546 /// insite the ES6 `class { ... }` node. |
| 549 JS.Statement _finishClassMembers(String name, JS.ClassExpression cls, | 547 JS.Statement _finishClassMembers(ClassElement classElem, |
| 550 List<ConstructorDeclaration> ctors, List<FieldDeclaration> staticFields) { | 548 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, |
| 549 List<FieldDeclaration> staticFields) { |
| 550 var name = classElem.name; |
| 551 |
| 551 var body = <JS.Statement>[]; | 552 var body = <JS.Statement>[]; |
| 552 body.add(new JS.ClassDeclaration(cls)); | 553 body.add(new JS.ClassDeclaration(cls)); |
| 553 | 554 |
| 555 // Interfaces |
| 556 if (classElem.interfaces.isNotEmpty) { |
| 557 body.add(js.statement('#[dart.implements] = #;', [ |
| 558 name, |
| 559 new JS.ArrayInitializer( |
| 560 classElem.interfaces.map(_emitTypeName).toList()) |
| 561 ])); |
| 562 } |
| 563 |
| 554 // Named constructors | 564 // Named constructors |
| 555 for (ConstructorDeclaration member in ctors) { | 565 for (ConstructorDeclaration member in ctors) { |
| 556 if (member.name != null) { | 566 if (member.name != null) { |
| 557 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ | 567 body.add(js.statement('dart.defineNamedConstructor(#, #);', [ |
| 558 name, | 568 name, |
| 559 _jsMemberName(member.name.name, isStatic: true) | 569 _jsMemberName(member.name.name, isStatic: true) |
| 560 ])); | 570 ])); |
| 561 } | 571 } |
| 562 } | 572 } |
| 563 | 573 |
| 564 // Static fields | 574 // Static fields |
| 565 var lazyStatics = <VariableDeclaration>[]; | 575 var lazyStatics = <VariableDeclaration>[]; |
| 566 for (FieldDeclaration member in staticFields) { | 576 for (FieldDeclaration member in staticFields) { |
| 567 for (VariableDeclaration field in member.fields.variables) { | 577 for (VariableDeclaration field in member.fields.variables) { |
| 568 var fieldName = field.name.name; | 578 var fieldName = field.name.name; |
| 569 if (field.isConst || _isFieldInitConstant(field)) { | 579 if (field.isConst || _isFieldInitConstant(field)) { |
| 570 var init = _visit(field.initializer); | 580 var init = _visit(field.initializer); |
| 571 if (init == null) init = new JS.LiteralNull(); | 581 if (init == null) init = new JS.LiteralNull(); |
| 572 body.add(js.statement('#.# = #;', [name, fieldName, init])); | 582 body.add(js.statement('#.# = #;', [name, fieldName, init])); |
| 573 } else { | 583 } else { |
| 574 lazyStatics.add(field); | 584 lazyStatics.add(field); |
| 575 } | 585 } |
| 576 } | 586 } |
| 577 } | 587 } |
| 578 var lazy = _emitLazyFields(new JS.Identifier(name), lazyStatics); | 588 var lazy = _emitLazyFields(new JS.Identifier(name), lazyStatics); |
| 579 if (lazy != null) body.add(lazy); | 589 if (lazy != null) body.add(lazy); |
| 590 |
| 580 return _statement(body); | 591 return _statement(body); |
| 581 } | 592 } |
| 582 | 593 |
| 583 /// Generates the implicit default constructor for class C of the form | 594 /// Generates the implicit default constructor for class C of the form |
| 584 /// `C() : super() {}`. | 595 /// `C() : super() {}`. |
| 585 JS.Method _emitImplicitConstructor( | 596 JS.Method _emitImplicitConstructor( |
| 586 ClassDeclaration node, String name, List<FieldDeclaration> fields) { | 597 ClassDeclaration node, String name, List<FieldDeclaration> fields) { |
| 587 // If we don't have a method body, skip this. | 598 // If we don't have a method body, skip this. |
| 588 if (fields.isEmpty) return null; | 599 if (fields.isEmpty) return null; |
| 589 | 600 |
| (...skipping 1763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2353 | 2364 |
| 2354 // TODO(jmesserly): in many cases marking the end will be unncessary. | 2365 // TODO(jmesserly): in many cases marking the end will be unncessary. |
| 2355 printer.mark(_location(node.end)); | 2366 printer.mark(_location(node.end)); |
| 2356 } | 2367 } |
| 2357 | 2368 |
| 2358 String _getIdentifier(AstNode node) { | 2369 String _getIdentifier(AstNode node) { |
| 2359 if (node is SimpleIdentifier) return node.name; | 2370 if (node is SimpleIdentifier) return node.name; |
| 2360 return null; | 2371 return null; |
| 2361 } | 2372 } |
| 2362 } | 2373 } |
| OLD | NEW |