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 ClassElement _currentClassElement = 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(_currentClassElement == null); | |
| 339 _currentClassElement = classElem; | |
| 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)); |
| 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(_currentClassElement == classElem); | |
| 366 _currentClassElement = 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; |
| 1248 var isCurrentClass = | |
| 1249 type is InterfaceType ? type.element == _currentClassElement : false; | |
| 1238 if (args.any((a) => a != types.dynamicType)) { | 1250 if (args.any((a) => a != types.dynamicType)) { |
| 1239 name = '$name\$'; | 1251 name = '$name\$'; |
| 1240 typeArgs = args.map(_emitTypeName); | 1252 typeArgs = args.map(_emitTypeName); |
| 1253 } else if (args.isNotEmpty && isCurrentClass) { | |
| 1254 // When creating a `new S<dynamic>` we try and use the raw form `new S() `, | |
|
Jennifer Messerly
2015/05/11 17:52:56
maybe a long line?
vsm
2015/05/11 17:56:03
Done.
| |
| 1255 // but this does not work if we're inside the same class, because `S` re fers | |
| 1256 // to the current S<T> we are generating. | |
| 1257 name = '$name\$'; | |
| 1258 typeArgs = []; | |
| 1241 } | 1259 } |
| 1242 } | 1260 } |
| 1243 | 1261 |
| 1244 JS.Expression result; | 1262 JS.Expression result; |
| 1245 if (_needQualifiedName(element)) { | 1263 if (_needQualifiedName(element)) { |
| 1246 result = js.call('#.#', [_libraryName(element.library), name]); | 1264 result = js.call('#.#', [_libraryName(element.library), name]); |
| 1247 } else { | 1265 } else { |
| 1248 result = new JS.Identifier(name); | 1266 result = new JS.Identifier(name); |
| 1249 } | 1267 } |
| 1250 | 1268 |
| (...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2594 // TODO(jmesserly): validate the library. See issue #135. | 2612 // TODO(jmesserly): validate the library. See issue #135. |
| 2595 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; | 2613 bool _isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName'; |
| 2596 | 2614 |
| 2597 bool _isJsPeerInterface(DartObjectImpl value) => | 2615 bool _isJsPeerInterface(DartObjectImpl value) => |
| 2598 value.type.name == 'JsPeerInterface'; | 2616 value.type.name == 'JsPeerInterface'; |
| 2599 | 2617 |
| 2600 // TODO(jacobr): we would like to do something like the following | 2618 // TODO(jacobr): we would like to do something like the following |
| 2601 // but we don't have summary support yet. | 2619 // but we don't have summary support yet. |
| 2602 // bool _supportJsExtensionMethod(AnnotatedNode node) => | 2620 // bool _supportJsExtensionMethod(AnnotatedNode node) => |
| 2603 // _getAnnotation(node, "SupportJsExtensionMethod") != null; | 2621 // _getAnnotation(node, "SupportJsExtensionMethod") != null; |
| OLD | NEW |