| 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 |