Index: pkg/front_end/lib/kernel_generator.dart |
diff --git a/pkg/front_end/lib/kernel_generator.dart b/pkg/front_end/lib/kernel_generator.dart |
index ce9eee88a23557ccf57f2018013505886939a734..a87bb683b44dc71eb28c9cf328fba10469ada4f6 100644 |
--- a/pkg/front_end/lib/kernel_generator.dart |
+++ b/pkg/front_end/lib/kernel_generator.dart |
@@ -9,6 +9,9 @@ import 'compilation_error.dart'; |
import 'compiler_options.dart'; |
import 'dart:async'; |
+import 'package:analyzer/src/generated/source.dart' show SourceKind; |
+import 'package:analyzer/src/summary/package_bundle_reader.dart' |
+ show InSummarySource; |
// TODO(sigmund): move loader logic under front_end/lib/src/kernel/ |
import 'package:kernel/analyzer/loader.dart'; |
import 'package:kernel/kernel.dart'; |
@@ -23,37 +26,50 @@ import 'package:source_span/source_span.dart' show SourceSpan; |
/// follows `import`, `export`, and `part` declarations to discover the whole |
/// program, and converts the result to Dart Kernel format. |
/// |
-/// If summaries are provided in [options], they may be used to speed up |
-/// analysis, but they will not take the place of Dart source code (since the |
-/// Dart source code is still needed to access the contents of method bodies). |
+/// If `compileSdk` in [options] is true, the generated program will include |
+/// code for the SDK. |
/// |
-/// TODO(paulberry): will the VM have a pickled version of the SDK inside it? If |
-/// so, then maybe this method should not convert SDK libraries to kernel. |
+/// If summaries are provided in [options], they may be used to speed up |
+/// analysis. If in addition `compileSdk` is false, this will speed up |
+/// compilation, as no source of the sdk will be generated. Note however, that |
+/// summaries for application code can also speed up analysis, but they will not |
+/// take the place of Dart source code (since the Dart source code is still |
+/// needed to access the contents of method bodies). |
Future<Program> kernelForProgram(Uri source, CompilerOptions options) async { |
- var loader = await _createLoader(options); |
- Program program = loader.loadProgram(source); |
+ var loader = await _createLoader(options, entry: source); |
+ // TODO(sigmund): merge what we have in loadEverything and the logic below in |
+ // kernelForBuildUnit so there is a single place where we crawl for |
+ // dependencies. |
+ Program program = loader.loadProgram(source, compileSdk: options.compileSdk); |
_reportErrors(loader.errors, options.onError); |
return program; |
} |
-/// Generates a kernel representation of the build unit whose source files are |
-/// in [sources]. |
+/// Generates a kernel representation for a build unit. |
/// |
/// Intended for modular compilation. |
/// |
-/// [sources] should be the complete set of source files for a build unit |
-/// (including both library and part files). All of the library files are |
-/// transformed into Dart Kernel Library objects. |
+/// The build unit by default contains only the source files in [sources] |
+/// (including library and part files), but if |
+/// [CompilerOptions.chaseDependencies] is true, it may include some additional |
+/// source files. All of the library files are transformed into Dart Kernel |
+/// Library objects. |
+/// |
+/// By default, the compilation process is hermetic, meaning that the only files |
+/// which will be read are those listed in [sources], |
+/// [CompilerOptions.inputSummaries], and [CompilerOptions.sdkSummary]. If a |
+/// source file attempts to refer to a file which is not obtainable from these |
+/// paths, that will result in an error, even if the file exists on the |
+/// filesystem. |
/// |
-/// The compilation process is hermetic, meaning that the only files which will |
-/// be read are those listed in [sources], [CompilerOptions.inputSummaries], and |
-/// [CompilerOptions.sdkSummary]. If a source file attempts to refer to a file |
-/// which is not obtainable from these paths, that will result in an error, even |
-/// if the file exists on the filesystem. |
+/// When [CompilerOptions.chaseDependencies] is true, this default behavior |
+/// changes, and any dependency of [sources] that is not listed in |
+/// [CompilerOptions.inputSummaries] and [CompilerOptions.sdkSummary] is treated |
+/// as an additional source file for the build unit. |
/// |
/// Any `part` declarations found in [sources] must refer to part files which |
-/// are also listed in [sources], otherwise an error results. (It is not |
-/// permitted to refer to a part file declared in another build unit). |
+/// are also listed in the build unit sources, otherwise an error results. (It |
+/// is not permitted to refer to a part file declared in another build unit). |
/// |
/// The return value is a [Program] object with no main method set. |
/// TODO(paulberry): would it be better to define a data type in kernel to |
@@ -63,27 +79,68 @@ Future<Program> kernelForProgram(Uri source, CompilerOptions options) async { |
/// caller to match up referenced elements to the summary files they were |
/// obtained from? |
Future<Program> kernelForBuildUnit( |
- List<Uri> sources, CompilerOptions options) async { |
+ List<Uri> sources, CompilerOptions options) async { |
var repository = new Repository(); |
var loader = await _createLoader(options, repository: repository); |
- // TODO(sigmund): add special handling for part files. |
- sources.forEach(loader.loadLibrary); |
+ var context = loader.context; |
+ |
+ // Process every library in the build unit. |
+ for (var uri in sources) { |
+ var source = context.sourceFactory.forUri2(uri); |
+ // We ignore part files, those are handled by their enclosing library. |
+ if (context.computeKindOf(source) == SourceKind.PART) { |
+ // TODO(sigmund): record it and ensure that this part is within a provided |
+ // library. |
+ continue; |
+ } |
+ loader.loadLibrary(uri); |
+ } |
+ |
+ // Check whether all dependencies were included in [sources]. |
+ // TODO(sigmund): we should look for dependencies using import, export, and |
+ // part directives intead of relying on the dartk-loader. In particular, if a |
+ // library is imported but not used, the logic below will not detect it. |
+ for (int i = 0; i < repository.libraries.length; ++i) { |
+ // Note: we don't use a for-in loop because repository.libraries grows as |
+ // the loader processes libraries. |
+ var lib = repository.libraries[i]; |
+ var source = context.sourceFactory.forUri2(lib.importUri); |
+ if (source is InSummarySource) continue; |
+ if (options.chaseDependencies) { |
+ loader.ensureLibraryIsLoaded(lib); |
+ } else if (lib.isExternal) { |
+ // Default behavior: the build should be hermetic and all dependencies |
+ // should be listed. |
+ options.onError(new _DartkError('hermetic build error: ' |
+ 'no source or summary was given for ${lib.importUri}')); |
+ } |
+ } |
+ |
Program program = new Program(repository.libraries); |
_reportErrors(loader.errors, options.onError); |
return program; |
} |
+/// Create a [DartLoader] using the provided [options]. |
+/// |
+/// If [options] contain no configuration to resolve `.packages`, the [entry] |
+/// file will be used to search for a `.packages` file. |
Future<DartLoader> _createLoader(CompilerOptions options, |
- {Repository repository}) async { |
+ {Repository repository, Uri entry}) async { |
var kernelOptions = _convertOptions(options); |
- var packages = await createPackages(options.packagesFilePath); |
+ var packages = await createPackages(options.packagesFilePath, |
+ discoveryPath: entry?.path); |
return new DartLoader( |
repository ?? new Repository(), kernelOptions, packages); |
} |
DartOptions _convertOptions(CompilerOptions options) { |
return new DartOptions( |
+ strongMode: options.strongMode, |
sdk: options.sdkPath, |
+ // TODO(sigmund): make it possible to use summaries and still compile the |
+ // sdk sources. |
+ sdkSummary: options.compileSdk ? null : options.sdkSummary, |
packagePath: options.packagesFilePath, |
declaredVariables: options.declaredVariables); |
} |