OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dart2js.semantics_visitor_test; | 5 library dart2js.semantics_visitor_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:mirrors'; | 8 import 'dart:mirrors'; |
9 import 'package:async_helper/async_helper.dart'; | 9 import 'package:async_helper/async_helper.dart'; |
10 import 'package:expect/expect.dart'; | 10 import 'package:expect/expect.dart'; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 sb.writeln(code); | 161 sb.writeln(code); |
162 if (codeByPrefix != null) { | 162 if (codeByPrefix != null) { |
163 sb.writeln('imported by prefix:'); | 163 sb.writeln('imported by prefix:'); |
164 sb.writeln(codeByPrefix); | 164 sb.writeln(codeByPrefix); |
165 } | 165 } |
166 return sb.toString(); | 166 return sb.toString(); |
167 } | 167 } |
168 } | 168 } |
169 | 169 |
170 const List<VisitKind> UNTESTABLE_KINDS = const <VisitKind>[ | 170 const List<VisitKind> UNTESTABLE_KINDS = const <VisitKind>[ |
| 171 // A final field shadowing a non-final field is currently not supported in |
| 172 // resolution. |
| 173 VisitKind.VISIT_SUPER_FIELD_FIELD_COMPOUND, |
| 174 VisitKind.VISIT_SUPER_FIELD_FIELD_PREFIX, |
| 175 VisitKind.VISIT_SUPER_FIELD_FIELD_POSTFIX, |
| 176 // Combination of method and setter with the same name is currently not |
| 177 // supported by the element model. |
171 VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND, | 178 VisitKind.VISIT_STATIC_METHOD_SETTER_COMPOUND, |
172 VisitKind.VISIT_STATIC_METHOD_SETTER_PREFIX, | 179 VisitKind.VISIT_STATIC_METHOD_SETTER_PREFIX, |
173 VisitKind.VISIT_STATIC_METHOD_SETTER_POSTFIX, | 180 VisitKind.VISIT_STATIC_METHOD_SETTER_POSTFIX, |
174 VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_COMPOUND, | 181 VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_COMPOUND, |
175 VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_PREFIX, | 182 VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_PREFIX, |
176 VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_POSTFIX, | 183 VisitKind.VISIT_TOP_LEVEL_METHOD_SETTER_POSTFIX, |
177 VisitKind.VISIT_SUPER_FIELD_FIELD_COMPOUND, | |
178 VisitKind.VISIT_SUPER_FIELD_FIELD_PREFIX, | |
179 VisitKind.VISIT_SUPER_FIELD_FIELD_POSTFIX, | |
180 VisitKind.VISIT_SUPER_METHOD_SETTER_COMPOUND, | 184 VisitKind.VISIT_SUPER_METHOD_SETTER_COMPOUND, |
181 VisitKind.VISIT_SUPER_METHOD_SETTER_PREFIX, | 185 VisitKind.VISIT_SUPER_METHOD_SETTER_PREFIX, |
182 VisitKind.VISIT_SUPER_METHOD_SETTER_POSTFIX, | 186 VisitKind.VISIT_SUPER_METHOD_SETTER_POSTFIX, |
| 187 // Invalid use of setters is currently reported through an erroneous element. |
| 188 VisitKind.VISIT_STATIC_SETTER_INVOKE, |
| 189 VisitKind.VISIT_STATIC_SETTER_GET, |
| 190 VisitKind.VISIT_TOP_LEVEL_SETTER_GET, |
| 191 VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE, |
| 192 // The constant expressions of assignment to constant type literals cannot be |
| 193 // handled the compile constant evaluator. |
183 VisitKind.VISIT_CLASS_TYPE_LITERAL_SET, | 194 VisitKind.VISIT_CLASS_TYPE_LITERAL_SET, |
184 VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_SET, | 195 VisitKind.VISIT_TYPEDEF_TYPE_LITERAL_SET, |
| 196 VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_SET, |
| 197 // Invalid assignments is currently report through an erroneous element. |
185 VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_SET, | 198 VisitKind.VISIT_TYPE_VARIABLE_TYPE_LITERAL_SET, |
186 VisitKind.VISIT_DYNAMIC_TYPE_LITERAL_SET, | |
187 VisitKind.VISIT_FINAL_PARAMETER_SET, | 199 VisitKind.VISIT_FINAL_PARAMETER_SET, |
188 VisitKind.VISIT_FINAL_LOCAL_VARIABLE_SET, | 200 VisitKind.VISIT_FINAL_LOCAL_VARIABLE_SET, |
189 VisitKind.VISIT_LOCAL_FUNCTION_SET, | 201 VisitKind.VISIT_LOCAL_FUNCTION_SET, |
190 VisitKind.VISIT_STATIC_GETTER_SET, | 202 VisitKind.VISIT_STATIC_GETTER_SET, |
191 VisitKind.VISIT_STATIC_SETTER_GET, | |
192 VisitKind.VISIT_STATIC_SETTER_INVOKE, | |
193 VisitKind.VISIT_FINAL_STATIC_FIELD_SET, | 203 VisitKind.VISIT_FINAL_STATIC_FIELD_SET, |
194 VisitKind.VISIT_STATIC_FUNCTION_SET, | 204 VisitKind.VISIT_STATIC_FUNCTION_SET, |
195 VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET, | 205 VisitKind.VISIT_FINAL_TOP_LEVEL_FIELD_SET, |
196 VisitKind.VISIT_TOP_LEVEL_GETTER_SET, | 206 VisitKind.VISIT_TOP_LEVEL_GETTER_SET, |
197 VisitKind.VISIT_TOP_LEVEL_SETTER_GET, | |
198 VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE, | |
199 VisitKind.VISIT_TOP_LEVEL_FUNCTION_SET, | 207 VisitKind.VISIT_TOP_LEVEL_FUNCTION_SET, |
200 VisitKind.VISIT_FINAL_SUPER_FIELD_SET, | 208 VisitKind.VISIT_FINAL_SUPER_FIELD_SET, |
201 VisitKind.VISIT_SUPER_GETTER_SET, | 209 VisitKind.VISIT_SUPER_GETTER_SET, |
202 VisitKind.VISIT_SUPER_METHOD_SET, | 210 VisitKind.VISIT_SUPER_METHOD_SET, |
| 211 // The only undefined unary, `+`, is currently handled and skipped in the |
| 212 // parser. |
| 213 VisitKind.ERROR_UNDEFINED_UNARY_EXPRESSION, |
| 214 // Constant expression are currently not computed during resolution. |
| 215 VisitKind.VISIT_CONSTANT_GET, |
| 216 VisitKind.VISIT_CONSTANT_INVOKE, |
203 ]; | 217 ]; |
204 | 218 |
205 main(List<String> arguments) { | 219 main(List<String> arguments) { |
206 Set<VisitKind> kinds = new Set<VisitKind>.from(VisitKind.values); | 220 Set<VisitKind> kinds = new Set<VisitKind>.from(VisitKind.values); |
207 asyncTest(() => Future.forEach([ | 221 asyncTest(() => Future.forEach([ |
208 () { | 222 () { |
209 return test( | 223 return test( |
210 kinds, | 224 kinds, |
211 arguments, | 225 arguments, |
212 SEND_TESTS, | 226 SEND_TESTS, |
(...skipping 25 matching lines...) Expand all Loading... |
238 ClassMirror mirror1 = reflectType(SemanticSendTestVisitor); | 252 ClassMirror mirror1 = reflectType(SemanticSendTestVisitor); |
239 Set<Symbol> symbols1 = mirror1.declarations.keys.toSet(); | 253 Set<Symbol> symbols1 = mirror1.declarations.keys.toSet(); |
240 ClassMirror mirror2 = reflectType(SemanticSendVisitor); | 254 ClassMirror mirror2 = reflectType(SemanticSendVisitor); |
241 Set<Symbol> symbols2 = | 255 Set<Symbol> symbols2 = |
242 mirror2.declarations.values | 256 mirror2.declarations.values |
243 .where((m) => m is MethodMirror && | 257 .where((m) => m is MethodMirror && |
244 !m.isConstructor && | 258 !m.isConstructor && |
245 m.simpleName != #apply) | 259 m.simpleName != #apply) |
246 .map((m) => m.simpleName).toSet(); | 260 .map((m) => m.simpleName).toSet(); |
247 symbols2.removeAll(symbols1); | 261 symbols2.removeAll(symbols1); |
248 print("Untested visit methods:\n ${symbols2.join(',\n ')},\n"); | 262 Expect.isTrue(symbols2.isEmpty, |
| 263 "Untested visit methods:\n ${symbols2.join(',\n ')},\n"); |
249 } | 264 } |
250 ], (f) => f())); | 265 ], (f) => f())); |
251 } | 266 } |
252 | 267 |
253 Future test(Set<VisitKind> unvisitedKinds, | 268 Future test(Set<VisitKind> unvisitedKinds, |
254 List<String> arguments, | 269 List<String> arguments, |
255 Map<String, List<Test>> TESTS, | 270 Map<String, List<Test>> TESTS, |
256 SemanticTestVisitor createVisitor(TreeElements elements)) { | 271 SemanticTestVisitor createVisitor(TreeElements elements)) { |
257 Map<String, String> sourceFiles = {}; | 272 Map<String, String> sourceFiles = {}; |
258 Map<String, Test> testMap = {}; | 273 Map<String, Test> testMap = {}; |
(...skipping 15 matching lines...) Expand all Loading... |
274 sourceFiles[filename] = testSource.toString(); | 289 sourceFiles[filename] = testSource.toString(); |
275 mainSource.writeln("import '$filename';"); | 290 mainSource.writeln("import '$filename';"); |
276 testMap[filename] = test; | 291 testMap[filename] = test; |
277 index++; | 292 index++; |
278 }); | 293 }); |
279 }); | 294 }); |
280 mainSource.writeln("main() {}"); | 295 mainSource.writeln("main() {}"); |
281 sourceFiles['main.dart'] = mainSource.toString(); | 296 sourceFiles['main.dart'] = mainSource.toString(); |
282 | 297 |
283 Compiler compiler = compilerFor(sourceFiles, | 298 Compiler compiler = compilerFor(sourceFiles, |
284 options: ['--analyze-all', '--analyze-only']); | 299 options: ['--analyze-all', |
| 300 '--analyze-only', |
| 301 '--enable-null-aware-operators']); |
285 return compiler.run(Uri.parse('memory:main.dart')).then((_) { | 302 return compiler.run(Uri.parse('memory:main.dart')).then((_) { |
286 testMap.forEach((String filename, Test test) { | 303 testMap.forEach((String filename, Test test) { |
287 LibraryElement library = compiler.libraryLoader.lookupLibrary( | 304 LibraryElement library = compiler.libraryLoader.lookupLibrary( |
288 Uri.parse('memory:$filename')); | 305 Uri.parse('memory:$filename')); |
289 var expectedVisits = test.expectedVisits; | |
290 if (expectedVisits is! List) { | |
291 expectedVisits = [expectedVisits]; | |
292 } | |
293 Element element; | 306 Element element; |
294 String cls = test.cls; | 307 String cls = test.cls; |
295 String method = test.method; | 308 String method = test.method; |
296 if (cls == null) { | 309 if (cls == null) { |
297 element = library.find(method); | 310 element = library.find(method); |
298 } else { | 311 } else { |
299 ClassElement classElement = library.find(cls); | 312 ClassElement classElement = library.find(cls); |
300 Expect.isNotNull(classElement, | 313 Expect.isNotNull(classElement, |
301 "Class '$cls' not found in:\n" | 314 "Class '$cls' not found in:\n" |
302 "${library.compilationUnit.script.text}"); | 315 "${library.compilationUnit.script.text}"); |
303 element = classElement.localLookup(method); | 316 element = classElement.localLookup(method); |
304 } | 317 } |
| 318 var expectedVisits = test.expectedVisits; |
| 319 if (expectedVisits == null) { |
| 320 Expect.isTrue(element.isErroneous, |
| 321 "Element '$method' expected to be have parse errors in:\n" |
| 322 "${library.compilationUnit.script.text}"); |
| 323 return; |
| 324 } else if (expectedVisits is! List) { |
| 325 expectedVisits = [expectedVisits]; |
| 326 } |
| 327 Expect.isFalse(element.isErroneous, |
| 328 "Element '$method' is not expected to be have parse errors in:\n" |
| 329 "${library.compilationUnit.script.text}"); |
305 | 330 |
306 void testAstElement(AstElement astElement) { | 331 void testAstElement(AstElement astElement) { |
307 Expect.isNotNull(astElement, "Element '$method' not found in:\n" | 332 Expect.isNotNull(astElement, "Element '$method' not found in:\n" |
308 "${library.compilationUnit.script.text}"); | 333 "${library.compilationUnit.script.text}"); |
309 ResolvedAst resolvedAst = astElement.resolvedAst; | 334 ResolvedAst resolvedAst = astElement.resolvedAst; |
310 SemanticTestVisitor visitor = createVisitor(resolvedAst.elements); | 335 SemanticTestVisitor visitor = createVisitor(resolvedAst.elements); |
311 try { | 336 try { |
312 compiler.withCurrentElement(resolvedAst.element, () { | 337 compiler.withCurrentElement(resolvedAst.element, () { |
313 //print(resolvedAst.node.toDebugString()); | 338 //print(resolvedAst.node.toDebugString()); |
314 resolvedAst.node.accept(visitor); | 339 resolvedAst.node.accept(visitor); |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 VISIT_OPTIONAL_PARAMETER_DECL, | 684 VISIT_OPTIONAL_PARAMETER_DECL, |
660 VISIT_NAMED_PARAMETER_DECL, | 685 VISIT_NAMED_PARAMETER_DECL, |
661 VISIT_REQUIRED_INITIALIZING_FORMAL_DECL, | 686 VISIT_REQUIRED_INITIALIZING_FORMAL_DECL, |
662 VISIT_OPTIONAL_INITIALIZING_FORMAL_DECL, | 687 VISIT_OPTIONAL_INITIALIZING_FORMAL_DECL, |
663 VISIT_NAMED_INITIALIZING_FORMAL_DECL, | 688 VISIT_NAMED_INITIALIZING_FORMAL_DECL, |
664 | 689 |
665 VISIT_UNRESOLVED_COMPOUND, | 690 VISIT_UNRESOLVED_COMPOUND, |
666 VISIT_UNRESOLVED_PREFIX, | 691 VISIT_UNRESOLVED_PREFIX, |
667 VISIT_UNRESOLVED_POSTFIX, | 692 VISIT_UNRESOLVED_POSTFIX, |
668 | 693 |
669 // TODO(johnniwinther): Add tests for more error cases. | 694 VISIT_IF_NULL, |
| 695 VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_GET, |
| 696 VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_SET, |
| 697 VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_INVOKE, |
| 698 VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_COMPOUND, |
| 699 VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_PREFIX, |
| 700 VISIT_IF_NOT_NULL_DYNAMIC_PROPERTY_POSTFIX, |
| 701 |
| 702 ERROR_INVALID_ASSERT, |
| 703 ERROR_UNDEFINED_UNARY_EXPRESSION, |
| 704 ERROR_UNDEFINED_BINARY_EXPRESSION, |
| 705 |
| 706 VISIT_CONSTANT_GET, |
| 707 VISIT_CONSTANT_INVOKE, |
670 } | 708 } |
OLD | NEW |