| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.test.message_kind_helper; | 5 library dart2js.test.message_kind_helper; |
| 6 | 6 |
| 7 import 'package:expect/expect.dart'; | 7 import 'package:expect/expect.dart'; |
| 8 import 'dart:async'; | 8 import 'dart:async'; |
| 9 | 9 |
| 10 import 'package:compiler/src/commandline_options.dart'; | 10 import 'package:compiler/src/commandline_options.dart'; |
| 11 import 'package:compiler/src/compiler.dart' show | 11 import 'package:compiler/src/compiler.dart' show Compiler; |
| 12 Compiler; | 12 import 'package:compiler/src/diagnostics/messages.dart' |
| 13 import 'package:compiler/src/diagnostics/messages.dart' show | 13 show MessageKind, MessageTemplate; |
| 14 MessageKind, | 14 import 'package:compiler/compiler_new.dart' show Diagnostic; |
| 15 MessageTemplate; | |
| 16 import 'package:compiler/compiler_new.dart' show | |
| 17 Diagnostic; | |
| 18 | 15 |
| 19 import 'memory_compiler.dart'; | 16 import 'memory_compiler.dart'; |
| 20 | 17 |
| 21 const String ESCAPE_REGEXP = r'[[\]{}()*+?.\\^$|]'; | 18 const String ESCAPE_REGEXP = r'[[\]{}()*+?.\\^$|]'; |
| 22 | 19 |
| 23 /// Most examples generate a single diagnostic. | 20 /// Most examples generate a single diagnostic. |
| 24 /// Add an exception here if a single diagnostic cannot be produced. | 21 /// Add an exception here if a single diagnostic cannot be produced. |
| 25 /// However, consider that a single concise diagnostic is easier to understand, | 22 /// However, consider that a single concise diagnostic is easier to understand, |
| 26 /// so try to change error reporting logic before adding an exception. | 23 /// so try to change error reporting logic before adding an exception. |
| 27 final Set<MessageKind> kindsWithExtraMessages = new Set<MessageKind>.from([ | 24 final Set<MessageKind> kindsWithExtraMessages = new Set<MessageKind>.from([ |
| 28 // If you add something here, please file a *new* bug report. | 25 // If you add something here, please file a *new* bug report. |
| 29 // See http://dartbug.com/18361: | 26 // See http://dartbug.com/18361: |
| 30 MessageKind.CANNOT_EXTEND_MALFORMED, | 27 MessageKind.CANNOT_EXTEND_MALFORMED, |
| 31 MessageKind.CANNOT_IMPLEMENT_MALFORMED, | 28 MessageKind.CANNOT_IMPLEMENT_MALFORMED, |
| 32 MessageKind.CANNOT_MIXIN, | 29 MessageKind.CANNOT_MIXIN, |
| 33 MessageKind.CANNOT_MIXIN_MALFORMED, | 30 MessageKind.CANNOT_MIXIN_MALFORMED, |
| 34 MessageKind.CANNOT_INSTANTIATE_ENUM, | 31 MessageKind.CANNOT_INSTANTIATE_ENUM, |
| 35 MessageKind.CYCLIC_TYPEDEF_ONE, | 32 MessageKind.CYCLIC_TYPEDEF_ONE, |
| 36 MessageKind.DUPLICATE_DEFINITION, | 33 MessageKind.DUPLICATE_DEFINITION, |
| 37 MessageKind.EQUAL_MAP_ENTRY_KEY, | 34 MessageKind.EQUAL_MAP_ENTRY_KEY, |
| 38 MessageKind.FINAL_FUNCTION_TYPE_PARAMETER, | 35 MessageKind.FINAL_FUNCTION_TYPE_PARAMETER, |
| 39 MessageKind.FORMAL_DECLARED_CONST, | 36 MessageKind.FORMAL_DECLARED_CONST, |
| 40 MessageKind.FORMAL_DECLARED_STATIC, | 37 MessageKind.FORMAL_DECLARED_STATIC, |
| 41 MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT, | 38 MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT, |
| 42 MessageKind.HIDDEN_IMPLICIT_IMPORT, | 39 MessageKind.HIDDEN_IMPLICIT_IMPORT, |
| 43 MessageKind.HIDDEN_IMPORT, | 40 MessageKind.HIDDEN_IMPORT, |
| 44 MessageKind.INHERIT_GETTER_AND_METHOD, | 41 MessageKind.INHERIT_GETTER_AND_METHOD, |
| 45 MessageKind.UNIMPLEMENTED_METHOD, | 42 MessageKind.UNIMPLEMENTED_METHOD, |
| 46 MessageKind.UNIMPLEMENTED_METHOD_ONE, | 43 MessageKind.UNIMPLEMENTED_METHOD_ONE, |
| 47 MessageKind.VAR_FUNCTION_TYPE_PARAMETER, | 44 MessageKind.VAR_FUNCTION_TYPE_PARAMETER, |
| 48 ]); | 45 ]); |
| 49 | 46 |
| 50 /// Most messages can be tested without causing a fatal error. Add an exception | 47 /// Most messages can be tested without causing a fatal error. Add an exception |
| 51 /// here if a fatal error is unavoidable and leads to pending classes. | 48 /// here if a fatal error is unavoidable and leads to pending classes. |
| 52 /// Try to avoid adding exceptions here; a fatal error causes the compiler to | 49 /// Try to avoid adding exceptions here; a fatal error causes the compiler to |
| 53 /// stop before analyzing all input, and it isn't safe to reuse it. | 50 /// stop before analyzing all input, and it isn't safe to reuse it. |
| 54 final Set<MessageKind> kindsWithPendingClasses = new Set<MessageKind>.from([ | 51 final Set<MessageKind> kindsWithPendingClasses = new Set<MessageKind>.from([ |
| 55 // If you add something here, please file a *new* bug report. | 52 // If you add something here, please file a *new* bug report. |
| 56 ]); | 53 ]); |
| 57 | 54 |
| 58 Future<Compiler> check(MessageTemplate template, Compiler cachedCompiler) { | 55 Future<Compiler> check(MessageTemplate template, Compiler cachedCompiler) { |
| 59 Expect.isFalse(template.examples.isEmpty); | 56 Expect.isFalse(template.examples.isEmpty); |
| 60 | 57 |
| 61 return Future.forEach(template.examples, (example) { | 58 return Future.forEach(template.examples, (example) { |
| 62 if (example is String) { | 59 if (example is String) { |
| 63 example = {'main.dart': example}; | 60 example = {'main.dart': example}; |
| 64 } else { | 61 } else { |
| 65 Expect.isTrue(example is Map, | 62 Expect.isTrue( |
| 66 "Example must be either a String or a Map."); | 63 example is Map, "Example must be either a String or a Map."); |
| 67 Expect.isTrue(example.containsKey('main.dart'), | 64 Expect.isTrue(example.containsKey('main.dart'), |
| 68 "Example map must contain a 'main.dart' entry."); | 65 "Example map must contain a 'main.dart' entry."); |
| 69 } | 66 } |
| 70 DiagnosticCollector collector = new DiagnosticCollector(); | 67 DiagnosticCollector collector = new DiagnosticCollector(); |
| 71 | 68 |
| 72 Compiler compiler = compilerFor( | 69 Compiler compiler = compilerFor( |
| 73 memorySourceFiles: example, | 70 memorySourceFiles: example, |
| 74 diagnosticHandler: collector, | 71 diagnosticHandler: collector, |
| 75 options: [Flags.analyzeOnly, | 72 options: [Flags.analyzeOnly, Flags.enableExperimentalMirrors] |
| 76 Flags.enableExperimentalMirrors]..addAll(template.options), | 73 ..addAll(template.options), |
| 77 cachedCompiler: cachedCompiler); | 74 cachedCompiler: cachedCompiler); |
| 78 | 75 |
| 79 return compiler.run(Uri.parse('memory:main.dart')).then((_) { | 76 return compiler.run(Uri.parse('memory:main.dart')).then((_) { |
| 80 Iterable<CollectedMessage> messages = collector.filterMessagesByKinds( | 77 Iterable<CollectedMessage> messages = collector.filterMessagesByKinds([ |
| 81 [Diagnostic.ERROR, | 78 Diagnostic.ERROR, |
| 82 Diagnostic.WARNING, | 79 Diagnostic.WARNING, |
| 83 Diagnostic.HINT, | 80 Diagnostic.HINT, |
| 84 Diagnostic.CRASH]); | 81 Diagnostic.CRASH |
| 82 ]); |
| 85 | 83 |
| 86 Expect.isFalse(messages.isEmpty, 'No messages in """$example"""'); | 84 Expect.isFalse(messages.isEmpty, 'No messages in """$example"""'); |
| 87 | 85 |
| 88 String expectedText = !template.hasHowToFix | 86 String expectedText = !template.hasHowToFix |
| 89 ? template.template : '${template.template}\n${template.howToFix}'; | 87 ? template.template |
| 88 : '${template.template}\n${template.howToFix}'; |
| 90 String pattern = expectedText.replaceAllMapped( | 89 String pattern = expectedText.replaceAllMapped( |
| 91 new RegExp(ESCAPE_REGEXP), (m) => '\\${m[0]}'); | 90 new RegExp(ESCAPE_REGEXP), (m) => '\\${m[0]}'); |
| 92 pattern = pattern.replaceAll(new RegExp(r'#\\\{[^}]*\\\}'), '.*'); | 91 pattern = pattern.replaceAll(new RegExp(r'#\\\{[^}]*\\\}'), '.*'); |
| 93 | 92 |
| 94 bool checkMessage(CollectedMessage message) { | 93 bool checkMessage(CollectedMessage message) { |
| 95 if (message.message.kind != MessageKind.GENERIC) { | 94 if (message.message.kind != MessageKind.GENERIC) { |
| 96 return message.message.kind == template.kind; | 95 return message.message.kind == template.kind; |
| 97 } else { | 96 } else { |
| 98 return new RegExp('^$pattern\$').hasMatch(message.text); | 97 return new RegExp('^$pattern\$').hasMatch(message.text); |
| 99 } | 98 } |
| 100 } | 99 } |
| 101 | 100 |
| 102 // TODO(johnniwinther): Extend MessageKind to contain information on | 101 // TODO(johnniwinther): Extend MessageKind to contain information on |
| 103 // where info messages are expected. | 102 // where info messages are expected. |
| 104 bool messageFound = false; | 103 bool messageFound = false; |
| 105 List unexpectedMessages = []; | 104 List unexpectedMessages = []; |
| 106 for (CollectedMessage message in messages) { | 105 for (CollectedMessage message in messages) { |
| 107 if (!messageFound && checkMessage(message)) { | 106 if (!messageFound && checkMessage(message)) { |
| 108 messageFound = true; | 107 messageFound = true; |
| 109 } else { | 108 } else { |
| 110 unexpectedMessages.add(message); | 109 unexpectedMessages.add(message); |
| 111 } | 110 } |
| 112 } | 111 } |
| 113 Expect.isTrue(messageFound, | 112 Expect.isTrue( |
| 113 messageFound, |
| 114 '${template.kind}} does not match any in\n ' | 114 '${template.kind}} does not match any in\n ' |
| 115 '${messages.join('\n ')}'); | 115 '${messages.join('\n ')}'); |
| 116 var reporter = compiler.reporter; | 116 var reporter = compiler.reporter; |
| 117 Expect.isFalse(reporter.hasCrashed); | 117 Expect.isFalse(reporter.hasCrashed); |
| 118 if (!unexpectedMessages.isEmpty) { | 118 if (!unexpectedMessages.isEmpty) { |
| 119 for (CollectedMessage message in unexpectedMessages) { | 119 for (CollectedMessage message in unexpectedMessages) { |
| 120 print("Unexpected message: $message"); | 120 print("Unexpected message: $message"); |
| 121 } | 121 } |
| 122 if (!kindsWithExtraMessages.contains(template.kind)) { | 122 if (!kindsWithExtraMessages.contains(template.kind)) { |
| 123 // Try changing the error reporting logic before adding an exception | 123 // Try changing the error reporting logic before adding an exception |
| 124 // to [kindsWithExtraMessages]. | 124 // to [kindsWithExtraMessages]. |
| 125 throw 'Unexpected messages found.'; | 125 throw 'Unexpected messages found.'; |
| 126 } | 126 } |
| 127 } | 127 } |
| 128 | 128 |
| 129 bool pendingStuff = false; | 129 bool pendingStuff = false; |
| 130 for (var e in compiler.resolver.pendingClassesToBePostProcessed) { | 130 for (var e in compiler.resolver.pendingClassesToBePostProcessed) { |
| 131 pendingStuff = true; | 131 pendingStuff = true; |
| 132 compiler.reporter.reportInfo( | 132 compiler.reporter.reportInfo(e, MessageKind.GENERIC, |
| 133 e, MessageKind.GENERIC, | |
| 134 {'text': 'Pending class to be post-processed.'}); | 133 {'text': 'Pending class to be post-processed.'}); |
| 135 } | 134 } |
| 136 for (var e in compiler.resolver.pendingClassesToBeResolved) { | 135 for (var e in compiler.resolver.pendingClassesToBeResolved) { |
| 137 pendingStuff = true; | 136 pendingStuff = true; |
| 138 compiler.reporter.reportInfo( | 137 compiler.reporter.reportInfo( |
| 139 e, MessageKind.GENERIC, | 138 e, MessageKind.GENERIC, {'text': 'Pending class to be resolved.'}); |
| 140 {'text': 'Pending class to be resolved.'}); | |
| 141 } | 139 } |
| 142 Expect.isTrue(!pendingStuff || | 140 Expect |
| 143 kindsWithPendingClasses.contains(template)); | 141 .isTrue(!pendingStuff || kindsWithPendingClasses.contains(template)); |
| 144 | 142 |
| 145 if (!pendingStuff) { | 143 if (!pendingStuff) { |
| 146 // If there is pending stuff, or the compiler was cancelled, we | 144 // If there is pending stuff, or the compiler was cancelled, we |
| 147 // shouldn't reuse the compiler. | 145 // shouldn't reuse the compiler. |
| 148 cachedCompiler = compiler; | 146 cachedCompiler = compiler; |
| 149 } | 147 } |
| 150 }); | 148 }); |
| 151 }).then((_) => cachedCompiler); | 149 }).then((_) => cachedCompiler); |
| 152 } | 150 } |
| OLD | NEW |