| 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; |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 } | 345 } |
| 346 | 346 |
| 347 /// Adapter to integrate dart2js in bazel. | 347 /// Adapter to integrate dart2js in bazel. |
| 348 /// | 348 /// |
| 349 /// To handle bazel's special layout: | 349 /// To handle bazel's special layout: |
| 350 /// | 350 /// |
| 351 /// * We specify a .packages configuration file that expands packages to their | 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 | 352 /// corresponding bazel location. This way there is no need to create a pub |
| 353 /// cache prior to invoking dart2js. | 353 /// cache prior to invoking dart2js. |
| 354 /// | 354 /// |
| 355 /// * We provide a mapping that can make all urls relative to the bazel root. | 355 /// * We provide an implicit mapping that can make all urls relative to the |
| 356 /// bazel root. |
| 356 /// To the compiler, URIs look like: | 357 /// To the compiler, URIs look like: |
| 357 /// file:///bazel-root/a/b/c.dart | 358 /// file:///bazel-root/a/b/c.dart |
| 358 /// | 359 /// |
| 359 /// even though in the file system the file is located at: | 360 /// even though in the file system the file is located at: |
| 360 /// file:///path/to/the/actual/bazel/root/a/b/c.dart | 361 /// file:///path/to/the/actual/bazel/root/a/b/c.dart |
| 361 /// | 362 /// |
| 362 /// This mapping serves two purposes: | 363 /// This mapping serves two purposes: |
| 363 /// - It makes compiler results independent of the machine layout, which | 364 /// - It makes compiler results independent of the machine layout, which |
| 364 /// enables us to share results across bazel runs and across machines. | 365 /// enables us to share results across bazel runs and across machines. |
| 365 /// | 366 /// |
| 366 /// - It hides the distinction between generated and source files. That way | 367 /// - It hides the distinction between generated and source files. That way |
| 367 /// we can use the standard package-resolution mechanism and ignore the | 368 /// we can use the standard package-resolution mechanism and ignore the |
| 368 /// internals of how files are organized within bazel. | 369 /// internals of how files are organized within bazel. |
| 369 /// | 370 /// |
| 370 /// This class is initialized using a dart2js-bazel configuration file. The file | 371 /// When invoking the compiler, bazel will use `package:` and |
| 371 /// follows the following custom format: | 372 /// `file:///bazel-root/` URIs to specify entrypoints. |
| 372 /// | 373 /// |
| 373 /// <generated-path-prefix> | 374 /// The mapping is specified using search paths relative to the current |
| 374 /// <file1-bazel-root-relative-path> | 375 /// directory. When this provider looks up a file, the bazel-root folder is |
| 375 /// <file2-bazel-root-relative-path> | 376 /// replaced by the first directory in the search path containing the file, if |
| 376 /// ... | 377 /// any. For example, given the search path ".,bazel-bin/", and a URL |
| 377 /// <fileN-bazel-root-relative-path> | 378 /// of the form `file:///bazel-root/a/b.dart`, this provider will check if the |
| 378 /// | 379 /// file exists under "./a/b.dart", then check under "bazel-bin/a/b.dart". If |
| 379 /// For example: | 380 /// none of the paths matches, it will attempt to load the file from |
| 380 /// | 381 /// `/bazel-root/a/b.dart` which will likely fail. |
| 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 | |
| 387 /// when invoking the compiler, bazel will use `package:` and | |
| 388 /// `file:///bazel-root/` URIs to specify entrypoints. | |
| 389 class BazelInputProvider extends SourceFileProvider { | 382 class BazelInputProvider extends SourceFileProvider { |
| 390 /// Anything above this root is treated as machine specific and will only be | 383 final List<Uri> dirs; |
| 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 | 384 |
| 395 /// Path prefix where generated files are located. | 385 BazelInputProvider(List<String> searchPaths) |
| 396 final String genPath; | 386 : dirs = searchPaths.map(_resolve).toList(); |
| 397 | 387 |
| 398 /// Mapping from bazel-root uris to relative paths on top of [bazelRoot]. | 388 static _resolve(String path) => currentDirectory.resolve(path); |
| 399 final Map<Uri, Uri> mappings = <Uri, Uri>{}; | |
| 400 | |
| 401 factory BazelInputProvider(String configPath) { | |
| 402 var config = new File(configPath).readAsLinesSync(); | |
| 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 | 389 |
| 419 @override | 390 @override |
| 420 Future readFromUri(Uri uri) => readUtf8BytesFromUri(mappings[uri] ?? uri); | 391 Future readFromUri(Uri uri) async { |
| 392 var path = uri.path; |
| 393 if (path.startsWith('/bazel-root')) { |
| 394 path = path.substring('/bazel-root/'.length); |
| 395 for (var dir in dirs) { |
| 396 var file = dir.resolve(path); |
| 397 if (await new File.fromUri(file).exists()) { |
| 398 uri = file; |
| 399 break; |
| 400 } |
| 401 } |
| 402 } |
| 403 return readUtf8BytesFromUri(uri); |
| 404 } |
| 421 } | 405 } |
| OLD | NEW |