Chromium Code Reviews| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 final HashSet<FieldElement> _fieldsNeedingStorage; | 61 final HashSet<FieldElement> _fieldsNeedingStorage; |
| 62 | 62 |
| 63 /// The variable for the target of the current `..` cascade expression. | 63 /// The variable for the target of the current `..` cascade expression. |
| 64 SimpleIdentifier _cascadeTarget; | 64 SimpleIdentifier _cascadeTarget; |
| 65 | 65 |
| 66 /// The variable for the current catch clause | 66 /// The variable for the current catch clause |
| 67 SimpleIdentifier _catchParameter; | 67 SimpleIdentifier _catchParameter; |
| 68 | 68 |
| 69 ConstantEvaluator _constEvaluator; | 69 ConstantEvaluator _constEvaluator; |
| 70 | 70 |
| 71 InterfaceType _currentClass = null; | |
| 72 | |
| 71 /// Imported libraries, and the temporaries used to refer to them. | 73 /// Imported libraries, and the temporaries used to refer to them. |
| 72 final _imports = new Map<LibraryElement, JS.TemporaryId>(); | 74 final _imports = new Map<LibraryElement, JS.TemporaryId>(); |
| 73 final _exports = new Set<String>(); | 75 final _exports = new Set<String>(); |
| 74 final _lazyFields = <VariableDeclaration>[]; | 76 final _lazyFields = <VariableDeclaration>[]; |
| 75 final _properties = <FunctionDeclaration>[]; | 77 final _properties = <FunctionDeclaration>[]; |
| 76 final _privateNames = new HashMap<String, JS.TemporaryId>(); | 78 final _privateNames = new HashMap<String, JS.TemporaryId>(); |
| 77 final _extensionMethodNames = new HashSet<String>(); | 79 final _extensionMethodNames = new HashSet<String>(); |
| 78 final _pendingStatements = <JS.Statement>[]; | 80 final _pendingStatements = <JS.Statement>[]; |
| 79 final _temps = new HashMap<Element, JS.TemporaryId>(); | 81 final _temps = new HashMap<Element, JS.TemporaryId>(); |
| 80 | 82 |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 325 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 327 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
| 326 // If we've already emitted this class, skip it. | 328 // If we've already emitted this class, skip it. |
| 327 var classElem = node.element; | 329 var classElem = node.element; |
| 328 var type = classElem.type; | 330 var type = classElem.type; |
| 329 if (_pendingClasses.remove(classElem) == null) return null; | 331 if (_pendingClasses.remove(classElem) == null) return null; |
| 330 | 332 |
| 331 var jsName = getAnnotationValue(node, _isJsNameAnnotation); | 333 var jsName = getAnnotationValue(node, _isJsNameAnnotation); |
| 332 | 334 |
| 333 if (jsName != null) return _emitJsType(node.name.name, jsName); | 335 if (jsName != null) return _emitJsType(node.name.name, jsName); |
| 334 | 336 |
| 337 // Set current class | |
| 338 assert(_currentClass == null); | |
| 339 _currentClass = type; | |
|
Jennifer Messerly
2015/05/11 16:35:08
suggestion: maybe save the Element here, not the t
vsm
2015/05/11 17:51:09
Done.
| |
| 340 | |
| 335 var ctors = <ConstructorDeclaration>[]; | 341 var ctors = <ConstructorDeclaration>[]; |
| 336 var fields = <FieldDeclaration>[]; | 342 var fields = <FieldDeclaration>[]; |
| 337 var staticFields = <FieldDeclaration>[]; | 343 var staticFields = <FieldDeclaration>[]; |
| 338 for (var member in node.members) { | 344 for (var member in node.members) { |
| 339 if (member is ConstructorDeclaration) { | 345 if (member is ConstructorDeclaration) { |
| 340 ctors.add(member); | 346 ctors.add(member); |
| 341 } else if (member is FieldDeclaration) { | 347 } else if (member is FieldDeclaration) { |
| 342 (member.isStatic ? staticFields : fields).add(member); | 348 (member.isStatic ? staticFields : fields).add(member); |
| 343 } | 349 } |
| 344 } | 350 } |
| 345 | 351 |
| 346 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), | 352 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), |
| 347 _classHeritage(node), _emitClassMethods(node, ctors, fields)); | 353 _classHeritage(node), _emitClassMethods(node, ctors, fields)); |
|
Jennifer Messerly
2015/05/11 16:35:08
I think after this change, calls to static methods
vsm
2015/05/11 17:51:09
Added a test case to track this.
| |
| 348 | 354 |
| 349 String jsPeerName; | 355 String jsPeerName; |
| 350 var jsPeer = getAnnotationValue(node, _isJsPeerInterface); | 356 var jsPeer = getAnnotationValue(node, _isJsPeerInterface); |
| 351 if (jsPeer != null) { | 357 if (jsPeer != null) { |
| 352 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); | 358 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); |
| 353 } | 359 } |
| 354 | 360 |
| 355 var body = _finishClassMembers( | 361 var body = _finishClassMembers( |
| 356 classElem, classExpr, ctors, fields, staticFields, jsPeerName); | 362 classElem, classExpr, ctors, fields, staticFields, jsPeerName); |
| 357 | 363 |
| 364 // Unset current class | |
| 365 assert(_currentClass == type); | |
| 366 _currentClass = null; | |
| 367 | |
| 358 var result = _finishClassDef(type, body); | 368 var result = _finishClassDef(type, body); |
| 359 | 369 |
| 360 if (jsPeerName != null) { | 370 if (jsPeerName != null) { |
| 361 // This class isn't allowed to be lazy, because we need to set up | 371 // This class isn't allowed to be lazy, because we need to set up |
| 362 // the native JS type eagerly at this point. | 372 // the native JS type eagerly at this point. |
| 363 // If we wanted to support laziness, we could defer the hookup until | 373 // If we wanted to support laziness, we could defer the hookup until |
| 364 // the end of the Dart library cycle load. | 374 // the end of the Dart library cycle load. |
| 365 assert(!_lazyClass(type)); | 375 assert(!_lazyClass(type)); |
| 366 | 376 |
| 367 // TODO(jmesserly): this copies the dynamic members. | 377 // TODO(jmesserly): this copies the dynamic members. |
| (...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1228 ]); | 1238 ]); |
| 1229 } | 1239 } |
| 1230 } | 1240 } |
| 1231 // TODO(jmesserly): remove when we're using coercion reifier. | 1241 // TODO(jmesserly): remove when we're using coercion reifier. |
| 1232 return _unimplementedCall('Unimplemented type $type'); | 1242 return _unimplementedCall('Unimplemented type $type'); |
| 1233 } | 1243 } |
| 1234 | 1244 |
| 1235 var typeArgs = null; | 1245 var typeArgs = null; |
| 1236 if (type is ParameterizedType) { | 1246 if (type is ParameterizedType) { |
| 1237 var args = type.typeArguments; | 1247 var args = type.typeArguments; |
| 1238 if (args.any((a) => a != types.dynamicType)) { | 1248 // For a generic class with dynamic type parameters, try to use the |
| 1249 // raw form: new S() instead of new S<dynamic>() if possible. | |
| 1250 var isCurrentClass = | |
|
Jennifer Messerly
2015/05/11 16:35:08
could this just be:
var isCurrentClass = type
vsm
2015/05/11 17:51:09
Done.
| |
| 1251 type is InterfaceType ? type.element.type == _currentClass : false; | |
| 1252 if (args.isNotEmpty && isCurrentClass || | |
|
Jennifer Messerly
2015/05/11 16:35:08
maybe split these into two cases:
if (args.any((a
vsm
2015/05/11 17:51:09
Ahh, nice. Done!
| |
| 1253 args.any((a) => a != types.dynamicType)) { | |
| 1239 name = '$name\$'; | 1254 name = '$name\$'; |
| 1240 typeArgs = args.map(_emitTypeName); | 1255 typeArgs = args.map(_emitTypeName); |
| 1241 } | 1256 } |
| 1242 } | 1257 } |
| 1243 | 1258 |
| 1244 JS.Expression result; | 1259 JS.Expression result; |
| 1245 if (_needQualifiedName(element)) { | 1260 if (_needQualifiedName(element)) { |
| 1246 result = js.call('#.#', [_libraryName(element.library), name]); | 1261 result = js.call('#.#', [_libraryName(element.library), name]); |
| 1247 } else { | 1262 } else { |
| 1248 result = new JS.Identifier(name); | 1263 result = new JS.Identifier(name); |
| (...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2594 // TODO(jmesserly): validate the library. See issue #135. | 2609 // TODO(jmesserly): validate the library. See issue #135. |
| 2595 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; | 2610 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; |
| 2596 | 2611 |
| 2597 bool _isJsPeerInterface(DartObjectImpl value) => | 2612 bool _isJsPeerInterface(DartObjectImpl value) => |
| 2598 value.type.name == 'JsPeerInterface'; | 2613 value.type.name == 'JsPeerInterface'; |
| 2599 | 2614 |
| 2600 // TODO(jacobr): we would like to do something like the following | 2615 // TODO(jacobr): we would like to do something like the following |
| 2601 // but we don't have summary support yet. | 2616 // but we don't have summary support yet. |
| 2602 // bool _supportJsExtensionMethod(AnnotatedNode node) => | 2617 // bool _supportJsExtensionMethod(AnnotatedNode node) => |
| 2603 // _getAnnotation(node, "SupportJsExtensionMethod") != null; | 2618 // _getAnnotation(node, "SupportJsExtensionMethod") != null; |
| OLD | NEW |