Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'package:kernel/ast.dart'; | |
| 6 import 'package:kernel/class_hierarchy.dart'; | |
| 7 import 'package:kernel/core_types.dart'; | |
| 8 import 'package:kernel/testing/mock_sdk_program.dart'; | |
| 9 import 'package:test/test.dart'; | |
| 10 import 'package:test_reflective_loader/test_reflective_loader.dart'; | |
|
Siggi Cherem (dart-lang)
2017/05/31 00:32:16
Kevin - you may note that there are a lot of struc
Siggi Cherem (dart-lang)
2017/05/31 00:32:16
note: this needs to be added as a dev_dependency i
ahe
2017/05/31 11:23:47
I'm not a big fan of the reflective test suite and
scheglov
2017/05/31 15:43:05
1. Well, I think making it easier to write unit te
| |
| 11 | |
| 12 main() { | |
| 13 defineReflectiveSuite(() { | |
| 14 defineReflectiveTests(ClosedWorldClassHierarchyTest); | |
| 15 }); | |
| 16 } | |
| 17 | |
| 18 @reflectiveTest | |
| 19 class ClosedWorldClassHierarchyTest extends _ClassHierarchyTest { | |
| 20 ClassHierarchy createClassHierarchy(Program program) { | |
| 21 return new ClosedWorldClassHierarchy(program); | |
| 22 } | |
| 23 } | |
| 24 | |
| 25 abstract class _ClassHierarchyTest { | |
| 26 Program program; | |
| 27 CoreTypes coreTypes; | |
| 28 | |
| 29 /// The test library. | |
| 30 Library library; | |
| 31 | |
| 32 ClassHierarchy _hierarchy; | |
| 33 | |
| 34 /// Return the new or existing instance of [ClassHierarchy]. | |
| 35 ClassHierarchy get hierarchy { | |
| 36 return _hierarchy ??= createClassHierarchy(program); | |
| 37 } | |
| 38 | |
| 39 Class get objectClass => coreTypes.objectClass; | |
| 40 | |
| 41 Supertype get objectSuper => coreTypes.objectClass.asThisSupertype; | |
| 42 | |
| 43 Class addClass(Class c) { | |
| 44 if (_hierarchy != null) { | |
| 45 fail('The classs hierarchy has already been created.'); | |
| 46 } | |
| 47 library.addClass(c); | |
| 48 return c; | |
| 49 } | |
| 50 | |
| 51 /// Add a new generic class with the given [name] and [typeParameterNames]. | |
| 52 /// The [TypeParameterType]s corresponding to [typeParameterNames] are | |
| 53 /// passed to optional [extends_] and [implements_] callbacks. | |
| 54 Class addGenericClass(String name, List<String> typeParameterNames, | |
| 55 {Supertype extends_(List<DartType> typeParameterTypes), | |
| 56 List<Supertype> implements_(List<DartType> typeParameterTypes)}) { | |
| 57 var typeParameters = typeParameterNames | |
| 58 .map((name) => new TypeParameter(name, objectClass.rawType)) | |
| 59 .toList(); | |
| 60 var typeParameterTypes = typeParameters | |
| 61 .map((parameter) => new TypeParameterType(parameter)) | |
| 62 .toList(); | |
| 63 var supertype = | |
| 64 extends_ != null ? extends_(typeParameterTypes) : objectSuper; | |
| 65 var implementedTypes = | |
| 66 implements_ != null ? implements_(typeParameterTypes) : []; | |
| 67 return addClass(new Class( | |
| 68 name: name, | |
| 69 typeParameters: typeParameters, | |
| 70 supertype: supertype, | |
| 71 implementedTypes: implementedTypes)); | |
| 72 } | |
| 73 | |
| 74 /// Add a new class with the given [name] that extends `Object` and | |
| 75 /// [implements_] the given classes. | |
| 76 Class addImplementsClass(String name, List<Class> implements_) { | |
| 77 return addClass(new Class( | |
| 78 name: name, | |
| 79 supertype: objectSuper, | |
| 80 implementedTypes: implements_.map((c) => c.asThisSupertype).toList())); | |
| 81 } | |
| 82 | |
| 83 ClassHierarchy createClassHierarchy(Program program); | |
| 84 | |
| 85 Procedure newEmptyMethod(String name, {bool abstract: false}) { | |
| 86 var body = abstract ? null : new Block([]); | |
| 87 return new Procedure( | |
| 88 new Name(name), ProcedureKind.Method, new FunctionNode(body)); | |
| 89 } | |
| 90 | |
| 91 Procedure newEmptySetter(String name) { | |
| 92 return new Procedure( | |
| 93 new Name(name), | |
| 94 ProcedureKind.Setter, | |
| 95 new FunctionNode(new Block([]), | |
| 96 positionalParameters: [new VariableDeclaration('_')])); | |
| 97 } | |
| 98 | |
| 99 void setUp() { | |
| 100 // Start with mock SDK libraries. | |
| 101 program = createMockSdkProgram(); | |
| 102 coreTypes = new CoreTypes(program); | |
| 103 | |
| 104 // Add the test library. | |
| 105 library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test'); | |
| 106 library.parent = program; | |
| 107 program.libraries.add(library); | |
| 108 } | |
| 109 | |
| 110 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'); | |
| 124 var aBar = newEmptyMethod('bar'); | |
| 125 var bFoo = newEmptyMethod('foo'); | |
| 126 var cBar = newEmptyMethod('bar'); | |
| 127 var a = addClass( | |
| 128 new Class(name: 'A', supertype: objectSuper, procedures: [aFoo, aBar])); | |
| 129 var b = addClass( | |
| 130 new Class(name: 'B', supertype: a.asThisSupertype, procedures: [bFoo])); | |
| 131 var c = addClass( | |
| 132 new Class(name: 'C', supertype: b.asThisSupertype, procedures: [cBar])); | |
| 133 | |
| 134 _assertOverridePairs(b, ['test::B::foo overrides test::A::foo']); | |
| 135 _assertOverridePairs(c, ['test::C::bar overrides test::A::bar']); | |
| 136 } | |
| 137 | |
| 138 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; | |
| 145 var bool = coreTypes.boolClass.rawType; | |
| 146 | |
| 147 var a = addGenericClass('A', ['T', 'U']); | |
| 148 | |
| 149 var bT = new TypeParameter('T', objectClass.rawType); | |
| 150 var bTT = new TypeParameterType(bT); | |
| 151 var b = addClass(new Class( | |
| 152 name: 'B', | |
| 153 typeParameters: [bT], | |
| 154 supertype: new Supertype(a, [bTT, bool]))); | |
| 155 | |
| 156 var c = addClass(new Class(name: 'C', supertype: new Supertype(b, [int]))); | |
| 157 | |
| 158 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | |
| 159 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | |
| 160 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); | |
| 161 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); | |
| 162 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); | |
| 163 } | |
| 164 | |
| 165 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; | |
| 172 var bool = coreTypes.boolClass.rawType; | |
| 173 | |
| 174 var a = addGenericClass('A', ['T', 'U']); | |
| 175 | |
| 176 var bT = new TypeParameter('T', objectClass.rawType); | |
| 177 var bTT = new TypeParameterType(bT); | |
| 178 var b = addClass(new Class( | |
| 179 name: 'B', | |
| 180 typeParameters: [bT], | |
| 181 supertype: objectSuper, | |
| 182 implementedTypes: [ | |
| 183 new Supertype(a, [bTT, bool]) | |
| 184 ])); | |
| 185 | |
| 186 var c = addClass( | |
| 187 new Class(name: 'C', supertype: objectSuper, implementedTypes: [ | |
| 188 new Supertype(b, [int]) | |
| 189 ])); | |
| 190 | |
| 191 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | |
| 192 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | |
| 193 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); | |
| 194 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); | |
| 195 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); | |
| 196 } | |
| 197 | |
| 198 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; | |
| 205 var bool = coreTypes.boolClass.rawType; | |
| 206 | |
| 207 var a = addGenericClass('A', ['T', 'U']); | |
| 208 | |
| 209 var bT = new TypeParameter('T', objectClass.rawType); | |
| 210 var bTT = new TypeParameterType(bT); | |
| 211 var b = addClass(new Class( | |
| 212 name: 'B', | |
| 213 typeParameters: [bT], | |
| 214 supertype: objectSuper, | |
| 215 mixedInType: new Supertype(a, [bTT, bool]))); | |
| 216 | |
| 217 var c = addClass(new Class( | |
| 218 name: 'C', | |
| 219 supertype: objectSuper, | |
| 220 mixedInType: new Supertype(b, [int]))); | |
| 221 | |
| 222 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | |
| 223 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | |
| 224 expect(hierarchy.getClassAsInstanceOf(b, a), new Supertype(a, [bTT, bool])); | |
| 225 expect(hierarchy.getClassAsInstanceOf(c, b), new Supertype(b, [int])); | |
| 226 expect(hierarchy.getClassAsInstanceOf(c, a), new Supertype(a, [int, bool])); | |
| 227 } | |
| 228 | |
| 229 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)); | |
| 237 var b = addClass(new Class(name: 'B', supertype: a.asThisSupertype)); | |
| 238 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | |
| 239 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); | |
| 240 | |
| 241 expect(hierarchy.getClassAsInstanceOf(a, objectClass), objectSuper); | |
| 242 expect(hierarchy.getClassAsInstanceOf(a, a), a.asThisSupertype); | |
| 243 expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype); | |
| 244 expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype); | |
| 245 expect(hierarchy.getClassAsInstanceOf(c, b), b.asThisSupertype); | |
| 246 expect(hierarchy.getClassAsInstanceOf(z, a), null); | |
| 247 expect(hierarchy.getClassAsInstanceOf(z, objectClass), objectSuper); | |
| 248 } | |
| 249 | |
| 250 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)); | |
| 260 var b = addClass(new Class(name: 'B', supertype: objectSuper)); | |
| 261 var c = addClass(new Class( | |
| 262 name: 'C', | |
| 263 supertype: objectSuper, | |
| 264 implementedTypes: [a.asThisSupertype])); | |
| 265 var d = addClass(new Class( | |
| 266 name: 'D', | |
| 267 supertype: objectSuper, | |
| 268 implementedTypes: [c.asThisSupertype])); | |
| 269 var e = addClass(new Class( | |
| 270 name: 'D', | |
| 271 supertype: a.asThisSupertype, | |
| 272 implementedTypes: [b.asThisSupertype])); | |
| 273 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); | |
| 274 | |
| 275 expect(hierarchy.getClassAsInstanceOf(c, a), a.asThisSupertype); | |
| 276 expect(hierarchy.getClassAsInstanceOf(d, a), a.asThisSupertype); | |
| 277 expect(hierarchy.getClassAsInstanceOf(d, c), c.asThisSupertype); | |
| 278 expect(hierarchy.getClassAsInstanceOf(e, a), a.asThisSupertype); | |
| 279 expect(hierarchy.getClassAsInstanceOf(e, b), b.asThisSupertype); | |
| 280 expect(hierarchy.getClassAsInstanceOf(z, a), null); | |
| 281 } | |
| 282 | |
| 283 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)); | |
| 290 var b = addClass(new Class( | |
| 291 name: 'B', supertype: objectSuper, mixedInType: a.asThisSupertype)); | |
| 292 var z = addClass(new Class(name: 'Z', supertype: objectSuper)); | |
| 293 | |
| 294 expect(hierarchy.getClassAsInstanceOf(b, objectClass), objectSuper); | |
| 295 expect(hierarchy.getClassAsInstanceOf(b, a), a.asThisSupertype); | |
| 296 expect(hierarchy.getClassAsInstanceOf(z, a), null); | |
| 297 } | |
| 298 | |
| 299 void test_getClassDepth() { | |
| 300 var base = addClass(new Class(name: 'base', supertype: objectSuper)); | |
| 301 var extends_ = | |
| 302 addClass(new Class(name: 'extends_', supertype: base.asThisSupertype)); | |
| 303 var with_ = addClass(new Class( | |
| 304 name: 'with_', | |
| 305 supertype: objectSuper, | |
| 306 mixedInType: base.asThisSupertype)); | |
| 307 var implements_ = addClass(new Class( | |
| 308 name: 'implements_', | |
| 309 supertype: objectSuper, | |
| 310 implementedTypes: [base.asThisSupertype])); | |
| 311 | |
| 312 expect(hierarchy.getClassDepth(objectClass), 0); | |
| 313 expect(hierarchy.getClassDepth(base), 1); | |
| 314 expect(hierarchy.getClassDepth(extends_), 2); | |
| 315 expect(hierarchy.getClassDepth(with_), 2); | |
| 316 expect(hierarchy.getClassDepth(implements_), 2); | |
| 317 } | |
| 318 | |
| 319 void test_getClassicLeastUpperBound_generic() { | |
| 320 var int = coreTypes.intClass.rawType; | |
| 321 var double = coreTypes.doubleClass.rawType; | |
| 322 var bool = coreTypes.boolClass.rawType; | |
| 323 | |
| 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', []); | |
| 338 var b = | |
| 339 addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]); | |
| 340 var c = | |
| 341 addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]); | |
| 342 var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) { | |
| 343 var t = typeParameterTypes[0]; | |
| 344 var u = typeParameterTypes[1]; | |
| 345 return [ | |
| 346 new Supertype(b, [t]), | |
| 347 new Supertype(c, [u]) | |
| 348 ]; | |
| 349 }); | |
| 350 var e = addGenericClass('E', [], | |
| 351 implements_: (_) => [ | |
| 352 new Supertype(d, [int, double]) | |
| 353 ]); | |
| 354 var f = addGenericClass('F', [], | |
| 355 implements_: (_) => [ | |
| 356 new Supertype(d, [int, bool]) | |
| 357 ]); | |
| 358 | |
| 359 expect( | |
| 360 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | |
| 361 new InterfaceType(d, [int, double])), | |
| 362 new InterfaceType(d, [int, double])); | |
| 363 expect( | |
| 364 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | |
| 365 new InterfaceType(d, [int, bool])), | |
| 366 new InterfaceType(b, [int])); | |
| 367 expect( | |
| 368 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | |
| 369 new InterfaceType(d, [bool, double])), | |
| 370 new InterfaceType(c, [double])); | |
| 371 expect( | |
| 372 hierarchy.getClassicLeastUpperBound(new InterfaceType(d, [int, double]), | |
| 373 new InterfaceType(d, [bool, int])), | |
| 374 a.rawType); | |
| 375 expect(hierarchy.getClassicLeastUpperBound(e.rawType, f.rawType), | |
| 376 new InterfaceType(b, [int])); | |
| 377 } | |
| 378 | |
| 379 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 b = addImplementsClass('B', []); | |
| 393 var c = addImplementsClass('C', [a]); | |
| 394 var d = addImplementsClass('D', [a]); | |
| 395 var e = addImplementsClass('E', [a]); | |
| 396 var f = addImplementsClass('F', [c, d]); | |
| 397 var g = addImplementsClass('G', [c, d]); | |
| 398 var h = addImplementsClass('H', [c, d, e]); | |
| 399 var i = addImplementsClass('I', [c, d, e]); | |
| 400 var hierarchy = new ClassHierarchy(program); | |
| 401 | |
| 402 expect(hierarchy.getClassicLeastUpperBound(a.rawType, b.rawType), | |
| 403 objectClass.rawType); | |
| 404 expect(hierarchy.getClassicLeastUpperBound(a.rawType, objectClass.rawType), | |
| 405 objectClass.rawType); | |
| 406 expect(hierarchy.getClassicLeastUpperBound(objectClass.rawType, b.rawType), | |
| 407 objectClass.rawType); | |
| 408 expect( | |
| 409 hierarchy.getClassicLeastUpperBound(c.rawType, d.rawType), a.rawType); | |
| 410 expect( | |
| 411 hierarchy.getClassicLeastUpperBound(c.rawType, a.rawType), a.rawType); | |
| 412 expect( | |
| 413 hierarchy.getClassicLeastUpperBound(a.rawType, d.rawType), a.rawType); | |
| 414 expect( | |
| 415 hierarchy.getClassicLeastUpperBound(f.rawType, g.rawType), a.rawType); | |
| 416 expect( | |
| 417 hierarchy.getClassicLeastUpperBound(h.rawType, i.rawType), a.rawType); | |
| 418 } | |
| 419 | |
| 420 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 aSetter = newEmptySetter('aSetter'); | |
| 434 var bMethod = newEmptyMethod('bMethod'); | |
| 435 var bSetter = newEmptySetter('bSetter'); | |
| 436 var a = addClass(new Class( | |
| 437 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); | |
| 438 var b = addClass(new Class( | |
| 439 name: 'B', | |
| 440 supertype: a.asThisSupertype, | |
| 441 procedures: [bMethod, bSetter])); | |
| 442 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | |
| 443 | |
| 444 var aMethodName = new Name('aMethod'); | |
| 445 var aSetterName = new Name('aSetter'); | |
| 446 var bMethodName = new Name('bMethod'); | |
| 447 var bSetterName = new Name('bSetter'); | |
| 448 expect(hierarchy.getDispatchTarget(a, aMethodName), aMethod); | |
| 449 expect(hierarchy.getDispatchTarget(a, bMethodName), isNull); | |
| 450 expect(hierarchy.getDispatchTarget(a, aSetterName, setter: true), aSetter); | |
| 451 expect(hierarchy.getDispatchTarget(a, bSetterName, setter: true), isNull); | |
| 452 expect(hierarchy.getDispatchTarget(b, aMethodName), aMethod); | |
| 453 expect(hierarchy.getDispatchTarget(b, bMethodName), bMethod); | |
| 454 expect(hierarchy.getDispatchTarget(b, aSetterName, setter: true), aSetter); | |
| 455 expect(hierarchy.getDispatchTarget(b, bSetterName, setter: true), bSetter); | |
| 456 expect(hierarchy.getDispatchTarget(c, aMethodName), aMethod); | |
| 457 expect(hierarchy.getDispatchTarget(c, bMethodName), bMethod); | |
| 458 expect(hierarchy.getDispatchTarget(c, aSetterName, setter: true), aSetter); | |
| 459 expect(hierarchy.getDispatchTarget(c, bSetterName, setter: true), bSetter); | |
| 460 } | |
| 461 | |
| 462 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 bMethodConcrete = newEmptyMethod('aMethodConcrete'); | |
| 477 var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [ | |
| 478 newEmptyMethod('aMethodAbstract', abstract: true), | |
| 479 aMethodConcrete | |
| 480 ])); | |
| 481 var b = addClass( | |
| 482 new Class(name: 'B', supertype: a.asThisSupertype, procedures: [ | |
| 483 newEmptyMethod('aMethodConcrete', abstract: true), | |
| 484 newEmptyMethod('bMethodAbstract', abstract: true), | |
| 485 bMethodConcrete | |
| 486 ])); | |
| 487 addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | |
| 488 | |
| 489 expect(hierarchy.getDispatchTarget(a, new Name('aMethodConcrete')), | |
| 490 aMethodConcrete); | |
| 491 // TODO(scheglov) The next two commented statements verify the behavior | |
| 492 // documented as "If the class is abstract, abstract members are ignored and | |
| 493 // the dispatch is resolved if the class was not abstract.". Unfortunately | |
| 494 // the implementation does not follow the documentation. We need to fix | |
| 495 // either documentation, or implementation. | |
| 496 // expect(hierarchy.getDispatchTarget(c, new Name('aMethodConcrete')), | |
| 497 // aMethodConcrete); | |
| 498 // expect(hierarchy.getDispatchTarget(b, new Name('aMethodConcrete')), | |
| 499 // aMethodConcrete); | |
| 500 } | |
| 501 | |
| 502 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'); | |
| 515 var aSetter = newEmptySetter('aSetter'); | |
| 516 var bMethod = newEmptyMethod('bMethod'); | |
| 517 var bSetter = newEmptySetter('bSetter'); | |
| 518 var a = addClass(new Class( | |
| 519 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); | |
| 520 var b = addClass(new Class( | |
| 521 name: 'B', | |
| 522 supertype: a.asThisSupertype, | |
| 523 procedures: [bMethod, bSetter])); | |
| 524 var c = addClass(new Class(name: 'C', supertype: b.asThisSupertype)); | |
| 525 | |
| 526 var aMethodName = new Name('aMethod'); | |
| 527 var aSetterName = new Name('aSetter'); | |
| 528 var bMethodName = new Name('bMethod'); | |
| 529 var bSetterName = new Name('bSetter'); | |
| 530 expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod); | |
| 531 expect(hierarchy.getInterfaceMember(a, bMethodName), isNull); | |
| 532 expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter); | |
| 533 expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull); | |
| 534 expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod); | |
| 535 expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod); | |
| 536 expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter); | |
| 537 expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter); | |
| 538 expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod); | |
| 539 expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod); | |
| 540 expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter); | |
| 541 expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter); | |
| 542 } | |
| 543 | |
| 544 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'); | |
| 557 var aSetter = newEmptySetter('aSetter'); | |
| 558 var bMethod = newEmptyMethod('bMethod'); | |
| 559 var bSetter = newEmptySetter('bSetter'); | |
| 560 var a = addClass(new Class( | |
| 561 name: 'A', supertype: objectSuper, procedures: [aMethod, aSetter])); | |
| 562 var b = addClass(new Class( | |
| 563 name: 'B', | |
| 564 supertype: objectSuper, | |
| 565 implementedTypes: [a.asThisSupertype], | |
| 566 procedures: [bMethod, bSetter])); | |
| 567 var c = addClass(new Class( | |
| 568 name: 'C', | |
| 569 supertype: objectSuper, | |
| 570 implementedTypes: [b.asThisSupertype])); | |
| 571 | |
| 572 var aMethodName = new Name('aMethod'); | |
| 573 var aSetterName = new Name('aSetter'); | |
| 574 var bMethodName = new Name('bMethod'); | |
| 575 var bSetterName = new Name('bSetter'); | |
| 576 expect(hierarchy.getInterfaceMember(a, aMethodName), aMethod); | |
| 577 expect(hierarchy.getInterfaceMember(a, bMethodName), isNull); | |
| 578 expect(hierarchy.getInterfaceMember(a, aSetterName, setter: true), aSetter); | |
| 579 expect(hierarchy.getInterfaceMember(a, bSetterName, setter: true), isNull); | |
| 580 expect(hierarchy.getInterfaceMember(b, aMethodName), aMethod); | |
| 581 expect(hierarchy.getInterfaceMember(b, bMethodName), bMethod); | |
| 582 expect(hierarchy.getInterfaceMember(b, aSetterName, setter: true), aSetter); | |
| 583 expect(hierarchy.getInterfaceMember(b, bSetterName, setter: true), bSetter); | |
| 584 expect(hierarchy.getInterfaceMember(c, aMethodName), aMethod); | |
| 585 expect(hierarchy.getInterfaceMember(c, bMethodName), bMethod); | |
| 586 expect(hierarchy.getInterfaceMember(c, aSetterName, setter: true), aSetter); | |
| 587 expect(hierarchy.getInterfaceMember(c, bSetterName, setter: true), bSetter); | |
| 588 } | |
| 589 | |
| 590 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', []); | |
| 603 var b = addImplementsClass('B', [a]); | |
| 604 var c = addImplementsClass('C', [a]); | |
| 605 var d = addImplementsClass('D', [c]); | |
| 606 var e = addImplementsClass('E', [b, d]); | |
| 607 | |
| 608 expect(hierarchy.getRankedSuperclasses(a), [a, objectClass]); | |
| 609 expect(hierarchy.getRankedSuperclasses(b), [b, a, objectClass]); | |
| 610 expect(hierarchy.getRankedSuperclasses(c), [c, a, objectClass]); | |
| 611 expect(hierarchy.getRankedSuperclasses(d), [d, c, a, objectClass]); | |
| 612 if (hierarchy.getClassIndex(b) < hierarchy.getClassIndex(c)) { | |
| 613 expect(hierarchy.getRankedSuperclasses(e), [e, d, b, c, a, objectClass]); | |
| 614 } else { | |
| 615 expect(hierarchy.getRankedSuperclasses(e), [e, d, c, b, a, objectClass]); | |
| 616 } | |
| 617 } | |
| 618 | |
| 619 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; | |
| 625 var bool = coreTypes.boolClass.rawType; | |
| 626 | |
| 627 var a = addGenericClass('A', ['T', 'U']); | |
| 628 | |
| 629 var bT = new TypeParameter('T', objectClass.rawType); | |
| 630 var bTT = new TypeParameterType(bT); | |
| 631 var b = addClass(new Class( | |
| 632 name: 'B', | |
| 633 typeParameters: [bT], | |
| 634 supertype: new Supertype(a, [bTT, bool]))); | |
| 635 | |
| 636 var b_int = new InterfaceType(b, [int]); | |
| 637 expect(hierarchy.getTypeAsInstanceOf(b_int, a), | |
| 638 new InterfaceType(a, [int, bool])); | |
| 639 expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass), | |
| 640 new InterfaceType(objectClass)); | |
| 641 } | |
| 642 | |
| 643 void test_rootClass() { | |
| 644 addClass(new Class(name: 'A', supertype: objectSuper)); | |
| 645 expect(hierarchy.rootClass, objectClass); | |
| 646 } | |
| 647 | |
| 648 void _assertOverridePairs(Class class_, List<String> expected) { | |
| 649 List<String> overrideDescriptions = []; | |
| 650 hierarchy.forEachOverridePair(class_, | |
| 651 (Member declaredMember, Member interfaceMember, bool isSetter) { | |
| 652 var desc = '$declaredMember overrides $interfaceMember'; | |
| 653 overrideDescriptions.add(desc); | |
| 654 }); | |
| 655 expect(overrideDescriptions, unorderedEquals(expected)); | |
| 656 } | |
| 657 } | |
| OLD | NEW |