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 part of dart2js; | 5 part of dart2js; |
6 | 6 |
7 /** | 7 /** |
8 * If true, print a warning for each method that was resolved, but not | 8 * If true, print a warning for each method that was resolved, but not |
9 * compiled. | 9 * compiled. |
10 */ | 10 */ |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 | 74 |
75 typedef void PostProcessAction(); | 75 typedef void PostProcessAction(); |
76 | 76 |
77 class PostProcessTask { | 77 class PostProcessTask { |
78 final Element element; | 78 final Element element; |
79 final PostProcessAction action; | 79 final PostProcessAction action; |
80 | 80 |
81 PostProcessTask(this.element, this.action); | 81 PostProcessTask(this.element, this.action); |
82 } | 82 } |
83 | 83 |
84 // TODO(rnystrom): Now that file reading is asynchronous, this task is no longer | |
85 // used and the time spent reading files isn't easily measurable (or even that | |
86 // well-defined). As Peter says: | |
87 // | |
88 // As far as I can tell, we can only count how much time is being spent reading | |
89 // files by having a global counter that covers the time from the beginning of | |
90 // the compiler until it reaches a point when all libraries are scanned, and | |
91 // subtract the time spent in other tasks. | |
92 // | |
93 // I think you should drop measureAsync. I think we can measure the time spent | |
94 // reading files in dart2js.dart (you can just add a TODO). | |
84 class ReadingFilesTask extends CompilerTask { | 95 class ReadingFilesTask extends CompilerTask { |
ahe
2013/08/06 16:29:17
Can you remove this task?
Johnni Winther
2013/08/27 11:05:00
Done.
| |
85 ReadingFilesTask(Compiler compiler) : super(compiler); | 96 ReadingFilesTask(Compiler compiler) : super(compiler); |
86 String get name => 'Reading input files'; | 97 String get name => 'Reading input files'; |
87 } | 98 } |
88 | 99 |
89 abstract class Backend { | 100 abstract class Backend { |
90 final Compiler compiler; | 101 final Compiler compiler; |
91 final ConstantSystem constantSystem; | 102 final ConstantSystem constantSystem; |
92 | 103 |
93 Backend(this.compiler, | 104 Backend(this.compiler, |
94 [ConstantSystem constantSystem = DART_CONSTANT_SYSTEM]) | 105 [ConstantSystem constantSystem = DART_CONSTANT_SYSTEM]) |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
661 return spanFromTokens(annotation.beginToken, annotation.endToken); | 672 return spanFromTokens(annotation.beginToken, annotation.endToken); |
662 } else { | 673 } else { |
663 throw 'No error location.'; | 674 throw 'No error location.'; |
664 } | 675 } |
665 } | 676 } |
666 | 677 |
667 void log(message) { | 678 void log(message) { |
668 reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO); | 679 reportDiagnostic(null, message, api.Diagnostic.VERBOSE_INFO); |
669 } | 680 } |
670 | 681 |
671 bool run(Uri uri) { | 682 Future<bool> run(Uri uri) { |
672 totalCompileTime.start(); | 683 totalCompileTime.start(); |
673 try { | 684 |
674 runCompiler(uri); | 685 return runCompiler(uri).then((_) { |
675 } on CompilerCancelledException catch (exception) { | 686 return true; |
ahe
2013/08/06 16:29:17
Can't you eliminate this call to then?
Johnni Winther
2013/08/27 11:05:00
Done.
| |
676 log('Error: $exception'); | 687 }).catchError((error) { |
677 return false; | 688 if (error is CompilerCancelledException) { |
678 } catch (exception) { | 689 log('Error: $error'); |
690 return false; | |
691 } | |
692 | |
679 try { | 693 try { |
680 if (!hasCrashed) { | 694 if (!hasCrashed) { |
681 hasCrashed = true; | 695 hasCrashed = true; |
682 reportDiagnostic(new SourceSpan(uri, 0, 0), | 696 reportDiagnostic(new SourceSpan(uri, 0, 0), |
683 MessageKind.COMPILER_CRASHED.error().toString(), | 697 MessageKind.COMPILER_CRASHED.error().toString(), |
684 api.Diagnostic.CRASH); | 698 api.Diagnostic.CRASH); |
685 pleaseReportCrash(); | 699 pleaseReportCrash(); |
686 } | 700 } |
687 } catch (doubleFault) { | 701 } catch (doubleFault) { |
688 // Ignoring exceptions in exception handling. | 702 // Ignoring exceptions in exception handling. |
689 } | 703 } |
690 rethrow; | 704 throw error; |
691 } finally { | 705 }).whenComplete(() { |
692 tracer.close(); | 706 tracer.close(); |
693 totalCompileTime.stop(); | 707 totalCompileTime.stop(); |
694 } | 708 }).then((_) { |
695 return !compilationFailed; | 709 return !compilationFailed; |
ahe
2013/08/06 16:29:17
As it should be handled by this.
| |
710 }); | |
696 } | 711 } |
697 | 712 |
698 bool hasIsolateSupport() => isolateLibrary != null; | 713 bool hasIsolateSupport() => isolateLibrary != null; |
699 | 714 |
700 /** | 715 /** |
701 * This method is called before [library] import and export scopes have been | 716 * This method is called before [library] import and export scopes have been |
702 * set up. | 717 * set up. |
703 */ | 718 */ |
704 void onLibraryScanned(LibraryElement library, Uri uri) { | 719 void onLibraryScanned(LibraryElement library, Uri uri) { |
705 if (dynamicClass != null) { | 720 if (dynamicClass != null) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
742 mirrorSystemGetNameFunction = | 757 mirrorSystemGetNameFunction = |
743 cls.lookupLocalMember(const SourceString('getName')); | 758 cls.lookupLocalMember(const SourceString('getName')); |
744 } else if (symbolClass == cls) { | 759 } else if (symbolClass == cls) { |
745 symbolConstructor = cls.constructors.head; | 760 symbolConstructor = cls.constructors.head; |
746 } else if (symbolImplementationClass == cls) { | 761 } else if (symbolImplementationClass == cls) { |
747 symbolValidatedConstructor = symbolImplementationClass.lookupConstructor( | 762 symbolValidatedConstructor = symbolImplementationClass.lookupConstructor( |
748 symbolValidatedConstructorSelector); | 763 symbolValidatedConstructorSelector); |
749 } | 764 } |
750 } | 765 } |
751 | 766 |
752 LibraryElement scanBuiltinLibrary(String filename); | 767 Future<LibraryElement> scanBuiltinLibrary(String filename); |
753 | 768 |
754 void initializeSpecialClasses() { | 769 void initializeSpecialClasses() { |
755 final List missingCoreClasses = []; | 770 final List missingCoreClasses = []; |
756 ClassElement lookupCoreClass(String name) { | 771 ClassElement lookupCoreClass(String name) { |
757 ClassElement result = coreLibrary.find(new SourceString(name)); | 772 ClassElement result = coreLibrary.find(new SourceString(name)); |
758 if (result == null) { | 773 if (result == null) { |
759 missingCoreClasses.add(name); | 774 missingCoreClasses.add(name); |
760 } | 775 } |
761 return result; | 776 return result; |
762 } | 777 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
818 | 833 |
819 Element _filledListConstructor; | 834 Element _filledListConstructor; |
820 Element get filledListConstructor { | 835 Element get filledListConstructor { |
821 if (_filledListConstructor != null) return _filledListConstructor; | 836 if (_filledListConstructor != null) return _filledListConstructor; |
822 Selector callConstructor = new Selector.callConstructor( | 837 Selector callConstructor = new Selector.callConstructor( |
823 const SourceString("filled"), listClass.getLibrary()); | 838 const SourceString("filled"), listClass.getLibrary()); |
824 return _filledListConstructor = | 839 return _filledListConstructor = |
825 listClass.lookupConstructor(callConstructor); | 840 listClass.lookupConstructor(callConstructor); |
826 } | 841 } |
827 | 842 |
828 void scanBuiltinLibraries() { | 843 Future scanBuiltinLibraries() { |
829 jsHelperLibrary = scanBuiltinLibrary('_js_helper'); | 844 return scanBuiltinLibrary('_js_helper').then((LibraryElement library) { |
830 interceptorsLibrary = scanBuiltinLibrary('_interceptors'); | 845 jsHelperLibrary = library; |
831 foreignLibrary = scanBuiltinLibrary('_foreign_helper'); | 846 return scanBuiltinLibrary('_interceptors'); |
832 isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper'); | 847 }).then((LibraryElement library) { |
848 interceptorsLibrary = library; | |
849 return scanBuiltinLibrary('_foreign_helper'); | |
850 }).then((LibraryElement library) { | |
851 foreignLibrary = library; | |
852 return scanBuiltinLibrary('_isolate_helper'); | |
853 }).then((LibraryElement library) { | |
854 isolateHelperLibrary = library; | |
833 | 855 |
834 assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); | 856 assertMethod = jsHelperLibrary.find(const SourceString('assertHelper')); |
835 identicalFunction = coreLibrary.find(const SourceString('identical')); | 857 identicalFunction = coreLibrary.find(const SourceString('identical')); |
836 | 858 |
837 initializeSpecialClasses(); | 859 initializeSpecialClasses(); |
838 | 860 |
839 functionClass.ensureResolved(this); | 861 functionClass.ensureResolved(this); |
840 functionApplyMethod = | 862 functionApplyMethod = |
841 functionClass.lookupLocalMember(const SourceString('apply')); | 863 functionClass.lookupLocalMember(const SourceString('apply')); |
842 jsInvocationMirrorClass.ensureResolved(this); | 864 jsInvocationMirrorClass.ensureResolved(this); |
843 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); | 865 invokeOnMethod = jsInvocationMirrorClass.lookupLocalMember(INVOKE_ON); |
844 | 866 |
845 if (preserveComments) { | 867 if (preserveComments) { |
846 var uri = new Uri(scheme: 'dart', path: 'mirrors'); | 868 var uri = new Uri(scheme: 'dart', path: 'mirrors'); |
847 LibraryElement libraryElement = | 869 return libraryLoader.loadLibrary(uri, null, uri).then( |
848 libraryLoader.loadLibrary(uri, null, uri); | 870 (LibraryElement libraryElement) { |
849 documentClass = libraryElement.find(const SourceString('Comment')); | 871 documentClass = libraryElement.find(const SourceString('Comment')); |
850 } | 872 }); |
873 } | |
874 }); | |
851 } | 875 } |
852 | 876 |
853 void importHelperLibrary(LibraryElement library) { | 877 void importHelperLibrary(LibraryElement library) { |
854 if (jsHelperLibrary != null) { | 878 if (jsHelperLibrary != null) { |
855 libraryLoader.importLibrary(library, jsHelperLibrary, null); | 879 libraryLoader.importLibrary(library, jsHelperLibrary, null); |
856 } | 880 } |
857 } | 881 } |
858 | 882 |
859 /** | 883 /** |
860 * Get an [Uri] pointing to a patch for the dart: library with | 884 * Get an [Uri] pointing to a patch for the dart: library with |
861 * the given path. Returns null if there is no patch. | 885 * the given path. Returns null if there is no patch. |
862 */ | 886 */ |
863 Uri resolvePatchUri(String dartLibraryPath); | 887 Uri resolvePatchUri(String dartLibraryPath); |
864 | 888 |
865 void runCompiler(Uri uri) { | 889 Future runCompiler(Uri uri) { |
866 // TODO(ahe): This prevents memory leaks when invoking the compiler | 890 // TODO(ahe): This prevents memory leaks when invoking the compiler |
867 // multiple times. Implement a better mechanism where StringWrapper | 891 // multiple times. Implement a better mechanism where StringWrapper |
868 // instances are shared on a per library basis. | 892 // instances are shared on a per library basis. |
869 SourceString.canonicalizedValues.clear(); | 893 SourceString.canonicalizedValues.clear(); |
870 | 894 |
871 assert(uri != null || analyzeOnly); | 895 assert(uri != null || analyzeOnly); |
872 scanBuiltinLibraries(); | 896 return scanBuiltinLibraries().then((_) { |
873 if (librariesToAnalyzeWhenRun != null) { | 897 if (librariesToAnalyzeWhenRun != null) { |
874 for (Uri libraryUri in librariesToAnalyzeWhenRun) { | 898 return Future.forEach(librariesToAnalyzeWhenRun, (libraryUri) { |
875 log('analyzing $libraryUri ($buildId)'); | 899 log('analyzing $libraryUri ($buildId)'); |
876 libraryLoader.loadLibrary(libraryUri, null, libraryUri); | 900 return libraryLoader.loadLibrary(libraryUri, null, libraryUri); |
877 } | |
878 } | |
879 if (uri != null) { | |
880 if (analyzeOnly) { | |
881 log('analyzing $uri ($buildId)'); | |
882 } else { | |
883 log('compiling $uri ($buildId)'); | |
884 } | |
885 mainApp = libraryLoader.loadLibrary(uri, null, uri); | |
886 } | |
887 Element main = null; | |
888 if (mainApp != null) { | |
889 main = mainApp.find(MAIN); | |
890 if (main == null) { | |
891 if (!analyzeOnly) { | |
892 // Allow analyze only of libraries with no main. | |
893 reportFatalError( | |
894 mainApp, | |
895 MessageKind.GENERIC, | |
896 {'text': 'Error: Could not find "${MAIN.slowToString()}".'}); | |
897 } else if (!analyzeAll) { | |
898 reportFatalError( | |
899 mainApp, | |
900 MessageKind.GENERIC, | |
901 {'text': 'Error: Could not find "${MAIN.slowToString()}". ' | |
902 'No source will be analyzed. ' | |
903 'Use "--analyze-all" to analyze all code in the library.'}); | |
904 } | |
905 } else { | |
906 if (!main.isFunction()) { | |
907 reportFatalError( | |
908 main, | |
909 MessageKind.GENERIC, | |
910 {'text': 'Error: "${MAIN.slowToString()}" is not a function.'}); | |
911 } | |
912 FunctionElement mainMethod = main; | |
913 FunctionSignature parameters = mainMethod.computeSignature(this); | |
914 parameters.forEachParameter((Element parameter) { | |
915 reportError( | |
916 parameter, | |
917 MessageKind.GENERIC, | |
918 {'text': | |
919 'Error: "${MAIN.slowToString()}" cannot have parameters.'}); | |
920 }); | 901 }); |
921 } | 902 } |
903 }).then((_) { | |
904 if (uri != null) { | |
905 if (analyzeOnly) { | |
906 log('analyzing $uri ($buildId)'); | |
907 } else { | |
908 log('compiling $uri ($buildId)'); | |
909 } | |
910 return libraryLoader.loadLibrary(uri, null, uri) | |
911 .then((LibraryElement library) { | |
912 mainApp = library; | |
913 }); | |
914 } | |
915 }).then((_) { | |
916 Element main = null; | |
ahe
2013/08/06 16:29:17
I think it would make sense to move the rest of th
Johnni Winther
2013/08/27 11:05:00
Done.
| |
917 if (mainApp != null) { | |
918 main = mainApp.find(MAIN); | |
919 if (main == null) { | |
920 if (!analyzeOnly) { | |
921 // Allow analyze only of libraries with no main. | |
922 reportFatalError( | |
923 mainApp, | |
924 MessageKind.GENERIC, | |
925 {'text': 'Error: Could not find "${MAIN.slowToString()}".'}); | |
926 } else if (!analyzeAll) { | |
927 reportFatalError( | |
928 mainApp, | |
929 MessageKind.GENERIC, | |
930 {'text': 'Error: Could not find "${MAIN.slowToString()}". ' | |
931 'No source will be analyzed. ' | |
932 'Use "--analyze-all" to analyze all code in the library.'}); | |
933 } | |
934 } else { | |
935 if (!main.isFunction()) { | |
936 reportFatalError( | |
937 main, | |
938 MessageKind.GENERIC, | |
939 {'text': 'Error: "${MAIN.slowToString()}" is not a function.'}); | |
940 } | |
941 FunctionElement mainMethod = main; | |
942 FunctionSignature parameters = mainMethod.computeSignature(this); | |
943 parameters.forEachParameter((Element parameter) { | |
944 reportError( | |
945 parameter, | |
946 MessageKind.GENERIC, | |
947 {'text': | |
948 'Error: "${MAIN.slowToString()}" cannot have parameters.'}); | |
949 }); | |
950 } | |
922 | 951 |
923 mirrorUsageAnalyzerTask.analyzeUsage(mainApp); | 952 mirrorUsageAnalyzerTask.analyzeUsage(mainApp); |
924 | 953 |
925 // In order to see if a library is deferred, we must compute the | 954 // In order to see if a library is deferred, we must compute the |
926 // compile-time constants that are metadata. This means adding | 955 // compile-time constants that are metadata. This means adding |
927 // something to the resolution queue. So we cannot wait with | 956 // something to the resolution queue. So we cannot wait with |
928 // this until after the resolution queue is processed. | 957 // this until after the resolution queue is processed. |
929 // TODO(ahe): Clean this up, for example, by not enqueueing | 958 // TODO(ahe): Clean this up, for example, by not enqueueing |
930 // classes only used for metadata. | 959 // classes only used for metadata. |
931 deferredLoadTask.findDeferredLibraries(mainApp); | 960 deferredLoadTask.findDeferredLibraries(mainApp); |
932 } | 961 } |
933 | 962 |
934 log('Resolving...'); | 963 log('Resolving...'); |
935 phase = PHASE_RESOLVING; | 964 phase = PHASE_RESOLVING; |
936 if (analyzeAll) { | 965 if (analyzeAll) { |
937 libraries.forEach( | 966 libraries.forEach( |
938 (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); | 967 (_, lib) => fullyEnqueueLibrary(lib, enqueuer.resolution)); |
939 } | 968 } |
940 // Elements required by enqueueHelpers are global dependencies | 969 // Elements required by enqueueHelpers are global dependencies |
941 // that are not pulled in by a particular element. | 970 // that are not pulled in by a particular element. |
942 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); | 971 backend.enqueueHelpers(enqueuer.resolution, globalDependencies); |
943 processQueue(enqueuer.resolution, main); | 972 processQueue(enqueuer.resolution, main); |
944 enqueuer.resolution.logSummary(log); | 973 enqueuer.resolution.logSummary(log); |
945 | 974 |
946 if (compilationFailed) return; | 975 if (compilationFailed) return; |
947 if (analyzeOnly) return; | 976 if (analyzeOnly) return; |
948 assert(main != null); | 977 assert(main != null); |
949 phase = PHASE_DONE_RESOLVING; | 978 phase = PHASE_DONE_RESOLVING; |
950 | 979 |
951 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution | 980 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution |
952 // should know this. | 981 // should know this. |
953 world.populate(); | 982 world.populate(); |
954 // Compute whole-program-knowledge that the backend needs. (This might | 983 // Compute whole-program-knowledge that the backend needs. (This might |
955 // require the information computed in [world.populate].) | 984 // require the information computed in [world.populate].) |
956 backend.onResolutionComplete(); | 985 backend.onResolutionComplete(); |
957 | 986 |
958 deferredLoadTask.onResolutionComplete(main); | 987 deferredLoadTask.onResolutionComplete(main); |
959 | 988 |
960 log('Inferring types...'); | 989 log('Inferring types...'); |
961 typesTask.onResolutionComplete(main); | 990 typesTask.onResolutionComplete(main); |
962 | 991 |
963 log('Compiling...'); | 992 log('Compiling...'); |
964 phase = PHASE_COMPILING; | 993 phase = PHASE_COMPILING; |
965 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. | 994 // TODO(johnniwinther): Move these to [CodegenEnqueuer]. |
966 if (hasIsolateSupport()) { | 995 if (hasIsolateSupport()) { |
967 enqueuer.codegen.addToWorkList( | 996 enqueuer.codegen.addToWorkList( |
968 isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); | 997 isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE)); |
969 enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); | 998 enqueuer.codegen.registerGetOfStaticFunction(mainApp.find(MAIN)); |
970 } | 999 } |
971 if (enabledNoSuchMethod) { | 1000 if (enabledNoSuchMethod) { |
972 enqueuer.codegen.registerInvocation(noSuchMethodSelector); | 1001 enqueuer.codegen.registerInvocation(noSuchMethodSelector); |
973 enqueuer.codegen.addToWorkList(createInvocationMirrorElement); | 1002 enqueuer.codegen.addToWorkList(createInvocationMirrorElement); |
974 } | 1003 } |
975 if (compileAll) { | 1004 if (compileAll) { |
976 libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, enqueuer.codegen)); | 1005 libraries.forEach((_, lib) => fullyEnqueueLibrary(lib, |
977 } | 1006 enqueuer.codegen)); |
978 processQueue(enqueuer.codegen, main); | 1007 } |
979 enqueuer.codegen.logSummary(log); | 1008 processQueue(enqueuer.codegen, main); |
1009 enqueuer.codegen.logSummary(log); | |
980 | 1010 |
981 if (compilationFailed) return; | 1011 if (compilationFailed) return; |
982 | 1012 |
983 backend.assembleProgram(); | 1013 backend.assembleProgram(); |
984 | 1014 |
985 checkQueues(); | 1015 checkQueues(); |
986 | 1016 |
987 if (compilationFailed) { | 1017 if (compilationFailed) { |
988 assembledCode = null; // Signals failure. | 1018 assembledCode = null; // Signals failure. |
989 } | 1019 } |
1020 }); | |
990 } | 1021 } |
991 | 1022 |
992 void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) { | 1023 void fullyEnqueueLibrary(LibraryElement library, Enqueuer world) { |
993 void enqueueAll(Element element) { | 1024 void enqueueAll(Element element) { |
994 fullyEnqueueTopLevelElement(element, world); | 1025 fullyEnqueueTopLevelElement(element, world); |
995 } | 1026 } |
996 library.implementation.forEachLocalMember(enqueueAll); | 1027 library.implementation.forEachLocalMember(enqueueAll); |
997 } | 1028 } |
998 | 1029 |
999 void fullyEnqueueTopLevelElement(Element element, Enqueuer world) { | 1030 void fullyEnqueueTopLevelElement(Element element, Enqueuer world) { |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1311 Uri translateResolvedUri(LibraryElement importingLibrary, | 1342 Uri translateResolvedUri(LibraryElement importingLibrary, |
1312 Uri resolvedUri, Node node) { | 1343 Uri resolvedUri, Node node) { |
1313 unimplemented('Compiler.translateResolvedUri'); | 1344 unimplemented('Compiler.translateResolvedUri'); |
1314 } | 1345 } |
1315 | 1346 |
1316 /** | 1347 /** |
1317 * Reads the script specified by the [readableUri]. | 1348 * Reads the script specified by the [readableUri]. |
1318 * | 1349 * |
1319 * See [LibraryLoader] for terminology on URIs. | 1350 * See [LibraryLoader] for terminology on URIs. |
1320 */ | 1351 */ |
1321 Script readScript(Uri readableUri, [Node node]) { | 1352 Future<Script> readScript(Uri readableUri, [Element element, Node node]) { |
1322 unimplemented('Compiler.readScript'); | 1353 unimplemented('Compiler.readScript'); |
1323 } | 1354 } |
1324 | 1355 |
1325 String get legDirectory { | 1356 String get legDirectory { |
1326 unimplemented('Compiler.legDirectory'); | 1357 unimplemented('Compiler.legDirectory'); |
1327 } | 1358 } |
1328 | 1359 |
1329 // TODO(karlklose): split into findHelperFunction and findHelperClass and | 1360 // TODO(karlklose): split into findHelperFunction and findHelperClass and |
1330 // add a check that the element has the expected kind. | 1361 // add a check that the element has the expected kind. |
1331 Element findHelper(SourceString name) | 1362 Element findHelper(SourceString name) |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1455 * [invariant] as the argument to an [:assert:] statement: | 1486 * [invariant] as the argument to an [:assert:] statement: |
1456 * | 1487 * |
1457 * assert(invariant(position, isValid)); | 1488 * assert(invariant(position, isValid)); |
1458 * | 1489 * |
1459 * [spannable] must be non-null and will be used to provide positional | 1490 * [spannable] must be non-null and will be used to provide positional |
1460 * information in the generated error message. | 1491 * information in the generated error message. |
1461 */ | 1492 */ |
1462 bool invariant(Spannable spannable, var condition, {var message: null}) { | 1493 bool invariant(Spannable spannable, var condition, {var message: null}) { |
1463 // TODO(johnniwinther): Use [spannable] and [message] to provide better | 1494 // TODO(johnniwinther): Use [spannable] and [message] to provide better |
1464 // information on assertion errors. | 1495 // information on assertion errors. |
1496 if (spannable == null) { | |
1497 throw new SpannableAssertionFailure(CURRENT_ELEMENT_SPANNABLE, | |
1498 "Spannable was null for invariant. Use CURRENT_ELEMENT_SPANNABLE."); | |
1499 } | |
1465 if (condition is Function){ | 1500 if (condition is Function){ |
1466 condition = condition(); | 1501 condition = condition(); |
1467 } | 1502 } |
1468 if (spannable == null || !condition) { | 1503 if (!condition) { |
1469 if (message is Function) { | 1504 if (message is Function) { |
1470 message = message(); | 1505 message = message(); |
1471 } | 1506 } |
1472 throw new SpannableAssertionFailure(spannable, message); | 1507 throw new SpannableAssertionFailure(spannable, message); |
1473 } | 1508 } |
1474 return true; | 1509 return true; |
1475 } | 1510 } |
1476 | 1511 |
1477 /// A sink that drains into /dev/null. | 1512 /// A sink that drains into /dev/null. |
1478 class NullSink implements EventSink<String> { | 1513 class NullSink implements EventSink<String> { |
1479 final String name; | 1514 final String name; |
1480 | 1515 |
1481 NullSink(this.name); | 1516 NullSink(this.name); |
1482 | 1517 |
1483 add(String value) {} | 1518 add(String value) {} |
1484 | 1519 |
1485 void addError(Object error) {} | 1520 void addError(Object error) {} |
1486 | 1521 |
1487 void close() {} | 1522 void close() {} |
1488 | 1523 |
1489 toString() => name; | 1524 toString() => name; |
1490 | 1525 |
1491 /// Convenience method for getting an [api.CompilerOutputProvider]. | 1526 /// Convenience method for getting an [api.CompilerOutputProvider]. |
1492 static NullSink outputProvider(String name, String extension) { | 1527 static NullSink outputProvider(String name, String extension) { |
1493 return new NullSink('$name.$extension'); | 1528 return new NullSink('$name.$extension'); |
1494 } | 1529 } |
1495 } | 1530 } |
OLD | NEW |