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 excludeSourceInformation => _raw.excludeSourceInformation; | |
95 | |
96 bool get errorsAreFatal => _raw.errorsAreFatal; | |
97 | |
98 bool get warningsAreFatal => _raw.warningsAreFatal; | |
99 | |
100 bool get nitsAreFatal => _raw.nitsAreFatal; | |
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, |
107 ticker = new Ticker(isVerbose: rawOptions.verbose); | 121 ticker = new Ticker(isVerbose: rawOptions.verbose); |
108 | 122 |
109 /// The logger to report compilation progress. | 123 /// The logger to report compilation progress. |
110 PerformanceLog get logger { | 124 PerformanceLog get logger { |
111 return _raw.logger; | 125 return _raw.logger; |
112 } | 126 } |
113 | 127 |
114 /// The byte storage to get and put serialized data. | 128 /// The byte storage to get and put serialized data. |
115 ByteStore get byteStore { | 129 ByteStore get byteStore { |
116 return _raw.byteStore; | 130 return _raw.byteStore; |
117 } | 131 } |
118 | 132 |
119 void reportMessage(LocatedMessage message) { | 133 bool get _reportMessages => _raw.reportMessages ?? (_raw.onError == null); |
120 _raw.onError(new _CompilationMessage(message)); | 134 |
135 void report(LocatedMessage message, Severity severity) { | |
136 if (_raw.onError != null) { | |
137 _raw.onError(new _CompilationMessage(message, severity)); | |
138 } | |
139 | |
140 if (_reportMessages) command_line_reporting.report(message, severity); | |
121 } | 141 } |
122 | 142 |
123 void reportMessageWithoutLocation(Message message) => | 143 void reportWithoutLocation(Message message, Severity severity) { |
124 reportMessage(message.withLocation(null, -1)); | 144 if (_raw.onError != null) { |
145 _raw.onError( | |
146 new _CompilationMessage(message.withLocation(null, -1), severity)); | |
147 } | |
148 | |
149 if (_reportMessages) { | |
150 command_line_reporting.reportWithoutLocation(message, severity); | |
151 } | |
152 } | |
125 | 153 |
126 /// Runs various validations checks on the input options. For instance, | 154 /// 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. | 155 /// if an option is a path to a file, it checks that the file exists. |
128 Future<bool> validateOptions() async { | 156 Future<bool> validateOptions() async { |
157 if (verbose) print(debugString()); | |
158 | |
129 if (inputs.isEmpty) { | 159 if (inputs.isEmpty) { |
130 reportMessageWithoutLocation(messageMissingInput); | 160 reportWithoutLocation(messageMissingInput, Severity.error); |
131 return false; | 161 return false; |
132 } | 162 } |
133 | 163 |
134 for (var source in inputs) { | 164 for (var source in inputs) { |
135 // Note: we don't translate Uris at this point because some of the | 165 // 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 | 166 // validation further below must be done before we even construct an |
137 // UriTranslator | 167 // UriTranslator |
138 // TODO(sigmund): consider validating dart/packages uri right after we | 168 // TODO(sigmund): consider validating dart/packages uri right after we |
139 // build the uri translator. | 169 // build the uri translator. |
140 if (source.scheme != 'dart' && | 170 if (source.scheme != 'dart' && |
141 source.scheme != 'packages' && | 171 source.scheme != 'packages' && |
142 !await fileSystem.entityForUri(source).exists()) { | 172 !await fileSystem.entityForUri(source).exists()) { |
143 reportMessageWithoutLocation( | 173 reportWithoutLocation( |
144 templateInputFileNotFound.withArguments('$source')); | 174 templateInputFileNotFound.withArguments('$source'), Severity.error); |
145 return false; | 175 return false; |
146 } | 176 } |
147 } | 177 } |
148 | 178 |
149 if (_raw.sdkRoot != null && | 179 if (_raw.sdkRoot != null && |
150 !await fileSystem.entityForUri(sdkRoot).exists()) { | 180 !await fileSystem.entityForUri(sdkRoot).exists()) { |
151 reportMessageWithoutLocation( | 181 reportWithoutLocation( |
152 templateSdkRootNotFound.withArguments('$sdkRoot')); | 182 templateSdkRootNotFound.withArguments('$sdkRoot'), Severity.error); |
153 return false; | 183 return false; |
154 } | 184 } |
155 | 185 |
156 var summary = sdkSummary; | 186 var summary = sdkSummary; |
157 if (summary != null && !await fileSystem.entityForUri(summary).exists()) { | 187 if (summary != null && !await fileSystem.entityForUri(summary).exists()) { |
158 reportMessageWithoutLocation( | 188 reportWithoutLocation( |
159 templateSdkSummaryNotFound.withArguments('$summary')); | 189 templateSdkSummaryNotFound.withArguments('$summary'), Severity.error); |
160 return false; | 190 return false; |
161 } | 191 } |
162 | 192 |
163 if (compileSdk && summary != null) { | 193 if (compileSdk && summary != null) { |
164 reportMessageWithoutLocation( | 194 reportWithoutLocation( |
165 templateInternalProblemUnsupported.withArguments( | 195 templateInternalProblemUnsupported.withArguments( |
166 "The compileSdk and sdkSummary options are mutually exclusive")); | 196 "The compileSdk and sdkSummary options are mutually exclusive"), |
197 Severity.internalProblem); | |
167 return false; | 198 return false; |
168 } | 199 } |
169 return true; | 200 return true; |
170 } | 201 } |
171 | 202 |
172 /// Determine whether to generate code for the SDK when compiling a | 203 /// Determine whether to generate code for the SDK when compiling a |
173 /// whole-program. | 204 /// whole-program. |
174 bool get compileSdk => _raw.compileSdk; | 205 bool get compileSdk => _raw.compileSdk; |
175 | 206 |
176 FileSystem _fileSystem; | 207 FileSystem _fileSystem; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 Future<Map<String, Uri>> _parseDartLibraries() async { | 287 Future<Map<String, Uri>> _parseDartLibraries() async { |
257 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); | 288 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); |
258 return await computeDartLibraries(fileSystem, librariesJson); | 289 return await computeDartLibraries(fileSystem, librariesJson); |
259 } | 290 } |
260 | 291 |
261 /// Get the package map which maps package names to URIs. | 292 /// Get the package map which maps package names to URIs. |
262 /// | 293 /// |
263 /// This is an asynchronous getter since file system operations may be | 294 /// This is an asynchronous getter since file system operations may be |
264 /// required to locate/read the packages file. | 295 /// required to locate/read the packages file. |
265 Future<Packages> _getPackages() async { | 296 Future<Packages> _getPackages() async { |
266 if (_packages == null) { | 297 if (_packages != null) return _packages; |
267 if (_raw.packagesFileUri == null) { | 298 if (_raw.packagesFileUri != null) { |
268 if (inputs.length > 1) { | 299 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 } | 300 } |
280 return _packages; | 301 |
302 if (inputs.length > 1) { | |
303 // TODO(sigmund): consider not reporting an error if we would infer | |
304 // the same .packages file from all of the inputs. | |
305 reportWithoutLocation( | |
306 messageCantInferPackagesFromManyInputs, Severity.error); | |
307 return _packages = Packages.noPackages; | |
308 } | |
309 | |
310 var input = inputs.first; | |
311 | |
312 // When compiling the SDK the input files are normaly `dart:` URIs. | |
Siggi Cherem (dart-lang)
2017/07/18 00:11:07
*FYI this is new logic (handling more error cases)
| |
313 if (input.scheme == 'dart') return _packages = Packages.noPackages; | |
314 | |
315 if (input.scheme == 'packages') { | |
316 report(messageCantInferPackagesFromPackageUri.withLocation(input, -1), | |
317 Severity.error); | |
318 return _packages = Packages.noPackages; | |
319 } | |
320 | |
321 return _packages = await _findPackages(inputs.first); | |
281 } | 322 } |
282 | 323 |
283 /// Create a [Packages] given the Uri to a `.packages` file. | 324 /// Create a [Packages] given the Uri to a `.packages` file. |
284 Future<Packages> createPackagesFromFile(Uri file) async { | 325 Future<Packages> createPackagesFromFile(Uri file) async { |
285 try { | 326 try { |
286 List<int> contents = await fileSystem.entityForUri(file).readAsBytes(); | 327 List<int> contents = await fileSystem.entityForUri(file).readAsBytes(); |
287 Map<String, Uri> map = package_config.parse(contents, file); | 328 Map<String, Uri> map = package_config.parse(contents, file); |
288 return new MapPackages(map); | 329 return new MapPackages(map); |
289 } catch (e) { | 330 } catch (e) { |
290 reportMessage(templateCannotReadPackagesFile | 331 report( |
291 .withArguments("$e") | 332 templateCannotReadPackagesFile |
292 .withLocation(file, -1)); | 333 .withArguments("$e") |
334 .withLocation(file, -1), | |
335 Severity.error); | |
293 return Packages.noPackages; | 336 return Packages.noPackages; |
294 } | 337 } |
295 } | 338 } |
296 | 339 |
297 /// Finds a package resolution strategy using a [FileSystem]. | 340 /// Finds a package resolution strategy using a [FileSystem]. |
298 /// | 341 /// |
299 /// The [scriptUri] points to a Dart script with a valid scheme accepted by | 342 /// The [scriptUri] points to a Dart script with a valid scheme accepted by |
300 /// the [FileSystem]. | 343 /// the [FileSystem]. |
301 /// | 344 /// |
302 /// This function first tries to locate a `.packages` file in the `scriptUri` | 345 /// 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 | 346 /// 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 | 347 /// `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 | 348 /// checking parent directories for a `.packages` file, and stops if it finds |
306 /// it. Otherwise it gives up and returns [Packages.noPackages]. | 349 /// it. Otherwise it gives up and returns [Packages.noPackages]. |
307 /// | 350 /// |
308 /// Note: this is a fork from `package:package_config/discovery.dart` to adapt | 351 /// 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 | 352 /// it to use [FileSystem]. The logic here is a mix of the logic in the |
310 /// `findPackagesFromFile` and `findPackagesFromNonFile`: | 353 /// `findPackagesFromFile` and `findPackagesFromNonFile`: |
311 /// | 354 /// |
312 /// * Like `findPackagesFromFile` resolution searches for parent | 355 /// * Like `findPackagesFromFile` resolution searches for parent |
313 /// directories | 356 /// directories |
314 /// | 357 /// |
315 /// * Like `findPackagesFromNonFile` if we resolve packages as the | 358 /// * Like `findPackagesFromNonFile` if we resolve packages as the |
316 /// `packages/` directory, we can't provide a list of packages that are | 359 /// `packages/` directory, we can't provide a list of packages that are |
317 /// visible. | 360 /// visible. |
318 Future<Packages> _findPackages(Uri scriptUri) async { | 361 Future<Packages> _findPackages(Uri scriptUri) async { |
319 var dir = scriptUri.resolve('.'); | 362 var dir = scriptUri.resolve('.'); |
320 if (!dir.isAbsolute) { | 363 if (!dir.isAbsolute) { |
321 reportMessageWithoutLocation(templateInternalProblemUnsupported | 364 reportWithoutLocation( |
322 .withArguments("Expected input Uri to be absolute: $scriptUri.")); | 365 templateInternalProblemUnsupported |
366 .withArguments("Expected input Uri to be absolute: $scriptUri."), | |
367 Severity.internalProblem); | |
323 return Packages.noPackages; | 368 return Packages.noPackages; |
324 } | 369 } |
325 | 370 |
326 Future<Uri> checkInDir(Uri dir) async { | 371 Future<Uri> checkInDir(Uri dir) async { |
327 Uri candidate = dir.resolve('.packages'); | 372 Uri candidate = dir.resolve('.packages'); |
328 if (await fileSystem.entityForUri(candidate).exists()) return candidate; | 373 if (await fileSystem.entityForUri(candidate).exists()) return candidate; |
329 return null; | 374 return null; |
330 } | 375 } |
331 | 376 |
332 // Check for $cwd/.packages | 377 // 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")); | 451 allInputs.add(sdkRoot.resolve("lib/libraries.json")); |
407 } | 452 } |
408 | 453 |
409 /// Note: Searching the file-system for the package-config is not | 454 /// Note: Searching the file-system for the package-config is not |
410 /// supported in hermetic builds. | 455 /// supported in hermetic builds. |
411 if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri); | 456 if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri); |
412 result = new HermeticFileSystem(allInputs, result); | 457 result = new HermeticFileSystem(allInputs, result); |
413 } | 458 } |
414 return result; | 459 return result; |
415 } | 460 } |
461 | |
462 String debugString() { | |
ahe
2017/07/18 16:54:36
Nice.
| |
463 var sb = new StringBuffer(); | |
464 writeList(String name, List elements) { | |
465 if (elements.isEmpty) { | |
466 sb.writeln('$name: <empty>'); | |
467 return; | |
468 } | |
469 sb.writeln('$name:'); | |
470 elements.forEach((s) { | |
471 sb.writeln(' - $s'); | |
472 }); | |
473 } | |
474 | |
475 sb.writeln('Inputs: ${inputs}'); | |
476 sb.writeln('Output: ${output}'); | |
477 | |
478 sb.writeln('Was error handler provided: ' | |
479 '${_raw.onError == null ? "no" : "yes"}'); | |
480 | |
481 sb.writeln('FileSystem: ${_fileSystem.runtimeType} ' | |
482 '(provided: ${_raw.fileSystem.runtimeType})'); | |
483 | |
484 writeList('Input Summaries', _raw.inputSummaries); | |
485 writeList('Linked Dependencies', _raw.linkedDependencies); | |
486 writeList('Multiroots', _raw.multiRoots); | |
487 | |
488 sb.writeln('Modular: ${_modularApi}'); | |
489 sb.writeln('Hermetic: ${!chaseDependencies}' | |
490 ' (provided: ${!_raw.chaseDependencies})'); | |
491 sb.writeln('Packages uri: ${_raw.packagesFileUri}'); | |
492 sb.writeln('Packages: ${_packages}'); | |
493 | |
494 sb.writeln('Compile SDK: ${compileSdk}'); | |
495 sb.writeln('SDK root: ${_sdkRoot} (provided: ${_raw.sdkRoot})'); | |
496 sb.writeln('SDK summary: ${_sdkSummary} (provided: ${_raw.sdkSummary})'); | |
497 | |
498 sb.writeln('Strong: ${strongMode}'); | |
499 sb.writeln('Target: ${_target?.name} (provided: ${_raw.target?.name})'); | |
500 | |
501 sb.writeln('errorsAreFatal: ${errorsAreFatal}'); | |
502 sb.writeln('warningsAreFatal: ${warningsAreFatal}'); | |
503 sb.writeln('nitsAreFatal: ${nitsAreFatal}'); | |
504 sb.writeln('exit on problem: ${setExitCodeOnProblem}'); | |
505 sb.writeln('Exclude sources: ${excludeSourceInformation}'); | |
506 sb.writeln('debugDump: ${debugDump}'); | |
507 sb.writeln('verbose: ${verbose}'); | |
508 sb.writeln('verify: ${verify}'); | |
509 return '$sb'; | |
510 } | |
416 } | 511 } |
417 | 512 |
418 /// A [FileSystem] that only allows access to files that have been explicitly | 513 /// A [FileSystem] that only allows access to files that have been explicitly |
419 /// whitelisted. | 514 /// whitelisted. |
420 class HermeticFileSystem implements FileSystem { | 515 class HermeticFileSystem implements FileSystem { |
421 final Set<Uri> includedFiles; | 516 final Set<Uri> includedFiles; |
422 final FileSystem _realFileSystem; | 517 final FileSystem _realFileSystem; |
423 | 518 |
424 HermeticFileSystem(this.includedFiles, this._realFileSystem); | 519 HermeticFileSystem(this.includedFiles, this._realFileSystem); |
425 | 520 |
426 FileSystemEntity entityForUri(Uri uri) { | 521 FileSystemEntity entityForUri(Uri uri) { |
427 if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri); | 522 if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri); |
428 throw new HermeticAccessException(uri); | 523 throw new HermeticAccessException(uri); |
429 } | 524 } |
430 } | 525 } |
431 | 526 |
432 class HermeticAccessException extends FileSystemException { | 527 class HermeticAccessException extends FileSystemException { |
433 HermeticAccessException(Uri uri) | 528 HermeticAccessException(Uri uri) |
434 : super( | 529 : super( |
435 uri, | 530 uri, |
436 'Invalid access to $uri: ' | 531 'Invalid access to $uri: ' |
437 'the file is accessed in a modular hermetic build, ' | 532 'the file is accessed in a modular hermetic build, ' |
438 'but it was not explicitly listed as an input.'); | 533 'but it was not explicitly listed as an input.'); |
439 | 534 |
440 @override | 535 @override |
441 String toString() => message; | 536 String toString() => message; |
442 } | 537 } |
443 | 538 |
444 /// Wraps a [LocatedMessage] to implement the public [CompilationError] API. | 539 /// Wraps a [LocatedMessage] to implement the public [CompilationMessage] API. |
445 class _CompilationMessage implements CompilationError { | 540 class _CompilationMessage implements CompilationMessage { |
ahe
2017/07/18 16:54:37
You may be able to merge this class with Compilati
Siggi Cherem (dart-lang)
2017/07/18 22:50:43
I have a slight preference to keep them separate b
| |
446 final LocatedMessage original; | 541 final LocatedMessage _original; |
542 final Severity severity; | |
447 | 543 |
448 String get message => original.message; | 544 String get message => _original.message; |
449 | 545 |
450 String get tip => original.tip; | 546 String get tip => _original.tip; |
547 | |
548 String get analyzerCode => _original.code.analyzerCode; | |
549 | |
550 String get dart2jsCode => _original.code.dart2jsCode; | |
451 | 551 |
452 SourceSpan get span => | 552 SourceSpan get span => |
453 new SourceLocation(original.charOffset, sourceUrl: original.uri) | 553 new SourceLocation(_original.charOffset, sourceUrl: _original.uri) |
454 .pointSpan(); | 554 .pointSpan(); |
455 | 555 |
456 _CompilationMessage(this.original); | 556 _CompilationMessage(this._original, this.severity); |
457 | 557 |
458 String toString() => message; | 558 String toString() => message; |
459 } | 559 } |
OLD | NEW |