|
3 | 3 | // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
|
5 | 5 | import 'package:front_end/src/api_prototype/compiler_options.dart' |
6 | | - show CompilerOptions; |
| 6 | + show CompilerOptions, DiagnosticMessage; |
7 | 7 | import 'package:front_end/src/api_prototype/experimental_flags.dart' |
8 | 8 | show ExperimentalFlag; |
9 | | -import 'package:front_end/src/testing/id_extractor.dart' show DataExtractor; |
| 9 | +import 'package:front_end/src/api_prototype/terminal_color_support.dart' |
| 10 | + show printDiagnosticMessage; |
| 11 | +import 'package:front_end/src/fasta/messages.dart' show FormattedMessage; |
| 12 | +import 'package:front_end/src/fasta/severity.dart' show Severity; |
10 | 13 | import 'package:kernel/ast.dart'; |
11 | 14 | import '../kernel_generator_impl.dart' show CompilerResult; |
12 | 15 | import 'compiler_common.dart' show compileScript, toTestUri; |
13 | | -import 'id.dart' show ActualData, ClassId, Id, IdValue, MemberId, NodeId; |
| 16 | +import 'id.dart' |
| 17 | + show ActualData, ClassId, Id, IdKind, IdValue, MemberId, NodeId; |
| 18 | +import 'id_extractor.dart' show DataExtractor; |
14 | 19 | import 'id_testing.dart' |
15 | 20 | show |
16 | 21 | CompiledData, |
@@ -74,6 +79,18 @@ abstract class DataComputer<T> { |
74 | 79 | Map<Id, ActualData<T>> actualMap, |
75 | 80 | {bool verbose}) {} |
76 | 81 |
|
| 82 | + /// Returns `true` if this data computer supports tests with compile-time |
| 83 | + /// errors. |
| 84 | + /// |
| 85 | + /// Unsuccessful compilation might leave the compiler in an inconsistent |
| 86 | + /// state, so this testing feature is opt-in. |
| 87 | + bool get supportsErrors => false; |
| 88 | + |
| 89 | + /// Returns data corresponding to [error]. |
| 90 | + T computeErrorData( |
| 91 | + CompilerResult compiler, Id id, List<FormattedMessage> errors) => |
| 92 | + null; |
| 93 | + |
77 | 94 | /// Returns the [DataInterpreter] used to check the actual data with the |
78 | 95 | /// expected data. |
79 | 96 | DataInterpreter<T> get dataValidator; |
@@ -201,16 +218,54 @@ Future<bool> runTestForConfig<T>( |
201 | 218 | testData.expectedMaps[config.marker]; |
202 | 219 | Iterable<Id> globalIds = memberAnnotations.globalData.keys; |
203 | 220 | CompilerOptions options = new CompilerOptions(); |
| 221 | + List<FormattedMessage> errors = []; |
| 222 | + options.onDiagnostic = (DiagnosticMessage message) { |
| 223 | + if (message is FormattedMessage && message.severity == Severity.error) { |
| 224 | + errors.add(message); |
| 225 | + } |
| 226 | + printDiagnosticMessage(message, print); |
| 227 | + }; |
204 | 228 | options.debugDump = printCode; |
205 | 229 | options.experimentalFlags.addAll(config.experimentalFlags); |
206 | 230 | CompilerResult compilerResult = await compileScript( |
207 | 231 | testData.memorySourceFiles, |
208 | 232 | options: options, |
209 | 233 | retainDataForTesting: true); |
| 234 | + |
210 | 235 | Component component = compilerResult.component; |
211 | 236 | Map<Uri, Map<Id, ActualData<T>>> actualMaps = <Uri, Map<Id, ActualData<T>>>{}; |
212 | 237 | Map<Id, ActualData<T>> globalData = <Id, ActualData<T>>{}; |
213 | 238 |
|
| 239 | + Map<Id, ActualData<T>> actualMapForUri(Uri uri) { |
| 240 | + return actualMaps.putIfAbsent(uri, () => <Id, ActualData<T>>{}); |
| 241 | + } |
| 242 | + |
| 243 | + if (errors.isNotEmpty) { |
| 244 | + if (!dataComputer.supportsErrors) { |
| 245 | + onFailure("Compilation with compile-time errors not supported for this " |
| 246 | + "testing setup."); |
| 247 | + } |
| 248 | + |
| 249 | + Map<Uri, Map<int, List<FormattedMessage>>> errorMap = {}; |
| 250 | + for (FormattedMessage error in errors) { |
| 251 | + Map<int, List<FormattedMessage>> map = |
| 252 | + errorMap.putIfAbsent(error.uri, () => {}); |
| 253 | + List<FormattedMessage> list = map.putIfAbsent(error.charOffset, () => []); |
| 254 | + list.add(error); |
| 255 | + } |
| 256 | + |
| 257 | + errorMap.forEach((Uri uri, Map<int, List<FormattedMessage>> map) { |
| 258 | + map.forEach((int offset, List<DiagnosticMessage> list) { |
| 259 | + NodeId id = new NodeId(offset, IdKind.error); |
| 260 | + T data = dataComputer.computeErrorData(compilerResult, id, list); |
| 261 | + if (data != null) { |
| 262 | + Map<Id, ActualData<T>> actualMap = actualMapForUri(uri); |
| 263 | + actualMap[id] = new ActualData<T>(id, data, uri, offset, list); |
| 264 | + } |
| 265 | + }); |
| 266 | + }); |
| 267 | + } |
| 268 | + |
214 | 269 | Map<Id, ActualData<T>> actualMapFor(TreeNode node) { |
215 | 270 | Uri uri = node is Library ? node.fileUri : node.location.file; |
216 | 271 | return actualMaps.putIfAbsent(uri, () => <Id, ActualData<T>>{}); |
|
0 commit comments