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 'dart:async'; | 5 import 'dart:async'; |
6 | 6 |
7 import 'package:front_end/compilation_error.dart'; | 7 import 'package:front_end/compilation_message.dart'; |
8 import 'package:front_end/compiler_options.dart'; | 8 import 'package:front_end/compiler_options.dart'; |
9 import 'package:front_end/file_system.dart'; | 9 import 'package:front_end/file_system.dart'; |
10 import 'package:front_end/src/base/performace_logger.dart'; | 10 import 'package:front_end/src/base/performace_logger.dart'; |
11 import 'package:front_end/src/fasta/fasta_codes.dart'; | 11 import 'package:front_end/src/fasta/fasta_codes.dart'; |
| 12 import 'package:front_end/src/fasta/problems.dart' show unimplemented; |
| 13 import 'package:front_end/src/fasta/severity.dart'; |
12 import 'package:front_end/src/fasta/ticker.dart'; | 14 import 'package:front_end/src/fasta/ticker.dart'; |
13 import 'package:front_end/src/fasta/uri_translator.dart'; | 15 import 'package:front_end/src/fasta/uri_translator.dart'; |
14 import 'package:front_end/src/fasta/uri_translator_impl.dart'; | 16 import 'package:front_end/src/fasta/uri_translator_impl.dart'; |
15 import 'package:front_end/src/fasta/problems.dart' show unimplemented; | |
16 import 'package:front_end/src/incremental/byte_store.dart'; | 17 import 'package:front_end/src/incremental/byte_store.dart'; |
17 import 'package:front_end/src/multi_root_file_system.dart'; | 18 import 'package:front_end/src/multi_root_file_system.dart'; |
18 import 'package:kernel/kernel.dart' | 19 import 'package:kernel/kernel.dart' |
19 show Program, loadProgramFromBytes, CanonicalName; | 20 show Program, loadProgramFromBytes, CanonicalName; |
20 import 'package:kernel/target/targets.dart'; | 21 import 'package:kernel/target/targets.dart'; |
21 import 'package:kernel/target/vm_fasta.dart'; | 22 import 'package:kernel/target/vm_fasta.dart'; |
22 import 'package:package_config/packages.dart' show Packages; | 23 import 'package:package_config/packages.dart' show Packages; |
23 import 'package:package_config/src/packages_impl.dart' | 24 import 'package:package_config/src/packages_impl.dart' |
24 show NonFilePackagesDirectoryPackages, MapPackages; | 25 show NonFilePackagesDirectoryPackages, MapPackages; |
25 import 'package:package_config/packages_file.dart' as package_config; | 26 import 'package:package_config/packages_file.dart' as package_config; |
26 import 'package:source_span/source_span.dart' show SourceSpan, SourceLocation; | 27 import 'package:source_span/source_span.dart' show SourceSpan, SourceLocation; |
| 28 import 'package:front_end/src/fasta/command_line_reporting.dart' |
| 29 as command_line_reporting; |
27 | 30 |
28 /// All options needed for the front end implementation. | 31 /// All options needed for the front end implementation. |
29 /// | 32 /// |
30 /// This includes: all of [CompilerOptions] in a form useful to the | 33 /// This includes: all of [CompilerOptions] in a form useful to the |
31 /// implementation, default values for options that were not provided, | 34 /// implementation, default values for options that were not provided, |
32 /// and information derived from how the compiler was invoked (like the | 35 /// and information derived from how the compiler was invoked (like the |
33 /// entry-points given to the compiler and whether a modular or whole-program | 36 /// entry-points given to the compiler and whether a modular or whole-program |
34 /// API was used). | 37 /// API was used). |
35 /// | 38 /// |
36 /// The intent is that the front end should immediately wrap any incoming | 39 /// The intent is that the front end should immediately wrap any incoming |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 Ticker ticker; | 84 Ticker ticker; |
82 | 85 |
83 bool get verbose => _raw.verbose; | 86 bool get verbose => _raw.verbose; |
84 | 87 |
85 bool get verify => _raw.verify; | 88 bool get verify => _raw.verify; |
86 | 89 |
87 bool get debugDump => _raw.debugDump; | 90 bool get debugDump => _raw.debugDump; |
88 | 91 |
89 bool get setExitCodeOnProblem => _raw.setExitCodeOnProblem; | 92 bool get setExitCodeOnProblem => _raw.setExitCodeOnProblem; |
90 | 93 |
| 94 bool get embedSourceText => _raw.embedSourceText; |
| 95 |
| 96 bool get throwOnErrors => _raw.throwOnErrors; |
| 97 |
| 98 bool get throwOnWarnings => _raw.throwOnWarnings; |
| 99 |
| 100 bool get throwOnNits => _raw.throwOnNits; |
| 101 |
91 /// Like [CompilerOptions.chaseDependencies] but with the appropriate default | 102 /// Like [CompilerOptions.chaseDependencies] but with the appropriate default |
92 /// value filled in. | 103 /// value filled in. |
93 bool get chaseDependencies => _raw.chaseDependencies ?? !_modularApi; | 104 bool get chaseDependencies => _raw.chaseDependencies ?? !_modularApi; |
94 | 105 |
95 /// Whether the compiler was invoked with a modular API. | 106 /// Whether the compiler was invoked with a modular API. |
96 /// | 107 /// |
97 /// Used to determine the default behavior for [chaseDependencies]. | 108 /// Used to determine the default behavior for [chaseDependencies]. |
98 final bool _modularApi; | 109 final bool _modularApi; |
99 | 110 |
100 /// The entry-points provided to the compiler. | 111 /// The entry-points provided to the compiler. |
101 final List<Uri> inputs; | 112 final List<Uri> inputs; |
102 | 113 |
| 114 /// The Uri where output is generated, may be null. |
| 115 final Uri output; |
| 116 |
103 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. | 117 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. |
104 ProcessedOptions(CompilerOptions rawOptions, | 118 ProcessedOptions(CompilerOptions rawOptions, |
105 [this._modularApi = false, this.inputs = const []]) | 119 [this._modularApi = false, this.inputs = const [], this.output]) |
106 : this._raw = rawOptions, | 120 : this._raw = rawOptions, |
| 121 // TODO(sigmund, ahe): create ticker even earlier or pass in a stopwatch |
| 122 // collecting time since the start of the VM. |
107 ticker = new Ticker(isVerbose: rawOptions.verbose); | 123 ticker = new Ticker(isVerbose: rawOptions.verbose); |
108 | 124 |
109 /// The logger to report compilation progress. | 125 /// The logger to report compilation progress. |
110 PerformanceLog get logger { | 126 PerformanceLog get logger { |
111 return _raw.logger; | 127 return _raw.logger; |
112 } | 128 } |
113 | 129 |
114 /// The byte storage to get and put serialized data. | 130 /// The byte storage to get and put serialized data. |
115 ByteStore get byteStore { | 131 ByteStore get byteStore { |
116 return _raw.byteStore; | 132 return _raw.byteStore; |
117 } | 133 } |
118 | 134 |
119 void reportMessage(LocatedMessage message) { | 135 bool get _reportMessages => _raw.reportMessages ?? (_raw.onError == null); |
120 _raw.onError(new _CompilationMessage(message)); | 136 |
| 137 void report(LocatedMessage message, Severity severity) { |
| 138 if (_raw.onError != null) { |
| 139 _raw.onError(new _CompilationMessage(message, severity)); |
| 140 } |
| 141 |
| 142 if (_reportMessages) command_line_reporting.report(message, severity); |
121 } | 143 } |
122 | 144 |
123 void reportMessageWithoutLocation(Message message) => | 145 void reportWithoutLocation(Message message, Severity severity) { |
124 reportMessage(message.withLocation(null, -1)); | 146 if (_raw.onError != null) { |
| 147 _raw.onError( |
| 148 new _CompilationMessage(message.withLocation(null, -1), severity)); |
| 149 } |
| 150 |
| 151 if (_reportMessages) { |
| 152 command_line_reporting.reportWithoutLocation(message, severity); |
| 153 } |
| 154 } |
125 | 155 |
126 /// Runs various validations checks on the input options. For instance, | 156 /// Runs various validations checks on the input options. For instance, |
127 /// if an option is a path to a file, it checks that the file exists. | 157 /// if an option is a path to a file, it checks that the file exists. |
128 Future<bool> validateOptions() async { | 158 Future<bool> validateOptions() async { |
| 159 if (verbose) print(debugString()); |
| 160 |
129 if (inputs.isEmpty) { | 161 if (inputs.isEmpty) { |
130 reportMessageWithoutLocation(messageMissingInput); | 162 reportWithoutLocation(messageMissingInput, Severity.error); |
131 return false; | 163 return false; |
132 } | 164 } |
133 | 165 |
134 for (var source in inputs) { | 166 for (var source in inputs) { |
135 // Note: we don't translate Uris at this point because some of the | 167 // Note: we don't translate Uris at this point because some of the |
136 // validation further below must be done before we even construct an | 168 // validation further below must be done before we even construct an |
137 // UriTranslator | 169 // UriTranslator |
138 // TODO(sigmund): consider validating dart/packages uri right after we | 170 // TODO(sigmund): consider validating dart/packages uri right after we |
139 // build the uri translator. | 171 // build the uri translator. |
140 if (source.scheme != 'dart' && | 172 if (source.scheme != 'dart' && |
141 source.scheme != 'packages' && | 173 source.scheme != 'packages' && |
142 !await fileSystem.entityForUri(source).exists()) { | 174 !await fileSystem.entityForUri(source).exists()) { |
143 reportMessageWithoutLocation( | 175 reportWithoutLocation( |
144 templateInputFileNotFound.withArguments('$source')); | 176 templateInputFileNotFound.withArguments('$source'), Severity.error); |
145 return false; | 177 return false; |
146 } | 178 } |
147 } | 179 } |
148 | 180 |
149 if (_raw.sdkRoot != null && | 181 if (_raw.sdkRoot != null && |
150 !await fileSystem.entityForUri(sdkRoot).exists()) { | 182 !await fileSystem.entityForUri(sdkRoot).exists()) { |
151 reportMessageWithoutLocation( | 183 reportWithoutLocation( |
152 templateSdkRootNotFound.withArguments('$sdkRoot')); | 184 templateSdkRootNotFound.withArguments('$sdkRoot'), Severity.error); |
153 return false; | 185 return false; |
154 } | 186 } |
155 | 187 |
156 var summary = sdkSummary; | 188 var summary = sdkSummary; |
157 if (summary != null && !await fileSystem.entityForUri(summary).exists()) { | 189 if (summary != null && !await fileSystem.entityForUri(summary).exists()) { |
158 reportMessageWithoutLocation( | 190 reportWithoutLocation( |
159 templateSdkSummaryNotFound.withArguments('$summary')); | 191 templateSdkSummaryNotFound.withArguments('$summary'), Severity.error); |
160 return false; | 192 return false; |
161 } | 193 } |
162 | 194 |
163 if (compileSdk && summary != null) { | 195 if (compileSdk && summary != null) { |
164 reportMessageWithoutLocation( | 196 reportWithoutLocation( |
165 templateInternalProblemUnsupported.withArguments( | 197 templateInternalProblemUnsupported.withArguments( |
166 "The compileSdk and sdkSummary options are mutually exclusive")); | 198 "The compileSdk and sdkSummary options are mutually exclusive"), |
| 199 Severity.internalProblem); |
167 return false; | 200 return false; |
168 } | 201 } |
169 return true; | 202 return true; |
170 } | 203 } |
171 | 204 |
172 /// Determine whether to generate code for the SDK when compiling a | 205 /// Determine whether to generate code for the SDK when compiling a |
173 /// whole-program. | 206 /// whole-program. |
174 bool get compileSdk => _raw.compileSdk; | 207 bool get compileSdk => _raw.compileSdk; |
175 | 208 |
176 FileSystem _fileSystem; | 209 FileSystem _fileSystem; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 Future<Map<String, Uri>> _parseDartLibraries() async { | 289 Future<Map<String, Uri>> _parseDartLibraries() async { |
257 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); | 290 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); |
258 return await computeDartLibraries(fileSystem, librariesJson); | 291 return await computeDartLibraries(fileSystem, librariesJson); |
259 } | 292 } |
260 | 293 |
261 /// Get the package map which maps package names to URIs. | 294 /// Get the package map which maps package names to URIs. |
262 /// | 295 /// |
263 /// This is an asynchronous getter since file system operations may be | 296 /// This is an asynchronous getter since file system operations may be |
264 /// required to locate/read the packages file. | 297 /// required to locate/read the packages file. |
265 Future<Packages> _getPackages() async { | 298 Future<Packages> _getPackages() async { |
266 if (_packages == null) { | 299 if (_packages != null) return _packages; |
267 if (_raw.packagesFileUri == null) { | 300 if (_raw.packagesFileUri != null) { |
268 if (inputs.length > 1) { | 301 return _packages = await createPackagesFromFile(_raw.packagesFileUri); |
269 // TODO(sigmund): consider not reporting an error if we would infer | |
270 // the same .packages file from all of the inputs. | |
271 reportMessageWithoutLocation(messageCantInferPackagesFromManyInputs); | |
272 _packages = Packages.noPackages; | |
273 } else { | |
274 _packages = await _findPackages(inputs.first); | |
275 } | |
276 } else { | |
277 _packages = await createPackagesFromFile(_raw.packagesFileUri); | |
278 } | |
279 } | 302 } |
280 return _packages; | 303 |
| 304 if (inputs.length > 1) { |
| 305 // TODO(sigmund): consider not reporting an error if we would infer |
| 306 // the same .packages file from all of the inputs. |
| 307 reportWithoutLocation( |
| 308 messageCantInferPackagesFromManyInputs, Severity.error); |
| 309 return _packages = Packages.noPackages; |
| 310 } |
| 311 |
| 312 var input = inputs.first; |
| 313 |
| 314 // When compiling the SDK the input files are normaly `dart:` URIs. |
| 315 if (input.scheme == 'dart') return _packages = Packages.noPackages; |
| 316 |
| 317 if (input.scheme == 'packages') { |
| 318 report(messageCantInferPackagesFromPackageUri.withLocation(input, -1), |
| 319 Severity.error); |
| 320 return _packages = Packages.noPackages; |
| 321 } |
| 322 |
| 323 return _packages = await _findPackages(inputs.first); |
281 } | 324 } |
282 | 325 |
283 /// Create a [Packages] given the Uri to a `.packages` file. | 326 /// Create a [Packages] given the Uri to a `.packages` file. |
284 Future<Packages> createPackagesFromFile(Uri file) async { | 327 Future<Packages> createPackagesFromFile(Uri file) async { |
285 try { | 328 try { |
286 List<int> contents = await fileSystem.entityForUri(file).readAsBytes(); | 329 List<int> contents = await fileSystem.entityForUri(file).readAsBytes(); |
287 Map<String, Uri> map = package_config.parse(contents, file); | 330 Map<String, Uri> map = package_config.parse(contents, file); |
288 return new MapPackages(map); | 331 return new MapPackages(map); |
289 } catch (e) { | 332 } catch (e) { |
290 reportMessage(templateCannotReadPackagesFile | 333 report( |
291 .withArguments("$e") | 334 templateCannotReadPackagesFile |
292 .withLocation(file, -1)); | 335 .withArguments("$e") |
| 336 .withLocation(file, -1), |
| 337 Severity.error); |
293 return Packages.noPackages; | 338 return Packages.noPackages; |
294 } | 339 } |
295 } | 340 } |
296 | 341 |
297 /// Finds a package resolution strategy using a [FileSystem]. | 342 /// Finds a package resolution strategy using a [FileSystem]. |
298 /// | 343 /// |
299 /// The [scriptUri] points to a Dart script with a valid scheme accepted by | 344 /// The [scriptUri] points to a Dart script with a valid scheme accepted by |
300 /// the [FileSystem]. | 345 /// the [FileSystem]. |
301 /// | 346 /// |
302 /// This function first tries to locate a `.packages` file in the `scriptUri` | 347 /// This function first tries to locate a `.packages` file in the `scriptUri` |
303 /// directory. If that is not found, it instead checks for the presence of a | 348 /// directory. If that is not found, it instead checks for the presence of a |
304 /// `packages/` directory in the same place. If that also fails, it starts | 349 /// `packages/` directory in the same place. If that also fails, it starts |
305 /// checking parent directories for a `.packages` file, and stops if it finds | 350 /// checking parent directories for a `.packages` file, and stops if it finds |
306 /// it. Otherwise it gives up and returns [Packages.noPackages]. | 351 /// it. Otherwise it gives up and returns [Packages.noPackages]. |
307 /// | 352 /// |
308 /// Note: this is a fork from `package:package_config/discovery.dart` to adapt | 353 /// Note: this is a fork from `package:package_config/discovery.dart` to adapt |
309 /// it to use [FileSystem]. The logic here is a mix of the logic in the | 354 /// it to use [FileSystem]. The logic here is a mix of the logic in the |
310 /// `findPackagesFromFile` and `findPackagesFromNonFile`: | 355 /// `findPackagesFromFile` and `findPackagesFromNonFile`: |
311 /// | 356 /// |
312 /// * Like `findPackagesFromFile` resolution searches for parent | 357 /// * Like `findPackagesFromFile` resolution searches for parent |
313 /// directories | 358 /// directories |
314 /// | 359 /// |
315 /// * Like `findPackagesFromNonFile` if we resolve packages as the | 360 /// * Like `findPackagesFromNonFile` if we resolve packages as the |
316 /// `packages/` directory, we can't provide a list of packages that are | 361 /// `packages/` directory, we can't provide a list of packages that are |
317 /// visible. | 362 /// visible. |
318 Future<Packages> _findPackages(Uri scriptUri) async { | 363 Future<Packages> _findPackages(Uri scriptUri) async { |
319 var dir = scriptUri.resolve('.'); | 364 var dir = scriptUri.resolve('.'); |
320 if (!dir.isAbsolute) { | 365 if (!dir.isAbsolute) { |
321 reportMessageWithoutLocation(templateInternalProblemUnsupported | 366 reportWithoutLocation( |
322 .withArguments("Expected input Uri to be absolute: $scriptUri.")); | 367 templateInternalProblemUnsupported |
| 368 .withArguments("Expected input Uri to be absolute: $scriptUri."), |
| 369 Severity.internalProblem); |
323 return Packages.noPackages; | 370 return Packages.noPackages; |
324 } | 371 } |
325 | 372 |
326 Future<Uri> checkInDir(Uri dir) async { | 373 Future<Uri> checkInDir(Uri dir) async { |
327 Uri candidate = dir.resolve('.packages'); | 374 Uri candidate = dir.resolve('.packages'); |
328 if (await fileSystem.entityForUri(candidate).exists()) return candidate; | 375 if (await fileSystem.entityForUri(candidate).exists()) return candidate; |
329 return null; | 376 return null; |
330 } | 377 } |
331 | 378 |
332 // Check for $cwd/.packages | 379 // Check for $cwd/.packages |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 allInputs.add(sdkRoot.resolve("lib/libraries.json")); | 453 allInputs.add(sdkRoot.resolve("lib/libraries.json")); |
407 } | 454 } |
408 | 455 |
409 /// Note: Searching the file-system for the package-config is not | 456 /// Note: Searching the file-system for the package-config is not |
410 /// supported in hermetic builds. | 457 /// supported in hermetic builds. |
411 if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri); | 458 if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri); |
412 result = new HermeticFileSystem(allInputs, result); | 459 result = new HermeticFileSystem(allInputs, result); |
413 } | 460 } |
414 return result; | 461 return result; |
415 } | 462 } |
| 463 |
| 464 String debugString() { |
| 465 var sb = new StringBuffer(); |
| 466 writeList(String name, List elements) { |
| 467 if (elements.isEmpty) { |
| 468 sb.writeln('$name: <empty>'); |
| 469 return; |
| 470 } |
| 471 sb.writeln('$name:'); |
| 472 elements.forEach((s) { |
| 473 sb.writeln(' - $s'); |
| 474 }); |
| 475 } |
| 476 |
| 477 sb.writeln('Inputs: ${inputs}'); |
| 478 sb.writeln('Output: ${output}'); |
| 479 |
| 480 sb.writeln('Was error handler provided: ' |
| 481 '${_raw.onError == null ? "no" : "yes"}'); |
| 482 |
| 483 sb.writeln('FileSystem: ${_fileSystem.runtimeType} ' |
| 484 '(provided: ${_raw.fileSystem.runtimeType})'); |
| 485 |
| 486 writeList('Input Summaries', _raw.inputSummaries); |
| 487 writeList('Linked Dependencies', _raw.linkedDependencies); |
| 488 writeList('Multiroots', _raw.multiRoots); |
| 489 |
| 490 sb.writeln('Modular: ${_modularApi}'); |
| 491 sb.writeln('Hermetic: ${!chaseDependencies}' |
| 492 ' (provided: ${!_raw.chaseDependencies})'); |
| 493 sb.writeln('Packages uri: ${_raw.packagesFileUri}'); |
| 494 sb.writeln('Packages: ${_packages}'); |
| 495 |
| 496 sb.writeln('Compile SDK: ${compileSdk}'); |
| 497 sb.writeln('SDK root: ${_sdkRoot} (provided: ${_raw.sdkRoot})'); |
| 498 sb.writeln('SDK summary: ${_sdkSummary} (provided: ${_raw.sdkSummary})'); |
| 499 |
| 500 sb.writeln('Strong: ${strongMode}'); |
| 501 sb.writeln('Target: ${_target?.name} (provided: ${_raw.target?.name})'); |
| 502 |
| 503 sb.writeln('throwOnErrorsAreFatal: ${throwOnErrors}'); |
| 504 sb.writeln('throwOnWarningsAreFatal: ${throwOnWarnings}'); |
| 505 sb.writeln('throwOnNits: ${throwOnNits}'); |
| 506 sb.writeln('exit on problem: ${setExitCodeOnProblem}'); |
| 507 sb.writeln('Embed sources: ${embedSourceText}'); |
| 508 sb.writeln('debugDump: ${debugDump}'); |
| 509 sb.writeln('verbose: ${verbose}'); |
| 510 sb.writeln('verify: ${verify}'); |
| 511 return '$sb'; |
| 512 } |
416 } | 513 } |
417 | 514 |
418 /// A [FileSystem] that only allows access to files that have been explicitly | 515 /// A [FileSystem] that only allows access to files that have been explicitly |
419 /// whitelisted. | 516 /// whitelisted. |
420 class HermeticFileSystem implements FileSystem { | 517 class HermeticFileSystem implements FileSystem { |
421 final Set<Uri> includedFiles; | 518 final Set<Uri> includedFiles; |
422 final FileSystem _realFileSystem; | 519 final FileSystem _realFileSystem; |
423 | 520 |
424 HermeticFileSystem(this.includedFiles, this._realFileSystem); | 521 HermeticFileSystem(this.includedFiles, this._realFileSystem); |
425 | 522 |
426 FileSystemEntity entityForUri(Uri uri) { | 523 FileSystemEntity entityForUri(Uri uri) { |
427 if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri); | 524 if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri); |
428 throw new HermeticAccessException(uri); | 525 throw new HermeticAccessException(uri); |
429 } | 526 } |
430 } | 527 } |
431 | 528 |
432 class HermeticAccessException extends FileSystemException { | 529 class HermeticAccessException extends FileSystemException { |
433 HermeticAccessException(Uri uri) | 530 HermeticAccessException(Uri uri) |
434 : super( | 531 : super( |
435 uri, | 532 uri, |
436 'Invalid access to $uri: ' | 533 'Invalid access to $uri: ' |
437 'the file is accessed in a modular hermetic build, ' | 534 'the file is accessed in a modular hermetic build, ' |
438 'but it was not explicitly listed as an input.'); | 535 'but it was not explicitly listed as an input.'); |
439 | 536 |
440 @override | 537 @override |
441 String toString() => message; | 538 String toString() => message; |
442 } | 539 } |
443 | 540 |
444 /// Wraps a [LocatedMessage] to implement the public [CompilationError] API. | 541 /// Wraps a [LocatedMessage] to implement the public [CompilationMessage] API. |
445 class _CompilationMessage implements CompilationError { | 542 class _CompilationMessage implements CompilationMessage { |
446 final LocatedMessage original; | 543 final LocatedMessage _original; |
| 544 final Severity severity; |
447 | 545 |
448 String get message => original.message; | 546 String get message => _original.message; |
449 | 547 |
450 String get tip => original.tip; | 548 String get tip => _original.tip; |
| 549 |
| 550 String get analyzerCode => _original.code.analyzerCode; |
| 551 |
| 552 String get dart2jsCode => _original.code.dart2jsCode; |
451 | 553 |
452 SourceSpan get span => | 554 SourceSpan get span => |
453 new SourceLocation(original.charOffset, sourceUrl: original.uri) | 555 new SourceLocation(_original.charOffset, sourceUrl: _original.uri) |
454 .pointSpan(); | 556 .pointSpan(); |
455 | 557 |
456 _CompilationMessage(this.original); | 558 _CompilationMessage(this._original, this.severity); |
457 | 559 |
458 String toString() => message; | 560 String toString() => message; |
459 } | 561 } |
OLD | NEW |