OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.compiler_base; | 5 library dart2js.compiler_base; |
6 | 6 |
7 import 'dart:async' show | 7 import 'dart:async' show |
8 EventSink, | 8 EventSink, |
9 Future; | 9 Future; |
10 | 10 |
(...skipping 26 matching lines...) Expand all Loading... |
37 import 'core_types.dart' show | 37 import 'core_types.dart' show |
38 CoreTypes; | 38 CoreTypes; |
39 import 'dart_backend/dart_backend.dart' as dart_backend; | 39 import 'dart_backend/dart_backend.dart' as dart_backend; |
40 import 'dart_types.dart' show | 40 import 'dart_types.dart' show |
41 DartType, | 41 DartType, |
42 DynamicType, | 42 DynamicType, |
43 InterfaceType, | 43 InterfaceType, |
44 Types; | 44 Types; |
45 import 'deferred_load.dart' show DeferredLoadTask, OutputUnit; | 45 import 'deferred_load.dart' show DeferredLoadTask, OutputUnit; |
46 import 'diagnostics/code_location.dart'; | 46 import 'diagnostics/code_location.dart'; |
47 import 'diagnostics/diagnostic_listener.dart'; | 47 import 'diagnostics/diagnostic_listener.dart' show |
| 48 DiagnosticMessage, |
| 49 DiagnosticOptions, |
| 50 DiagnosticReporter; |
48 import 'diagnostics/invariant.dart' show | 51 import 'diagnostics/invariant.dart' show |
49 invariant, | 52 invariant, |
50 REPORT_EXCESS_RESOLUTION; | 53 REPORT_EXCESS_RESOLUTION; |
51 import 'diagnostics/messages.dart' show | 54 import 'diagnostics/messages.dart' show |
52 Message, | 55 Message, |
53 MessageKind, | 56 MessageKind, |
54 MessageTemplate; | 57 MessageTemplate; |
55 import 'diagnostics/source_span.dart' show | 58 import 'diagnostics/source_span.dart' show |
56 SourceSpan; | 59 SourceSpan; |
57 import 'diagnostics/spannable.dart' show | 60 import 'diagnostics/spannable.dart' show |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 import 'universe/selector.dart' show | 135 import 'universe/selector.dart' show |
133 Selector; | 136 Selector; |
134 import 'universe/universe.dart' show | 137 import 'universe/universe.dart' show |
135 Universe; | 138 Universe; |
136 import 'util/util.dart' show | 139 import 'util/util.dart' show |
137 Link, | 140 Link, |
138 Setlet; | 141 Setlet; |
139 import 'world.dart' show | 142 import 'world.dart' show |
140 World; | 143 World; |
141 | 144 |
142 abstract class Compiler extends DiagnosticListener { | 145 abstract class Compiler { |
143 | 146 |
144 final Stopwatch totalCompileTime = new Stopwatch(); | 147 final Stopwatch totalCompileTime = new Stopwatch(); |
145 int nextFreeClassId = 0; | 148 int nextFreeClassId = 0; |
146 World world; | 149 World world; |
147 Types types; | 150 Types types; |
148 _CompilerCoreTypes _coreTypes; | 151 _CompilerCoreTypes _coreTypes; |
| 152 _CompilerDiagnosticReporter _reporter; |
149 _CompilerResolution _resolution; | 153 _CompilerResolution _resolution; |
150 _CompilerParsing _parsing; | 154 _CompilerParsing _parsing; |
151 | 155 |
152 final CacheStrategy cacheStrategy; | 156 final CacheStrategy cacheStrategy; |
153 | 157 |
154 /** | 158 /** |
155 * Map from token to the first preceding comment token. | 159 * Map from token to the first preceding comment token. |
156 */ | 160 */ |
157 final TokenMap commentMap = new TokenMap(); | 161 final TokenMap commentMap = new TokenMap(); |
158 | 162 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 * URI of the main output if the compiler is generating source maps. | 245 * URI of the main output if the compiler is generating source maps. |
242 */ | 246 */ |
243 final Uri outputUri; | 247 final Uri outputUri; |
244 | 248 |
245 /// Emit terse diagnostics without howToFix. | 249 /// Emit terse diagnostics without howToFix. |
246 final bool terseDiagnostics; | 250 final bool terseDiagnostics; |
247 | 251 |
248 /// If `true`, warnings and hints not from user code are reported. | 252 /// If `true`, warnings and hints not from user code are reported. |
249 final bool showPackageWarnings; | 253 final bool showPackageWarnings; |
250 | 254 |
251 /// `true` if the last diagnostic was filtered, in which case the | |
252 /// accompanying info message should be filtered as well. | |
253 bool lastDiagnosticWasFiltered = false; | |
254 | |
255 /// Map containing information about the warnings and hints that have been | |
256 /// suppressed for each library. | |
257 Map<Uri, SuppressionInfo> suppressedWarnings = <Uri, SuppressionInfo>{}; | |
258 | |
259 final bool suppressWarnings; | 255 final bool suppressWarnings; |
260 final bool fatalWarnings; | 256 final bool fatalWarnings; |
261 | 257 |
262 /// If `true`, some values are cached for reuse in incremental compilation. | 258 /// If `true`, some values are cached for reuse in incremental compilation. |
263 /// Incremental compilation is basically calling [run] more than once. | 259 /// Incremental compilation is basically calling [run] more than once. |
264 final bool hasIncrementalSupport; | 260 final bool hasIncrementalSupport; |
265 | 261 |
266 /// If `true` native extension syntax is supported by the frontend. | 262 /// If `true` native extension syntax is supported by the frontend. |
267 final bool allowNativeExtensions; | 263 final bool allowNativeExtensions; |
268 | 264 |
(...skipping 11 matching lines...) Expand all Loading... |
280 List<Uri> librariesToAnalyzeWhenRun; | 276 List<Uri> librariesToAnalyzeWhenRun; |
281 | 277 |
282 /// The set of platform libraries reported as unsupported. | 278 /// The set of platform libraries reported as unsupported. |
283 /// | 279 /// |
284 /// For instance when importing 'dart:io' without '--categories=Server'. | 280 /// For instance when importing 'dart:io' without '--categories=Server'. |
285 Set<Uri> disallowedLibraryUris = new Setlet<Uri>(); | 281 Set<Uri> disallowedLibraryUris = new Setlet<Uri>(); |
286 | 282 |
287 Tracer tracer; | 283 Tracer tracer; |
288 | 284 |
289 CompilerTask measuredTask; | 285 CompilerTask measuredTask; |
290 Element _currentElement; | |
291 LibraryElement coreLibrary; | 286 LibraryElement coreLibrary; |
292 LibraryElement asyncLibrary; | 287 LibraryElement asyncLibrary; |
293 | 288 |
294 LibraryElement mainApp; | 289 LibraryElement mainApp; |
295 FunctionElement mainFunction; | 290 FunctionElement mainFunction; |
296 | 291 |
297 /// Initialized when dart:mirrors is loaded. | 292 /// Initialized when dart:mirrors is loaded. |
298 LibraryElement mirrorsLibrary; | 293 LibraryElement mirrorsLibrary; |
299 | 294 |
300 /// Initialized when dart:typed_data is loaded. | 295 /// Initialized when dart:typed_data is loaded. |
(...skipping 10 matching lines...) Expand all Loading... |
311 ClassElement get nullClass => _coreTypes.nullClass; | 306 ClassElement get nullClass => _coreTypes.nullClass; |
312 ClassElement get listClass => _coreTypes.listClass; | 307 ClassElement get listClass => _coreTypes.listClass; |
313 ClassElement get typeClass => _coreTypes.typeClass; | 308 ClassElement get typeClass => _coreTypes.typeClass; |
314 ClassElement get mapClass => _coreTypes.mapClass; | 309 ClassElement get mapClass => _coreTypes.mapClass; |
315 ClassElement get symbolClass => _coreTypes.symbolClass; | 310 ClassElement get symbolClass => _coreTypes.symbolClass; |
316 ClassElement get stackTraceClass => _coreTypes.stackTraceClass; | 311 ClassElement get stackTraceClass => _coreTypes.stackTraceClass; |
317 ClassElement get futureClass => _coreTypes.futureClass; | 312 ClassElement get futureClass => _coreTypes.futureClass; |
318 ClassElement get iterableClass => _coreTypes.iterableClass; | 313 ClassElement get iterableClass => _coreTypes.iterableClass; |
319 ClassElement get streamClass => _coreTypes.streamClass; | 314 ClassElement get streamClass => _coreTypes.streamClass; |
320 | 315 |
| 316 DiagnosticReporter get reporter => _reporter; |
321 CoreTypes get coreTypes => _coreTypes; | 317 CoreTypes get coreTypes => _coreTypes; |
322 Resolution get resolution => _resolution; | 318 Resolution get resolution => _resolution; |
323 Parsing get parsing => _parsing; | 319 Parsing get parsing => _parsing; |
324 | 320 |
325 ClassElement typedDataClass; | 321 ClassElement typedDataClass; |
326 | 322 |
327 /// The constant for the [proxy] variable defined in dart:core. | 323 /// The constant for the [proxy] variable defined in dart:core. |
328 ConstantValue proxyConstant; | 324 ConstantValue proxyConstant; |
329 | 325 |
330 // TODO(johnniwinther): Move this to the JavaScriptBackend. | 326 // TODO(johnniwinther): Move this to the JavaScriptBackend. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 ConstructorElement boolEnvironment; | 367 ConstructorElement boolEnvironment; |
372 | 368 |
373 /// The [String.fromEnvironment] constructor. | 369 /// The [String.fromEnvironment] constructor. |
374 ConstructorElement stringEnvironment; | 370 ConstructorElement stringEnvironment; |
375 | 371 |
376 /// Tracks elements with compile-time errors. | 372 /// Tracks elements with compile-time errors. |
377 final Set<Element> elementsWithCompileTimeErrors = new Set<Element>(); | 373 final Set<Element> elementsWithCompileTimeErrors = new Set<Element>(); |
378 | 374 |
379 fromEnvironment(String name) => null; | 375 fromEnvironment(String name) => null; |
380 | 376 |
381 Element get currentElement => _currentElement; | 377 Element get currentElement => _reporter.currentElement; |
382 | |
383 String tryToString(object) { | |
384 try { | |
385 return object.toString(); | |
386 } catch (_) { | |
387 return '<exception in toString()>'; | |
388 } | |
389 } | |
390 | |
391 /** | |
392 * Perform an operation, [f], returning the return value from [f]. If an | |
393 * error occurs then report it as having occurred during compilation of | |
394 * [element]. Can be nested. | |
395 */ | |
396 withCurrentElement(Element element, f()) { | |
397 Element old = currentElement; | |
398 _currentElement = element; | |
399 try { | |
400 return f(); | |
401 } on SpannableAssertionFailure catch (ex) { | |
402 if (!hasCrashed) { | |
403 reportAssertionFailure(ex); | |
404 pleaseReportCrash(); | |
405 } | |
406 hasCrashed = true; | |
407 rethrow; | |
408 } on StackOverflowError { | |
409 // We cannot report anything useful in this case, because we | |
410 // do not have enough stack space. | |
411 rethrow; | |
412 } catch (ex) { | |
413 if (hasCrashed) rethrow; | |
414 try { | |
415 unhandledExceptionOnElement(element); | |
416 } catch (doubleFault) { | |
417 // Ignoring exceptions in exception handling. | |
418 } | |
419 rethrow; | |
420 } finally { | |
421 _currentElement = old; | |
422 } | |
423 } | |
424 | 378 |
425 List<CompilerTask> tasks; | 379 List<CompilerTask> tasks; |
426 ScannerTask scanner; | 380 ScannerTask scanner; |
427 DietParserTask dietParser; | 381 DietParserTask dietParser; |
428 ParserTask parser; | 382 ParserTask parser; |
429 PatchParserTask patchParser; | 383 PatchParserTask patchParser; |
430 LibraryLoaderTask libraryLoader; | 384 LibraryLoaderTask libraryLoader; |
431 SerializationTask serialization; | 385 SerializationTask serialization; |
432 ResolverTask resolver; | 386 ResolverTask resolver; |
433 closureMapping.ClosureTask closureToClassMapper; | 387 closureMapping.ClosureTask closureToClassMapper; |
(...skipping 23 matching lines...) Expand all Loading... |
457 'createInvocationMirror'; | 411 'createInvocationMirror'; |
458 | 412 |
459 static const String UNDETERMINED_BUILD_ID = | 413 static const String UNDETERMINED_BUILD_ID = |
460 "build number could not be determined"; | 414 "build number could not be determined"; |
461 | 415 |
462 bool enabledRuntimeType = false; | 416 bool enabledRuntimeType = false; |
463 bool enabledFunctionApply = false; | 417 bool enabledFunctionApply = false; |
464 bool enabledInvokeOn = false; | 418 bool enabledInvokeOn = false; |
465 bool hasIsolateSupport = false; | 419 bool hasIsolateSupport = false; |
466 | 420 |
| 421 bool get hasCrashed => _reporter.hasCrashed; |
| 422 |
467 Stopwatch progress; | 423 Stopwatch progress; |
468 | 424 |
469 bool get shouldPrintProgress { | 425 bool get shouldPrintProgress { |
470 return verbose && progress.elapsedMilliseconds > 500; | 426 return verbose && progress.elapsedMilliseconds > 500; |
471 } | 427 } |
472 | 428 |
473 static const int PHASE_SCANNING = 0; | 429 static const int PHASE_SCANNING = 0; |
474 static const int PHASE_RESOLVING = 1; | 430 static const int PHASE_RESOLVING = 1; |
475 static const int PHASE_DONE_RESOLVING = 2; | 431 static const int PHASE_DONE_RESOLVING = 2; |
476 static const int PHASE_COMPILING = 3; | 432 static const int PHASE_COMPILING = 3; |
477 int phase; | 433 int phase; |
478 | 434 |
479 bool compilationFailedInternal = false; | 435 bool compilationFailedInternal = false; |
480 | 436 |
481 bool get compilationFailed => compilationFailedInternal; | 437 bool get compilationFailed => compilationFailedInternal; |
482 | 438 |
483 void set compilationFailed(bool value) { | 439 void set compilationFailed(bool value) { |
484 if (value) { | 440 if (value) { |
485 elementsWithCompileTimeErrors.add(currentElement); | 441 elementsWithCompileTimeErrors.add(currentElement); |
486 } | 442 } |
487 compilationFailedInternal = value; | 443 compilationFailedInternal = value; |
488 } | 444 } |
489 | 445 |
490 bool hasCrashed = false; | |
491 | |
492 /// Set by the backend if real reflection is detected in use of dart:mirrors. | 446 /// Set by the backend if real reflection is detected in use of dart:mirrors. |
493 bool disableTypeInferenceForMirrors = false; | 447 bool disableTypeInferenceForMirrors = false; |
494 | 448 |
495 Compiler({this.enableTypeAssertions: false, | 449 Compiler({this.enableTypeAssertions: false, |
496 this.enableUserAssertions: false, | 450 this.enableUserAssertions: false, |
497 this.trustTypeAnnotations: false, | 451 this.trustTypeAnnotations: false, |
498 this.trustPrimitives: false, | 452 this.trustPrimitives: false, |
499 bool disableTypeInferenceFlag: false, | 453 bool disableTypeInferenceFlag: false, |
500 this.maxConcreteTypeSize: 5, | 454 this.maxConcreteTypeSize: 5, |
501 this.enableMinification: false, | 455 this.enableMinification: false, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 this.userOutputProvider = outputProvider == null | 496 this.userOutputProvider = outputProvider == null |
543 ? const NullCompilerOutput() : outputProvider { | 497 ? const NullCompilerOutput() : outputProvider { |
544 if (hasIncrementalSupport) { | 498 if (hasIncrementalSupport) { |
545 // TODO(ahe): This is too much. Any method from platform and package | 499 // TODO(ahe): This is too much. Any method from platform and package |
546 // libraries can be inlined. | 500 // libraries can be inlined. |
547 disableInlining = true; | 501 disableInlining = true; |
548 } | 502 } |
549 world = new World(this); | 503 world = new World(this); |
550 // TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and | 504 // TODO(johnniwinther): Initialize core types in [initializeCoreClasses] and |
551 // make its field final. | 505 // make its field final. |
| 506 _reporter = new _CompilerDiagnosticReporter(this, |
| 507 new DiagnosticOptions( |
| 508 suppressWarnings: suppressWarnings, |
| 509 terseDiagnostics: terseDiagnostics, |
| 510 showPackageWarnings: showPackageWarnings)); |
552 _parsing = new _CompilerParsing(this); | 511 _parsing = new _CompilerParsing(this); |
553 _resolution = new _CompilerResolution(this); | 512 _resolution = new _CompilerResolution(this); |
554 _coreTypes = new _CompilerCoreTypes(_resolution); | 513 _coreTypes = new _CompilerCoreTypes(_resolution); |
555 types = new Types(this); | 514 types = new Types(this); |
556 tracer = new Tracer(this, this.outputProvider); | 515 tracer = new Tracer(this, this.outputProvider); |
557 | 516 |
558 if (verbose) { | 517 if (verbose) { |
559 progress = new Stopwatch()..start(); | 518 progress = new Stopwatch()..start(); |
560 } | 519 } |
561 | 520 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 | 568 |
610 bool get compileAll => false; | 569 bool get compileAll => false; |
611 | 570 |
612 bool get disableTypeInference { | 571 bool get disableTypeInference { |
613 return disableTypeInferenceFlag || compilationFailed; | 572 return disableTypeInferenceFlag || compilationFailed; |
614 } | 573 } |
615 | 574 |
616 int getNextFreeClassId() => nextFreeClassId++; | 575 int getNextFreeClassId() => nextFreeClassId++; |
617 | 576 |
618 void unimplemented(Spannable spannable, String methodName) { | 577 void unimplemented(Spannable spannable, String methodName) { |
619 internalError(spannable, "$methodName not implemented."); | 578 reporter.internalError(spannable, "$methodName not implemented."); |
620 } | |
621 | |
622 internalError(Spannable node, reason) { | |
623 String message = tryToString(reason); | |
624 reportDiagnosticInternal( | |
625 createMessage(node, MessageKind.GENERIC, {'text': message}), | |
626 const <DiagnosticMessage>[], | |
627 api.Diagnostic.CRASH); | |
628 throw 'Internal Error: $message'; | |
629 } | |
630 | |
631 void unhandledExceptionOnElement(Element element) { | |
632 if (hasCrashed) return; | |
633 hasCrashed = true; | |
634 reportDiagnostic( | |
635 createMessage(element, MessageKind.COMPILER_CRASHED), | |
636 const <DiagnosticMessage>[], | |
637 api.Diagnostic.CRASH); | |
638 pleaseReportCrash(); | |
639 } | |
640 | |
641 void pleaseReportCrash() { | |
642 print( | |
643 MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH] | |
644 .message({'buildId': buildId})); | |
645 } | |
646 | |
647 SourceSpan spanFromSpannable(Spannable node) { | |
648 // TODO(johnniwinther): Disallow `node == null` ? | |
649 if (node == null) return null; | |
650 if (node == CURRENT_ELEMENT_SPANNABLE) { | |
651 node = currentElement; | |
652 } else if (node == NO_LOCATION_SPANNABLE) { | |
653 if (currentElement == null) return null; | |
654 node = currentElement; | |
655 } | |
656 if (node is SourceSpan) { | |
657 return node; | |
658 } else if (node is Node) { | |
659 return spanFromNode(node); | |
660 } else if (node is TokenPair) { | |
661 return spanFromTokens(node.begin, node.end); | |
662 } else if (node is Token) { | |
663 return spanFromTokens(node, node); | |
664 } else if (node is HInstruction) { | |
665 return spanFromHInstruction(node); | |
666 } else if (node is Element) { | |
667 return spanFromElement(node); | |
668 } else if (node is MetadataAnnotation) { | |
669 Uri uri = node.annotatedElement.compilationUnit.script.resourceUri; | |
670 return spanFromTokens(node.beginToken, node.endToken, uri); | |
671 } else if (node is Local) { | |
672 Local local = node; | |
673 return spanFromElement(local.executableContext); | |
674 } else { | |
675 throw 'No error location.'; | |
676 } | |
677 } | |
678 | |
679 Element _elementFromHInstruction(HInstruction instruction) { | |
680 return instruction.sourceElement is Element | |
681 ? instruction.sourceElement : null; | |
682 } | |
683 | |
684 /// Finds the approximate [Element] for [node]. [currentElement] is used as | |
685 /// the default value. | |
686 Element elementFromSpannable(Spannable node) { | |
687 Element element; | |
688 if (node is Element) { | |
689 element = node; | |
690 } else if (node is HInstruction) { | |
691 element = _elementFromHInstruction(node); | |
692 } else if (node is MetadataAnnotation) { | |
693 element = node.annotatedElement; | |
694 } | |
695 return element != null ? element : currentElement; | |
696 } | |
697 | |
698 void log(message) { | |
699 Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC] | |
700 .message({'text': '$message'}); | |
701 reportDiagnostic( | |
702 new DiagnosticMessage(null, null, msg), | |
703 const <DiagnosticMessage>[], | |
704 api.Diagnostic.VERBOSE_INFO); | |
705 } | 579 } |
706 | 580 |
707 Future<bool> run(Uri uri) { | 581 Future<bool> run(Uri uri) { |
708 totalCompileTime.start(); | 582 totalCompileTime.start(); |
709 | 583 |
710 return new Future.sync(() => runCompiler(uri)).catchError((error) { | 584 return new Future.sync(() => runCompiler(uri)) |
711 try { | 585 .catchError((error) => _reporter.onError(uri, error)) |
712 if (!hasCrashed) { | 586 .whenComplete(() { |
713 hasCrashed = true; | |
714 if (error is SpannableAssertionFailure) { | |
715 reportAssertionFailure(error); | |
716 } else { | |
717 reportDiagnostic( | |
718 createMessage( | |
719 new SourceSpan(uri, 0, 0), | |
720 MessageKind.COMPILER_CRASHED), | |
721 const <DiagnosticMessage>[], | |
722 api.Diagnostic.CRASH); | |
723 } | |
724 pleaseReportCrash(); | |
725 } | |
726 } catch (doubleFault) { | |
727 // Ignoring exceptions in exception handling. | |
728 } | |
729 throw error; | |
730 }).whenComplete(() { | |
731 tracer.close(); | 587 tracer.close(); |
732 totalCompileTime.stop(); | 588 totalCompileTime.stop(); |
733 }).then((_) { | 589 }).then((_) { |
734 return !compilationFailed; | 590 return !compilationFailed; |
735 }); | 591 }); |
736 } | 592 } |
737 | 593 |
738 /// This method is called immediately after the [LibraryElement] [library] has | 594 /// This method is called immediately after the [LibraryElement] [library] has |
739 /// been created. | 595 /// been created. |
740 /// | 596 /// |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 /// [loadedLibraries] contains the newly loaded libraries. | 715 /// [loadedLibraries] contains the newly loaded libraries. |
860 /// | 716 /// |
861 /// The method returns a [Future] allowing for the loading of additional | 717 /// The method returns a [Future] allowing for the loading of additional |
862 /// libraries. | 718 /// libraries. |
863 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { | 719 Future onLibrariesLoaded(LoadedLibraries loadedLibraries) { |
864 return new Future.sync(() { | 720 return new Future.sync(() { |
865 for (Uri uri in disallowedLibraryUris) { | 721 for (Uri uri in disallowedLibraryUris) { |
866 if (loadedLibraries.containsLibrary(uri)) { | 722 if (loadedLibraries.containsLibrary(uri)) { |
867 Set<String> importChains = | 723 Set<String> importChains = |
868 computeImportChainsFor(loadedLibraries, Uri.parse('dart:io')); | 724 computeImportChainsFor(loadedLibraries, Uri.parse('dart:io')); |
869 reportInfo(NO_LOCATION_SPANNABLE, | 725 reporter.reportInfo(NO_LOCATION_SPANNABLE, |
870 MessageKind.DISALLOWED_LIBRARY_IMPORT, | 726 MessageKind.DISALLOWED_LIBRARY_IMPORT, |
871 {'uri': uri, | 727 {'uri': uri, |
872 'importChain': importChains.join( | 728 'importChain': importChains.join( |
873 MessageTemplate.DISALLOWED_LIBRARY_IMPORT_PADDING)}); | 729 MessageTemplate.DISALLOWED_LIBRARY_IMPORT_PADDING)}); |
874 } | 730 } |
875 } | 731 } |
876 | 732 |
877 if (!loadedLibraries.containsLibrary(Uris.dart_core)) { | 733 if (!loadedLibraries.containsLibrary(Uris.dart_core)) { |
878 return null; | 734 return null; |
879 } | 735 } |
880 | 736 |
881 bool importsMirrorsLibrary = | 737 bool importsMirrorsLibrary = |
882 loadedLibraries.containsLibrary(Uris.dart_mirrors); | 738 loadedLibraries.containsLibrary(Uris.dart_mirrors); |
883 if (importsMirrorsLibrary && !backend.supportsReflection) { | 739 if (importsMirrorsLibrary && !backend.supportsReflection) { |
884 Set<String> importChains = | 740 Set<String> importChains = |
885 computeImportChainsFor(loadedLibraries, Uris.dart_mirrors); | 741 computeImportChainsFor(loadedLibraries, Uris.dart_mirrors); |
886 reportErrorMessage( | 742 reporter.reportErrorMessage( |
887 NO_LOCATION_SPANNABLE, | 743 NO_LOCATION_SPANNABLE, |
888 MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND, | 744 MessageKind.MIRRORS_LIBRARY_NOT_SUPPORT_BY_BACKEND, |
889 {'importChain': importChains.join( | 745 {'importChain': importChains.join( |
890 MessageTemplate.MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING)}); | 746 MessageTemplate.MIRRORS_NOT_SUPPORTED_BY_BACKEND_PADDING)}); |
891 } else if (importsMirrorsLibrary && !enableExperimentalMirrors) { | 747 } else if (importsMirrorsLibrary && !enableExperimentalMirrors) { |
892 Set<String> importChains = | 748 Set<String> importChains = |
893 computeImportChainsFor(loadedLibraries, Uris.dart_mirrors); | 749 computeImportChainsFor(loadedLibraries, Uris.dart_mirrors); |
894 reportWarningMessage( | 750 reporter.reportWarningMessage( |
895 NO_LOCATION_SPANNABLE, | 751 NO_LOCATION_SPANNABLE, |
896 MessageKind.IMPORT_EXPERIMENTAL_MIRRORS, | 752 MessageKind.IMPORT_EXPERIMENTAL_MIRRORS, |
897 {'importChain': importChains.join( | 753 {'importChain': importChains.join( |
898 MessageTemplate.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)}); | 754 MessageTemplate.IMPORT_EXPERIMENTAL_MIRRORS_PADDING)}); |
899 } | 755 } |
900 | 756 |
901 functionClass.ensureResolved(resolution); | 757 functionClass.ensureResolved(resolution); |
902 functionApplyMethod = functionClass.lookupLocalMember('apply'); | 758 functionApplyMethod = functionClass.lookupLocalMember('apply'); |
903 | 759 |
904 if (preserveComments) { | 760 if (preserveComments) { |
(...skipping 13 matching lines...) Expand all Loading... |
918 proxyConstant = | 774 proxyConstant = |
919 constants.getConstantValue( | 775 constants.getConstantValue( |
920 resolver.constantCompiler.compileConstant(field)); | 776 resolver.constantCompiler.compileConstant(field)); |
921 } | 777 } |
922 return proxyConstant == value; | 778 return proxyConstant == value; |
923 } | 779 } |
924 | 780 |
925 Element findRequiredElement(LibraryElement library, String name) { | 781 Element findRequiredElement(LibraryElement library, String name) { |
926 var element = library.find(name); | 782 var element = library.find(name); |
927 if (element == null) { | 783 if (element == null) { |
928 internalError(library, | 784 reporter.internalError(library, |
929 "The library '${library.canonicalUri}' does not contain required " | 785 "The library '${library.canonicalUri}' does not contain required " |
930 "element: '$name'."); | 786 "element: '$name'."); |
931 } | 787 } |
932 return element; | 788 return element; |
933 } | 789 } |
934 | 790 |
935 // TODO(johnniwinther): Move this to [PatchParser] when it is moved to the | 791 // TODO(johnniwinther): Move this to [PatchParser] when it is moved to the |
936 // [JavaScriptBackend]. Currently needed for testing. | 792 // [JavaScriptBackend]. Currently needed for testing. |
937 String get patchVersion => backend.patchVersion; | 793 String get patchVersion => backend.patchVersion; |
938 | 794 |
939 void onClassResolved(ClassElement cls) { | 795 void onClassResolved(ClassElement cls) { |
940 if (mirrorSystemClass == cls) { | 796 if (mirrorSystemClass == cls) { |
941 mirrorSystemGetNameFunction = | 797 mirrorSystemGetNameFunction = |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 _coreTypes.stringClass = lookupCoreClass('String'); | 832 _coreTypes.stringClass = lookupCoreClass('String'); |
977 _coreTypes.functionClass = lookupCoreClass('Function'); | 833 _coreTypes.functionClass = lookupCoreClass('Function'); |
978 _coreTypes.listClass = lookupCoreClass('List'); | 834 _coreTypes.listClass = lookupCoreClass('List'); |
979 _coreTypes.typeClass = lookupCoreClass('Type'); | 835 _coreTypes.typeClass = lookupCoreClass('Type'); |
980 _coreTypes.mapClass = lookupCoreClass('Map'); | 836 _coreTypes.mapClass = lookupCoreClass('Map'); |
981 _coreTypes.nullClass = lookupCoreClass('Null'); | 837 _coreTypes.nullClass = lookupCoreClass('Null'); |
982 _coreTypes.stackTraceClass = lookupCoreClass('StackTrace'); | 838 _coreTypes.stackTraceClass = lookupCoreClass('StackTrace'); |
983 _coreTypes.iterableClass = lookupCoreClass('Iterable'); | 839 _coreTypes.iterableClass = lookupCoreClass('Iterable'); |
984 _coreTypes.symbolClass = lookupCoreClass('Symbol'); | 840 _coreTypes.symbolClass = lookupCoreClass('Symbol'); |
985 if (!missingCoreClasses.isEmpty) { | 841 if (!missingCoreClasses.isEmpty) { |
986 internalError( | 842 reporter.internalError( |
987 coreLibrary, | 843 coreLibrary, |
988 'dart:core library does not contain required classes: ' | 844 'dart:core library does not contain required classes: ' |
989 '$missingCoreClasses'); | 845 '$missingCoreClasses'); |
990 } | 846 } |
991 } | 847 } |
992 | 848 |
993 Element _unnamedListConstructor; | 849 Element _unnamedListConstructor; |
994 Element get unnamedListConstructor { | 850 Element get unnamedListConstructor { |
995 if (_unnamedListConstructor != null) return _unnamedListConstructor; | 851 if (_unnamedListConstructor != null) return _unnamedListConstructor; |
996 return _unnamedListConstructor = listClass.lookupDefaultConstructor(); | 852 return _unnamedListConstructor = listClass.lookupDefaultConstructor(); |
(...skipping 16 matching lines...) Expand all Loading... |
1013 // multiple times. Implement a better mechanism where we can store | 869 // multiple times. Implement a better mechanism where we can store |
1014 // such caches in the compiler and get access to them through a | 870 // such caches in the compiler and get access to them through a |
1015 // suitably maintained static reference to the current compiler. | 871 // suitably maintained static reference to the current compiler. |
1016 StringToken.canonicalizedSubstrings.clear(); | 872 StringToken.canonicalizedSubstrings.clear(); |
1017 Selector.canonicalizedValues.clear(); | 873 Selector.canonicalizedValues.clear(); |
1018 | 874 |
1019 assert(uri != null || analyzeOnly || hasIncrementalSupport); | 875 assert(uri != null || analyzeOnly || hasIncrementalSupport); |
1020 return new Future.sync(() { | 876 return new Future.sync(() { |
1021 if (librariesToAnalyzeWhenRun != null) { | 877 if (librariesToAnalyzeWhenRun != null) { |
1022 return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) { | 878 return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) { |
1023 log('Analyzing $libraryUri ($buildId)'); | 879 reporter.log('Analyzing $libraryUri ($buildId)'); |
1024 return libraryLoader.loadLibrary(libraryUri); | 880 return libraryLoader.loadLibrary(libraryUri); |
1025 }); | 881 }); |
1026 } | 882 } |
1027 }).then((_) { | 883 }).then((_) { |
1028 if (uri != null) { | 884 if (uri != null) { |
1029 if (analyzeOnly) { | 885 if (analyzeOnly) { |
1030 log('Analyzing $uri ($buildId)'); | 886 reporter.log('Analyzing $uri ($buildId)'); |
1031 } else { | 887 } else { |
1032 log('Compiling $uri ($buildId)'); | 888 reporter.log('Compiling $uri ($buildId)'); |
1033 } | 889 } |
1034 return libraryLoader.loadLibrary(uri).then((LibraryElement library) { | 890 return libraryLoader.loadLibrary(uri).then((LibraryElement library) { |
1035 mainApp = library; | 891 mainApp = library; |
1036 }); | 892 }); |
1037 } | 893 } |
1038 }).then((_) { | 894 }).then((_) { |
1039 compileLoadedLibraries(); | 895 compileLoadedLibraries(); |
1040 }); | 896 }); |
1041 } | 897 } |
1042 | 898 |
(...skipping 13 matching lines...) Expand all Loading... |
1056 // Compilation requires a main method. | 912 // Compilation requires a main method. |
1057 errorElement = new ErroneousElementX( | 913 errorElement = new ErroneousElementX( |
1058 MessageKind.MISSING_MAIN, {'main': Identifiers.main}, | 914 MessageKind.MISSING_MAIN, {'main': Identifiers.main}, |
1059 Identifiers.main, mainApp); | 915 Identifiers.main, mainApp); |
1060 } | 916 } |
1061 mainFunction = backend.helperForMissingMain(); | 917 mainFunction = backend.helperForMissingMain(); |
1062 } else if (main.isErroneous && main.isSynthesized) { | 918 } else if (main.isErroneous && main.isSynthesized) { |
1063 if (main is ErroneousElement) { | 919 if (main is ErroneousElement) { |
1064 errorElement = main; | 920 errorElement = main; |
1065 } else { | 921 } else { |
1066 internalError(main, 'Problem with ${Identifiers.main}.'); | 922 reporter.internalError(main, 'Problem with ${Identifiers.main}.'); |
1067 } | 923 } |
1068 mainFunction = backend.helperForBadMain(); | 924 mainFunction = backend.helperForBadMain(); |
1069 } else if (!main.isFunction) { | 925 } else if (!main.isFunction) { |
1070 errorElement = new ErroneousElementX( | 926 errorElement = new ErroneousElementX( |
1071 MessageKind.MAIN_NOT_A_FUNCTION, {'main': Identifiers.main}, | 927 MessageKind.MAIN_NOT_A_FUNCTION, {'main': Identifiers.main}, |
1072 Identifiers.main, main); | 928 Identifiers.main, main); |
1073 mainFunction = backend.helperForBadMain(); | 929 mainFunction = backend.helperForBadMain(); |
1074 } else { | 930 } else { |
1075 mainFunction = main; | 931 mainFunction = main; |
1076 mainFunction.computeType(resolution); | 932 mainFunction.computeType(resolution); |
1077 FunctionSignature parameters = mainFunction.functionSignature; | 933 FunctionSignature parameters = mainFunction.functionSignature; |
1078 if (parameters.requiredParameterCount > 2) { | 934 if (parameters.requiredParameterCount > 2) { |
1079 int index = 0; | 935 int index = 0; |
1080 parameters.orderedForEachParameter((Element parameter) { | 936 parameters.orderedForEachParameter((Element parameter) { |
1081 if (index++ < 2) return; | 937 if (index++ < 2) return; |
1082 errorElement = new ErroneousElementX( | 938 errorElement = new ErroneousElementX( |
1083 MessageKind.MAIN_WITH_EXTRA_PARAMETER, {'main': Identifiers.main}, | 939 MessageKind.MAIN_WITH_EXTRA_PARAMETER, {'main': Identifiers.main}, |
1084 Identifiers.main, | 940 Identifiers.main, |
1085 parameter); | 941 parameter); |
1086 mainFunction = backend.helperForMainArity(); | 942 mainFunction = backend.helperForMainArity(); |
1087 // Don't warn about main not being used: | 943 // Don't warn about main not being used: |
1088 enqueuer.resolution.registerStaticUse(main); | 944 enqueuer.resolution.registerStaticUse(main); |
1089 }); | 945 }); |
1090 } | 946 } |
1091 } | 947 } |
1092 if (mainFunction == null) { | 948 if (mainFunction == null) { |
1093 if (errorElement == null && !analyzeOnly && !analyzeAll) { | 949 if (errorElement == null && !analyzeOnly && !analyzeAll) { |
1094 internalError(mainApp, "Problem with '${Identifiers.main}'."); | 950 reporter.internalError(mainApp, "Problem with '${Identifiers.main}'."); |
1095 } else { | 951 } else { |
1096 mainFunction = errorElement; | 952 mainFunction = errorElement; |
1097 } | 953 } |
1098 } | 954 } |
1099 if (errorElement != null && | 955 if (errorElement != null && |
1100 errorElement.isSynthesized && | 956 errorElement.isSynthesized && |
1101 !mainApp.isSynthesized) { | 957 !mainApp.isSynthesized) { |
1102 reportWarningMessage( | 958 reporter.reportWarningMessage( |
1103 errorElement, errorElement.messageKind, | 959 errorElement, errorElement.messageKind, |
1104 errorElement.messageArguments); | 960 errorElement.messageArguments); |
1105 } | 961 } |
1106 } | 962 } |
1107 | 963 |
1108 /// Analyze all member of the library in [libraryUri]. | 964 /// Analyze all member of the library in [libraryUri]. |
1109 /// | 965 /// |
1110 /// If [skipLibraryWithPartOfTag] is `true`, member analysis is skipped if the | 966 /// If [skipLibraryWithPartOfTag] is `true`, member analysis is skipped if the |
1111 /// library has a `part of` tag, assuming it is a part and not a library. | 967 /// library has a `part of` tag, assuming it is a part and not a library. |
1112 /// | 968 /// |
1113 /// This operation assumes an unclosed resolution queue and is only supported | 969 /// This operation assumes an unclosed resolution queue and is only supported |
1114 /// when the '--analyze-main' option is used. | 970 /// when the '--analyze-main' option is used. |
1115 Future<LibraryElement> analyzeUri( | 971 Future<LibraryElement> analyzeUri( |
1116 Uri libraryUri, | 972 Uri libraryUri, |
1117 {bool skipLibraryWithPartOfTag: true}) { | 973 {bool skipLibraryWithPartOfTag: true}) { |
1118 assert(analyzeMain); | 974 assert(analyzeMain); |
1119 log('Analyzing $libraryUri ($buildId)'); | 975 reporter.log('Analyzing $libraryUri ($buildId)'); |
1120 return libraryLoader.loadLibrary(libraryUri).then((LibraryElement library) { | 976 return libraryLoader.loadLibrary(libraryUri).then((LibraryElement library) { |
1121 var compilationUnit = library.compilationUnit; | 977 var compilationUnit = library.compilationUnit; |
1122 if (skipLibraryWithPartOfTag && compilationUnit.partTag != null) { | 978 if (skipLibraryWithPartOfTag && compilationUnit.partTag != null) { |
1123 return null; | 979 return null; |
1124 } | 980 } |
1125 fullyEnqueueLibrary(library, enqueuer.resolution); | 981 fullyEnqueueLibrary(library, enqueuer.resolution); |
1126 emptyQueue(enqueuer.resolution); | 982 emptyQueue(enqueuer.resolution); |
1127 enqueuer.resolution.logSummary(log); | 983 enqueuer.resolution.logSummary(reporter.log); |
1128 return library; | 984 return library; |
1129 }); | 985 }); |
1130 } | 986 } |
1131 | 987 |
1132 /// Performs the compilation when all libraries have been loaded. | 988 /// Performs the compilation when all libraries have been loaded. |
1133 void compileLoadedLibraries() { | 989 void compileLoadedLibraries() { |
1134 computeMain(); | 990 computeMain(); |
1135 | 991 |
1136 mirrorUsageAnalyzerTask.analyzeUsage(mainApp); | 992 mirrorUsageAnalyzerTask.analyzeUsage(mainApp); |
1137 | 993 |
1138 // In order to see if a library is deferred, we must compute the | 994 // In order to see if a library is deferred, we must compute the |
1139 // compile-time constants that are metadata. This means adding | 995 // compile-time constants that are metadata. This means adding |
1140 // something to the resolution queue. So we cannot wait with | 996 // something to the resolution queue. So we cannot wait with |
1141 // this until after the resolution queue is processed. | 997 // this until after the resolution queue is processed. |
1142 deferredLoadTask.beforeResolution(this); | 998 deferredLoadTask.beforeResolution(this); |
1143 | 999 |
1144 phase = PHASE_RESOLVING; | 1000 phase = PHASE_RESOLVING; |
1145 if (analyzeAll) { | 1001 if (analyzeAll) { |
1146 libraryLoader.libraries.forEach((LibraryElement library) { | 1002 libraryLoader.libraries.forEach((LibraryElement library) { |
1147 log('Enqueuing ${library.canonicalUri}'); | 1003 reporter.log('Enqueuing ${library.canonicalUri}'); |
1148 fullyEnqueueLibrary(library, enqueuer.resolution); | 1004 fullyEnqueueLibrary(library, enqueuer.resolution); |
1149 }); | 1005 }); |
1150 } else if (analyzeMain && mainApp != null) { | 1006 } else if (analyzeMain && mainApp != null) { |
1151 fullyEnqueueLibrary(mainApp, enqueuer.resolution); | 1007 fullyEnqueueLibrary(mainApp, enqueuer.resolution); |
1152 } | 1008 } |
1153 // Elements required by enqueueHelpers are global dependencies | 1009 // Elements required by enqueueHelpers are global dependencies |
1154 // that are not pulled in by a particular element. | 1010 // that are not pulled in by a particular element. |
1155 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); | 1011 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); |
1156 resolveLibraryMetadata(); | 1012 resolveLibraryMetadata(); |
1157 log('Resolving...'); | 1013 reporter.log('Resolving...'); |
1158 processQueue(enqueuer.resolution, mainFunction); | 1014 processQueue(enqueuer.resolution, mainFunction); |
1159 enqueuer.resolution.logSummary(log); | 1015 enqueuer.resolution.logSummary(reporter.log); |
1160 | 1016 |
1161 if (!showPackageWarnings && !suppressWarnings) { | 1017 _reporter.reportSuppressedMessagesSummary(); |
1162 suppressedWarnings.forEach((Uri uri, SuppressionInfo info) { | |
1163 MessageKind kind = MessageKind.HIDDEN_WARNINGS_HINTS; | |
1164 if (info.warnings == 0) { | |
1165 kind = MessageKind.HIDDEN_HINTS; | |
1166 } else if (info.hints == 0) { | |
1167 kind = MessageKind.HIDDEN_WARNINGS; | |
1168 } | |
1169 MessageTemplate template = MessageTemplate.TEMPLATES[kind]; | |
1170 Message message = template.message( | |
1171 {'warnings': info.warnings, | |
1172 'hints': info.hints, | |
1173 'uri': uri}, | |
1174 terseDiagnostics); | |
1175 reportDiagnostic( | |
1176 new DiagnosticMessage(null, null, message), | |
1177 const <DiagnosticMessage>[], | |
1178 api.Diagnostic.HINT); | |
1179 }); | |
1180 } | |
1181 | 1018 |
1182 if (compilationFailed){ | 1019 if (compilationFailed){ |
1183 if (!generateCodeWithCompileTimeErrors) return; | 1020 if (!generateCodeWithCompileTimeErrors) return; |
1184 if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) { | 1021 if (!backend.enableCodegenWithErrorsIfSupported(NO_LOCATION_SPANNABLE)) { |
1185 return; | 1022 return; |
1186 } | 1023 } |
1187 } | 1024 } |
1188 | 1025 |
1189 if (analyzeOnly) { | 1026 if (analyzeOnly) { |
1190 if (!analyzeAll && !compilationFailed) { | 1027 if (!analyzeAll && !compilationFailed) { |
(...skipping 10 matching lines...) Expand all Loading... |
1201 assert(mainFunction != null); | 1038 assert(mainFunction != null); |
1202 phase = PHASE_DONE_RESOLVING; | 1039 phase = PHASE_DONE_RESOLVING; |
1203 | 1040 |
1204 world.populate(); | 1041 world.populate(); |
1205 // Compute whole-program-knowledge that the backend needs. (This might | 1042 // Compute whole-program-knowledge that the backend needs. (This might |
1206 // require the information computed in [world.populate].) | 1043 // require the information computed in [world.populate].) |
1207 backend.onResolutionComplete(); | 1044 backend.onResolutionComplete(); |
1208 | 1045 |
1209 deferredLoadTask.onResolutionComplete(mainFunction); | 1046 deferredLoadTask.onResolutionComplete(mainFunction); |
1210 | 1047 |
1211 log('Inferring types...'); | 1048 reporter.log('Inferring types...'); |
1212 typesTask.onResolutionComplete(mainFunction); | 1049 typesTask.onResolutionComplete(mainFunction); |
1213 | 1050 |
1214 if (stopAfterTypeInference) return; | 1051 if (stopAfterTypeInference) return; |
1215 | 1052 |
1216 backend.onTypeInferenceComplete(); | 1053 backend.onTypeInferenceComplete(); |
1217 | 1054 |
1218 log('Compiling...'); | 1055 reporter.log('Compiling...'); |
1219 phase = PHASE_COMPILING; | 1056 phase = PHASE_COMPILING; |
1220 backend.onCodegenStart(); | 1057 backend.onCodegenStart(); |
1221 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. | 1058 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. |
1222 if (hasIsolateSupport) { | 1059 if (hasIsolateSupport) { |
1223 backend.enableIsolateSupport(enqueuer.codegen); | 1060 backend.enableIsolateSupport(enqueuer.codegen); |
1224 } | 1061 } |
1225 if (compileAll) { | 1062 if (compileAll) { |
1226 libraryLoader.libraries.forEach((LibraryElement library) { | 1063 libraryLoader.libraries.forEach((LibraryElement library) { |
1227 fullyEnqueueLibrary(library, enqueuer.codegen); | 1064 fullyEnqueueLibrary(library, enqueuer.codegen); |
1228 }); | 1065 }); |
1229 } | 1066 } |
1230 processQueue(enqueuer.codegen, mainFunction); | 1067 processQueue(enqueuer.codegen, mainFunction); |
1231 enqueuer.codegen.logSummary(log); | 1068 enqueuer.codegen.logSummary(reporter.log); |
1232 | 1069 |
1233 int programSize = backend.assembleProgram(); | 1070 int programSize = backend.assembleProgram(); |
1234 | 1071 |
1235 if (dumpInfo) { | 1072 if (dumpInfo) { |
1236 dumpInfoTask.reportSize(programSize); | 1073 dumpInfoTask.reportSize(programSize); |
1237 dumpInfoTask.dumpInfo(); | 1074 dumpInfoTask.dumpInfo(); |
1238 } | 1075 } |
1239 | 1076 |
1240 checkQueues(); | 1077 checkQueues(); |
1241 } | 1078 } |
(...skipping 28 matching lines...) Expand all Loading... |
1270 } | 1107 } |
1271 } | 1108 } |
1272 } | 1109 } |
1273 } | 1110 } |
1274 | 1111 |
1275 /** | 1112 /** |
1276 * Empty the [world] queue. | 1113 * Empty the [world] queue. |
1277 */ | 1114 */ |
1278 void emptyQueue(Enqueuer world) { | 1115 void emptyQueue(Enqueuer world) { |
1279 world.forEach((WorkItem work) { | 1116 world.forEach((WorkItem work) { |
1280 withCurrentElement(work.element, () { | 1117 reporter.withCurrentElement(work.element, () { |
1281 world.applyImpact(work.element, work.run(this, world)); | 1118 world.applyImpact(work.element, work.run(this, world)); |
1282 }); | 1119 }); |
1283 }); | 1120 }); |
1284 } | 1121 } |
1285 | 1122 |
1286 void processQueue(Enqueuer world, Element main) { | 1123 void processQueue(Enqueuer world, Element main) { |
1287 world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries); | 1124 world.nativeEnqueuer.processNativeClasses(libraryLoader.libraries); |
1288 if (main != null && !main.isErroneous) { | 1125 if (main != null && !main.isErroneous) { |
1289 FunctionElement mainMethod = main; | 1126 FunctionElement mainMethod = main; |
1290 mainMethod.computeType(resolution); | 1127 mainMethod.computeType(resolution); |
(...skipping 21 matching lines...) Expand all Loading... |
1312 | 1149 |
1313 /** | 1150 /** |
1314 * Perform various checks of the queues. This includes checking that | 1151 * Perform various checks of the queues. This includes checking that |
1315 * the queues are empty (nothing was added after we stopped | 1152 * the queues are empty (nothing was added after we stopped |
1316 * processing the queues). Also compute the number of methods that | 1153 * processing the queues). Also compute the number of methods that |
1317 * were resolved, but not compiled (aka excess resolution). | 1154 * were resolved, but not compiled (aka excess resolution). |
1318 */ | 1155 */ |
1319 checkQueues() { | 1156 checkQueues() { |
1320 for (Enqueuer world in [enqueuer.resolution, enqueuer.codegen]) { | 1157 for (Enqueuer world in [enqueuer.resolution, enqueuer.codegen]) { |
1321 world.forEach((WorkItem work) { | 1158 world.forEach((WorkItem work) { |
1322 internalError(work.element, "Work list is not empty."); | 1159 reporter.internalError(work.element, "Work list is not empty."); |
1323 }); | 1160 }); |
1324 } | 1161 } |
1325 if (!REPORT_EXCESS_RESOLUTION) return; | 1162 if (!REPORT_EXCESS_RESOLUTION) return; |
1326 var resolved = new Set.from(enqueuer.resolution.resolvedElements); | 1163 var resolved = new Set.from(enqueuer.resolution.resolvedElements); |
1327 for (Element e in enqueuer.codegen.generatedCode.keys) { | 1164 for (Element e in enqueuer.codegen.generatedCode.keys) { |
1328 resolved.remove(e); | 1165 resolved.remove(e); |
1329 } | 1166 } |
1330 for (Element e in new Set.from(resolved)) { | 1167 for (Element e in new Set.from(resolved)) { |
1331 if (e.isClass || | 1168 if (e.isClass || |
1332 e.isField || | 1169 e.isField || |
1333 e.isTypeVariable || | 1170 e.isTypeVariable || |
1334 e.isTypedef || | 1171 e.isTypedef || |
1335 identical(e.kind, ElementKind.ABSTRACT_FIELD)) { | 1172 identical(e.kind, ElementKind.ABSTRACT_FIELD)) { |
1336 resolved.remove(e); | 1173 resolved.remove(e); |
1337 } | 1174 } |
1338 if (identical(e.kind, ElementKind.GENERATIVE_CONSTRUCTOR)) { | 1175 if (identical(e.kind, ElementKind.GENERATIVE_CONSTRUCTOR)) { |
1339 resolved.remove(e); | 1176 resolved.remove(e); |
1340 } | 1177 } |
1341 if (backend.isBackendLibrary(e.library)) { | 1178 if (backend.isBackendLibrary(e.library)) { |
1342 resolved.remove(e); | 1179 resolved.remove(e); |
1343 } | 1180 } |
1344 } | 1181 } |
1345 log('Excess resolution work: ${resolved.length}.'); | 1182 reporter.log('Excess resolution work: ${resolved.length}.'); |
1346 for (Element e in resolved) { | 1183 for (Element e in resolved) { |
1347 reportWarningMessage(e, | 1184 reporter.reportWarningMessage(e, |
1348 MessageKind.GENERIC, | 1185 MessageKind.GENERIC, |
1349 {'text': 'Warning: $e resolved but not compiled.'}); | 1186 {'text': 'Warning: $e resolved but not compiled.'}); |
1350 } | 1187 } |
1351 } | 1188 } |
1352 | 1189 |
1353 WorldImpact analyzeElement(Element element) { | 1190 WorldImpact analyzeElement(Element element) { |
1354 assert(invariant(element, | 1191 assert(invariant(element, |
1355 element.impliesType || | 1192 element.impliesType || |
1356 element.isField || | 1193 element.isField || |
1357 element.isFunction || | 1194 element.isFunction || |
(...skipping 21 matching lines...) Expand all Loading... |
1379 } | 1216 } |
1380 | 1217 |
1381 WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) { | 1218 WorldImpact analyze(ResolutionWorkItem work, ResolutionEnqueuer world) { |
1382 assert(invariant(work.element, identical(world, enqueuer.resolution))); | 1219 assert(invariant(work.element, identical(world, enqueuer.resolution))); |
1383 assert(invariant(work.element, !work.isAnalyzed, | 1220 assert(invariant(work.element, !work.isAnalyzed, |
1384 message: 'Element ${work.element} has already been analyzed')); | 1221 message: 'Element ${work.element} has already been analyzed')); |
1385 if (shouldPrintProgress) { | 1222 if (shouldPrintProgress) { |
1386 // TODO(ahe): Add structured diagnostics to the compiler API and | 1223 // TODO(ahe): Add structured diagnostics to the compiler API and |
1387 // use it to separate this from the --verbose option. | 1224 // use it to separate this from the --verbose option. |
1388 if (phase == PHASE_RESOLVING) { | 1225 if (phase == PHASE_RESOLVING) { |
1389 log('Resolved ${enqueuer.resolution.resolvedElements.length} ' | 1226 reporter.log( |
| 1227 'Resolved ${enqueuer.resolution.resolvedElements.length} ' |
1390 'elements.'); | 1228 'elements.'); |
1391 progress.reset(); | 1229 progress.reset(); |
1392 } | 1230 } |
1393 } | 1231 } |
1394 AstElement element = work.element; | 1232 AstElement element = work.element; |
1395 if (world.hasBeenResolved(element)) { | 1233 if (world.hasBeenResolved(element)) { |
1396 return const WorldImpact(); | 1234 return const WorldImpact(); |
1397 } | 1235 } |
1398 WorldImpact worldImpact = analyzeElement(element); | 1236 WorldImpact worldImpact = analyzeElement(element); |
1399 backend.onElementResolved(element, element.resolvedAst.elements); | 1237 backend.onElementResolved(element, element.resolvedAst.elements); |
1400 return worldImpact; | 1238 return worldImpact; |
1401 } | 1239 } |
1402 | 1240 |
1403 WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) { | 1241 WorldImpact codegen(CodegenWorkItem work, CodegenEnqueuer world) { |
1404 assert(invariant(work.element, identical(world, enqueuer.codegen))); | 1242 assert(invariant(work.element, identical(world, enqueuer.codegen))); |
1405 if (shouldPrintProgress) { | 1243 if (shouldPrintProgress) { |
1406 // TODO(ahe): Add structured diagnostics to the compiler API and | 1244 // TODO(ahe): Add structured diagnostics to the compiler API and |
1407 // use it to separate this from the --verbose option. | 1245 // use it to separate this from the --verbose option. |
1408 log('Compiled ${enqueuer.codegen.generatedCode.length} methods.'); | 1246 reporter.log( |
| 1247 'Compiled ${enqueuer.codegen.generatedCode.length} methods.'); |
1409 progress.reset(); | 1248 progress.reset(); |
1410 } | 1249 } |
1411 return backend.codegen(work); | 1250 return backend.codegen(work); |
1412 } | 1251 } |
1413 | 1252 |
1414 DiagnosticMessage createMessage( | |
1415 Spannable spannable, | |
1416 MessageKind messageKind, | |
1417 [Map arguments = const {}]) { | |
1418 SourceSpan span = spanFromSpannable(spannable); | |
1419 MessageTemplate template = MessageTemplate.TEMPLATES[messageKind]; | |
1420 Message message = template.message(arguments, terseDiagnostics); | |
1421 return new DiagnosticMessage(span, spannable, message); | |
1422 } | |
1423 | |
1424 void reportError( | |
1425 DiagnosticMessage message, | |
1426 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { | |
1427 reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR); | |
1428 } | |
1429 | |
1430 void reportWarning( | |
1431 DiagnosticMessage message, | |
1432 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { | |
1433 reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING); | |
1434 } | |
1435 | |
1436 void reportHint( | |
1437 DiagnosticMessage message, | |
1438 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { | |
1439 reportDiagnosticInternal(message, infos, api.Diagnostic.HINT); | |
1440 } | |
1441 | |
1442 @deprecated | |
1443 void reportInfo(Spannable node, MessageKind messageKind, | |
1444 [Map arguments = const {}]) { | |
1445 reportDiagnosticInternal( | |
1446 createMessage(node, messageKind, arguments), | |
1447 const <DiagnosticMessage>[], | |
1448 api.Diagnostic.INFO); | |
1449 } | |
1450 | |
1451 void reportDiagnosticInternal(DiagnosticMessage message, | |
1452 List<DiagnosticMessage> infos, | |
1453 api.Diagnostic kind) { | |
1454 if (!showPackageWarnings && message.spannable != NO_LOCATION_SPANNABLE) { | |
1455 switch (kind) { | |
1456 case api.Diagnostic.WARNING: | |
1457 case api.Diagnostic.HINT: | |
1458 Element element = elementFromSpannable(message.spannable); | |
1459 if (!inUserCode(element, assumeInUserCode: true)) { | |
1460 Uri uri = getCanonicalUri(element); | |
1461 SuppressionInfo info = | |
1462 suppressedWarnings.putIfAbsent(uri, () => new SuppressionInfo()); | |
1463 if (kind == api.Diagnostic.WARNING) { | |
1464 info.warnings++; | |
1465 } else { | |
1466 info.hints++; | |
1467 } | |
1468 lastDiagnosticWasFiltered = true; | |
1469 return; | |
1470 } | |
1471 break; | |
1472 case api.Diagnostic.INFO: | |
1473 if (lastDiagnosticWasFiltered) { | |
1474 return; | |
1475 } | |
1476 break; | |
1477 } | |
1478 } | |
1479 lastDiagnosticWasFiltered = false; | |
1480 reportDiagnostic(message, infos, kind); | |
1481 } | |
1482 | |
1483 void reportDiagnostic(DiagnosticMessage message, | 1253 void reportDiagnostic(DiagnosticMessage message, |
1484 List<DiagnosticMessage> infos, | 1254 List<DiagnosticMessage> infos, |
1485 api.Diagnostic kind); | 1255 api.Diagnostic kind); |
1486 | 1256 |
1487 void reportAssertionFailure(SpannableAssertionFailure ex) { | 1257 void reportCrashInUserCode(String message, exception, stackTrace) { |
1488 String message = (ex.message != null) ? tryToString(ex.message) | 1258 _reporter.onCrashInUserCode(message, exception, stackTrace); |
1489 : tryToString(ex); | |
1490 reportDiagnosticInternal( | |
1491 createMessage(ex.node, MessageKind.GENERIC, {'text': message}), | |
1492 const <DiagnosticMessage>[], | |
1493 api.Diagnostic.CRASH); | |
1494 } | |
1495 | |
1496 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { | |
1497 if (begin == null || end == null) { | |
1498 // TODO(ahe): We can almost always do better. Often it is only | |
1499 // end that is null. Otherwise, we probably know the current | |
1500 // URI. | |
1501 throw 'Cannot find tokens to produce error message.'; | |
1502 } | |
1503 if (uri == null && currentElement != null) { | |
1504 uri = currentElement.compilationUnit.script.resourceUri; | |
1505 } | |
1506 return new SourceSpan.fromTokens(uri, begin, end); | |
1507 } | |
1508 | |
1509 SourceSpan spanFromNode(Node node) { | |
1510 return spanFromTokens(node.getBeginToken(), node.getEndToken()); | |
1511 } | |
1512 | |
1513 SourceSpan spanFromElement(Element element) { | |
1514 if (element != null && element.sourcePosition != null) { | |
1515 return element.sourcePosition; | |
1516 } | |
1517 while (element != null && element.isSynthesized) { | |
1518 element = element.enclosingElement; | |
1519 } | |
1520 if (element != null && | |
1521 element.sourcePosition == null && | |
1522 !element.isLibrary && | |
1523 !element.isCompilationUnit) { | |
1524 // Sometimes, the backend fakes up elements that have no | |
1525 // position. So we use the enclosing element instead. It is | |
1526 // not a good error location, but cancel really is "internal | |
1527 // error" or "not implemented yet", so the vicinity is good | |
1528 // enough for now. | |
1529 element = element.enclosingElement; | |
1530 // TODO(ahe): I plan to overhaul this infrastructure anyways. | |
1531 } | |
1532 if (element == null) { | |
1533 element = currentElement; | |
1534 } | |
1535 if (element == null) { | |
1536 return null; | |
1537 } | |
1538 | |
1539 if (element.sourcePosition != null) { | |
1540 return element.sourcePosition; | |
1541 } | |
1542 Token position = element.position; | |
1543 Uri uri = element.compilationUnit.script.resourceUri; | |
1544 return (position == null) | |
1545 ? new SourceSpan(uri, 0, 0) | |
1546 : spanFromTokens(position, position, uri); | |
1547 } | |
1548 | |
1549 SourceSpan spanFromHInstruction(HInstruction instruction) { | |
1550 Element element = _elementFromHInstruction(instruction); | |
1551 if (element == null) element = currentElement; | |
1552 SourceInformation position = instruction.sourceInformation; | |
1553 if (position == null) return spanFromElement(element); | |
1554 return position.sourceSpan; | |
1555 } | 1259 } |
1556 | 1260 |
1557 /** | 1261 /** |
1558 * Translates the [resolvedUri] into a readable URI. | 1262 * Translates the [resolvedUri] into a readable URI. |
1559 * | 1263 * |
1560 * The [importingLibrary] holds the library importing [resolvedUri] or | 1264 * The [importingLibrary] holds the library importing [resolvedUri] or |
1561 * [:null:] if [resolvedUri] is loaded as the main library. The | 1265 * [:null:] if [resolvedUri] is loaded as the main library. The |
1562 * [importingLibrary] is used to grant access to internal libraries from | 1266 * [importingLibrary] is used to grant access to internal libraries from |
1563 * platform libraries and patch libraries. | 1267 * platform libraries and patch libraries. |
1564 * | 1268 * |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1620 currentToken = currentToken.next; | 1324 currentToken = currentToken.next; |
1621 } | 1325 } |
1622 return firstToken; | 1326 return firstToken; |
1623 } | 1327 } |
1624 | 1328 |
1625 void reportUnusedCode() { | 1329 void reportUnusedCode() { |
1626 void checkLive(member) { | 1330 void checkLive(member) { |
1627 if (member.isErroneous) return; | 1331 if (member.isErroneous) return; |
1628 if (member.isFunction) { | 1332 if (member.isFunction) { |
1629 if (!enqueuer.resolution.hasBeenResolved(member)) { | 1333 if (!enqueuer.resolution.hasBeenResolved(member)) { |
1630 reportHintMessage( | 1334 reporter.reportHintMessage( |
1631 member, MessageKind.UNUSED_METHOD, {'name': member.name}); | 1335 member, MessageKind.UNUSED_METHOD, {'name': member.name}); |
1632 } | 1336 } |
1633 } else if (member.isClass) { | 1337 } else if (member.isClass) { |
1634 if (!member.isResolved) { | 1338 if (!member.isResolved) { |
1635 reportHintMessage( | 1339 reporter.reportHintMessage( |
1636 member, MessageKind.UNUSED_CLASS, {'name': member.name}); | 1340 member, MessageKind.UNUSED_CLASS, {'name': member.name}); |
1637 } else { | 1341 } else { |
1638 member.forEachLocalMember(checkLive); | 1342 member.forEachLocalMember(checkLive); |
1639 } | 1343 } |
1640 } else if (member.isTypedef) { | 1344 } else if (member.isTypedef) { |
1641 if (!member.isResolved) { | 1345 if (!member.isResolved) { |
1642 reportHintMessage( | 1346 reporter.reportHintMessage( |
1643 member, MessageKind.UNUSED_TYPEDEF, {'name': member.name}); | 1347 member, MessageKind.UNUSED_TYPEDEF, {'name': member.name}); |
1644 } | 1348 } |
1645 } | 1349 } |
1646 } | 1350 } |
1647 libraryLoader.libraries.forEach((LibraryElement library) { | 1351 libraryLoader.libraries.forEach((LibraryElement library) { |
1648 // TODO(ahe): Implement better heuristics to discover entry points of | 1352 // TODO(ahe): Implement better heuristics to discover entry points of |
1649 // packages and use that to discover unused implementation details in | 1353 // packages and use that to discover unused implementation details in |
1650 // packages. | 1354 // packages. |
1651 if (library.isPlatformLibrary || library.isPackageLibrary) return; | 1355 if (library.isPlatformLibrary || library.isPackageLibrary) return; |
1652 library.compilationUnits.forEach((unit) { | 1356 library.compilationUnits.forEach((unit) { |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1862 @override | 1566 @override |
1863 InterfaceType streamType([DartType elementType]) { | 1567 InterfaceType streamType([DartType elementType]) { |
1864 InterfaceType type = streamClass.computeType(resolution); | 1568 InterfaceType type = streamClass.computeType(resolution); |
1865 if (elementType == null) { | 1569 if (elementType == null) { |
1866 return streamClass.rawType; | 1570 return streamClass.rawType; |
1867 } | 1571 } |
1868 return type.createInstantiation([elementType]); | 1572 return type.createInstantiation([elementType]); |
1869 } | 1573 } |
1870 } | 1574 } |
1871 | 1575 |
| 1576 class _CompilerDiagnosticReporter extends DiagnosticReporter { |
| 1577 final Compiler compiler; |
| 1578 final DiagnosticOptions options; |
| 1579 |
| 1580 Element _currentElement; |
| 1581 bool hasCrashed = false; |
| 1582 |
| 1583 /// `true` if the last diagnostic was filtered, in which case the |
| 1584 /// accompanying info message should be filtered as well. |
| 1585 bool lastDiagnosticWasFiltered = false; |
| 1586 |
| 1587 /// Map containing information about the warnings and hints that have been |
| 1588 /// suppressed for each library. |
| 1589 Map<Uri, SuppressionInfo> suppressedWarnings = <Uri, SuppressionInfo>{}; |
| 1590 |
| 1591 _CompilerDiagnosticReporter(this.compiler, this.options); |
| 1592 |
| 1593 Element get currentElement => _currentElement; |
| 1594 |
| 1595 DiagnosticMessage createMessage( |
| 1596 Spannable spannable, |
| 1597 MessageKind messageKind, |
| 1598 [Map arguments = const {}]) { |
| 1599 SourceSpan span = spanFromSpannable(spannable); |
| 1600 MessageTemplate template = MessageTemplate.TEMPLATES[messageKind]; |
| 1601 Message message = template.message(arguments, options.terseDiagnostics); |
| 1602 return new DiagnosticMessage(span, spannable, message); |
| 1603 } |
| 1604 |
| 1605 void reportError( |
| 1606 DiagnosticMessage message, |
| 1607 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { |
| 1608 reportDiagnosticInternal(message, infos, api.Diagnostic.ERROR); |
| 1609 } |
| 1610 |
| 1611 void reportWarning( |
| 1612 DiagnosticMessage message, |
| 1613 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { |
| 1614 reportDiagnosticInternal(message, infos, api.Diagnostic.WARNING); |
| 1615 } |
| 1616 |
| 1617 void reportHint( |
| 1618 DiagnosticMessage message, |
| 1619 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { |
| 1620 reportDiagnosticInternal(message, infos, api.Diagnostic.HINT); |
| 1621 } |
| 1622 |
| 1623 @deprecated |
| 1624 void reportInfo(Spannable node, MessageKind messageKind, |
| 1625 [Map arguments = const {}]) { |
| 1626 reportDiagnosticInternal( |
| 1627 createMessage(node, messageKind, arguments), |
| 1628 const <DiagnosticMessage>[], |
| 1629 api.Diagnostic.INFO); |
| 1630 } |
| 1631 |
| 1632 void reportDiagnosticInternal(DiagnosticMessage message, |
| 1633 List<DiagnosticMessage> infos, |
| 1634 api.Diagnostic kind) { |
| 1635 if (!options.showPackageWarnings && |
| 1636 message.spannable != NO_LOCATION_SPANNABLE) { |
| 1637 switch (kind) { |
| 1638 case api.Diagnostic.WARNING: |
| 1639 case api.Diagnostic.HINT: |
| 1640 Element element = elementFromSpannable(message.spannable); |
| 1641 if (!compiler.inUserCode(element, assumeInUserCode: true)) { |
| 1642 Uri uri = compiler.getCanonicalUri(element); |
| 1643 SuppressionInfo info = |
| 1644 suppressedWarnings.putIfAbsent(uri, () => new SuppressionInfo()); |
| 1645 if (kind == api.Diagnostic.WARNING) { |
| 1646 info.warnings++; |
| 1647 } else { |
| 1648 info.hints++; |
| 1649 } |
| 1650 lastDiagnosticWasFiltered = true; |
| 1651 return; |
| 1652 } |
| 1653 break; |
| 1654 case api.Diagnostic.INFO: |
| 1655 if (lastDiagnosticWasFiltered) { |
| 1656 return; |
| 1657 } |
| 1658 break; |
| 1659 } |
| 1660 } |
| 1661 lastDiagnosticWasFiltered = false; |
| 1662 reportDiagnostic(message, infos, kind); |
| 1663 } |
| 1664 |
| 1665 void reportDiagnostic(DiagnosticMessage message, |
| 1666 List<DiagnosticMessage> infos, |
| 1667 api.Diagnostic kind) { |
| 1668 compiler.reportDiagnostic(message, infos, kind); |
| 1669 } |
| 1670 |
| 1671 /** |
| 1672 * Perform an operation, [f], returning the return value from [f]. If an |
| 1673 * error occurs then report it as having occurred during compilation of |
| 1674 * [element]. Can be nested. |
| 1675 */ |
| 1676 withCurrentElement(Element element, f()) { |
| 1677 Element old = currentElement; |
| 1678 _currentElement = element; |
| 1679 try { |
| 1680 return f(); |
| 1681 } on SpannableAssertionFailure catch (ex) { |
| 1682 if (!hasCrashed) { |
| 1683 reportAssertionFailure(ex); |
| 1684 pleaseReportCrash(); |
| 1685 } |
| 1686 hasCrashed = true; |
| 1687 rethrow; |
| 1688 } on StackOverflowError { |
| 1689 // We cannot report anything useful in this case, because we |
| 1690 // do not have enough stack space. |
| 1691 rethrow; |
| 1692 } catch (ex) { |
| 1693 if (hasCrashed) rethrow; |
| 1694 try { |
| 1695 unhandledExceptionOnElement(element); |
| 1696 } catch (doubleFault) { |
| 1697 // Ignoring exceptions in exception handling. |
| 1698 } |
| 1699 rethrow; |
| 1700 } finally { |
| 1701 _currentElement = old; |
| 1702 } |
| 1703 } |
| 1704 |
| 1705 void reportAssertionFailure(SpannableAssertionFailure ex) { |
| 1706 String message = (ex.message != null) ? tryToString(ex.message) |
| 1707 : tryToString(ex); |
| 1708 reportDiagnosticInternal( |
| 1709 createMessage(ex.node, MessageKind.GENERIC, {'text': message}), |
| 1710 const <DiagnosticMessage>[], |
| 1711 api.Diagnostic.CRASH); |
| 1712 } |
| 1713 |
| 1714 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { |
| 1715 if (begin == null || end == null) { |
| 1716 // TODO(ahe): We can almost always do better. Often it is only |
| 1717 // end that is null. Otherwise, we probably know the current |
| 1718 // URI. |
| 1719 throw 'Cannot find tokens to produce error message.'; |
| 1720 } |
| 1721 if (uri == null && currentElement != null) { |
| 1722 uri = currentElement.compilationUnit.script.resourceUri; |
| 1723 } |
| 1724 return new SourceSpan.fromTokens(uri, begin, end); |
| 1725 } |
| 1726 |
| 1727 SourceSpan spanFromNode(Node node) { |
| 1728 return spanFromTokens(node.getBeginToken(), node.getEndToken()); |
| 1729 } |
| 1730 |
| 1731 SourceSpan spanFromElement(Element element) { |
| 1732 if (element != null && element.sourcePosition != null) { |
| 1733 return element.sourcePosition; |
| 1734 } |
| 1735 while (element != null && element.isSynthesized) { |
| 1736 element = element.enclosingElement; |
| 1737 } |
| 1738 if (element != null && |
| 1739 element.sourcePosition == null && |
| 1740 !element.isLibrary && |
| 1741 !element.isCompilationUnit) { |
| 1742 // Sometimes, the backend fakes up elements that have no |
| 1743 // position. So we use the enclosing element instead. It is |
| 1744 // not a good error location, but cancel really is "internal |
| 1745 // error" or "not implemented yet", so the vicinity is good |
| 1746 // enough for now. |
| 1747 element = element.enclosingElement; |
| 1748 // TODO(ahe): I plan to overhaul this infrastructure anyways. |
| 1749 } |
| 1750 if (element == null) { |
| 1751 element = currentElement; |
| 1752 } |
| 1753 if (element == null) { |
| 1754 return null; |
| 1755 } |
| 1756 |
| 1757 if (element.sourcePosition != null) { |
| 1758 return element.sourcePosition; |
| 1759 } |
| 1760 Token position = element.position; |
| 1761 Uri uri = element.compilationUnit.script.resourceUri; |
| 1762 return (position == null) |
| 1763 ? new SourceSpan(uri, 0, 0) |
| 1764 : spanFromTokens(position, position, uri); |
| 1765 } |
| 1766 |
| 1767 SourceSpan spanFromHInstruction(HInstruction instruction) { |
| 1768 Element element = _elementFromHInstruction(instruction); |
| 1769 if (element == null) element = currentElement; |
| 1770 SourceInformation position = instruction.sourceInformation; |
| 1771 if (position == null) return spanFromElement(element); |
| 1772 return position.sourceSpan; |
| 1773 } |
| 1774 |
| 1775 SourceSpan spanFromSpannable(Spannable node) { |
| 1776 // TODO(johnniwinther): Disallow `node == null` ? |
| 1777 if (node == null) return null; |
| 1778 if (node == CURRENT_ELEMENT_SPANNABLE) { |
| 1779 node = currentElement; |
| 1780 } else if (node == NO_LOCATION_SPANNABLE) { |
| 1781 if (currentElement == null) return null; |
| 1782 node = currentElement; |
| 1783 } |
| 1784 if (node is SourceSpan) { |
| 1785 return node; |
| 1786 } else if (node is Node) { |
| 1787 return spanFromNode(node); |
| 1788 } else if (node is TokenPair) { |
| 1789 return spanFromTokens(node.begin, node.end); |
| 1790 } else if (node is Token) { |
| 1791 return spanFromTokens(node, node); |
| 1792 } else if (node is HInstruction) { |
| 1793 return spanFromHInstruction(node); |
| 1794 } else if (node is Element) { |
| 1795 return spanFromElement(node); |
| 1796 } else if (node is MetadataAnnotation) { |
| 1797 Uri uri = node.annotatedElement.compilationUnit.script.resourceUri; |
| 1798 return spanFromTokens(node.beginToken, node.endToken, uri); |
| 1799 } else if (node is Local) { |
| 1800 Local local = node; |
| 1801 return spanFromElement(local.executableContext); |
| 1802 } else { |
| 1803 throw 'No error location.'; |
| 1804 } |
| 1805 } |
| 1806 |
| 1807 Element _elementFromHInstruction(HInstruction instruction) { |
| 1808 return instruction.sourceElement is Element |
| 1809 ? instruction.sourceElement : null; |
| 1810 } |
| 1811 |
| 1812 internalError(Spannable node, reason) { |
| 1813 String message = tryToString(reason); |
| 1814 reportDiagnosticInternal( |
| 1815 createMessage(node, MessageKind.GENERIC, {'text': message}), |
| 1816 const <DiagnosticMessage>[], |
| 1817 api.Diagnostic.CRASH); |
| 1818 throw 'Internal Error: $message'; |
| 1819 } |
| 1820 |
| 1821 void unhandledExceptionOnElement(Element element) { |
| 1822 if (hasCrashed) return; |
| 1823 hasCrashed = true; |
| 1824 reportDiagnostic( |
| 1825 createMessage(element, MessageKind.COMPILER_CRASHED), |
| 1826 const <DiagnosticMessage>[], |
| 1827 api.Diagnostic.CRASH); |
| 1828 pleaseReportCrash(); |
| 1829 } |
| 1830 |
| 1831 void pleaseReportCrash() { |
| 1832 print( |
| 1833 MessageTemplate.TEMPLATES[MessageKind.PLEASE_REPORT_THE_CRASH] |
| 1834 .message({'buildId': compiler.buildId})); |
| 1835 } |
| 1836 |
| 1837 /// Finds the approximate [Element] for [node]. [currentElement] is used as |
| 1838 /// the default value. |
| 1839 Element elementFromSpannable(Spannable node) { |
| 1840 Element element; |
| 1841 if (node is Element) { |
| 1842 element = node; |
| 1843 } else if (node is HInstruction) { |
| 1844 element = _elementFromHInstruction(node); |
| 1845 } else if (node is MetadataAnnotation) { |
| 1846 element = node.annotatedElement; |
| 1847 } |
| 1848 return element != null ? element : currentElement; |
| 1849 } |
| 1850 |
| 1851 void log(message) { |
| 1852 Message msg = MessageTemplate.TEMPLATES[MessageKind.GENERIC] |
| 1853 .message({'text': '$message'}); |
| 1854 reportDiagnostic( |
| 1855 new DiagnosticMessage(null, null, msg), |
| 1856 const <DiagnosticMessage>[], |
| 1857 api.Diagnostic.VERBOSE_INFO); |
| 1858 } |
| 1859 |
| 1860 String tryToString(object) { |
| 1861 try { |
| 1862 return object.toString(); |
| 1863 } catch (_) { |
| 1864 return '<exception in toString()>'; |
| 1865 } |
| 1866 } |
| 1867 |
| 1868 onError(Uri uri, error) { |
| 1869 try { |
| 1870 if (!hasCrashed) { |
| 1871 hasCrashed = true; |
| 1872 if (error is SpannableAssertionFailure) { |
| 1873 reportAssertionFailure(error); |
| 1874 } else { |
| 1875 reportDiagnostic( |
| 1876 createMessage( |
| 1877 new SourceSpan(uri, 0, 0), |
| 1878 MessageKind.COMPILER_CRASHED), |
| 1879 const <DiagnosticMessage>[], |
| 1880 api.Diagnostic.CRASH); |
| 1881 } |
| 1882 pleaseReportCrash(); |
| 1883 } |
| 1884 } catch (doubleFault) { |
| 1885 // Ignoring exceptions in exception handling. |
| 1886 } |
| 1887 throw error; |
| 1888 } |
| 1889 |
| 1890 void onCrashInUserCode(String message, exception, stackTrace) { |
| 1891 hasCrashed = true; |
| 1892 print('$message: ${tryToString(exception)}'); |
| 1893 print(tryToString(stackTrace)); |
| 1894 } |
| 1895 |
| 1896 void reportSuppressedMessagesSummary() { |
| 1897 if (!options.showPackageWarnings && !options.suppressWarnings) { |
| 1898 suppressedWarnings.forEach((Uri uri, SuppressionInfo info) { |
| 1899 MessageKind kind = MessageKind.HIDDEN_WARNINGS_HINTS; |
| 1900 if (info.warnings == 0) { |
| 1901 kind = MessageKind.HIDDEN_HINTS; |
| 1902 } else if (info.hints == 0) { |
| 1903 kind = MessageKind.HIDDEN_WARNINGS; |
| 1904 } |
| 1905 MessageTemplate template = MessageTemplate.TEMPLATES[kind]; |
| 1906 Message message = template.message( |
| 1907 {'warnings': info.warnings, |
| 1908 'hints': info.hints, |
| 1909 'uri': uri}, |
| 1910 options.terseDiagnostics); |
| 1911 reportDiagnostic( |
| 1912 new DiagnosticMessage(null, null, message), |
| 1913 const <DiagnosticMessage>[], |
| 1914 api.Diagnostic.HINT); |
| 1915 }); |
| 1916 } |
| 1917 } |
| 1918 } |
| 1919 |
1872 // TODO(johnniwinther): Move [ResolverTask] here. | 1920 // TODO(johnniwinther): Move [ResolverTask] here. |
1873 class _CompilerResolution implements Resolution { | 1921 class _CompilerResolution implements Resolution { |
1874 final Compiler compiler; | 1922 final Compiler compiler; |
1875 | 1923 |
1876 _CompilerResolution(this.compiler); | 1924 _CompilerResolution(this.compiler); |
1877 | 1925 |
1878 @override | 1926 @override |
1879 DiagnosticListener get listener => compiler; | 1927 DiagnosticReporter get reporter => compiler.reporter; |
1880 | 1928 |
1881 @override | 1929 @override |
1882 Parsing get parsing => compiler.parsing; | 1930 Parsing get parsing => compiler.parsing; |
1883 | 1931 |
1884 @override | 1932 @override |
1885 CoreTypes get coreTypes => compiler.coreTypes; | 1933 CoreTypes get coreTypes => compiler.coreTypes; |
1886 | 1934 |
1887 @override | 1935 @override |
1888 void registerClass(ClassElement cls) { | 1936 void registerClass(ClassElement cls) { |
1889 compiler.world.registerClass(cls); | 1937 compiler.world.registerClass(cls); |
(...skipping 26 matching lines...) Expand all Loading... |
1916 } | 1964 } |
1917 | 1965 |
1918 // TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask] | 1966 // TODO(johnniwinther): Move [ParserTask], [PatchParserTask], [DietParserTask] |
1919 // and [ScannerTask] here. | 1967 // and [ScannerTask] here. |
1920 class _CompilerParsing implements Parsing { | 1968 class _CompilerParsing implements Parsing { |
1921 final Compiler compiler; | 1969 final Compiler compiler; |
1922 | 1970 |
1923 _CompilerParsing(this.compiler); | 1971 _CompilerParsing(this.compiler); |
1924 | 1972 |
1925 @override | 1973 @override |
1926 DiagnosticListener get listener => compiler; | 1974 DiagnosticReporter get reporter => compiler.reporter; |
1927 | 1975 |
1928 @override | 1976 @override |
1929 measure(f()) => compiler.parser.measure(f); | 1977 measure(f()) => compiler.parser.measure(f); |
1930 | 1978 |
1931 @override | 1979 @override |
1932 void parsePatchClass(ClassElement cls) { | 1980 void parsePatchClass(ClassElement cls) { |
1933 compiler.patchParser.measure(() { | 1981 compiler.patchParser.measure(() { |
1934 if (cls.isPatch) { | 1982 if (cls.isPatch) { |
1935 compiler.patchParser.parsePatchClassNode(cls); | 1983 compiler.patchParser.parsePatchClassNode(cls); |
1936 } | 1984 } |
1937 }); | 1985 }); |
1938 } | 1986 } |
1939 } | 1987 } |
OLD | NEW |