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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 328 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
| 329 // If we've already emitted this class, skip it. | 329 // If we've already emitted this class, skip it. |
| 330 var classElem = node.element; | 330 var classElem = node.element; |
| 331 var type = classElem.type; | 331 var type = classElem.type; |
| 332 var jsName = getAnnotationValue(node, _isJsNameAnnotation); | 332 var jsName = getAnnotationValue(node, _isJsNameAnnotation); |
| 333 | 333 |
| 334 if (jsName != null) return _emitJsType(node.name.name, jsName); | 334 if (jsName != null) return _emitJsType(node.name.name, jsName); |
| 335 | 335 |
| 336 var ctors = <ConstructorDeclaration>[]; | 336 var ctors = <ConstructorDeclaration>[]; |
| 337 var fields = <FieldDeclaration>[]; | 337 var fields = <FieldDeclaration>[]; |
| 338 var methods = <MethodDeclaration>[]; | |
| 338 for (var member in node.members) { | 339 for (var member in node.members) { |
| 339 if (member is ConstructorDeclaration) { | 340 if (member is ConstructorDeclaration) { |
| 340 ctors.add(member); | 341 ctors.add(member); |
| 341 } else if (member is FieldDeclaration && !member.isStatic) { | 342 } else if (member is FieldDeclaration && !member.isStatic) { |
| 342 fields.add(member); | 343 fields.add(member); |
| 344 } else if (member is MethodDeclaration) { | |
| 345 methods.add(member); | |
| 343 } | 346 } |
| 344 } | 347 } |
| 345 | 348 |
| 346 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), | 349 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), |
| 347 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); | 350 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); |
| 348 | 351 |
| 349 String jsPeerName; | 352 String jsPeerName; |
| 350 var jsPeer = getAnnotationValue(node, _isJsPeerInterface); | 353 var jsPeer = getAnnotationValue(node, _isJsPeerInterface); |
| 351 if (jsPeer != null) { | 354 if (jsPeer != null) { |
| 352 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); | 355 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); |
| 353 } | 356 } |
| 354 | 357 |
| 355 var body = | 358 var body = _finishClassMembers( |
| 356 _finishClassMembers(classElem, classExpr, ctors, fields, jsPeerName); | 359 classElem, classExpr, ctors, fields, methods, jsPeerName); |
| 357 | 360 |
| 358 var result = _finishClassDef(type, body); | 361 var result = _finishClassDef(type, body); |
| 359 | 362 |
| 360 if (jsPeerName != null) { | 363 if (jsPeerName != null) { |
| 361 // This class isn't allowed to be lazy, because we need to set up | 364 // This class isn't allowed to be lazy, because we need to set up |
| 362 // the native JS type eagerly at this point. | 365 // the native JS type eagerly at this point. |
| 363 // If we wanted to support laziness, we could defer the hookup until | 366 // If we wanted to support laziness, we could defer the hookup until |
| 364 // the end of the Dart library cycle load. | 367 // the end of the Dart library cycle load. |
| 365 assert(_loader.isLoaded(classElem)); | 368 assert(_loader.isLoaded(classElem)); |
| 366 | 369 |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( | 532 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( |
| 530 'function() { return new dart.JsIterator(this.#); }', | 533 'function() { return new dart.JsIterator(this.#); }', |
| 531 [_emitMemberName('iterator', type: t)])); | 534 [_emitMemberName('iterator', type: t)])); |
| 532 } | 535 } |
| 533 | 536 |
| 534 /// Emit class members that need to come after the class declaration, such | 537 /// Emit class members that need to come after the class declaration, such |
| 535 /// as static fields. See [_emitClassMethods] for things that are emitted | 538 /// as static fields. See [_emitClassMethods] for things that are emitted |
| 536 /// inside the ES6 `class { ... }` node. | 539 /// inside the ES6 `class { ... }` node. |
| 537 JS.Statement _finishClassMembers(ClassElement classElem, | 540 JS.Statement _finishClassMembers(ClassElement classElem, |
| 538 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, | 541 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, |
| 539 List<FieldDeclaration> fields, String jsPeerName) { | 542 List<FieldDeclaration> fields, List<MethodDeclaration> methods, |
| 543 String jsPeerName) { | |
| 540 var name = classElem.name; | 544 var name = classElem.name; |
| 541 var body = <JS.Statement>[]; | 545 var body = <JS.Statement>[]; |
| 542 body.add(new JS.ClassDeclaration(cls)); | 546 body.add(new JS.ClassDeclaration(cls)); |
| 543 | 547 |
| 544 // TODO(jmesserly): we should really just extend native Array. | 548 // TODO(jmesserly): we should really just extend native Array. |
| 545 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { | 549 if (jsPeerName != null && classElem.typeParameters.isNotEmpty) { |
| 546 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', [ | 550 body.add(js.statement('dart.setBaseClass(#, dart.global.#);', [ |
| 547 classElem.name, | 551 classElem.name, |
| 548 _propertyName(jsPeerName) | 552 _propertyName(jsPeerName) |
| 549 ])); | 553 ])); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 571 // Instance fields, if they override getter/setter pairs | 575 // Instance fields, if they override getter/setter pairs |
| 572 for (FieldDeclaration member in fields) { | 576 for (FieldDeclaration member in fields) { |
| 573 for (VariableDeclaration fieldDecl in member.fields.variables) { | 577 for (VariableDeclaration fieldDecl in member.fields.variables) { |
| 574 var field = fieldDecl.element; | 578 var field = fieldDecl.element; |
| 575 if (_fieldsNeedingStorage.contains(field)) { | 579 if (_fieldsNeedingStorage.contains(field)) { |
| 576 body.add(_overrideField(field)); | 580 body.add(_overrideField(field)); |
| 577 } | 581 } |
| 578 } | 582 } |
| 579 } | 583 } |
| 580 | 584 |
| 585 { | |
|
vsm
2015/05/18 17:35:10
Add comment to this block ... e.g, // Emit signatu
Leaf
2015/05/19 00:02:21
Done.
| |
| 586 var tStatics = []; | |
| 587 var tMethods = []; | |
| 588 var sNames = []; | |
| 589 var cType = classElem.type; | |
| 590 for (MethodDeclaration node in methods) { | |
| 591 if (!(node.isSetter || node.isGetter || node.isAbstract)) { | |
| 592 var name = node.name.name; | |
| 593 var element = node.element; | |
| 594 var unary = node.parameters.parameters.isEmpty; | |
| 595 var memberName = _emitMemberName(name, | |
| 596 type: cType, unary: unary, isStatic: node.isStatic); | |
| 597 var property = | |
| 598 new JS.Property(memberName, _emitTypeName(element.type)); | |
| 599 if (node.isStatic) { | |
| 600 tStatics.add(property); | |
| 601 sNames.add(memberName); | |
| 602 } else tMethods.add(property); | |
| 603 } | |
| 604 } | |
| 605 build(name, elements) { | |
| 606 var o = | |
| 607 new JS.ObjectInitializer(elements, vertical: elements.length > 1); | |
| 608 var e = js.call('() => #', o); | |
| 609 var p = new JS.Property(_propertyName(name), e); | |
| 610 return p; | |
| 611 } | |
| 612 var sigFields = []; | |
| 613 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); | |
| 614 if (!tStatics.isEmpty) { | |
| 615 assert(!sNames.isEmpty); | |
| 616 var aNames = new JS.Property( | |
| 617 _propertyName('names'), new JS.ArrayInitializer(sNames)); | |
| 618 sigFields.add(build('statics', tStatics)); | |
| 619 sigFields.add(aNames); | |
| 620 } | |
| 621 | |
| 622 var sig = new JS.ObjectInitializer(sigFields); | |
| 623 var classExpr = new JS.Identifier(name); | |
| 624 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); | |
| 625 } | |
| 626 | |
| 581 return _statement(body); | 627 return _statement(body); |
| 582 } | 628 } |
| 583 | 629 |
| 584 JS.Statement _overrideField(FieldElement e) { | 630 JS.Statement _overrideField(FieldElement e) { |
| 585 var cls = e.enclosingElement; | 631 var cls = e.enclosingElement; |
| 586 return js.statement('dart.virtualField(#, #)', [ | 632 return js.statement('dart.virtualField(#, #)', [ |
| 587 cls.name, | 633 cls.name, |
| 588 _emitMemberName(e.name, type: cls.type) | 634 _emitMemberName(e.name, type: cls.type) |
| 589 ]); | 635 ]); |
| 590 } | 636 } |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 908 if (node.isGetter || node.isSetter) { | 954 if (node.isGetter || node.isSetter) { |
| 909 // Add these later so we can use getter/setter syntax. | 955 // Add these later so we can use getter/setter syntax. |
| 910 _properties.add(node); | 956 _properties.add(node); |
| 911 return null; | 957 return null; |
| 912 } | 958 } |
| 913 | 959 |
| 914 var body = <JS.Statement>[]; | 960 var body = <JS.Statement>[]; |
| 915 _flushLibraryProperties(body); | 961 _flushLibraryProperties(body); |
| 916 | 962 |
| 917 var name = node.name.name; | 963 var name = node.name.name; |
| 918 body.add(js.comment('Function $name: ${node.element.type}')); | |
| 919 | 964 |
| 920 body.add(new JS.FunctionDeclaration( | 965 var id = new JS.Identifier(name); |
| 921 new JS.Identifier(name), _visit(node.functionExpression))); | 966 body.add(new JS.FunctionDeclaration(id, _visit(node.functionExpression))); |
| 967 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) | |
| 968 .toStatement()); | |
| 922 | 969 |
| 923 if (isPublic(name)) _addExport(name); | 970 if (isPublic(name)) _addExport(name); |
| 924 return _statement(body); | 971 return _statement(body); |
| 925 } | 972 } |
| 926 | 973 |
| 927 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { | 974 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { |
| 928 var name = node.name.name; | 975 var name = node.name.name; |
| 929 return new JS.Method(_propertyName(name), _visit(node.functionExpression), | 976 return new JS.Method(_propertyName(name), _visit(node.functionExpression), |
| 930 isGetter: node.isGetter, isSetter: node.isSetter); | 977 isGetter: node.isGetter, isSetter: node.isSetter); |
| 931 } | 978 } |
| 932 | 979 |
| 980 bool _executesAtTopLevel(AstNode node) { | |
| 981 var ancestor = node.getAncestor((n) => n is FunctionBody || | |
| 982 (n is FieldDeclaration && n.staticKeyword == null) || | |
| 983 (n is ConstructorDeclaration && n.constKeyword == null)); | |
| 984 return ancestor == null; | |
| 985 } | |
| 986 | |
| 987 bool _typeIsLoaded(DartType type) { | |
| 988 if (type is FunctionType && (type.name == '' || type.name == null)) { | |
| 989 return (_typeIsLoaded(type.returnType) && | |
| 990 type.optionalParameterTypes.every(_typeIsLoaded) && | |
| 991 type.namedParameterTypes.values.every(_typeIsLoaded) && | |
| 992 type.normalParameterTypes.every(_typeIsLoaded)); | |
| 993 } | |
| 994 if (type.isDynamic || type.isVoid || type.isBottom) return true; | |
| 995 return _loader.isLoaded(type.element); | |
| 996 } | |
| 997 | |
| 998 JS.Expression _emitFunctionTagged(JS.Expression clos, DartType type, | |
| 999 {topLevel: false}) { | |
| 1000 var name = type.name; | |
| 1001 var lazy = topLevel && !_typeIsLoaded(type); | |
|
Jennifer Messerly
2015/05/19 18:19:01
Definitely not something that needs to be changed
Leaf
2015/05/19 22:31:12
Acknowledged.
| |
| 1002 | |
| 1003 if (type is FunctionType && (name == '' || name == null)) { | |
| 1004 if (type.returnType.isDynamic && | |
| 1005 type.optionalParameterTypes.isEmpty && | |
| 1006 type.namedParameterTypes.isEmpty && | |
| 1007 type.normalParameterTypes.every((t) => t.isDynamic)) { | |
| 1008 return js.call('dart.fn(#)', [clos]); | |
| 1009 } | |
| 1010 if (lazy) { | |
| 1011 return js.call('dart.fn(#, () => #)', [clos, _emitTypeName(type)]); | |
| 1012 } | |
| 1013 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); | |
| 1014 } | |
| 1015 throw 'Function has non function type: $type'; | |
| 1016 } | |
| 1017 | |
| 933 @override | 1018 @override |
| 934 JS.Expression visitFunctionExpression(FunctionExpression node) { | 1019 JS.Expression visitFunctionExpression(FunctionExpression node) { |
| 935 var params = _visit(node.parameters); | 1020 var params = _visit(node.parameters); |
| 936 if (params == null) params = []; | 1021 if (params == null) params = []; |
| 937 | 1022 |
| 938 var parent = node.parent; | 1023 var parent = node.parent; |
| 939 if (parent is FunctionDeclaration && | 1024 if (parent is FunctionDeclaration && |
| 940 parent.parent is! FunctionDeclarationStatement) { | 1025 parent.parent is! FunctionDeclarationStatement) { |
| 941 return new JS.Fun(params, _visit(node.body)); | 1026 return new JS.Fun(params, _visit(node.body)); |
| 942 } else { | 1027 } else { |
| 943 String code; | 1028 String code; |
| 944 AstNode body; | 1029 AstNode body; |
| 945 var nodeBody = node.body; | 1030 var nodeBody = node.body; |
| 946 if (nodeBody is ExpressionFunctionBody) { | 1031 if (nodeBody is ExpressionFunctionBody) { |
| 947 code = '(#) => #'; | 1032 code = '(#) => #'; |
| 948 body = nodeBody.expression; | 1033 body = nodeBody.expression; |
| 949 } else { | 1034 } else { |
| 950 code = '(#) => { #; }'; | 1035 code = '(#) => { #; }'; |
| 951 body = nodeBody; | 1036 body = nodeBody; |
| 952 } | 1037 } |
| 953 return js.call(code, [params, _visit(body)]); | 1038 var clos = js.call(code, [params, _visit(body)]); |
| 1039 if (parent.parent is! FunctionDeclarationStatement) { | |
|
Jennifer Messerly
2015/05/19 18:19:01
maybe pull out `parent.parent is! FunctionDeclarat
Leaf
2015/05/19 22:31:13
Done.
| |
| 1040 var type = getStaticType(node); | |
| 1041 return _emitFunctionTagged(clos, type, | |
| 1042 topLevel: _executesAtTopLevel(node)); | |
| 1043 } | |
| 1044 return clos; | |
| 954 } | 1045 } |
| 955 } | 1046 } |
| 956 | 1047 |
| 957 @override | 1048 @override |
| 958 JS.Statement visitFunctionDeclarationStatement( | 1049 JS.Statement visitFunctionDeclarationStatement( |
| 959 FunctionDeclarationStatement node) { | 1050 FunctionDeclarationStatement node) { |
| 960 var func = node.functionDeclaration; | 1051 var func = node.functionDeclaration; |
| 961 if (func.isGetter || func.isSetter) { | 1052 if (func.isGetter || func.isSetter) { |
| 962 return js.comment('Unimplemented function get/set statement: $node'); | 1053 return js.comment('Unimplemented function get/set statement: $node'); |
| 963 } | 1054 } |
| 964 | 1055 |
| 965 // Use an => function to bind this. | 1056 // Use an => function to bind this. |
| 966 // Technically we only need to do this if the function actually closes over | 1057 // Technically we only need to do this if the function actually closes over |
| 967 // `this`, but it seems harmless enough to just do it always. | 1058 // `this`, but it seems harmless enough to just do it always. |
| 968 var name = new JS.Identifier(func.name.name); | 1059 var name = new JS.Identifier(func.name.name); |
| 969 return new JS.Block([ | 1060 return new JS.Block([ |
| 970 js.comment("// Function ${func.name.name}: ${func.element.type}\n"), | 1061 js.statement('let # = #;', [name, _visit(func.functionExpression)]), |
| 971 js.statement('let # = #;', [name, _visit(func.functionExpression)]) | 1062 _emitFunctionTagged(name, func.element.type).toStatement() |
| 972 ]); | 1063 ]); |
| 973 } | 1064 } |
| 974 | 1065 |
| 975 /// Writes a simple identifier. This can handle implicit `this` as well as | 1066 /// Writes a simple identifier. This can handle implicit `this` as well as |
| 976 /// going through the qualified library name if necessary. | 1067 /// going through the qualified library name if necessary. |
| 977 @override | 1068 @override |
| 978 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 1069 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
| 979 var accessor = node.staticElement; | 1070 var accessor = node.staticElement; |
| 980 if (accessor == null) { | 1071 if (accessor == null) { |
| 981 return js.commentExpression( | 1072 return js.commentExpression( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1052 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 1143 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
| 1053 var properties = <JS.Property>[]; | 1144 var properties = <JS.Property>[]; |
| 1054 types.forEach((name, type) { | 1145 types.forEach((name, type) { |
| 1055 var key = new JS.LiteralString(name); | 1146 var key = new JS.LiteralString(name); |
| 1056 var value = _emitTypeName(type); | 1147 var value = _emitTypeName(type); |
| 1057 properties.add(new JS.Property(key, value)); | 1148 properties.add(new JS.Property(key, value)); |
| 1058 }); | 1149 }); |
| 1059 return new JS.ObjectInitializer(properties); | 1150 return new JS.ObjectInitializer(properties); |
| 1060 } | 1151 } |
| 1061 | 1152 |
| 1153 List<JS.Expression> _emitFunctionTypeParts(FunctionType type) { | |
| 1154 var returnType = type.returnType; | |
| 1155 var parameterTypes = type.normalParameterTypes; | |
| 1156 var optionalTypes = type.optionalParameterTypes; | |
| 1157 var namedTypes = type.namedParameterTypes; | |
| 1158 var rt = _emitTypeName(returnType); | |
| 1159 var ra = _emitTypeNames(parameterTypes); | |
| 1160 if (!namedTypes.isEmpty) { | |
| 1161 assert(optionalTypes.isEmpty); | |
| 1162 var na = _emitTypeProperties(namedTypes); | |
| 1163 return [rt, ra, na]; | |
| 1164 } | |
| 1165 if (!optionalTypes.isEmpty) { | |
| 1166 assert(namedTypes.isEmpty); | |
| 1167 var oa = _emitTypeNames(optionalTypes); | |
| 1168 return [rt, ra, oa]; | |
| 1169 } | |
| 1170 return [rt, ra]; | |
| 1171 } | |
| 1172 | |
| 1062 /// Emits a Dart [type] into code. | 1173 /// Emits a Dart [type] into code. |
| 1063 /// | 1174 /// |
| 1064 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a | 1175 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a |
| 1065 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form | 1176 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form |
| 1066 /// will be used instead of `List`. These flags are used when generating | 1177 /// will be used instead of `List`. These flags are used when generating |
| 1067 /// the definitions for typedefs and generic types, respectively. | 1178 /// the definitions for typedefs and generic types, respectively. |
| 1068 JS.Expression _emitTypeName(DartType type, | 1179 JS.Expression _emitTypeName(DartType type, |
| 1069 {bool lowerTypedef: false, bool lowerGeneric: false}) { | 1180 {bool lowerTypedef: false, bool lowerGeneric: false}) { |
| 1070 | 1181 |
| 1071 // The void and dynamic types are not defined in core. | 1182 // The void and dynamic types are not defined in core. |
| 1072 if (type.isVoid) { | 1183 if (type.isVoid) { |
| 1073 return js.call('dart.void'); | 1184 return js.call('dart.void'); |
| 1074 } else if (type.isDynamic) { | 1185 } else if (type.isDynamic) { |
| 1075 return js.call('dart.dynamic'); | 1186 return js.call('dart.dynamic'); |
| 1187 } else if (type.isBottom) { | |
| 1188 return js.call('dart.bottom'); | |
| 1076 } | 1189 } |
| 1077 | 1190 |
| 1078 _loader.declareBeforeUse(type.element); | 1191 _loader.declareBeforeUse(type.element); |
| 1079 | 1192 |
| 1080 // TODO(jmesserly): like constants, should we hoist function types out of | 1193 // TODO(jmesserly): like constants, should we hoist function types out of |
| 1081 // methods? Similar issue with generic types. For all of these, we may want | 1194 // methods? Similar issue with generic types. For all of these, we may want |
| 1082 // to canonicalize them too, at least when inside the same library. | 1195 // to canonicalize them too, at least when inside the same library. |
| 1083 var name = type.name; | 1196 var name = type.name; |
| 1084 var element = type.element; | 1197 var element = type.element; |
| 1085 if (name == '' || lowerTypedef) { | 1198 if (name == '' || name == null || lowerTypedef) { |
| 1086 var fnType = type as FunctionType; | 1199 var parts = _emitFunctionTypeParts(type as FunctionType); |
| 1087 var returnType = fnType.returnType; | 1200 return js.call('dart.functionType(#)', [parts]); |
| 1088 var parameterTypes = fnType.normalParameterTypes; | |
| 1089 var optionalTypes = fnType.optionalParameterTypes; | |
| 1090 var namedTypes = fnType.namedParameterTypes; | |
| 1091 if (namedTypes.isEmpty) { | |
| 1092 if (optionalTypes.isEmpty) { | |
| 1093 return js.call('dart.functionType(#, #)', [ | |
| 1094 _emitTypeName(returnType), | |
| 1095 _emitTypeNames(parameterTypes) | |
| 1096 ]); | |
| 1097 } else { | |
| 1098 return js.call('dart.functionType(#, #, #)', [ | |
| 1099 _emitTypeName(returnType), | |
| 1100 _emitTypeNames(parameterTypes), | |
| 1101 _emitTypeNames(optionalTypes) | |
| 1102 ]); | |
| 1103 } | |
| 1104 } else { | |
| 1105 assert(optionalTypes.isEmpty); | |
| 1106 return js.call('dart.functionType(#, #, #)', [ | |
| 1107 _emitTypeName(returnType), | |
| 1108 _emitTypeNames(parameterTypes), | |
| 1109 _emitTypeProperties(namedTypes) | |
| 1110 ]); | |
| 1111 } | |
| 1112 } | 1201 } |
| 1113 | 1202 |
| 1114 if (type is TypeParameterType) { | 1203 if (type is TypeParameterType) { |
| 1115 return new JS.Identifier(name); | 1204 return new JS.Identifier(name); |
| 1116 } | 1205 } |
| 1117 | 1206 |
| 1118 if (type is ParameterizedType) { | 1207 if (type is ParameterizedType) { |
| 1119 var args = type.typeArguments; | 1208 var args = type.typeArguments; |
| 1120 var isCurrentClass = | 1209 var isCurrentClass = |
| 1121 args.isNotEmpty && _loader.isCurrentElement(type.element); | 1210 args.isNotEmpty && _loader.isCurrentElement(type.element); |
| (...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2468 | 2557 |
| 2469 /// A special kind of element created by the compiler, signifying a temporary | 2558 /// A special kind of element created by the compiler, signifying a temporary |
| 2470 /// variable. These objects use instance equality, and should be shared | 2559 /// variable. These objects use instance equality, and should be shared |
| 2471 /// everywhere in the tree where they are treated as the same variable. | 2560 /// everywhere in the tree where they are treated as the same variable. |
| 2472 class TemporaryVariableElement extends LocalVariableElementImpl { | 2561 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 2473 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2562 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 2474 | 2563 |
| 2475 int get hashCode => identityHashCode(this); | 2564 int get hashCode => identityHashCode(this); |
| 2476 bool operator ==(Object other) => identical(this, other); | 2565 bool operator ==(Object other) => identical(this, other); |
| 2477 } | 2566 } |
| OLD | NEW |