| 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 // Emit the signature on the class recording the runtime type information |
| 586 { |
| 587 var tStatics = []; |
| 588 var tMethods = []; |
| 589 var sNames = []; |
| 590 var cType = classElem.type; |
| 591 for (MethodDeclaration node in methods) { |
| 592 if (!(node.isSetter || node.isGetter || node.isAbstract)) { |
| 593 var name = node.name.name; |
| 594 var element = node.element; |
| 595 var unary = node.parameters.parameters.isEmpty; |
| 596 var memberName = _emitMemberName(name, |
| 597 type: cType, unary: unary, isStatic: node.isStatic); |
| 598 var property = |
| 599 new JS.Property(memberName, _emitTypeName(element.type)); |
| 600 if (node.isStatic) { |
| 601 tStatics.add(property); |
| 602 sNames.add(memberName); |
| 603 } else tMethods.add(property); |
| 604 } |
| 605 } |
| 606 build(name, elements) { |
| 607 var o = |
| 608 new JS.ObjectInitializer(elements, vertical: elements.length > 1); |
| 609 var e = js.call('() => #', o); |
| 610 var p = new JS.Property(_propertyName(name), e); |
| 611 return p; |
| 612 } |
| 613 var sigFields = []; |
| 614 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); |
| 615 if (!tStatics.isEmpty) { |
| 616 assert(!sNames.isEmpty); |
| 617 var aNames = new JS.Property( |
| 618 _propertyName('names'), new JS.ArrayInitializer(sNames)); |
| 619 sigFields.add(build('statics', tStatics)); |
| 620 sigFields.add(aNames); |
| 621 } |
| 622 |
| 623 var sig = new JS.ObjectInitializer(sigFields); |
| 624 var classExpr = new JS.Identifier(name); |
| 625 body.add(js.statement('dart.setSignature(#, #);', [classExpr, sig])); |
| 626 } |
| 627 |
| 581 return _statement(body); | 628 return _statement(body); |
| 582 } | 629 } |
| 583 | 630 |
| 584 JS.Statement _overrideField(FieldElement e) { | 631 JS.Statement _overrideField(FieldElement e) { |
| 585 var cls = e.enclosingElement; | 632 var cls = e.enclosingElement; |
| 586 return js.statement('dart.virtualField(#, #)', [ | 633 return js.statement('dart.virtualField(#, #)', [ |
| 587 cls.name, | 634 cls.name, |
| 588 _emitMemberName(e.name, type: cls.type) | 635 _emitMemberName(e.name, type: cls.type) |
| 589 ]); | 636 ]); |
| 590 } | 637 } |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 if (node.isGetter || node.isSetter) { | 955 if (node.isGetter || node.isSetter) { |
| 909 // Add these later so we can use getter/setter syntax. | 956 // Add these later so we can use getter/setter syntax. |
| 910 _properties.add(node); | 957 _properties.add(node); |
| 911 return null; | 958 return null; |
| 912 } | 959 } |
| 913 | 960 |
| 914 var body = <JS.Statement>[]; | 961 var body = <JS.Statement>[]; |
| 915 _flushLibraryProperties(body); | 962 _flushLibraryProperties(body); |
| 916 | 963 |
| 917 var name = node.name.name; | 964 var name = node.name.name; |
| 918 body.add(js.comment('Function $name: ${node.element.type}')); | |
| 919 | 965 |
| 920 body.add(new JS.FunctionDeclaration( | 966 var id = new JS.Identifier(name); |
| 921 new JS.Identifier(name), _visit(node.functionExpression))); | 967 body.add(new JS.FunctionDeclaration(id, _visit(node.functionExpression))); |
| 968 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) |
| 969 .toStatement()); |
| 922 | 970 |
| 923 if (isPublic(name)) _addExport(name); | 971 if (isPublic(name)) _addExport(name); |
| 924 return _statement(body); | 972 return _statement(body); |
| 925 } | 973 } |
| 926 | 974 |
| 927 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { | 975 JS.Method _emitTopLevelProperty(FunctionDeclaration node) { |
| 928 var name = node.name.name; | 976 var name = node.name.name; |
| 929 return new JS.Method(_propertyName(name), _visit(node.functionExpression), | 977 return new JS.Method(_propertyName(name), _visit(node.functionExpression), |
| 930 isGetter: node.isGetter, isSetter: node.isSetter); | 978 isGetter: node.isGetter, isSetter: node.isSetter); |
| 931 } | 979 } |
| 932 | 980 |
| 981 bool _executesAtTopLevel(AstNode node) { |
| 982 var ancestor = node.getAncestor((n) => n is FunctionBody || |
| 983 (n is FieldDeclaration && n.staticKeyword == null) || |
| 984 (n is ConstructorDeclaration && n.constKeyword == null)); |
| 985 return ancestor == null; |
| 986 } |
| 987 |
| 988 bool _typeIsLoaded(DartType type) { |
| 989 if (type is FunctionType && (type.name == '' || type.name == null)) { |
| 990 return (_typeIsLoaded(type.returnType) && |
| 991 type.optionalParameterTypes.every(_typeIsLoaded) && |
| 992 type.namedParameterTypes.values.every(_typeIsLoaded) && |
| 993 type.normalParameterTypes.every(_typeIsLoaded)); |
| 994 } |
| 995 if (type.isDynamic || type.isVoid || type.isBottom) return true; |
| 996 return _loader.isLoaded(type.element); |
| 997 } |
| 998 |
| 999 JS.Expression _emitFunctionTagged(JS.Expression clos, DartType type, |
| 1000 {topLevel: false}) { |
| 1001 var name = type.name; |
| 1002 var lazy = topLevel && !_typeIsLoaded(type); |
| 1003 |
| 1004 if (type is FunctionType && (name == '' || name == null)) { |
| 1005 if (type.returnType.isDynamic && |
| 1006 type.optionalParameterTypes.isEmpty && |
| 1007 type.namedParameterTypes.isEmpty && |
| 1008 type.normalParameterTypes.every((t) => t.isDynamic)) { |
| 1009 return js.call('dart.fn(#)', [clos]); |
| 1010 } |
| 1011 if (lazy) { |
| 1012 return js.call('dart.fn(#, () => #)', [clos, _emitTypeName(type)]); |
| 1013 } |
| 1014 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); |
| 1015 } |
| 1016 throw 'Function has non function type: $type'; |
| 1017 } |
| 1018 |
| 933 @override | 1019 @override |
| 934 JS.Expression visitFunctionExpression(FunctionExpression node) { | 1020 JS.Expression visitFunctionExpression(FunctionExpression node) { |
| 935 var params = _visit(node.parameters); | 1021 var params = _visit(node.parameters); |
| 936 if (params == null) params = []; | 1022 if (params == null) params = []; |
| 937 | 1023 |
| 938 var parent = node.parent; | 1024 var parent = node.parent; |
| 939 if (parent is FunctionDeclaration && | 1025 var inDecl = parent is FunctionDeclaration; |
| 940 parent.parent is! FunctionDeclarationStatement) { | 1026 var inStmt = parent.parent is FunctionDeclarationStatement; |
| 1027 if (inDecl && !inStmt) { |
| 941 return new JS.Fun(params, _visit(node.body)); | 1028 return new JS.Fun(params, _visit(node.body)); |
| 942 } else { | 1029 } else { |
| 943 String code; | 1030 String code; |
| 944 AstNode body; | 1031 AstNode body; |
| 945 var nodeBody = node.body; | 1032 var nodeBody = node.body; |
| 946 if (nodeBody is ExpressionFunctionBody) { | 1033 if (nodeBody is ExpressionFunctionBody) { |
| 947 code = '(#) => #'; | 1034 code = '(#) => #'; |
| 948 body = nodeBody.expression; | 1035 body = nodeBody.expression; |
| 949 } else { | 1036 } else { |
| 950 code = '(#) => { #; }'; | 1037 code = '(#) => { #; }'; |
| 951 body = nodeBody; | 1038 body = nodeBody; |
| 952 } | 1039 } |
| 953 return js.call(code, [params, _visit(body)]); | 1040 var clos = js.call(code, [params, _visit(body)]); |
| 1041 if (!inStmt) { |
| 1042 var type = getStaticType(node); |
| 1043 return _emitFunctionTagged(clos, type, |
| 1044 topLevel: _executesAtTopLevel(node)); |
| 1045 } |
| 1046 return clos; |
| 954 } | 1047 } |
| 955 } | 1048 } |
| 956 | 1049 |
| 957 @override | 1050 @override |
| 958 JS.Statement visitFunctionDeclarationStatement( | 1051 JS.Statement visitFunctionDeclarationStatement( |
| 959 FunctionDeclarationStatement node) { | 1052 FunctionDeclarationStatement node) { |
| 960 var func = node.functionDeclaration; | 1053 var func = node.functionDeclaration; |
| 961 if (func.isGetter || func.isSetter) { | 1054 if (func.isGetter || func.isSetter) { |
| 962 return js.comment('Unimplemented function get/set statement: $node'); | 1055 return js.comment('Unimplemented function get/set statement: $node'); |
| 963 } | 1056 } |
| 964 | 1057 |
| 965 // Use an => function to bind this. | 1058 // Use an => function to bind this. |
| 966 // Technically we only need to do this if the function actually closes over | 1059 // 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. | 1060 // `this`, but it seems harmless enough to just do it always. |
| 968 var name = new JS.Identifier(func.name.name); | 1061 var name = new JS.Identifier(func.name.name); |
| 969 return new JS.Block([ | 1062 return new JS.Block([ |
| 970 js.comment("// Function ${func.name.name}: ${func.element.type}\n"), | 1063 js.statement('let # = #;', [name, _visit(func.functionExpression)]), |
| 971 js.statement('let # = #;', [name, _visit(func.functionExpression)]) | 1064 _emitFunctionTagged(name, func.element.type).toStatement() |
| 972 ]); | 1065 ]); |
| 973 } | 1066 } |
| 974 | 1067 |
| 975 /// Writes a simple identifier. This can handle implicit `this` as well as | 1068 /// Writes a simple identifier. This can handle implicit `this` as well as |
| 976 /// going through the qualified library name if necessary. | 1069 /// going through the qualified library name if necessary. |
| 977 @override | 1070 @override |
| 978 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { | 1071 JS.Expression visitSimpleIdentifier(SimpleIdentifier node) { |
| 979 var accessor = node.staticElement; | 1072 var accessor = node.staticElement; |
| 980 if (accessor == null) { | 1073 if (accessor == null) { |
| 981 return js.commentExpression( | 1074 return js.commentExpression( |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1059 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 1152 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
| 1060 var properties = <JS.Property>[]; | 1153 var properties = <JS.Property>[]; |
| 1061 types.forEach((name, type) { | 1154 types.forEach((name, type) { |
| 1062 var key = new JS.LiteralString(name); | 1155 var key = new JS.LiteralString(name); |
| 1063 var value = _emitTypeName(type); | 1156 var value = _emitTypeName(type); |
| 1064 properties.add(new JS.Property(key, value)); | 1157 properties.add(new JS.Property(key, value)); |
| 1065 }); | 1158 }); |
| 1066 return new JS.ObjectInitializer(properties); | 1159 return new JS.ObjectInitializer(properties); |
| 1067 } | 1160 } |
| 1068 | 1161 |
| 1162 List<JS.Expression> _emitFunctionTypeParts(FunctionType type) { |
| 1163 var returnType = type.returnType; |
| 1164 var parameterTypes = type.normalParameterTypes; |
| 1165 var optionalTypes = type.optionalParameterTypes; |
| 1166 var namedTypes = type.namedParameterTypes; |
| 1167 var rt = _emitTypeName(returnType); |
| 1168 var ra = _emitTypeNames(parameterTypes); |
| 1169 if (!namedTypes.isEmpty) { |
| 1170 assert(optionalTypes.isEmpty); |
| 1171 var na = _emitTypeProperties(namedTypes); |
| 1172 return [rt, ra, na]; |
| 1173 } |
| 1174 if (!optionalTypes.isEmpty) { |
| 1175 assert(namedTypes.isEmpty); |
| 1176 var oa = _emitTypeNames(optionalTypes); |
| 1177 return [rt, ra, oa]; |
| 1178 } |
| 1179 return [rt, ra]; |
| 1180 } |
| 1181 |
| 1069 /// Emits a Dart [type] into code. | 1182 /// Emits a Dart [type] into code. |
| 1070 /// | 1183 /// |
| 1071 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a | 1184 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a |
| 1072 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form | 1185 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form |
| 1073 /// will be used instead of `List`. These flags are used when generating | 1186 /// will be used instead of `List`. These flags are used when generating |
| 1074 /// the definitions for typedefs and generic types, respectively. | 1187 /// the definitions for typedefs and generic types, respectively. |
| 1075 JS.Expression _emitTypeName(DartType type, | 1188 JS.Expression _emitTypeName(DartType type, |
| 1076 {bool lowerTypedef: false, bool lowerGeneric: false}) { | 1189 {bool lowerTypedef: false, bool lowerGeneric: false}) { |
| 1077 | 1190 |
| 1078 // The void and dynamic types are not defined in core. | 1191 // The void and dynamic types are not defined in core. |
| 1079 if (type.isVoid) { | 1192 if (type.isVoid) { |
| 1080 return js.call('dart.void'); | 1193 return js.call('dart.void'); |
| 1081 } else if (type.isDynamic) { | 1194 } else if (type.isDynamic) { |
| 1082 return js.call('dart.dynamic'); | 1195 return js.call('dart.dynamic'); |
| 1196 } else if (type.isBottom) { |
| 1197 return js.call('dart.bottom'); |
| 1083 } | 1198 } |
| 1084 | 1199 |
| 1085 _loader.declareBeforeUse(type.element); | 1200 _loader.declareBeforeUse(type.element); |
| 1086 | 1201 |
| 1087 // TODO(jmesserly): like constants, should we hoist function types out of | 1202 // TODO(jmesserly): like constants, should we hoist function types out of |
| 1088 // methods? Similar issue with generic types. For all of these, we may want | 1203 // methods? Similar issue with generic types. For all of these, we may want |
| 1089 // to canonicalize them too, at least when inside the same library. | 1204 // to canonicalize them too, at least when inside the same library. |
| 1090 var name = type.name; | 1205 var name = type.name; |
| 1091 var element = type.element; | 1206 var element = type.element; |
| 1092 if (name == '' || lowerTypedef) { | 1207 if (name == '' || name == null || lowerTypedef) { |
| 1093 var fnType = type as FunctionType; | 1208 var parts = _emitFunctionTypeParts(type as FunctionType); |
| 1094 var returnType = fnType.returnType; | 1209 return js.call('dart.functionType(#)', [parts]); |
| 1095 var parameterTypes = fnType.normalParameterTypes; | |
| 1096 var optionalTypes = fnType.optionalParameterTypes; | |
| 1097 var namedTypes = fnType.namedParameterTypes; | |
| 1098 if (namedTypes.isEmpty) { | |
| 1099 if (optionalTypes.isEmpty) { | |
| 1100 return js.call('dart.functionType(#, #)', [ | |
| 1101 _emitTypeName(returnType), | |
| 1102 _emitTypeNames(parameterTypes) | |
| 1103 ]); | |
| 1104 } else { | |
| 1105 return js.call('dart.functionType(#, #, #)', [ | |
| 1106 _emitTypeName(returnType), | |
| 1107 _emitTypeNames(parameterTypes), | |
| 1108 _emitTypeNames(optionalTypes) | |
| 1109 ]); | |
| 1110 } | |
| 1111 } else { | |
| 1112 assert(optionalTypes.isEmpty); | |
| 1113 return js.call('dart.functionType(#, #, #)', [ | |
| 1114 _emitTypeName(returnType), | |
| 1115 _emitTypeNames(parameterTypes), | |
| 1116 _emitTypeProperties(namedTypes) | |
| 1117 ]); | |
| 1118 } | |
| 1119 } | 1210 } |
| 1120 | 1211 |
| 1121 if (type is TypeParameterType) { | 1212 if (type is TypeParameterType) { |
| 1122 return new JS.Identifier(name); | 1213 return new JS.Identifier(name); |
| 1123 } | 1214 } |
| 1124 | 1215 |
| 1125 if (type is ParameterizedType) { | 1216 if (type is ParameterizedType) { |
| 1126 var args = type.typeArguments; | 1217 var args = type.typeArguments; |
| 1127 var isCurrentClass = | 1218 var isCurrentClass = |
| 1128 args.isNotEmpty && _loader.isCurrentElement(type.element); | 1219 args.isNotEmpty && _loader.isCurrentElement(type.element); |
| (...skipping 1346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2475 | 2566 |
| 2476 /// A special kind of element created by the compiler, signifying a temporary | 2567 /// A special kind of element created by the compiler, signifying a temporary |
| 2477 /// variable. These objects use instance equality, and should be shared | 2568 /// variable. These objects use instance equality, and should be shared |
| 2478 /// everywhere in the tree where they are treated as the same variable. | 2569 /// everywhere in the tree where they are treated as the same variable. |
| 2479 class TemporaryVariableElement extends LocalVariableElementImpl { | 2570 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 2480 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2571 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 2481 | 2572 |
| 2482 int get hashCode => identityHashCode(this); | 2573 int get hashCode => identityHashCode(this); |
| 2483 bool operator ==(Object other) => identical(this, other); | 2574 bool operator ==(Object other) => identical(this, other); |
| 2484 } | 2575 } |
| OLD | NEW |