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/src/incremental_class_hierarchy.dart'; | 8 import 'package:kernel/src/incremental_class_hierarchy.dart'; |
9 import 'package:kernel/testing/mock_sdk_program.dart'; | 9 import 'package:kernel/testing/mock_sdk_program.dart'; |
10 import 'package:kernel/text/ast_to_text.dart'; | 10 import 'package:kernel/text/ast_to_text.dart'; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 /// [implements_] the given classes. | 122 /// [implements_] the given classes. |
123 Class addImplementsClass(String name, List<Class> implements_) { | 123 Class addImplementsClass(String name, List<Class> implements_) { |
124 return addClass(new Class( | 124 return addClass(new Class( |
125 name: name, | 125 name: name, |
126 supertype: objectSuper, | 126 supertype: objectSuper, |
127 implementedTypes: implements_.map((c) => c.asThisSupertype).toList())); | 127 implementedTypes: implements_.map((c) => c.asThisSupertype).toList())); |
128 } | 128 } |
129 | 129 |
130 ClassHierarchy createClassHierarchy(Program program); | 130 ClassHierarchy createClassHierarchy(Program program); |
131 | 131 |
| 132 Procedure newEmptyGetter(String name, |
| 133 {DartType returnType: const DynamicType()}) { |
| 134 var body = new Block([new ReturnStatement(new NullLiteral())]); |
| 135 return new Procedure(new Name(name), ProcedureKind.Getter, |
| 136 new FunctionNode(body, returnType: returnType)); |
| 137 } |
| 138 |
132 Procedure newEmptyMethod(String name, {bool isAbstract: false}) { | 139 Procedure newEmptyMethod(String name, {bool isAbstract: false}) { |
133 var body = isAbstract ? null : new Block([]); | 140 var body = isAbstract ? null : new Block([]); |
134 return new Procedure(new Name(name), ProcedureKind.Method, | 141 return new Procedure(new Name(name), ProcedureKind.Method, |
135 new FunctionNode(body, returnType: const VoidType()), | 142 new FunctionNode(body, returnType: const VoidType()), |
136 isAbstract: isAbstract); | 143 isAbstract: isAbstract); |
137 } | 144 } |
138 | 145 |
139 Procedure newEmptySetter(String name, {bool abstract: false}) { | 146 Procedure newEmptySetter(String name, |
| 147 {bool abstract: false, DartType type: const DynamicType()}) { |
140 var body = abstract ? null : new Block([]); | 148 var body = abstract ? null : new Block([]); |
141 return new Procedure( | 149 return new Procedure( |
142 new Name(name), | 150 new Name(name), |
143 ProcedureKind.Setter, | 151 ProcedureKind.Setter, |
144 new FunctionNode(body, | 152 new FunctionNode(body, |
145 returnType: const VoidType(), | 153 returnType: const VoidType(), |
146 positionalParameters: [new VariableDeclaration('_')])); | 154 positionalParameters: [new VariableDeclaration('_', type: type)])); |
147 } | 155 } |
148 | 156 |
149 void setUp() { | 157 void setUp() { |
150 // Start with mock SDK libraries. | 158 // Start with mock SDK libraries. |
151 program = createMockSdkProgram(); | 159 program = createMockSdkProgram(); |
152 coreTypes = new CoreTypes(program); | 160 coreTypes = new CoreTypes(program); |
153 | 161 |
154 // Add the test library. | 162 // Add the test library. |
155 library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test'); | 163 library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test'); |
156 library.parent = program; | 164 library.parent = program; |
157 program.libraries.add(library); | 165 program.libraries.add(library); |
158 } | 166 } |
159 | 167 |
| 168 void test_forEachOverridePair_crossGetterSetter_extends() { |
| 169 var int = coreTypes.intClass.rawType; |
| 170 var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [ |
| 171 newEmptySetter('foo', type: int), |
| 172 newEmptyGetter('bar', returnType: int) |
| 173 ])); |
| 174 var b = addClass(new Class( |
| 175 name: 'B', |
| 176 supertype: a.asThisSupertype, |
| 177 procedures: [newEmptyGetter('foo'), newEmptySetter('bar')])); |
| 178 |
| 179 _assertTestLibraryText(''' |
| 180 class A { |
| 181 set foo(core::int _) → void {} |
| 182 get bar() → core::int { |
| 183 return null; |
| 184 } |
| 185 } |
| 186 class B extends self::A { |
| 187 get foo() → dynamic { |
| 188 return null; |
| 189 } |
| 190 set bar(dynamic _) → void {} |
| 191 } |
| 192 '''); |
| 193 |
| 194 // No overrides of getters with getters, or setters with setters. |
| 195 _assertOverridePairs(b, []); |
| 196 |
| 197 // Has cross-overrides between getters and setters. |
| 198 _assertOverridePairs( |
| 199 b, |
| 200 [ |
| 201 'test::B::foo overrides test::A::foo=', |
| 202 'test::B::bar= overrides test::A::bar' |
| 203 ], |
| 204 crossGettersSetters: true); |
| 205 } |
| 206 |
| 207 void test_forEachOverridePair_crossGetterSetter_implements() { |
| 208 var int = coreTypes.intClass.rawType; |
| 209 var double = coreTypes.doubleClass.rawType; |
| 210 var a = addClass(new Class(name: 'A', supertype: objectSuper, procedures: [ |
| 211 newEmptySetter('foo', type: int), |
| 212 ])); |
| 213 var b = addClass(new Class(name: 'B', supertype: objectSuper, procedures: [ |
| 214 newEmptySetter('foo', type: double), |
| 215 ])); |
| 216 var c = addClass(new Class( |
| 217 name: 'C', |
| 218 supertype: objectSuper, |
| 219 implementedTypes: [a.asThisSupertype, b.asThisSupertype], |
| 220 procedures: [newEmptyGetter('foo')])); |
| 221 |
| 222 _assertTestLibraryText(''' |
| 223 class A { |
| 224 set foo(core::int _) → void {} |
| 225 } |
| 226 class B { |
| 227 set foo(core::double _) → void {} |
| 228 } |
| 229 class C implements self::A, self::B { |
| 230 get foo() → dynamic { |
| 231 return null; |
| 232 } |
| 233 } |
| 234 '''); |
| 235 |
| 236 // No overrides of getters with getters, or setters with setters. |
| 237 _assertOverridePairs(c, []); |
| 238 |
| 239 // Has cross-overrides between getters and setters. |
| 240 // Even if these overrides are incompatible with each other. |
| 241 _assertOverridePairs( |
| 242 c, |
| 243 [ |
| 244 'test::C::foo overrides test::A::foo=', |
| 245 'test::C::foo overrides test::B::foo=', |
| 246 ], |
| 247 crossGettersSetters: true); |
| 248 } |
| 249 |
160 /// 2. A non-abstract member is inherited from a superclass, and in the | 250 /// 2. A non-abstract member is inherited from a superclass, and in the |
161 /// context of this class, it overrides an abstract member inheritable through | 251 /// context of this class, it overrides an abstract member inheritable through |
162 /// one of its superinterfaces. | 252 /// one of its superinterfaces. |
163 void test_forEachOverridePair_supertypeOverridesInterface() { | 253 void test_forEachOverridePair_supertypeOverridesInterface() { |
164 var a = addClass(new Class( | 254 var a = addClass(new Class( |
165 name: 'A', | 255 name: 'A', |
166 supertype: objectSuper, | 256 supertype: objectSuper, |
167 procedures: [newEmptyMethod('foo'), newEmptyMethod('bar')])); | 257 procedures: [newEmptyMethod('foo'), newEmptyMethod('bar')])); |
168 var b = addClass(new Class( | 258 var b = addClass(new Class( |
169 name: 'B', | 259 name: 'B', |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 class B<T> extends self::A<self::B::T, core::bool> {} | 985 class B<T> extends self::A<self::B::T, core::bool> {} |
896 '''); | 986 '''); |
897 | 987 |
898 var b_int = new InterfaceType(b, [int]); | 988 var b_int = new InterfaceType(b, [int]); |
899 expect(hierarchy.getTypeAsInstanceOf(b_int, a), | 989 expect(hierarchy.getTypeAsInstanceOf(b_int, a), |
900 new InterfaceType(a, [int, bool])); | 990 new InterfaceType(a, [int, bool])); |
901 expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass), | 991 expect(hierarchy.getTypeAsInstanceOf(b_int, objectClass), |
902 new InterfaceType(objectClass)); | 992 new InterfaceType(objectClass)); |
903 } | 993 } |
904 | 994 |
905 void _assertOverridePairs(Class class_, List<String> expected) { | 995 void _assertOverridePairs(Class class_, List<String> expected, |
| 996 {bool crossGettersSetters: false}) { |
906 List<String> overrideDescriptions = []; | 997 List<String> overrideDescriptions = []; |
907 hierarchy.forEachOverridePair(class_, | 998 hierarchy.forEachOverridePair(class_, |
908 (Member declaredMember, Member interfaceMember, bool isSetter) { | 999 (Member declaredMember, Member interfaceMember, bool isSetter) { |
909 String declaredName = '$declaredMember${isSetter ? '=': ''}'; | 1000 String declaredSuffix; |
910 String interfaceName = '$interfaceMember${isSetter ? '=': ''}'; | 1001 String interfaceSuffix; |
| 1002 if (crossGettersSetters) { |
| 1003 declaredSuffix = _isSetter(declaredMember) ? '=' : ''; |
| 1004 interfaceSuffix = _isSetter(interfaceMember) ? '=' : ''; |
| 1005 } else { |
| 1006 declaredSuffix = isSetter ? '=' : ''; |
| 1007 interfaceSuffix = isSetter ? '=' : ''; |
| 1008 } |
| 1009 String declaredName = '$declaredMember$declaredSuffix'; |
| 1010 String interfaceName = '$interfaceMember$interfaceSuffix'; |
911 var desc = '$declaredName overrides $interfaceName'; | 1011 var desc = '$declaredName overrides $interfaceName'; |
912 overrideDescriptions.add(desc); | 1012 overrideDescriptions.add(desc); |
913 }); | 1013 }, crossGettersSetters: crossGettersSetters); |
914 expect(overrideDescriptions, unorderedEquals(expected)); | 1014 expect(overrideDescriptions, unorderedEquals(expected)); |
915 } | 1015 } |
916 | 1016 |
917 /// Assert that the test [library] has the [expectedText] presentation. | 1017 /// Assert that the test [library] has the [expectedText] presentation. |
918 /// The presentation is close, but not identical to the normal Kernel one. | 1018 /// The presentation is close, but not identical to the normal Kernel one. |
919 void _assertTestLibraryText(String expectedText) { | 1019 void _assertTestLibraryText(String expectedText) { |
920 StringBuffer sb = new StringBuffer(); | 1020 StringBuffer sb = new StringBuffer(); |
921 Printer printer = new Printer(sb); | 1021 Printer printer = new Printer(sb); |
922 printer.writeLibraryFile(library); | 1022 printer.writeLibraryFile(library); |
923 | 1023 |
924 String actualText = sb.toString(); | 1024 String actualText = sb.toString(); |
925 | 1025 |
926 // Clean up the text a bit. | 1026 // Clean up the text a bit. |
927 const oftenUsedPrefix = ''' | 1027 const oftenUsedPrefix = ''' |
928 library test; | 1028 library test; |
929 import self as self; | 1029 import self as self; |
930 import "dart:core" as core; | 1030 import "dart:core" as core; |
931 | 1031 |
932 '''; | 1032 '''; |
933 if (actualText.startsWith(oftenUsedPrefix)) { | 1033 if (actualText.startsWith(oftenUsedPrefix)) { |
934 actualText = actualText.substring(oftenUsedPrefix.length); | 1034 actualText = actualText.substring(oftenUsedPrefix.length); |
935 } | 1035 } |
936 actualText = actualText.replaceAll('{\n}', '{}'); | 1036 actualText = actualText.replaceAll('{\n}', '{}'); |
937 actualText = actualText.replaceAll(' extends core::Object', ''); | 1037 actualText = actualText.replaceAll(' extends core::Object', ''); |
938 | 1038 |
939 // if (actualText != expectedText) { | 1039 if (actualText != expectedText) { |
940 // print('-------- Actual --------'); | 1040 print('-------- Actual --------'); |
941 // print(actualText + '------------------------'); | 1041 print(actualText + '------------------------'); |
942 // } | 1042 } |
943 | 1043 |
944 expect(actualText, expectedText); | 1044 expect(actualText, expectedText); |
945 } | 1045 } |
| 1046 |
| 1047 static bool _isSetter(Member member) { |
| 1048 return member is Procedure && member.kind == ProcedureKind.Setter; |
| 1049 } |
946 } | 1050 } |
OLD | NEW |