Chromium Code Reviews| 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 |