Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(936)

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 2656363003: Fix mocking native classes and add a regression test. (Closed)
Patch Set: Fix mocking native classes and add a regression test. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/lib_strong/html/html_mock_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib_strong/html/html_mock_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698