Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 source_file_provider; | 5 library source_file_provider; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:io'; | 9 import 'dart:io'; |
| 10 import 'dart:math' as math; | 10 import 'dart:math' as math; |
| 11 import 'dart:typed_data'; | 11 import 'dart:typed_data'; |
| 12 | 12 |
| 13 import '../compiler.dart' as api show Diagnostic; | 13 import '../compiler.dart' as api show Diagnostic; |
| 14 import '../compiler_new.dart' as api; | 14 import '../compiler_new.dart' as api; |
| 15 import '../compiler_new.dart'; | 15 import '../compiler_new.dart'; |
| 16 import 'colors.dart' as colors; | 16 import 'colors.dart' as colors; |
| 17 import 'dart2js.dart' show AbortLeg; | 17 import 'dart2js.dart' show AbortLeg; |
| 18 import 'filenames.dart'; | 18 import 'filenames.dart'; |
| 19 import 'io/source_file.dart'; | 19 import 'io/source_file.dart'; |
| 20 import 'util/uri_extras.dart'; | 20 import 'util/uri_extras.dart'; |
| 21 | 21 |
| 22 List<int> readAll(String filename) { | |
| 23 var file = (new File(filename)).openSync(); | |
| 24 var length = file.lengthSync(); | |
| 25 // +1 to have a 0 terminated list, see [Scanner]. | |
| 26 var buffer = new Uint8List(length + 1); | |
| 27 file.readIntoSync(buffer, 0, length); | |
| 28 file.closeSync(); | |
| 29 return buffer; | |
| 30 } | |
| 31 | |
| 32 abstract class SourceFileProvider implements CompilerInput { | 22 abstract class SourceFileProvider implements CompilerInput { |
| 33 bool isWindows = (Platform.operatingSystem == 'windows'); | 23 bool isWindows = (Platform.operatingSystem == 'windows'); |
| 34 Uri cwd = currentDirectory; | 24 Uri cwd = currentDirectory; |
| 35 Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{}; | 25 Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{}; |
| 36 int dartCharactersRead = 0; | 26 int dartCharactersRead = 0; |
| 37 | 27 |
| 38 Future<String> readStringFromUri(Uri resourceUri) { | 28 Future<String> readStringFromUri(Uri resourceUri) { |
| 39 return readUtf8BytesFromUri(resourceUri).then(UTF8.decode); | 29 return readUtf8BytesFromUri(resourceUri).then(UTF8.decode); |
| 40 } | 30 } |
| 41 | 31 |
| 42 Future<List<int>> readUtf8BytesFromUri(Uri resourceUri) { | 32 Future<List<int>> readUtf8BytesFromUri(Uri resourceUri) { |
| 43 if (resourceUri.scheme == 'file') { | 33 if (resourceUri.scheme == 'file') { |
| 44 return _readFromFile(resourceUri); | 34 return _readFromFile(resourceUri); |
| 45 } else if (resourceUri.scheme == 'http' || resourceUri.scheme == 'https') { | 35 } else if (resourceUri.scheme == 'http' || resourceUri.scheme == 'https') { |
| 46 return _readFromHttp(resourceUri); | 36 return _readFromHttp(resourceUri); |
| 47 } else { | 37 } else { |
| 48 throw new ArgumentError("Unknown scheme in uri '$resourceUri'"); | 38 throw new ArgumentError("Unknown scheme in uri '$resourceUri'"); |
| 49 } | 39 } |
| 50 } | 40 } |
| 51 | 41 |
| 52 Future<List<int>> _readFromFile(Uri resourceUri) { | 42 Future<List<int>> _readFromFile(Uri resourceUri) { |
| 53 assert(resourceUri.scheme == 'file'); | 43 assert(resourceUri.scheme == 'file'); |
| 54 List<int> source; | 44 List<int> source; |
| 55 try { | 45 try { |
| 56 source = readAll(resourceUri.toFilePath()); | 46 source = _readAll(resourceUri.toFilePath()); |
| 57 } on FileSystemException catch (ex) { | 47 } on FileSystemException catch (ex) { |
| 58 OSError ose = ex.osError; | 48 String message = ex.osError?.message; |
| 59 String detail = | 49 String detail = message != null ? ' ($message)' : ''; |
| 60 (ose != null && ose.message != null) ? ' (${ose.message})' : ''; | |
| 61 return new Future.error( | 50 return new Future.error( |
| 62 "Error reading '${relativize(cwd, resourceUri, isWindows)}'" | 51 "Error reading '${relativizeUri(resourceUri)}' $detail"); |
| 63 "$detail"); | |
| 64 } | 52 } |
| 65 dartCharactersRead += source.length; | 53 dartCharactersRead += source.length; |
| 66 sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile( | 54 sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile( |
| 67 resourceUri, relativizeUri(resourceUri), source); | 55 resourceUri, relativizeUri(resourceUri), source); |
| 68 return new Future.value(source); | 56 return new Future.value(source); |
| 69 } | 57 } |
| 70 | 58 |
| 71 Future<List<int>> _readFromHttp(Uri resourceUri) { | 59 Future<List<int>> _readFromHttp(Uri resourceUri) { |
| 72 assert(resourceUri.scheme == 'http'); | 60 assert(resourceUri.scheme == 'http'); |
| 73 HttpClient client = new HttpClient(); | 61 HttpClient client = new HttpClient(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 93 } | 81 } |
| 94 dartCharactersRead += totalLength; | 82 dartCharactersRead += totalLength; |
| 95 sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile( | 83 sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile( |
| 96 resourceUri, resourceUri.toString(), result); | 84 resourceUri, resourceUri.toString(), result); |
| 97 return result; | 85 return result; |
| 98 }); | 86 }); |
| 99 } | 87 } |
| 100 | 88 |
| 101 // TODO(johnniwinther): Remove this when no longer needed for the old compiler | 89 // TODO(johnniwinther): Remove this when no longer needed for the old compiler |
| 102 // API. | 90 // API. |
| 103 Future/*<List<int> | String>*/ call(Uri resourceUri); | 91 Future/*<List<int> | String>*/ call(Uri resourceUri) => throw "unimplemented"; |
| 104 | 92 |
| 105 relativizeUri(Uri uri) => relativize(cwd, uri, isWindows); | 93 relativizeUri(Uri uri) => relativize(cwd, uri, isWindows); |
| 106 | 94 |
| 107 SourceFile getSourceFile(Uri resourceUri) { | 95 SourceFile getSourceFile(Uri resourceUri) { |
| 108 return sourceFiles[resourceUri]; | 96 return sourceFiles[resourceUri]; |
| 109 } | 97 } |
| 110 } | 98 } |
| 111 | 99 |
| 100 List<int> _readAll(String filename) { | |
| 101 var file = (new File(filename)).openSync(); | |
| 102 var length = file.lengthSync(); | |
| 103 // +1 to have a 0 terminated list, see [Scanner]. | |
| 104 var buffer = new Uint8List(length + 1); | |
| 105 file.readIntoSync(buffer, 0, length); | |
| 106 file.closeSync(); | |
| 107 return buffer; | |
| 108 } | |
| 109 | |
| 112 class CompilerSourceFileProvider extends SourceFileProvider { | 110 class CompilerSourceFileProvider extends SourceFileProvider { |
| 113 // TODO(johnniwinther): Remove this when no longer needed for the old compiler | 111 // TODO(johnniwinther): Remove this when no longer needed for the old compiler |
| 114 // API. | 112 // API. |
| 115 Future<List<int>> call(Uri resourceUri) => readFromUri(resourceUri); | 113 Future<List<int>> call(Uri resourceUri) => readFromUri(resourceUri); |
| 116 | 114 |
| 117 @override | 115 @override |
| 118 Future readFromUri(Uri uri) => readUtf8BytesFromUri(uri); | 116 Future readFromUri(Uri uri) => readUtf8BytesFromUri(uri); |
| 119 } | 117 } |
| 120 | 118 |
| 121 class FormattingDiagnosticHandler implements CompilerDiagnostics { | 119 class FormattingDiagnosticHandler implements CompilerDiagnostics { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 charactersWritten += data.length; | 321 charactersWritten += data.length; |
| 324 } | 322 } |
| 325 | 323 |
| 326 onDone() { | 324 onDone() { |
| 327 output.closeSync(); | 325 output.closeSync(); |
| 328 if (isPrimaryOutput) { | 326 if (isPrimaryOutput) { |
| 329 totalCharactersWritten += charactersWritten; | 327 totalCharactersWritten += charactersWritten; |
| 330 } | 328 } |
| 331 } | 329 } |
| 332 | 330 |
| 333 return new EventSinkWrapper(writeStringSync, onDone); | 331 return new _EventSinkWrapper(writeStringSync, onDone); |
| 334 } | 332 } |
| 335 } | 333 } |
| 336 | 334 |
| 337 class EventSinkWrapper extends EventSink<String> { | 335 class _EventSinkWrapper extends EventSink<String> { |
| 338 var onAdd, onClose; | 336 var onAdd, onClose; |
| 339 | 337 |
| 340 EventSinkWrapper(this.onAdd, this.onClose); | 338 _EventSinkWrapper(this.onAdd, this.onClose); |
| 341 | 339 |
| 342 void add(String data) => onAdd(data); | 340 void add(String data) => onAdd(data); |
| 343 | 341 |
| 344 void addError(error, [StackTrace stackTrace]) => throw error; | 342 void addError(error, [StackTrace stackTrace]) => throw error; |
| 345 | 343 |
| 346 void close() => onClose(); | 344 void close() => onClose(); |
| 347 } | 345 } |
| 346 | |
| 347 /// Adapter to integrate dart2js in bazel. | |
| 348 /// | |
| 349 /// To handle bazel's special layout: | |
| 350 /// | |
| 351 /// * We specify a .packages configuration file that expands packages to their | |
| 352 /// corresponding bazel location. This way there is no need to create a pub | |
| 353 /// cache prior to invoking dart2js. | |
| 354 /// | |
| 355 /// * We provide a mapping that can make all urls relative to the bazel root. | |
| 356 /// To the compiler, URIs look like: | |
| 357 /// file:///bazel-root/a/b/c.dart | |
| 358 /// | |
| 359 /// even though in the file system the file is located at: | |
| 360 /// file:///path/to/the/actual/bazel/root/a/b/c.dart | |
| 361 /// | |
| 362 /// This mapping serves two purposes: | |
| 363 /// - It makes compiler results independent of the machine layout, which | |
| 364 /// enables us to share results across bazel runs and across machines. | |
| 365 /// | |
| 366 /// - It hides the distinction between generated and source files. That way | |
| 367 /// we can use the standard package-resolution mechanism and ignore the | |
| 368 /// internals of how files are organized within bazel. | |
| 369 /// | |
| 370 /// This class is initialized using a dart2js-bazel configuration file. The file | |
| 371 /// follows the following custom format: | |
| 372 /// | |
| 373 /// <generated-path-prefix> | |
| 374 /// <file1-bazel-root-relative-path> | |
| 375 /// <file2-bazel-root-relative-path> | |
| 376 /// ... | |
| 377 /// <fileN-bazel-root-relative-path> | |
| 378 /// | |
| 379 /// For example: | |
| 380 /// | |
| 381 /// bazel-bin/123/ | |
| 382 /// a/b/c.dart | |
| 383 /// bazel-bin/123/a/b/d.dart | |
| 384 /// a/b/e.dart | |
| 385 /// | |
| 386 /// THe current working directory will be used to resolve the bazel-root and | |
|
Harry Terkelsen
2016/08/08 23:15:29
THe -> The
Siggi Cherem (dart-lang)
2016/08/08 23:16:17
thanks!
| |
| 387 /// when invoking the compiler, bazel will use `package:` and | |
| 388 /// `file:///bazel-root/` URIs to specify entrypoints. | |
| 389 class BazelInputProvider extends SourceFileProvider { | |
| 390 /// Anything above this root is treated as machine specific and will only be | |
| 391 /// used to locate files on disk, but otherwise it's abstracted away in the | |
| 392 /// representation of canonical uris in the compiler. | |
| 393 final Uri bazelRoot; | |
| 394 | |
| 395 /// Path prefix where generated files are located. | |
| 396 final String genPath; | |
| 397 | |
| 398 /// Mapping from bazel-root uris to relative paths on top of [bazelRoot]. | |
| 399 final Map<Uri, Uri> mappings = <Uri, Uri>{}; | |
| 400 | |
| 401 factory BazelInputProvider(String configPath) { | |
| 402 var config = new File(configPath).readAsStringSync().split('\n'); | |
|
kevmoo
2016/08/08 23:19:23
Or new File(...).readAsLines() ?
Siggi Cherem (dart-lang)
2016/08/08 23:57:37
neat - done.
| |
| 403 var bazelRoot = currentDirectory; | |
| 404 var outPrefix = config[0]; | |
| 405 var files = config.skip(1); | |
| 406 return new BazelInputProvider._(bazelRoot, outPrefix, files); | |
| 407 } | |
| 408 | |
| 409 BazelInputProvider._(this.bazelRoot, this.genPath, Iterable<String> files) { | |
| 410 var fakeBazelRoot = Uri.parse('file:///bazel-root/'); | |
| 411 for (var path in files) { | |
| 412 var absolute = currentDirectory.resolve(path); | |
| 413 var bazelRelativeUri = fakeBazelRoot.resolve( | |
| 414 path.startsWith(genPath) ? path.substring(genPath.length) : path); | |
| 415 mappings[bazelRelativeUri] = absolute; | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 @override | |
| 420 Future readFromUri(Uri uri) => readUtf8BytesFromUri(mappings[uri] ?? uri); | |
| 421 } | |
| OLD | NEW |