OLD | NEW |
---|---|
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:kernel/ast.dart'; | 5 import 'package:kernel/ast.dart'; |
6 import 'package:kernel/class_hierarchy.dart'; | 6 import 'package:kernel/class_hierarchy.dart'; |
7 import 'package:kernel/core_types.dart'; | 7 import 'package:kernel/core_types.dart'; |
8 import 'package:kernel/testing/mock_sdk_program.dart'; | 8 import 'package:kernel/testing/mock_sdk_program.dart'; |
9 import 'package:kernel/text/ast_to_text.dart'; | |
9 import 'package:test/test.dart'; | 10 import 'package:test/test.dart'; |
10 import 'package:test_reflective_loader/test_reflective_loader.dart'; | 11 import 'package:test_reflective_loader/test_reflective_loader.dart'; |
11 | 12 |
12 main() { | 13 main() { |
13 defineReflectiveSuite(() { | 14 defineReflectiveSuite(() { |
14 defineReflectiveTests(ClosedWorldClassHierarchyTest); | 15 defineReflectiveTests(ClosedWorldClassHierarchyTest); |
15 }); | 16 }); |
16 } | 17 } |
17 | 18 |
18 @reflectiveTest | 19 @reflectiveTest |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
77 return addClass(new Class( | 78 return addClass(new Class( |
78 name: name, | 79 name: name, |
79 supertype: objectSuper, | 80 supertype: objectSuper, |
80 implementedTypes: implements_.map((c) => c.asThisSupertype).toList())); | 81 implementedTypes: implements_.map((c) => c.asThisSupertype).toList())); |
81 } | 82 } |
82 | 83 |
83 ClassHierarchy createClassHierarchy(Program program); | 84 ClassHierarchy createClassHierarchy(Program program); |
84 | 85 |
85 Procedure newEmptyMethod(String name, {bool abstract: false}) { | 86 Procedure newEmptyMethod(String name, {bool abstract: false}) { |
86 var body = abstract ? null : new Block([]); | 87 var body = abstract ? null : new Block([]); |
87 return new Procedure( | 88 return new Procedure(new Name(name), ProcedureKind.Method, |
88 new Name(name), ProcedureKind.Method, new FunctionNode(body)); | 89 new FunctionNode(body, returnType: const VoidType())); |
89 } | 90 } |
90 | 91 |
91 Procedure newEmptySetter(String name) { | 92 Procedure newEmptySetter(String name) { |
92 return new Procedure( | 93 return new Procedure( |
93 new Name(name), | 94 new Name(name), |
94 ProcedureKind.Setter, | 95 ProcedureKind.Setter, |
95 new FunctionNode(new Block([]), | 96 new FunctionNode(new Block([]), |
97 returnType: const VoidType(), | |
96 positionalParameters: [new VariableDeclaration('_')])); | 98 positionalParameters: [new VariableDeclaration('_')])); |
97 } | 99 } |
98 | 100 |
99 void setUp() { | 101 void setUp() { |
100 // Start with mock SDK libraries. | 102 // Start with mock SDK libraries. |
101 program = createMockSdkProgram(); | 103 program = createMockSdkProgram(); |
102 coreTypes = new CoreTypes(program); | 104 coreTypes = new CoreTypes(program); |
103 | 105 |
104 // Add the test library. | 106 // Add the test library. |
105 library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test'); | 107 library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test'); |
106 library.parent = program; | 108 library.parent = program; |
107 program.libraries.add(library); | 109 program.libraries.add(library); |
108 } | 110 } |
109 | 111 |
110 void test_forEachOverridePair_overrideSupertype() { | 112 void test_forEachOverridePair_overrideSupertype() { |
111 // Create the class hierarchy: | |
112 // | |
113 // abstract class A extends Object { | |
114 // foo() {} | |
115 // bar() {} | |
116 // } | |
117 // class B extends A { | |
118 // foo() {} | |
119 // } | |
120 // class C extends B { | |
121 // bar() {} | |
122 // } | |
123 var aFoo = newEmptyMethod('foo'); | 113 var aFoo = newEmptyMethod('foo'); |
124 var aBar = newEmptyMethod('bar'); | 114 var aBar = newEmptyMethod('bar'); |
125 var bFoo = newEmptyMethod('foo'); | 115 var bFoo = newEmptyMethod('foo'); |
126 var cBar = newEmptyMethod('bar'); | 116 var cBar = newEmptyMethod('bar'); |
127 var a = addClass( | 117 var a = addClass( |
128 new Class(name: 'A', supertype: objectSuper, procedures: [aFoo, aBar])); | 118 new Class(name: 'A', supertype: objectSuper, procedures: [aFoo, aBar])); |
129 var b = addClass( | 119 var b = addClass( |
130 new Class(name: 'B', supertype: a.asThisSupertype, procedures: [bFoo])); | 120 new Class(name: 'B', supertype: a.asThisSupertype, procedures: [bFoo])); |
131 var c = addClass( | 121 var c = addClass( |
132 new Class(name: 'C', supertype: b.asThisSupertype, procedures: [cBar])); | 122 new Class(name: 'C', supertype: b.asThisSupertype, procedures: [cBar])); |
133 | 123 |
124 _assertTestLibraryText(''' | |
125 class A { | |
126 method foo() → void {} | |
127 method bar() → void {} | |
128 } | |
129 class B extends self::A { | |
130 method foo() → void {} | |
131 } | |
132 class C extends self::B { | |
133 method bar() → void {} | |
134 } | |
135 '''); | |
136 | |
134 _assertOverridePairs(b, ['test::B::foo overrides test::A::foo']); | 137 _assertOverridePairs(b, ['test::B::foo overrides test::A::foo']); |
135 _assertOverridePairs(c, ['test::C::bar overrides test::A::bar']); | 138 _assertOverridePairs(c, ['test::C::bar overrides test::A::bar']); |
136 } | 139 } |
137 | 140 |
138 void test_getClassAsInstanceOf_generic_extends() { | 141 void test_getClassAsInstanceOf_generic_extends() { |
139 // Create the class hierarchy: | |
140 // | |
141 // class A<T, U> extends Object {} | |
142 // class B<T> extends A<T, bool> {} | |
143 // class C extends B<int> {} | |
144 var int = coreTypes.intClass.rawType; | 142 var int = coreTypes.intClass.rawType; |
145 var bool = coreTypes.boolClass.rawType; | 143 var bool = coreTypes.boolClass.rawType; |
146 | 144 |
147 var a = addGenericClass('A', ['T', 'U']); | 145 var a = addGenericClass('A', ['T', 'U']); |
148 | 146 |
149 var bT = new TypeParameter('T', objectClass.rawType); | 147 var bT = new TypeParameter('T', objectClass.rawType); |
150 var bTT = new TypeParameterType(bT); | 148 var bTT = new TypeParameterType(bT); |
151 var b = addClass(new Class( | 149 var b = addClass(new Class( |
152 name: 'B', | 150 name: 'B', |
153 typeParameters: [bT], | 151 typeParameters: [bT], |
154 supertype: new Supertype(a, [bTT, bool]))); | 152 supertype: new Supertype(a, [bTT, bool]))); |
155 | 153 |
156 var c = addClass(new Class(name: 'C', supertype: new Supertype(b, [int]))); | 154 var c = addClass(new Class(name: 'C', supertype: new Supertype(b, [int]))); |
157 | 155 |
156 _assertTestLibraryText(''' | |
157 class A<T, U> {} | |
158 class B<T> extends self::A<self::B::T, core::bool> {} | |
159 class C extends self::B<core::int> {} | |
160 '''); | |
161 | |
158 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | 162 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); |
159 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | 163 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); |
160 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); | 164 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); |
161 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); | 165 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); |
162 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); | 166 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); |
163 } | 167 } |
164 | 168 |
165 void test_getClassAsInstanceOf_generic_implements() { | 169 void test_getClassAsInstanceOf_generic_implements() { |
166 // Create the class hierarchy: | |
167 // | |
168 // class A<T, U> extends Object {} | |
169 // class B<T> extends Object implements A<T, bool> {} | |
170 // class C extends Object implements B<int> {} | |
171 var int = coreTypes.intClass.rawType; | 170 var int = coreTypes.intClass.rawType; |
172 var bool = coreTypes.boolClass.rawType; | 171 var bool = coreTypes.boolClass.rawType; |
173 | 172 |
174 var a = addGenericClass('A', ['T', 'U']); | 173 var a = addGenericClass('A', ['T', 'U']); |
175 | 174 |
176 var bT = new TypeParameter('T', objectClass.rawType); | 175 var bT = new TypeParameter('T', objectClass.rawType); |
177 var bTT = new TypeParameterType(bT); | 176 var bTT = new TypeParameterType(bT); |
178 var b = addClass(new Class( | 177 var b = addClass(new Class( |
179 name: 'B', | 178 name: 'B', |
180 typeParameters: [bT], | 179 typeParameters: [bT], |
181 supertype: objectSuper, | 180 supertype: objectSuper, |
182 implementedTypes: [ | 181 implementedTypes: [ |
183 new Supertype(a, [bTT, bool]) | 182 new Supertype(a, [bTT, bool]) |
184 ])); | 183 ])); |
185 | 184 |
186 var c = addClass( | 185 var c = addClass( |
187 new Class(name: 'C', supertype: objectSuper, implementedTypes: [ | 186 new Class(name: 'C', supertype: objectSuper, implementedTypes: [ |
188 new Supertype(b, [int]) | 187 new Supertype(b, [int]) |
189 ])); | 188 ])); |
190 | 189 |
190 _assertTestLibraryText(''' | |
191 class A<T, U> {} | |
192 class B<T> implements self::A<self::B::T, core::bool> {} | |
193 class C implements self::B<core::int> {} | |
194 '''); | |
195 | |
191 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | 196 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); |
192 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | 197 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); |
193 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); | 198 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); |
194 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); | 199 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); |
195 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); | 200 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); |
196 } | 201 } |
197 | 202 |
198 void test_getClassAsInstanceOf_generic_with() { | 203 void test_getClassAsInstanceOf_generic_with() { |
199 // Create the class hierarchy: | |
200 // | |
201 // class A<T, U> extends Object {} | |
202 // class B<T> extends Object with A<T, bool> {} | |
203 // class C extends Object with B<int> {} | |
204 var int = coreTypes.intClass.rawType; | 204 var int = coreTypes.intClass.rawType; |
205 var bool = coreTypes.boolClass.rawType; | 205 var bool = coreTypes.boolClass.rawType; |
206 | 206 |
207 var a = addGenericClass('A', ['T', 'U']); | 207 var a = addGenericClass('A', ['T', 'U']); |
208 | 208 |
209 var bT = new TypeParameter('T', objectClass.rawType); | 209 var bT = new TypeParameter('T', objectClass.rawType); |
210 var bTT = new TypeParameterType(bT); | 210 var bTT = new TypeParameterType(bT); |
211 var b = addClass(new Class( | 211 var b = addClass(new Class( |
212 name: 'B', | 212 name: 'B', |
213 typeParameters: [bT], | 213 typeParameters: [bT], |
214 supertype: objectSuper, | 214 supertype: objectSuper, |
215 mixedInType: new Supertype(a, [bTT, bool]))); | 215 mixedInType: new Supertype(a, [bTT, bool]))); |
216 | 216 |
217 var c = addClass(new Class( | 217 var c = addClass(new Class( |
218 name: 'C', | 218 name: 'C', |
219 supertype: objectSuper, | 219 supertype: objectSuper, |
220 mixedInType: new Supertype(b, [int]))); | 220 mixedInType: new Supertype(b, [int]))); |
221 | 221 |
222 _assertTestLibraryText(''' | |
223 class A<T, U> {} | |
224 class B<T> = core::Object with self::A<self::B::T, core::bool> {} | |
225 class C = core::Object with self::B<core::int> {} | |
226 '''); | |
227 | |
222 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | 228 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); |
223 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | 229 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); |
224 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); | 230 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); |
225 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); | 231 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); |
226 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); | 232 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); |
227 } | 233 } |
228 | 234 |
229 void test_getClassAsInstanceOf_notGeneric_extends() { | 235 void test_getClassAsInstanceOf_notGeneric_extends() { |
230 // Create the class hierarchy: | |
231 // | |
232 // class A extends Object {} | |
233 // class B extends A {} | |
234 // class C extends B {} | |
235 // class Z extends Object {} | |
236 var a = addClass(new Class(name: 'A', supertype: objectSuper)); | 236 var a = addClass(new Class(name: 'A', supertype: objectSuper)); |
237 var b = addClass(new Class(name: 'B', supertype: a.asThisSupertype)); | 237 var b = addClass(new Class(name: 'B', supertype: a.asThisSupertype)); |
238 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | 238 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); |
239 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); | 239 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); |
240 | 240 |
241 _assertTestLibraryText(''' | |
242 class A {} | |
243 class B extends self::A {} | |
244 class C extends self::B {} | |
245 class Z {} | |
246 '''); | |
247 | |
241 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | 248 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); |
242 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | 249 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); |
243 expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype); | 250 expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype); |
244 expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype); | 251 expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype); |
245 expect(hierarchy.getClassAsInstanceOf(c, b), b.asThisSupertype); | 252 expect(hierarchy.getClassAsInstanceOf(c, b), b.asThisSupertype); |
246 expect(hierarchy.getClassAsInstanceOf(z, a), null); | 253 expect(hierarchy.getClassAsInstanceOf(z, a), null); |
247 expect(hierarchy.getClassAsInstanceOf(z, objectClass), objectSuper); | 254 expect(hierarchy.getClassAsInstanceOf(z, objectClass), objectSuper); |
248 } | 255 } |
249 | 256 |
250 void test_getClassAsInstanceOf_notGeneric_implements() { | 257 void test_getClassAsInstanceOf_notGeneric_implements() { |
251 // Create the class hierarchy: | |
252 // | |
253 // class A extends Object {} | |
254 // class B extends Object {} | |
255 // class C extends Object implements A {} | |
256 // class D extends Object implements C {} | |
257 // class E extends A implements B {} | |
258 // class Z extends Object {} | |
259 var a = addClass(new Class(name: 'A', supertype: objectSuper)); | 258 var a = addClass(new Class(name: 'A', supertype: objectSuper)); |
260 var b = addClass(new Class(name: 'B', supertype: objectSuper)); | 259 var b = addClass(new Class(name: 'B', supertype: objectSuper)); |
261 var c = addClass(new Class( | 260 var c = addClass(new Class( |
262 name: 'C', | 261 name: 'C', |
263 supertype: objectSuper, | 262 supertype: objectSuper, |
264 implementedTypes: [a.asThisSupertype])); | 263 implementedTypes: [a.asThisSupertype])); |
265 var d = addClass(new Class( | 264 var d = addClass(new Class( |
266 name: 'D', | 265 name: 'D', |
267 supertype: objectSuper, | 266 supertype: objectSuper, |
268 implementedTypes: [c.asThisSupertype])); | 267 implementedTypes: [c.asThisSupertype])); |
269 var e = addClass(new Class( | 268 var e = addClass(new Class( |
270 name: 'D', | 269 name: 'D', |
271 supertype: a.asThisSupertype, | 270 supertype: a.asThisSupertype, |
272 implementedTypes: [b.asThisSupertype])); | 271 implementedTypes: [b.asThisSupertype])); |
273 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); | 272 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); |
274 | 273 |
274 _assertTestLibraryText(''' | |
275 class A {} | |
276 class B {} | |
277 class C implements self::A {} | |
278 class D implements self::C {} | |
279 class D extends self::A implements self::B {} | |
280 class Z {} | |
281 '''); | |
282 | |
275 expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype); | 283 expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype); |
276 expect(hierarchy.getClassAsInstanceOf(d, a), a.asThisSupertype); | 284 expect(hierarchy.getClassAsInstanceOf(d, a), a.asThisSupertype); |
277 expect(hierarchy.getClassAsInstanceOf(d, c), c.asThisSupertype); | 285 expect(hierarchy.getClassAsInstanceOf(d, c), c.asThisSupertype); |
278 expect(hierarchy.getClassAsInstanceOf(e, a), a.asThisSupertype); | 286 expect(hierarchy.getClassAsInstanceOf(e, a), a.asThisSupertype); |
279 expect(hierarchy.getClassAsInstanceOf(e, b), b.asThisSupertype); | 287 expect(hierarchy.getClassAsInstanceOf(e, b), b.asThisSupertype); |
280 expect(hierarchy.getClassAsInstanceOf(z, a), null); | 288 expect(hierarchy.getClassAsInstanceOf(z, a), null); |
281 } | 289 } |
282 | 290 |
283 void test_getClassAsInstanceOf_notGeneric_with() { | 291 void test_getClassAsInstanceOf_notGeneric_with() { |
284 // Create the class hierarchy: | |
285 // | |
286 // class A extends Object {} | |
287 // class B extends Object with A {} | |
288 // class Z extends Object {} | |
289 var a = addClass(new Class(name: 'A', supertype: objectSuper)); | 292 var a = addClass(new Class(name: 'A', supertype: objectSuper)); |
290 var b = addClass(new Class( | 293 var b = addClass(new Class( |
291 name: 'B', supertype: objectSuper, mixedInType: a.asThisSupertype)); | 294 name: 'B', supertype: objectSuper, mixedInType: a.asThisSupertype)); |
292 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); | 295 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); |
293 | 296 |
297 _assertTestLibraryText(''' | |
298 class A {} | |
299 class B = core::Object with self::A {} | |
300 class Z {} | |
301 '''); | |
302 | |
294 expect(hierarchy.getClassAsInstanceOf(b, objectClass), objectSuper); | 303 expect(hierarchy.getClassAsInstanceOf(b, objectClass), objectSuper); |
295 expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype); | 304 expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype); |
296 expect(hierarchy.getClassAsInstanceOf(z, a), null); | 305 expect(hierarchy.getClassAsInstanceOf(z, a), null); |
297 } | 306 } |
298 | 307 |
299 void test_getClassDepth() { | 308 void test_getClassDepth() { |
300 var base = addClass(new Class(name: 'base', supertype: objectSuper)); | 309 var base = addClass(new Class(name: 'base', supertype: objectSuper)); |
301 var extends_ = | 310 var extends_ = |
302 addClass(new Class(name: 'extends_', supertype: base.asThisSupertype)); | 311 addClass(new Class(name: 'extends_', supertype: base.asThisSupertype)); |
303 var with_ = addClass(new Class( | 312 var with_ = addClass(new Class( |
304 name: 'with_', | 313 name: 'with_', |
305 supertype: objectSuper, | 314 supertype: objectSuper, |
306 mixedInType: base.asThisSupertype)); | 315 mixedInType: base.asThisSupertype)); |
307 var implements_ = addClass(new Class( | 316 var implements_ = addClass(new Class( |
308 name: 'implements_', | 317 name: 'implements_', |
309 supertype: objectSuper, | 318 supertype: objectSuper, |
310 implementedTypes: [base.asThisSupertype])); | 319 implementedTypes: [base.asThisSupertype])); |
311 | 320 |
321 _assertTestLibraryText(''' | |
322 class base {} | |
323 class extends_ extends self::base {} | |
324 class with_ = core::Object with self::base {} | |
325 class implements_ implements self::base {} | |
326 '''); | |
327 | |
312 expect(hierarchy.getClassDepth(objectClass), 0); | 328 expect(hierarchy.getClassDepth(objectClass), 0); |
313 expect(hierarchy.getClassDepth(base), 1); | 329 expect(hierarchy.getClassDepth(base), 1); |
314 expect(hierarchy.getClassDepth(extends_), 2); | 330 expect(hierarchy.getClassDepth(extends_), 2); |
315 expect(hierarchy.getClassDepth(with_), 2); | 331 expect(hierarchy.getClassDepth(with_), 2); |
316 expect(hierarchy.getClassDepth(implements_), 2); | 332 expect(hierarchy.getClassDepth(implements_), 2); |
317 } | 333 } |
318 | 334 |
319 void test_getClassicLeastUpperBound_generic() { | 335 void test_getClassicLeastUpperBound_generic() { |
320 var int = coreTypes.intClass.rawType; | 336 var int = coreTypes.intClass.rawType; |
321 var double = coreTypes.doubleClass.rawType; | 337 var double = coreTypes.doubleClass.rawType; |
322 var bool = coreTypes.boolClass.rawType; | 338 var bool = coreTypes.boolClass.rawType; |
323 | 339 |
324 // Create the class hierarchy: | |
325 // | |
326 // Object | |
327 // | | |
328 // A | |
329 // / \ | |
330 // B<T> C<U> | |
331 // \ / | |
332 // D<T,U> | |
333 // / \ | |
334 // E F | |
335 // | |
336 // Where E implements D<int, double> and F implements D<int, bool>. | |
337 var a = addGenericClass('A', []); | 340 var a = addGenericClass('A', []); |
338 var b = | 341 var b = |
339 addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]); | 342 addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]); |
340 var c = | 343 var c = |
341 addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]); | 344 addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]); |
342 var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) { | 345 var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) { |
343 var t = typeParameterTypes[0]; | 346 var t = typeParameterTypes[0]; |
344 var u = typeParameterTypes[1]; | 347 var u = typeParameterTypes[1]; |
345 return [ | 348 return [ |
346 new Supertype(b, [t]), | 349 new Supertype(b, [t]), |
347 new Supertype(c, [u]) | 350 new Supertype(c, [u]) |
348 ]; | 351 ]; |
349 }); | 352 }); |
350 var e = addGenericClass('E', [], | 353 var e = addGenericClass('E', [], |
351 implements_: (_) => [ | 354 implements_: (_) => [ |
352 new Supertype(d, [int, double]) | 355 new Supertype(d, [int, double]) |
353 ]); | 356 ]); |
354 var f = addGenericClass('F', [], | 357 var f = addGenericClass('F', [], |
355 implements_: (_) => [ | 358 implements_: (_) => [ |
356 new Supertype(d, [int, bool]) | 359 new Supertype(d, [int, bool]) |
357 ]); | 360 ]); |
358 | 361 |
362 _assertTestLibraryText(''' | |
363 class A {} | |
364 class B<T> implements self::A {} | |
365 class C<U> implements self::A {} | |
366 class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {} | |
367 class E implements self::D<core::int, core::double> {} | |
368 class F implements self::D<core::int, core::bool> {} | |
ahe
2017/06/01 13:59:18
In this case, I find the code more helpful than th
| |
369 '''); | |
370 | |
359 expect( | 371 expect( |
360 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | 372 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), |
361 new InterfaceType(d, [int, double])), | 373 new InterfaceType(d, [int, double])), |
362 new InterfaceType(d, [int, double])); | 374 new InterfaceType(d, [int, double])); |
363 expect( | 375 expect( |
364 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | 376 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), |
365 new InterfaceType(d, [int, bool])), | 377 new InterfaceType(d, [int, bool])), |
366 new InterfaceType(b, [int])); | 378 new InterfaceType(b, [int])); |
367 expect( | 379 expect( |
368 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | 380 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), |
369 new InterfaceType(d, [bool, double])), | 381 new InterfaceType(d, [bool, double])), |
370 new InterfaceType(c, [double])); | 382 new InterfaceType(c, [double])); |
371 expect( | 383 expect( |
372 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | 384 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), |
373 new InterfaceType(d, [bool, int])), | 385 new InterfaceType(d, [bool, int])), |
374 a.rawType); | 386 a.rawType); |
375 expect(hierarchy.getClassicLeastUpperBound(e.rawType, f.rawType), | 387 expect(hierarchy.getClassicLeastUpperBound(e.rawType, f.rawType), |
376 new InterfaceType(b, [int])); | 388 new InterfaceType(b, [int])); |
377 } | 389 } |
378 | 390 |
379 void test_getClassicLeastUpperBound_nonGeneric() { | 391 void test_getClassicLeastUpperBound_nonGeneric() { |
380 // Create the class hierarchy: | |
381 // | |
382 // Object | |
383 // / \ | |
384 // A B | |
385 // /|\ | |
386 // C D E | |
387 // |X|/ | |
388 // FG HI | |
389 // | |
390 // (F and G both implement (C, D); H and I both implement (C, D, E). | |
391 var a = addImplementsClass('A', []); | 392 var a = addImplementsClass('A', []); |
392 var b = addImplementsClass('B', []); | 393 var b = addImplementsClass('B', []); |
393 var c = addImplementsClass('C', [a]); | 394 var c = addImplementsClass('C', [a]); |
394 var d = addImplementsClass('D', [a]); | 395 var d = addImplementsClass('D', [a]); |
395 var e = addImplementsClass('E', [a]); | 396 var e = addImplementsClass('E', [a]); |
396 var f = addImplementsClass('F', [c, d]); | 397 var f = addImplementsClass('F', [c, d]); |
397 var g = addImplementsClass('G', [c, d]); | 398 var g = addImplementsClass('G', [c, d]); |
398 var h = addImplementsClass('H', [c, d, e]); | 399 var h = addImplementsClass('H', [c, d, e]); |
399 var i = addImplementsClass('I', [c, d, e]); | 400 var i = addImplementsClass('I', [c, d, e]); |
400 var hierarchy = new ClassHierarchy(program); | 401 |
402 _assertTestLibraryText(''' | |
403 class A {} | |
404 class B {} | |
405 class C implements self::A {} | |
406 class D implements self::A {} | |
407 class E implements self::A {} | |
408 class F implements self::C, self::D {} | |
409 class G implements self::C, self::D {} | |
410 class H implements self::C, self::D, self::E {} | |
411 class I implements self::C, self::D, self::E {} | |
412 '''); | |
401 | 413 |
402 expect(hierarchy.getClassicLeastUpperBound(a.rawType, b.rawType), | 414 expect(hierarchy.getClassicLeastUpperBound(a.rawType, b.rawType), |
403 objectClass.rawType); | 415 objectClass.rawType); |
404 expect(hierarchy.getClassicLeastUpperBound(a.rawType, objectClass.rawType), | 416 expect(hierarchy.getClassicLeastUpperBound(a.rawType, objectClass.rawType), |
405 objectClass.rawType); | 417 objectClass.rawType); |
406 expect(hierarchy.getClassicLeastUpperBound(objectClass.rawType, b.rawType), | 418 expect(hierarchy.getClassicLeastUpperBound(objectClass.rawType, b.rawType), |
407 objectClass.rawType); | 419 objectClass.rawType); |
408 expect( | 420 expect( |
409 hierarchy.getClassicLeastUpperBound(c.rawType, d.rawType), a.rawType); | 421 hierarchy.getClassicLeastUpperBound(c.rawType, d.rawType), a.rawType); |
410 expect( | 422 expect( |
411 hierarchy.getClassicLeastUpperBound(c.rawType, a.rawType), a.rawType); | 423 hierarchy.getClassicLeastUpperBound(c.rawType, a.rawType), a.rawType); |
412 expect( | 424 expect( |
413 hierarchy.getClassicLeastUpperBound(a.rawType, d.rawType), a.rawType); | 425 hierarchy.getClassicLeastUpperBound(a.rawType, d.rawType), a.rawType); |
414 expect( | 426 expect( |
415 hierarchy.getClassicLeastUpperBound(f.rawType, g.rawType), a.rawType); | 427 hierarchy.getClassicLeastUpperBound(f.rawType, g.rawType), a.rawType); |
416 expect( | 428 expect( |
417 hierarchy.getClassicLeastUpperBound(h.rawType, i.rawType), a.rawType); | 429 hierarchy.getClassicLeastUpperBound(h.rawType, i.rawType), a.rawType); |
418 } | 430 } |
419 | 431 |
420 void test_getDispatchTarget() { | 432 void test_getDispatchTarget() { |
421 // Create the class hierarchy: | |
422 // | |
423 // class A extends Object { | |
424 // aMethod() {} | |
425 // void set aSetter(_) {} | |
426 // } | |
427 // class B extends A { | |
428 // bMethod() {} | |
429 // void set bSetter(_) {} | |
430 // } | |
431 // class C extends B {} | |
432 var aMethod = newEmptyMethod('aMethod'); | 433 var aMethod = newEmptyMethod('aMethod'); |
433 var aSetter = newEmptySetter('aSetter'); | 434 var aSetter = newEmptySetter('aSetter'); |
434 var bMethod = newEmptyMethod('bMethod'); | 435 var bMethod = newEmptyMethod('bMethod'); |
435 var bSetter = newEmptySetter('bSetter'); | 436 var bSetter = newEmptySetter('bSetter'); |
436 var a = addClass(new Class( | 437 var a = addClass(new Class( |
437 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); | 438 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); |
438 var b = addClass(new Class( | 439 var b = addClass(new Class( |
439 name: 'B', | 440 name: 'B', |
440 supertype: a.asThisSupertype, | 441 supertype: a.asThisSupertype, |
441 procedures: [bMethod, bSetter])); | 442 procedures: [bMethod, bSetter])); |
442 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | 443 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); |
443 | 444 |
445 _assertTestLibraryText(''' | |
446 class A { | |
447 method aMethod() → void {} | |
448 set aSetter(dynamic _) → void {} | |
449 } | |
450 class B extends self::A { | |
451 method bMethod() → void {} | |
452 set bSetter(dynamic _) → void {} | |
453 } | |
454 class C extends self::B {} | |
455 '''); | |
456 | |
444 var aMethodName = new Name('aMethod'); | 457 var aMethodName = new Name('aMethod'); |
445 var aSetterName = new Name('aSetter'); | 458 var aSetterName = new Name('aSetter'); |
446 var bMethodName = new Name('bMethod'); | 459 var bMethodName = new Name('bMethod'); |
447 var bSetterName = new Name('bSetter'); | 460 var bSetterName = new Name('bSetter'); |
448 expect(hierarchy.getDispatchTarget(a, aMethodName), aMethod); | 461 expect(hierarchy.getDispatchTarget(a, aMethodName), aMethod); |
449 expect(hierarchy.getDispatchTarget(a, bMethodName), isNull); | 462 expect(hierarchy.getDispatchTarget(a, bMethodName), isNull); |
450 expect(hierarchy.getDispatchTarget(a, aSetterName, setter: true), aSetter); | 463 expect(hierarchy.getDispatchTarget(a, aSetterName, setter: true), aSetter); |
451 expect(hierarchy.getDispatchTarget(a, bSetterName, setter: true), isNull); | 464 expect(hierarchy.getDispatchTarget(a, bSetterName, setter: true), isNull); |
452 expect(hierarchy.getDispatchTarget(b, aMethodName), aMethod); | 465 expect(hierarchy.getDispatchTarget(b, aMethodName), aMethod); |
453 expect(hierarchy.getDispatchTarget(b, bMethodName), bMethod); | 466 expect(hierarchy.getDispatchTarget(b, bMethodName), bMethod); |
454 expect(hierarchy.getDispatchTarget(b, aSetterName, setter: true), aSetter); | 467 expect(hierarchy.getDispatchTarget(b, aSetterName, setter: true), aSetter); |
455 expect(hierarchy.getDispatchTarget(b, bSetterName, setter: true), bSetter); | 468 expect(hierarchy.getDispatchTarget(b, bSetterName, setter: true), bSetter); |
456 expect(hierarchy.getDispatchTarget(c, aMethodName), aMethod); | 469 expect(hierarchy.getDispatchTarget(c, aMethodName), aMethod); |
457 expect(hierarchy.getDispatchTarget(c, bMethodName), bMethod); | 470 expect(hierarchy.getDispatchTarget(c, bMethodName), bMethod); |
458 expect(hierarchy.getDispatchTarget(c, aSetterName, setter: true), aSetter); | 471 expect(hierarchy.getDispatchTarget(c, aSetterName, setter: true), aSetter); |
459 expect(hierarchy.getDispatchTarget(c, bSetterName, setter: true), bSetter); | 472 expect(hierarchy.getDispatchTarget(c, bSetterName, setter: true), bSetter); |
460 } | 473 } |
461 | 474 |
462 void test_getDispatchTarget_abstract() { | 475 void test_getDispatchTarget_abstract() { |
463 // Create the class hierarchy: | |
464 // | |
465 // abstract class A extends Object { | |
466 // aMethodAbstract(); | |
467 // aMethodConcrete() {} | |
468 // } | |
469 // abstract class B extends A { | |
470 // aMethodConcrete(); | |
471 // bMethodAbstract(); | |
472 // bMethodConcrete() {} | |
473 // } | |
474 // class C extends B {} | |
475 var aMethodConcrete = newEmptyMethod('aMethodConcrete'); | 476 var aMethodConcrete = newEmptyMethod('aMethodConcrete'); |
476 var bMethodConcrete = newEmptyMethod('aMethodConcrete'); | 477 var bMethodConcrete = newEmptyMethod('aMethodConcrete'); |
477 var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [ | 478 var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [ |
478 newEmptyMethod('aMethodAbstract', abstract: true), | 479 newEmptyMethod('aMethodAbstract', abstract: true), |
479 aMethodConcrete | 480 aMethodConcrete |
480 ])); | 481 ])); |
481 var b = addClass( | 482 var b = addClass( |
482 new Class(name: 'B', supertype: a.asThisSupertype, procedures: [ | 483 new Class(name: 'B', supertype: a.asThisSupertype, procedures: [ |
483 newEmptyMethod('aMethodConcrete', abstract: true), | 484 newEmptyMethod('aMethodConcrete', abstract: true), |
484 newEmptyMethod('bMethodAbstract', abstract: true), | 485 newEmptyMethod('bMethodAbstract', abstract: true), |
485 bMethodConcrete | 486 bMethodConcrete |
486 ])); | 487 ])); |
487 addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | 488 addClass(new Class(name: 'C', supertype: b.asThisSupertype)); |
488 | 489 |
490 _assertTestLibraryText(''' | |
491 class A { | |
492 method aMethodAbstract() → void; | |
493 method aMethodConcrete() → void {} | |
494 } | |
495 class B extends self::A { | |
496 method aMethodConcrete() → void; | |
497 method bMethodAbstract() → void; | |
498 method aMethodConcrete() → void {} | |
499 } | |
500 class C extends self::B {} | |
501 '''); | |
502 | |
489 expect(hierarchy.getDispatchTarget(a, new Name('aMethodConcrete')), | 503 expect(hierarchy.getDispatchTarget(a, new Name('aMethodConcrete')), |
490 aMethodConcrete); | 504 aMethodConcrete); |
491 // TODO(scheglov): The next two commented statements verify the behavior | 505 // TODO(scheglov): The next two commented statements verify the behavior |
492 // documented as "If the class is abstract, abstract members are ignored and | 506 // documented as "If the class is abstract, abstract members are ignored and |
493 // the dispatch is resolved if the class was not abstract.". Unfortunately | 507 // the dispatch is resolved if the class was not abstract.". Unfortunately |
494 // the implementation does not follow the documentation. We need to fix | 508 // the implementation does not follow the documentation. We need to fix |
495 // either documentation, or implementation. | 509 // either documentation, or implementation. |
496 // expect(hierarchy.getDispatchTarget(c, new Name('aMethodConcrete')), | 510 // expect(hierarchy.getDispatchTarget(c, new Name('aMethodConcrete')), |
497 // aMethodConcrete); | 511 // aMethodConcrete); |
498 // expect(hierarchy.getDispatchTarget(b, new Name('aMethodConcrete')), | 512 // expect(hierarchy.getDispatchTarget(b, new Name('aMethodConcrete')), |
499 // aMethodConcrete); | 513 // aMethodConcrete); |
500 } | 514 } |
501 | 515 |
502 void test_getInterfaceMember_extends() { | 516 void test_getInterfaceMember_extends() { |
503 // Create the class hierarchy: | |
504 // | |
505 // class A extends Object { | |
506 // aMethod() {} | |
507 // void set aSetter(_) {} | |
508 // } | |
509 // class B extends A { | |
510 // bMethod() {} | |
511 // void set bSetter(_) {} | |
512 // } | |
513 // class C extends B {} | |
514 var aMethod = newEmptyMethod('aMethod'); | 517 var aMethod = newEmptyMethod('aMethod'); |
515 var aSetter = newEmptySetter('aSetter'); | 518 var aSetter = newEmptySetter('aSetter'); |
516 var bMethod = newEmptyMethod('bMethod'); | 519 var bMethod = newEmptyMethod('bMethod'); |
517 var bSetter = newEmptySetter('bSetter'); | 520 var bSetter = newEmptySetter('bSetter'); |
518 var a = addClass(new Class( | 521 var a = addClass(new Class( |
519 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); | 522 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); |
520 var b = addClass(new Class( | 523 var b = addClass(new Class( |
521 name: 'B', | 524 name: 'B', |
522 supertype: a.asThisSupertype, | 525 supertype: a.asThisSupertype, |
523 procedures: [bMethod, bSetter])); | 526 procedures: [bMethod, bSetter])); |
524 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | 527 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); |
525 | 528 |
529 _assertTestLibraryText(''' | |
530 class A { | |
531 method aMethod() → void {} | |
532 set aSetter(dynamic _) → void {} | |
533 } | |
534 class B extends self::A { | |
535 method bMethod() → void {} | |
536 set bSetter(dynamic _) → void {} | |
537 } | |
538 class C extends self::B {} | |
539 '''); | |
540 | |
526 var aMethodName = new Name('aMethod'); | 541 var aMethodName = new Name('aMethod'); |
527 var aSetterName = new Name('aSetter'); | 542 var aSetterName = new Name('aSetter'); |
528 var bMethodName = new Name('bMethod'); | 543 var bMethodName = new Name('bMethod'); |
529 var bSetterName = new Name('bSetter'); | 544 var bSetterName = new Name('bSetter'); |
530 expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod); | 545 expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod); |
531 expect(hierarchy.getInterfaceMember(a, bMethodName), isNull); | 546 expect(hierarchy.getInterfaceMember(a, bMethodName), isNull); |
532 expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter); | 547 expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter); |
533 expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull); | 548 expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull); |
534 expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod); | 549 expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod); |
535 expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod); | 550 expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod); |
536 expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter); | 551 expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter); |
537 expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter); | 552 expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter); |
538 expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod); | 553 expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod); |
539 expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod); | 554 expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod); |
540 expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter); | 555 expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter); |
541 expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter); | 556 expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter); |
542 } | 557 } |
543 | 558 |
544 void test_getInterfaceMember_implements() { | 559 void test_getInterfaceMember_implements() { |
545 // Create the class hierarchy: | |
546 // | |
547 // class A extends Object { | |
548 // aMethod() {} | |
549 // void set aSetter(_) {} | |
550 // } | |
551 // class B extends Object implements A { | |
552 // bMethod() {} | |
553 // void set bSetter(_) {} | |
554 // } | |
555 // class C extends Object implements B {} | |
556 var aMethod = newEmptyMethod('aMethod'); | 560 var aMethod = newEmptyMethod('aMethod'); |
557 var aSetter = newEmptySetter('aSetter'); | 561 var aSetter = newEmptySetter('aSetter'); |
558 var bMethod = newEmptyMethod('bMethod'); | 562 var bMethod = newEmptyMethod('bMethod'); |
559 var bSetter = newEmptySetter('bSetter'); | 563 var bSetter = newEmptySetter('bSetter'); |
560 var a = addClass(new Class( | 564 var a = addClass(new Class( |
561 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); | 565 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); |
562 var b = addClass(new Class( | 566 var b = addClass(new Class( |
563 name: 'B', | 567 name: 'B', |
564 supertype: objectSuper, | 568 supertype: objectSuper, |
565 implementedTypes: [a.asThisSupertype], | 569 implementedTypes: [a.asThisSupertype], |
566 procedures: [bMethod, bSetter])); | 570 procedures: [bMethod, bSetter])); |
567 var c = addClass(new Class( | 571 var c = addClass(new Class( |
568 name: 'C', | 572 name: 'C', |
569 supertype: objectSuper, | 573 supertype: objectSuper, |
570 implementedTypes: [b.asThisSupertype])); | 574 implementedTypes: [b.asThisSupertype])); |
571 | 575 |
576 _assertTestLibraryText(''' | |
577 class A { | |
578 method aMethod() → void {} | |
579 set aSetter(dynamic _) → void {} | |
580 } | |
581 class B implements self::A { | |
582 method bMethod() → void {} | |
583 set bSetter(dynamic _) → void {} | |
584 } | |
585 class C implements self::B {} | |
586 '''); | |
587 | |
572 var aMethodName = new Name('aMethod'); | 588 var aMethodName = new Name('aMethod'); |
573 var aSetterName = new Name('aSetter'); | 589 var aSetterName = new Name('aSetter'); |
574 var bMethodName = new Name('bMethod'); | 590 var bMethodName = new Name('bMethod'); |
575 var bSetterName = new Name('bSetter'); | 591 var bSetterName = new Name('bSetter'); |
576 expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod); | 592 expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod); |
577 expect(hierarchy.getInterfaceMember(a, bMethodName), isNull); | 593 expect(hierarchy.getInterfaceMember(a, bMethodName), isNull); |
578 expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter); | 594 expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter); |
579 expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull); | 595 expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull); |
580 expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod); | 596 expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod); |
581 expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod); | 597 expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod); |
582 expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter); | 598 expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter); |
583 expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter); | 599 expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter); |
584 expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod); | 600 expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod); |
585 expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod); | 601 expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod); |
586 expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter); | 602 expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter); |
587 expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter); | 603 expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter); |
588 } | 604 } |
589 | 605 |
590 void test_getRankedSuperclasses() { | 606 void test_getRankedSuperclasses() { |
591 // Create the class hierarchy: | |
592 // | |
593 // Object | |
594 // | | |
595 // A | |
596 // / \ | |
597 // B C | |
598 // | | | |
599 // | D | |
600 // \ / | |
601 // E | |
602 var a = addImplementsClass('A', []); | 607 var a = addImplementsClass('A', []); |
603 var b = addImplementsClass('B', [a]); | 608 var b = addImplementsClass('B', [a]); |
604 var c = addImplementsClass('C', [a]); | 609 var c = addImplementsClass('C', [a]); |
605 var d = addImplementsClass('D', [c]); | 610 var d = addImplementsClass('D', [c]); |
606 var e = addImplementsClass('E', [b, d]); | 611 var e = addImplementsClass('E', [b, d]); |
607 | 612 |
613 _assertTestLibraryText(''' | |
614 class A {} | |
615 class B implements self::A {} | |
616 class C implements self::A {} | |
617 class D implements self::C {} | |
618 class E implements self::B, self::D {} | |
619 '''); | |
620 | |
608 expect(hierarchy.getRankedSuperclasses(a), [a, objectClass]); | 621 expect(hierarchy.getRankedSuperclasses(a), [a, objectClass]); |
609 expect(hierarchy.getRankedSuperclasses(b), [b, a, objectClass]); | 622 expect(hierarchy.getRankedSuperclasses(b), [b, a, objectClass]); |
610 expect(hierarchy.getRankedSuperclasses(c), [c, a, objectClass]); | 623 expect(hierarchy.getRankedSuperclasses(c), [c, a, objectClass]); |
611 expect(hierarchy.getRankedSuperclasses(d), [d, c, a, objectClass]); | 624 expect(hierarchy.getRankedSuperclasses(d), [d, c, a, objectClass]); |
612 if (hierarchy.getClassIndex(b) < hierarchy.getClassIndex(c)) { | 625 if (hierarchy.getClassIndex(b) < hierarchy.getClassIndex(c)) { |
613 expect(hierarchy.getRankedSuperclasses(e), [e, d, b, c, a, objectClass]); | 626 expect(hierarchy.getRankedSuperclasses(e), [e, d, b, c, a, objectClass]); |
614 } else { | 627 } else { |
615 expect(hierarchy.getRankedSuperclasses(e), [e, d, c, b, a, objectClass]); | 628 expect(hierarchy.getRankedSuperclasses(e), [e, d, c, b, a, objectClass]); |
616 } | 629 } |
617 } | 630 } |
618 | 631 |
619 void test_getTypeAsInstanceOf_generic_extends() { | 632 void test_getTypeAsInstanceOf_generic_extends() { |
620 // Create the class hierarchy: | |
621 // | |
622 // class A<T, U> extends Object {} | |
623 // class B<T> extends A<T, bool> {} | |
624 var int = coreTypes.intClass.rawType; | 633 var int = coreTypes.intClass.rawType; |
625 var bool = coreTypes.boolClass.rawType; | 634 var bool = coreTypes.boolClass.rawType; |
626 | 635 |
627 var a = addGenericClass('A', ['T', 'U']); | 636 var a = addGenericClass('A', ['T', 'U']); |
628 | 637 |
629 var bT = new TypeParameter('T', objectClass.rawType); | 638 var bT = new TypeParameter('T', objectClass.rawType); |
630 var bTT = new TypeParameterType(bT); | 639 var bTT = new TypeParameterType(bT); |
631 var b = addClass(new Class( | 640 var b = addClass(new Class( |
632 name: 'B', | 641 name: 'B', |
633 typeParameters: [bT], | 642 typeParameters: [bT], |
634 supertype: new Supertype(a, [bTT, bool]))); | 643 supertype: new Supertype(a, [bTT, bool]))); |
635 | 644 |
645 _assertTestLibraryText(''' | |
646 class A<T, U> {} | |
647 class B<T> extends self::A<self::B::T, core::bool> {} | |
648 '''); | |
649 | |
636 var b_int = new InterfaceType(b, [int]); | 650 var b_int = new InterfaceType(b, [int]); |
637 expect(hierarchy.getTypeAsInstanceOf(b_int, a), | 651 expect(hierarchy.getTypeAsInstanceOf(b_int, a), |
638 new InterfaceType(a, [int, bool])); | 652 new InterfaceType(a, [int, bool])); |
639 expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass), | 653 expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass), |
640 new InterfaceType(objectClass)); | 654 new InterfaceType(objectClass)); |
641 } | 655 } |
642 | 656 |
643 void test_rootClass() { | 657 void test_rootClass() { |
644 addClass(new Class(name: 'A', supertype: objectSuper)); | 658 addClass(new Class(name: 'A', supertype: objectSuper)); |
645 expect(hierarchy.rootClass, objectClass); | 659 expect(hierarchy.rootClass, objectClass); |
646 } | 660 } |
647 | 661 |
648 void _assertOverridePairs(Class class_, List<String> expected) { | 662 void _assertOverridePairs(Class class_, List<String> expected) { |
649 List<String> overrideDescriptions = []; | 663 List<String> overrideDescriptions = []; |
650 hierarchy.forEachOverridePair(class_, | 664 hierarchy.forEachOverridePair(class_, |
651 (Member declaredMember, Member interfaceMember, bool isSetter) { | 665 (Member declaredMember, Member interfaceMember, bool isSetter) { |
652 var desc = '$declaredMember overrides $interfaceMember'; | 666 var desc = '$declaredMember overrides $interfaceMember'; |
653 overrideDescriptions.add(desc); | 667 overrideDescriptions.add(desc); |
654 }); | 668 }); |
655 expect(overrideDescriptions, unorderedEquals(expected)); | 669 expect(overrideDescriptions, unorderedEquals(expected)); |
656 } | 670 } |
671 | |
672 /// Assert that the test [library] has the [expectedText] presentation. | |
673 /// The presentation is close, but not identical to the normal Kernel one. | |
674 void _assertTestLibraryText(String expectedText) { | |
675 StringBuffer sb = new StringBuffer(); | |
676 Printer printer = new Printer(sb); | |
677 printer.writeLibraryFile(library); | |
678 | |
679 String actualText = sb.toString(); | |
680 | |
681 // Clean up the text a bit. | |
682 const oftenUsedPrefix = ''' | |
683 library test; | |
684 import self as self; | |
685 import "dart:core" as core; | |
686 | |
687 '''; | |
688 if (actualText.startsWith(oftenUsedPrefix)) { | |
689 actualText = actualText.substring(oftenUsedPrefix.length); | |
690 } | |
691 actualText = actualText.replaceAll('{\n}', '{}'); | |
692 actualText = actualText.replaceAll(' extends core::Object', ''); | |
693 | |
694 // if (actualText != expectedText) { | |
695 // print('-------- Actual --------'); | |
696 // print(actualText + '------------------------'); | |
697 // } | |
698 | |
699 expect(actualText, expectedText); | |
700 } | |
657 } | 701 } |
OLD | NEW |