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 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 return js.statement('dart.virtualField(#, #)', [ | 644 return js.statement('dart.virtualField(#, #)', [ |
645 cls.name, | 645 cls.name, |
646 _emitMemberName(e.name, type: cls.type) | 646 _emitMemberName(e.name, type: cls.type) |
647 ]); | 647 ]); |
648 } | 648 } |
649 | 649 |
650 /// Generates the implicit default constructor for class C of the form | 650 /// Generates the implicit default constructor for class C of the form |
651 /// `C() : super() {}`. | 651 /// `C() : super() {}`. |
652 JS.Method _emitImplicitConstructor( | 652 JS.Method _emitImplicitConstructor( |
653 ClassDeclaration node, String name, List<FieldDeclaration> fields) { | 653 ClassDeclaration node, String name, List<FieldDeclaration> fields) { |
| 654 assert(_hasUnnamedConstructor(node.element) == fields.isNotEmpty); |
| 655 |
654 // If we don't have a method body, skip this. | 656 // If we don't have a method body, skip this. |
655 if (fields.isEmpty) return null; | 657 if (fields.isEmpty) return null; |
656 | 658 |
657 dynamic body = _initializeFields(fields); | 659 dynamic body = _initializeFields(fields); |
658 var superCall = _superConstructorCall(node); | 660 var superCall = _superConstructorCall(node); |
659 if (superCall != null) body = [[body, superCall]]; | 661 if (superCall != null) body = [[body, superCall]]; |
660 return new JS.Method( | 662 return new JS.Method( |
661 _propertyName(name), js.call('function() { #; }', body)); | 663 _propertyName(name), js.call('function() { #; }', body)); |
662 } | 664 } |
663 | 665 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 | 770 |
769 var name = _constructorName(className, node.constructorName); | 771 var name = _constructorName(className, node.constructorName); |
770 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); | 772 return js.statement('this.#(#);', [name, _visit(node.argumentList)]); |
771 } | 773 } |
772 | 774 |
773 JS.Statement _superConstructorCall(ClassDeclaration clazz, | 775 JS.Statement _superConstructorCall(ClassDeclaration clazz, |
774 [SuperConstructorInvocation node]) { | 776 [SuperConstructorInvocation node]) { |
775 var superCtorName = node != null ? node.constructorName : null; | 777 var superCtorName = node != null ? node.constructorName : null; |
776 | 778 |
777 var element = clazz.element; | 779 var element = clazz.element; |
778 if (superCtorName == null && | 780 if (superCtorName == null && !_shouldCallUnnamedSuperCtor(element)) { |
779 (element.type.isObject || element.supertype.isObject)) { | |
780 return null; | 781 return null; |
781 } | 782 } |
782 | 783 |
783 var supertypeName = element.supertype.name; | 784 var supertypeName = element.supertype.name; |
784 var name = _constructorName(supertypeName, superCtorName); | 785 var name = _constructorName(supertypeName, superCtorName); |
785 | 786 |
786 var args = node != null ? _visit(node.argumentList) : []; | 787 var args = node != null ? _visit(node.argumentList) : []; |
787 return js.statement('super.#(#);', [name, args])..sourceInformation = node; | 788 return js.statement('super.#(#);', [name, args])..sourceInformation = node; |
788 } | 789 } |
789 | 790 |
| 791 bool _shouldCallUnnamedSuperCtor(ClassElement e) { |
| 792 var supertype = e.supertype; |
| 793 if (supertype == null) return false; |
| 794 if (_hasUnnamedConstructor(supertype.element)) return true; |
| 795 for (var mixin in e.mixins) { |
| 796 if (_hasUnnamedConstructor(mixin.element)) return true; |
| 797 } |
| 798 return false; |
| 799 } |
| 800 |
| 801 bool _hasUnnamedConstructor(ClassElement e) { |
| 802 if (e.type.isObject) return false; |
| 803 if (!e.unnamedConstructor.isSynthetic) return true; |
| 804 return e.fields.any((f) => !f.isStatic && !f.isSynthetic); |
| 805 } |
| 806 |
790 /// Initialize fields. They follow the sequence: | 807 /// Initialize fields. They follow the sequence: |
791 /// | 808 /// |
792 /// 1. field declaration initializer if non-const, | 809 /// 1. field declaration initializer if non-const, |
793 /// 2. field initializing parameters, | 810 /// 2. field initializing parameters, |
794 /// 3. constructor field initializers, | 811 /// 3. constructor field initializers, |
795 /// 4. initialize fields not covered in 1-3 | 812 /// 4. initialize fields not covered in 1-3 |
796 JS.Statement _initializeFields(List<FieldDeclaration> fieldDecls, | 813 JS.Statement _initializeFields(List<FieldDeclaration> fieldDecls, |
797 [FormalParameterList parameters, | 814 [FormalParameterList parameters, |
798 NodeList<ConstructorInitializer> initializers]) { | 815 NodeList<ConstructorInitializer> initializers]) { |
799 | 816 |
(...skipping 1569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 return filepath; | 2386 return filepath; |
2370 } | 2387 } |
2371 | 2388 |
2372 // TODO(jmesserly): validate the library. See issue #135. | 2389 // TODO(jmesserly): validate the library. See issue #135. |
2373 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; | 2390 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; |
2374 | 2391 |
2375 // TODO(jacobr): we would like to do something like the following | 2392 // TODO(jacobr): we would like to do something like the following |
2376 // but we don't have summary support yet. | 2393 // but we don't have summary support yet. |
2377 // bool _supportJsExtensionMethod(AnnotatedNode node) => | 2394 // bool _supportJsExtensionMethod(AnnotatedNode node) => |
2378 // _getAnnotation(node, "SupportJsExtensionMethod") != null; | 2395 // _getAnnotation(node, "SupportJsExtensionMethod") != null; |
OLD | NEW |