| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 library kernel.type_substitute_bounds_test; | |
| 5 | |
| 6 import 'package:kernel/kernel.dart'; | |
| 7 import 'package:kernel/type_algebra.dart'; | |
| 8 import 'package:test/test.dart'; | |
| 9 import 'type_parser.dart'; | |
| 10 | |
| 11 final List<TestCase> testCases = <TestCase>[ | |
| 12 testCase('T', {'T': bound('_', 'String')}, 'String'), | |
| 13 testCase('List<T>', {'T': bound('_', 'String')}, 'List<String>'), | |
| 14 testCase('List<List<T>>', {'T': bound('_', 'String')}, 'List<List<String>>'), | |
| 15 testCase('(T) => T', {'T': bound('_', 'String')}, '(_) => String'), | |
| 16 testCase('<G>(G,T) => T', {'T': bound('_', 'String')}, '<G>(G,_) => String'), | |
| 17 testCase( | |
| 18 '<G>(G,x:T) => T', {'T': bound('_', 'String')}, '<G>(G,x:_) => String'), | |
| 19 testCase('<G:T>(G) => G', {'T': bound('_', 'String')}, '<G:_>(G) => G'), | |
| 20 testCase('<G:T>(G) => G', {'T': bound('int', 'num')}, '<G:int>(G) => G'), | |
| 21 testCase('<G>(T,G) => void', {'T': bound('_', 'String')}, '<G>(_,G) => void'), | |
| 22 testCase('(T) => void', {'T': bound('_', 'String')}, '(_) => void'), | |
| 23 testCase('(int) => T', {'T': bound('_', 'String')}, '(int) => String'), | |
| 24 testCase('(int) => int', {'T': bound('_', 'String')}, '(int) => int'), | |
| 25 testCase('((T) => int) => int', {'T': bound('_', 'String')}, | |
| 26 '((String) => int) => int'), | |
| 27 testCase('<E>(<F>(T) => int) => int', {'T': bound('_', 'String')}, | |
| 28 '<E>(<F>(String) => int) => int'), | |
| 29 testCase('(<F>(T) => int) => int', {'T': bound('_', 'String')}, | |
| 30 '(<F>(String) => int) => int'), | |
| 31 testCase('<E>((T) => int) => int', {'T': bound('_', 'String')}, | |
| 32 '<E>((String) => int) => int'), | |
| 33 ]; | |
| 34 | |
| 35 class TestCase { | |
| 36 final String type; | |
| 37 final Map<String, TypeBound> bounds; | |
| 38 final String expected; | |
| 39 | |
| 40 TestCase(this.type, this.bounds, this.expected); | |
| 41 | |
| 42 String toString() { | |
| 43 var substitution = bounds.keys.map((key) { | |
| 44 var bound = bounds[key]; | |
| 45 return '${bound.lower} <: $key <: ${bound.upper}'; | |
| 46 }).join(','); | |
| 47 return '$type [$substitution] <: $expected'; | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 class TypeBound { | |
| 52 final String lower, upper; | |
| 53 | |
| 54 TypeBound(this.lower, this.upper); | |
| 55 } | |
| 56 | |
| 57 TypeBound bound(String lower, String upper) => new TypeBound(lower, upper); | |
| 58 | |
| 59 TestCase testCase(String type, Map<String, TypeBound> bounds, String expected) { | |
| 60 return new TestCase(type, bounds, expected); | |
| 61 } | |
| 62 | |
| 63 main() { | |
| 64 for (var testCase in testCases) { | |
| 65 test('$testCase', () { | |
| 66 var environment = new LazyTypeEnvironment(); | |
| 67 var type = environment.parse(testCase.type); | |
| 68 var upperBounds = <TypeParameter, DartType>{}; | |
| 69 var lowerBounds = <TypeParameter, DartType>{}; | |
| 70 testCase.bounds.forEach((String name, TypeBound bounds) { | |
| 71 var parameter = environment.getTypeParameter(name); | |
| 72 upperBounds[parameter] = environment.parse(bounds.upper); | |
| 73 lowerBounds[parameter] = environment.parse(bounds.lower); | |
| 74 }); | |
| 75 var substituted = Substitution | |
| 76 .fromUpperAndLowerBounds(upperBounds, lowerBounds) | |
| 77 .substituteType(type); | |
| 78 var expected = environment.parse(testCase.expected); | |
| 79 if (substituted != expected) { | |
| 80 fail('Expected `$expected` but got `$substituted`'); | |
| 81 } | |
| 82 }); | |
| 83 } | |
| 84 } | |
| OLD | NEW |