| 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 |