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 | 2 |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1498 } else if (property.isSetter) { | 1498 } else if (property.isSetter) { |
1499 addProperty('isSetter', js.boolean(true)); | 1499 addProperty('isSetter', js.boolean(true)); |
1500 | 1500 |
1501 fnArgs.add(args); | 1501 fnArgs.add(args); |
1502 positionalArgs = new JS.ArrayInitializer([args]); | 1502 positionalArgs = new JS.ArrayInitializer([args]); |
1503 } | 1503 } |
1504 } | 1504 } |
1505 | 1505 |
1506 var fnBody = js.call('this.noSuchMethod(new #.InvocationImpl(#, #, #))', [ | 1506 var fnBody = js.call('this.noSuchMethod(new #.InvocationImpl(#, #, #))', [ |
1507 _runtimeModule, | 1507 _runtimeModule, |
1508 _declareMemberName(method), | 1508 _declareMemberName(method, useDisplayName: true), |
Jennifer Messerly
2017/01/11 03:25:44
it might be good to just change InovcationImpl rat
| |
1509 positionalArgs, | 1509 positionalArgs, |
1510 new JS.ObjectInitializer(invocationProps) | 1510 new JS.ObjectInitializer(invocationProps) |
1511 ]); | 1511 ]); |
1512 | 1512 |
1513 if (!method.returnType.isDynamic) { | 1513 if (!method.returnType.isDynamic) { |
1514 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); | 1514 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); |
1515 } | 1515 } |
1516 | 1516 |
1517 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), | 1517 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), |
1518 typeParams: _emitTypeFormals(method.type.typeFormals)); | 1518 typeParams: _emitTypeFormals(method.type.typeFormals)); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1932 } | 1932 } |
1933 } | 1933 } |
1934 if (dartxNames.isNotEmpty) { | 1934 if (dartxNames.isNotEmpty) { |
1935 body.add(_callHelperStatement('defineExtensionNames(#)', | 1935 body.add(_callHelperStatement('defineExtensionNames(#)', |
1936 [new JS.ArrayInitializer(dartxNames, multiline: true)])); | 1936 [new JS.ArrayInitializer(dartxNames, multiline: true)])); |
1937 } | 1937 } |
1938 } | 1938 } |
1939 } | 1939 } |
1940 | 1940 |
1941 List<ExecutableElement> _extensionsToImplement(ClassElement element) { | 1941 List<ExecutableElement> _extensionsToImplement(ClassElement element) { |
1942 var members = <ExecutableElement>[]; | 1942 if (_extensionTypes.isNativeClass(element)) return []; |
1943 if (_extensionTypes.isNativeClass(element)) return members; | |
1944 | 1943 |
1945 // Collect all extension types we implement. | 1944 // Collect all extension types we implement. |
1946 var type = element.type; | 1945 var type = element.type; |
1947 var types = _extensionTypes.collectNativeInterfaces(element); | 1946 var types = _extensionTypes.collectNativeInterfaces(element); |
1948 if (types.isEmpty) return members; | 1947 if (types.isEmpty) return []; |
1949 | 1948 |
1949 var members = new Set<ExecutableElement>(); | |
1950 // Collect all possible extension method names. | 1950 // Collect all possible extension method names. |
1951 var extensionMembers = new HashSet<String>(); | 1951 var extensionMembers = new HashSet<String>(); |
1952 for (var t in types) { | 1952 for (var t in types) { |
1953 for (var m in [t.methods, t.accessors].expand((e) => e)) { | 1953 for (var m in [t.methods, t.accessors].expand((e) => e)) { |
1954 if (!m.isStatic && m.isPublic) extensionMembers.add(m.name); | 1954 if (!m.isStatic && m.isPublic) extensionMembers.add(m.name); |
1955 } | 1955 } |
1956 } | 1956 } |
1957 | 1957 |
1958 // Collect all of extension methods this type implements. | 1958 // Collect all of extension methods this type implements. |
1959 for (var m in [type.methods, type.accessors].expand((e) => e)) { | 1959 for (var m in [type.methods, type.accessors].expand((e) => e)) { |
1960 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) { | 1960 if (!m.isStatic && !m.isAbstract && extensionMembers.contains(m.name)) { |
1961 members.add(m); | 1961 members.add(m); |
1962 } | 1962 } |
1963 } | 1963 } |
1964 return members; | 1964 members.addAll(_collectMockMethods(type) |
1965 .where((m) => extensionMembers.contains(m.name))); | |
1966 return members.toList(); | |
1965 } | 1967 } |
1966 | 1968 |
1967 /// Generates the implicit default constructor for class C of the form | 1969 /// Generates the implicit default constructor for class C of the form |
1968 /// `C() : super() {}`. | 1970 /// `C() : super() {}`. |
1969 JS.Method _emitImplicitConstructor( | 1971 JS.Method _emitImplicitConstructor( |
1970 ClassDeclaration node, | 1972 ClassDeclaration node, |
1971 List<FieldDeclaration> fields, | 1973 List<FieldDeclaration> fields, |
1972 Map<FieldElement, JS.TemporaryId> virtualFields) { | 1974 Map<FieldElement, JS.TemporaryId> virtualFields) { |
1973 // If we don't have a method body, skip this. | 1975 // If we don't have a method body, skip this. |
1974 var superCall = _superConstructorCall(node.element); | 1976 var superCall = _superConstructorCall(node.element); |
(...skipping 3481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5456 } | 5458 } |
5457 JS.Expression result = _visit(node); | 5459 JS.Expression result = _visit(node); |
5458 if (isNullable(node)) result = _callHelper('test(#)', result); | 5460 if (isNullable(node)) result = _callHelper('test(#)', result); |
5459 return result; | 5461 return result; |
5460 } | 5462 } |
5461 | 5463 |
5462 /// Like [_emitMemberName], but for declaration sites. | 5464 /// Like [_emitMemberName], but for declaration sites. |
5463 /// | 5465 /// |
5464 /// Unlike call sites, we always have an element available, so we can use it | 5466 /// Unlike call sites, we always have an element available, so we can use it |
5465 /// directly rather than computing the relevant options for [_emitMemberName]. | 5467 /// directly rather than computing the relevant options for [_emitMemberName]. |
5466 JS.Expression _declareMemberName(ExecutableElement e, {bool useExtension}) { | 5468 JS.Expression _declareMemberName(ExecutableElement e, |
5467 String name; | 5469 {bool useExtension, useDisplayName = false}) { |
5468 if (e is PropertyAccessorElement) { | 5470 var name = (e is PropertyAccessorElement) ? e.variable.name : e.name; |
5469 name = e.variable.name; | |
5470 } else { | |
5471 name = e.name; | |
5472 } | |
5473 return _emitMemberName(name, | 5471 return _emitMemberName(name, |
5474 isStatic: e.isStatic, | 5472 isStatic: e.isStatic, |
5475 useExtension: | 5473 useExtension: |
5476 useExtension ?? _extensionTypes.isNativeClass(e.enclosingElement)); | 5474 useExtension ?? _extensionTypes.isNativeClass(e.enclosingElement), |
5475 useDisplayName: useDisplayName); | |
5477 } | 5476 } |
5478 | 5477 |
5479 /// This handles member renaming for private names and operators. | 5478 /// This handles member renaming for private names and operators. |
5480 /// | 5479 /// |
5481 /// Private names are generated using ES6 symbols: | 5480 /// Private names are generated using ES6 symbols: |
5482 /// | 5481 /// |
5483 /// // At the top of the module: | 5482 /// // At the top of the module: |
5484 /// let _x = Symbol('_x'); | 5483 /// let _x = Symbol('_x'); |
5485 /// let _y = Symbol('_y'); | 5484 /// let _y = Symbol('_y'); |
5486 /// ... | 5485 /// ... |
(...skipping 26 matching lines...) Expand all Loading... | |
5513 /// | 5512 /// |
5514 /// Unary minus looks like: `x._negate()`. | 5513 /// Unary minus looks like: `x._negate()`. |
5515 /// | 5514 /// |
5516 /// Equality is a bit special, it is generated via the Dart `equals` runtime | 5515 /// Equality is a bit special, it is generated via the Dart `equals` runtime |
5517 /// helper, that checks for null. The user defined method is called '=='. | 5516 /// helper, that checks for null. The user defined method is called '=='. |
5518 /// | 5517 /// |
5519 JS.Expression _emitMemberName(String name, | 5518 JS.Expression _emitMemberName(String name, |
5520 {DartType type, | 5519 {DartType type, |
5521 bool isStatic: false, | 5520 bool isStatic: false, |
5522 bool useExtension, | 5521 bool useExtension, |
5522 bool useDisplayName: false, | |
5523 Element element}) { | 5523 Element element}) { |
5524 // Static members skip the rename steps and may require JS interop renames. | 5524 // Static members skip the rename steps and may require JS interop renames. |
5525 if (isStatic) { | 5525 if (isStatic) { |
5526 return _emitJSInteropStaticMemberName(element) ?? _propertyName(name); | 5526 return _emitJSInteropStaticMemberName(element) ?? _propertyName(name); |
5527 } | 5527 } |
5528 | 5528 |
5529 if (name.startsWith('_')) { | 5529 if (name.startsWith('_')) { |
5530 return _emitPrivateNameSymbol(currentLibrary, name); | 5530 return _emitPrivateNameSymbol(currentLibrary, name); |
5531 } | 5531 } |
5532 | 5532 |
5533 // When generating synthetic names, we use _ as the prefix, since Dart names | 5533 // When generating synthetic names, we use _ as the prefix, since Dart names |
5534 // won't have this (eliminated above), nor will static names reach here. | 5534 // won't have this (eliminated above), nor will static names reach here. |
5535 switch (name) { | 5535 if (!useDisplayName) { |
5536 case '[]': | 5536 switch (name) { |
5537 name = '_get'; | 5537 case '[]': |
5538 break; | 5538 name = '_get'; |
5539 case '[]=': | 5539 break; |
5540 name = '_set'; | 5540 case '[]=': |
5541 break; | 5541 name = '_set'; |
5542 case 'unary-': | 5542 break; |
5543 name = '_negate'; | 5543 case 'unary-': |
5544 break; | 5544 name = '_negate'; |
5545 case 'constructor': | 5545 break; |
5546 case 'prototype': | 5546 case 'constructor': |
5547 name = '_$name'; | 5547 case 'prototype': |
5548 break; | 5548 name = '_$name'; |
5549 break; | |
5550 } | |
5549 } | 5551 } |
5550 | 5552 |
5551 var result = _propertyName(name); | 5553 var result = _propertyName(name); |
5552 | 5554 |
5553 if (useExtension == null) { | 5555 if (useExtension == null) { |
5554 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. | 5556 // Dart "extension" methods. Used for JS Array, Boolean, Number, String. |
5555 var baseType = type; | 5557 var baseType = type; |
5556 while (baseType is TypeParameterType) { | 5558 while (baseType is TypeParameterType) { |
5557 baseType = (baseType.element as TypeParameterElement).bound; | 5559 baseType = (baseType.element as TypeParameterElement).bound; |
5558 } | 5560 } |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5815 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5817 if (targetIdentifier.staticElement is! PrefixElement) return false; |
5816 var prefix = targetIdentifier.staticElement as PrefixElement; | 5818 var prefix = targetIdentifier.staticElement as PrefixElement; |
5817 | 5819 |
5818 // The library the prefix is referring to must come from a deferred import. | 5820 // The library the prefix is referring to must come from a deferred import. |
5819 var containingLibrary = resolutionMap | 5821 var containingLibrary = resolutionMap |
5820 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 5822 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
5821 .library; | 5823 .library; |
5822 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5824 var imports = containingLibrary.getImportsWithPrefix(prefix); |
5823 return imports.length == 1 && imports[0].isDeferred; | 5825 return imports.length == 1 && imports[0].isDeferred; |
5824 } | 5826 } |
OLD | NEW |