| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #library('dart2js'); | |
| 6 | |
| 7 #import('dart:io'); | |
| 8 #import('dart:utf'); | |
| 9 | |
| 10 #import('../../lib/uri/uri.dart'); | |
| 11 #import('../../frog/leg/api.dart', prefix: 'api'); | |
| 12 #import('../../frog/leg/io/io.dart', prefix: 'io'); | |
| 13 #import('../../frog/leg/colors.dart'); | |
| 14 #import('source_file.dart'); | |
| 15 | |
| 16 String relativize(Uri base, Uri uri) { | |
| 17 if (base.scheme == 'file' && | |
| 18 base.scheme == uri.scheme && | |
| 19 base.userInfo == uri.userInfo && | |
| 20 base.domain == uri.domain && | |
| 21 base.port == uri.port && | |
| 22 uri.query == "" && uri.fragment == "") { | |
| 23 if (uri.path.startsWith(base.path)) { | |
| 24 return uri.path.substring(base.path.length); | |
| 25 } | |
| 26 List<String> uriParts = uri.path.split('/'); | |
| 27 List<String> baseParts = base.path.split('/'); | |
| 28 int common = 0; | |
| 29 int length = Math.min(uriParts.length, baseParts.length); | |
| 30 while (common < length && uriParts[common] == baseParts[common]) { | |
| 31 common++; | |
| 32 } | |
| 33 StringBuffer sb = new StringBuffer(); | |
| 34 for (int i = common + 1; i < baseParts.length; i++) { | |
| 35 sb.add('../'); | |
| 36 } | |
| 37 for (int i = common; i < uriParts.length - 1; i++) { | |
| 38 sb.add('${uriParts[i]}/'); | |
| 39 } | |
| 40 sb.add('${uriParts.last()}'); | |
| 41 return sb.toString(); | |
| 42 } | |
| 43 return uri.toString(); | |
| 44 } | |
| 45 | |
| 46 void compile(List<String> argv) { | |
| 47 Uri cwd = new Uri(scheme: 'file', path: io.getCurrentDirectory()); | |
| 48 bool throwOnError = false; | |
| 49 bool showWarnings = true; | |
| 50 bool verbose = false; | |
| 51 Uri libraryRoot = cwd; | |
| 52 Uri out = cwd.resolve('out.js'); | |
| 53 | |
| 54 List<String> arguments = <String>[]; | |
| 55 for (String argument in argv) { | |
| 56 if ('--throw-on-error' == argument) { | |
| 57 throwOnError = true; | |
| 58 } else if ('--suppress-warnings' == argument) { | |
| 59 showWarnings = false; | |
| 60 } else if ('--verbose' == argument) { | |
| 61 verbose = true; | |
| 62 } else if (argument.startsWith('--library-root=')) { | |
| 63 String path = argument.substring(argument.indexOf('=') + 1); | |
| 64 if (!path.endsWith("/")) path = "$path/"; | |
| 65 libraryRoot = cwd.resolve(path); | |
| 66 } else if (argument.startsWith('--out=')) { | |
| 67 String path = argument.substring(argument.indexOf('=') + 1); | |
| 68 out = cwd.resolve(path); | |
| 69 } else if (argument.startsWith('-')) { | |
| 70 throw new AbortLeg('unknown option $argument'); | |
| 71 } else { | |
| 72 arguments.add(argument); | |
| 73 } | |
| 74 } | |
| 75 if (arguments.isEmpty()) { | |
| 76 throw new AbortLeg('no files to compile'); | |
| 77 } | |
| 78 if (arguments.length > 1) { | |
| 79 var extra = arguments.getRange(1, arguments.length - 1); | |
| 80 throw new AbortLeg('extra arguments: $extra'); | |
| 81 } | |
| 82 | |
| 83 Map<String, SourceFile> sourceFiles = <SourceFile>{}; | |
| 84 int dartBytesRead = 0; | |
| 85 | |
| 86 Future<String> provider(Uri uri) { | |
| 87 if (uri.scheme != 'file') { | |
| 88 throw new IllegalArgumentException(uri); | |
| 89 } | |
| 90 String source = readAll(uri.path); | |
| 91 dartBytesRead += source.length; | |
| 92 sourceFiles[uri.toString()] = | |
| 93 new SourceFile(relativize(cwd, uri), source); | |
| 94 Completer<String> completer = new Completer<String>(); | |
| 95 completer.complete(source); | |
| 96 return completer.future; | |
| 97 } | |
| 98 | |
| 99 void info(var message) { | |
| 100 if (verbose) print('${green("info:")} $message'); | |
| 101 } | |
| 102 | |
| 103 void handler(Uri uri, int begin, int end, String message, bool fatal) { | |
| 104 if (uri === null && !fatal) { | |
| 105 info(message); | |
| 106 return; | |
| 107 } | |
| 108 if (uri === null) { | |
| 109 assert(fatal); | |
| 110 print(message); | |
| 111 } else if (fatal || showWarnings) { | |
| 112 SourceFile file = sourceFiles[uri.toString()]; | |
| 113 print(file.getLocationMessage(message, begin, end, true)); | |
| 114 } | |
| 115 if (fatal && throwOnError) throw new AbortLeg(message); | |
| 116 } | |
| 117 | |
| 118 Uri uri = cwd.resolve(arguments[0]); | |
| 119 info('compiling $uri'); | |
| 120 | |
| 121 // TODO(ahe): We expect the future to be complete and call value | |
| 122 // directly. In effect, we don't support truly asynchronous API. | |
| 123 String code = api.compile(uri, libraryRoot, provider, handler).value; | |
| 124 if (code === null) throw new AbortLeg('compilation failed'); | |
| 125 writeString(out, code); | |
| 126 int jsBytesWritten = code.length; | |
| 127 info('compiled $dartBytesRead bytes Dart -> $jsBytesWritten bytes JS ' | |
| 128 + 'in ${relativize(cwd, out)}'); | |
| 129 } | |
| 130 | |
| 131 class AbortLeg { | |
| 132 final message; | |
| 133 AbortLeg(this.message); | |
| 134 toString() => 'Aborted due to --throw-on-error: $message'; | |
| 135 } | |
| 136 | |
| 137 void writeString(Uri uri, String text) { | |
| 138 if (uri.scheme != 'file') { | |
| 139 throw new AbortLeg('unhandled scheme ${uri.scheme}'); | |
| 140 } | |
| 141 var file = new File(uri.path).openSync(FileMode.WRITE); | |
| 142 file.writeStringSync(text); | |
| 143 file.closeSync(); | |
| 144 } | |
| 145 | |
| 146 String readAll(String filename) { | |
| 147 var file = (new File(filename)).openSync(); | |
| 148 var length = file.lengthSync(); | |
| 149 var buffer = new List<int>(length); | |
| 150 var bytes = file.readListSync(buffer, 0, length); | |
| 151 file.closeSync(); | |
| 152 return new String.fromCharCodes(new Utf8Decoder(buffer).decodeRest()); | |
| 153 } | |
| OLD | NEW |