| 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 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1456 // abstract members. For example: | 1456 // abstract members. For example: |
| 1457 // | 1457 // |
| 1458 // class C { m(); noSuchMethod(...) { ... } } | 1458 // class C { m(); noSuchMethod(...) { ... } } |
| 1459 // class D extends C { m(); noSuchMethod(...) { ... } } | 1459 // class D extends C { m(); noSuchMethod(...) { ... } } |
| 1460 // | 1460 // |
| 1461 // We'll generate D.m even though it is not necessary. | 1461 // We'll generate D.m even though it is not necessary. |
| 1462 // | 1462 // |
| 1463 // Doing better is a bit tricky, as our current codegen strategy for the | 1463 // Doing better is a bit tricky, as our current codegen strategy for the |
| 1464 // mock methods encodes information about the number of arguments (and type | 1464 // mock methods encodes information about the number of arguments (and type |
| 1465 // arguments) that D expects. | 1465 // arguments) that D expects. |
| 1466 return _collectMockMethods(type).map(_implementMockMethod); | 1466 return _collectMockMethods(type) |
| 1467 .map((method) => _implementMockMethod(method, type)); |
| 1467 } | 1468 } |
| 1468 | 1469 |
| 1469 /// Given a class C that implements method M from interface I, but does not | 1470 /// Given a class C that implements method M from interface I, but does not |
| 1470 /// declare M, this will generate an implementation that forwards to | 1471 /// declare M, this will generate an implementation that forwards to |
| 1471 /// noSuchMethod. | 1472 /// noSuchMethod. |
| 1472 /// | 1473 /// |
| 1473 /// For example: | 1474 /// For example: |
| 1474 /// | 1475 /// |
| 1475 /// class Cat { | 1476 /// class Cat { |
| 1476 /// bool eatFood(String food) => true; | 1477 /// bool eatFood(String food) => true; |
| 1477 /// } | 1478 /// } |
| 1478 /// class MockCat implements Cat { | 1479 /// class MockCat implements Cat { |
| 1479 /// noSuchMethod(Invocation invocation) => 3; | 1480 /// noSuchMethod(Invocation invocation) => 3; |
| 1480 /// } | 1481 /// } |
| 1481 /// | 1482 /// |
| 1482 /// It will generate an `eatFood` that looks like: | 1483 /// It will generate an `eatFood` that looks like: |
| 1483 /// | 1484 /// |
| 1484 /// eatFood(...args) { | 1485 /// eatFood(...args) { |
| 1485 /// return core.bool.as(this.noSuchMethod( | 1486 /// return core.bool.as(this.noSuchMethod( |
| 1486 /// new dart.InvocationImpl('eatFood', args))); | 1487 /// new dart.InvocationImpl('eatFood', args))); |
| 1487 /// } | 1488 /// } |
| 1488 JS.Method _implementMockMethod(ExecutableElement method) { | 1489 JS.Method _implementMockMethod(ExecutableElement method, InterfaceType type) { |
| 1489 var invocationProps = <JS.Property>[]; | 1490 var invocationProps = <JS.Property>[]; |
| 1490 addProperty(String name, JS.Expression value) { | 1491 addProperty(String name, JS.Expression value) { |
| 1491 invocationProps.add(new JS.Property(js.string(name), value)); | 1492 invocationProps.add(new JS.Property(js.string(name), value)); |
| 1492 } | 1493 } |
| 1493 | 1494 |
| 1494 var args = new JS.TemporaryId('args'); | 1495 var args = new JS.TemporaryId('args'); |
| 1495 var fnArgs = <JS.Parameter>[]; | 1496 var fnArgs = <JS.Parameter>[]; |
| 1496 JS.Expression positionalArgs; | 1497 JS.Expression positionalArgs; |
| 1497 | 1498 |
| 1498 if (method.type.namedParameterTypes.isNotEmpty) { | 1499 if (method.type.namedParameterTypes.isNotEmpty) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1529 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); | 1530 fnBody = js.call('#._check(#)', [_emitType(method.returnType), fnBody]); |
| 1530 } | 1531 } |
| 1531 | 1532 |
| 1532 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), | 1533 var fn = new JS.Fun(fnArgs, js.statement('{ return #; }', [fnBody]), |
| 1533 typeParams: _emitTypeFormals(method.type.typeFormals)); | 1534 typeParams: _emitTypeFormals(method.type.typeFormals)); |
| 1534 | 1535 |
| 1535 // TODO(jmesserly): generic type arguments will get dropped. | 1536 // TODO(jmesserly): generic type arguments will get dropped. |
| 1536 // We have a similar issue with `dgsend` helpers. | 1537 // We have a similar issue with `dgsend` helpers. |
| 1537 return new JS.Method( | 1538 return new JS.Method( |
| 1538 _declareMemberName(method, | 1539 _declareMemberName(method, |
| 1539 useExtension: | 1540 useExtension: _extensionTypes.isNativeClass(type.element)), |
| 1540 _extensionTypes.isNativeClass(method.enclosingElement)), | |
| 1541 _makeGenericFunction(fn), | 1541 _makeGenericFunction(fn), |
| 1542 isGetter: method is PropertyAccessorElement && method.isGetter, | 1542 isGetter: method is PropertyAccessorElement && method.isGetter, |
| 1543 isSetter: method is PropertyAccessorElement && method.isSetter, | 1543 isSetter: method is PropertyAccessorElement && method.isSetter, |
| 1544 isStatic: false); | 1544 isStatic: false); |
| 1545 } | 1545 } |
| 1546 | 1546 |
| 1547 /// Return `true` if the given [classElement] has a noSuchMethod() method | 1547 /// Return `true` if the given [classElement] has a noSuchMethod() method |
| 1548 /// distinct from the one declared in class Object, as per the Dart Language | 1548 /// distinct from the one declared in class Object, as per the Dart Language |
| 1549 /// Specification (section 10.4). | 1549 /// Specification (section 10.4). |
| 1550 // TODO(jmesserly): this was taken from error_verifier.dart | 1550 // TODO(jmesserly): this was taken from error_verifier.dart |
| (...skipping 4339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5890 if (targetIdentifier.staticElement is! PrefixElement) return false; | 5890 if (targetIdentifier.staticElement is! PrefixElement) return false; |
| 5891 var prefix = targetIdentifier.staticElement as PrefixElement; | 5891 var prefix = targetIdentifier.staticElement as PrefixElement; |
| 5892 | 5892 |
| 5893 // The library the prefix is referring to must come from a deferred import. | 5893 // The library the prefix is referring to must come from a deferred import. |
| 5894 var containingLibrary = resolutionMap | 5894 var containingLibrary = resolutionMap |
| 5895 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 5895 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
| 5896 .library; | 5896 .library; |
| 5897 var imports = containingLibrary.getImportsWithPrefix(prefix); | 5897 var imports = containingLibrary.getImportsWithPrefix(prefix); |
| 5898 return imports.length == 1 && imports[0].isDeferred; | 5898 return imports.length == 1 && imports[0].isDeferred; |
| 5899 } | 5899 } |
| OLD | NEW |