Add flutter track widget creation transform to bazel kernel worker

Had to do a few changes to make this happen:
1. Restored some of the code removed in the transformer, making class
hierarchy optional.
2. Split the "compile" method in bazel_worker.dart into two, since we
need the intermediate Component object in one of the case.

Change-Id: I0ee004467e76dff0025f7979834c62b9db328ecc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100480
Commit-Queue: Jake Macdonald <jakemac@google.com>
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Jacob Richman <jacobr@google.com>
This commit is contained in:
Chingjun Lau 2019-05-06 19:20:08 +00:00 committed by commit-bot@chromium.org
parent 8d1ed856d2
commit 51730db51b
3 changed files with 69 additions and 18 deletions

View file

@ -10,7 +10,7 @@
//
// The following modifications were made:
// - remove "package:vm" dependency (only used for one interface)
// - pass in the class hierarchy that DDC already has available.
// - optionally pass in the class hierarchy that DDC already has available.
library track_widget_constructor_locations;
// The kernel/src import below that requires lint `ignore_for_file`
@ -314,9 +314,9 @@ class WidgetCreatorTracker {
/// [ClassHierarchy] instance, with new dispatch targets; or at least let
/// the existing instance know that some of its dispatch tables are not
/// valid anymore.
final ClassHierarchy hierarchy;
ClassHierarchy hierarchy;
WidgetCreatorTracker(this.hierarchy);
WidgetCreatorTracker([this.hierarchy]);
void _resolveFlutterClasses(Iterable<Library> libraries) {
// If the Widget or Debug location classes have been updated we need to get
@ -438,6 +438,23 @@ class WidgetCreatorTracker {
clazz.constructors.forEach(handleConstructor);
}
Component _computeFullProgram(Component deltaProgram) {
final Set<Library> libraries = new Set<Library>();
final List<Library> workList = <Library>[];
for (Library library in deltaProgram.libraries) {
workList.add(library);
}
while (workList.isNotEmpty) {
final Library library = workList.removeLast();
for (LibraryDependency dependency in library.dependencies) {
if (libraries.add(dependency.targetLibrary)) {
workList.add(dependency.targetLibrary);
}
}
}
return new Component()..libraries.addAll(libraries);
}
/// Transform the given [module].
void transform(Component module) {
final List<Library> libraries = module.libraries;
@ -453,6 +470,14 @@ class WidgetCreatorTracker {
return;
}
// TODO(jacobr): once there is a working incremental ClassHierarchy
// constructor switch to using it instead of building a ClassHierarchy off
// the full program.
hierarchy ??= new ClassHierarchy(
_computeFullProgram(module),
onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) {},
);
final Set<Class> transformedClasses = new Set<Class>.identity();
final Set<Library> librariesToTransform = new Set<Library>.identity()
..addAll(module.libraries);

View file

@ -23,9 +23,7 @@ import '../fasta/compiler_context.dart' show CompilerContext;
import '../fasta/incremental_compiler.dart' show IncrementalCompiler;
import '../fasta/kernel/utils.dart' show serializeComponent;
import '../kernel_generator_impl.dart' show generateKernel;
import '../kernel_generator_impl.dart' show CompilerResult, generateKernel;
import 'compiler_state.dart'
show InitializedCompilerState, WorkerInputComponent, digestsEqual;
@ -193,9 +191,9 @@ Future<InitializedCompilerState> initializeCompiler(
return new InitializedCompilerState(options, processedOpts);
}
Future<List<int>> compile(InitializedCompilerState compilerState,
Future<CompilerResult> _compile(InitializedCompilerState compilerState,
List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler,
{bool summaryOnly}) async {
{bool summaryOnly}) {
summaryOnly ??= true;
CompilerOptions options = compilerState.options;
options..onDiagnostic = diagnosticMessageHandler;
@ -204,11 +202,24 @@ Future<List<int>> compile(InitializedCompilerState compilerState,
processedOpts.inputs.clear();
processedOpts.inputs.addAll(inputs);
var result = await generateKernel(processedOpts,
return generateKernel(processedOpts,
buildSummary: summaryOnly, buildComponent: !summaryOnly);
}
Future<List<int>> compileSummary(InitializedCompilerState compilerState,
List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler) async {
var result = await _compile(compilerState, inputs, diagnosticMessageHandler,
summaryOnly: true);
return result?.summary;
}
Future<Component> compileComponent(InitializedCompilerState compilerState,
List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler) async {
var result = await _compile(compilerState, inputs, diagnosticMessageHandler,
summaryOnly: false);
var component = result?.component;
if (component != null && !summaryOnly) {
if (component != null) {
for (var lib in component.libraries) {
if (!inputs.contains(lib.importUri)) {
// Excluding the library also means that their canonical names will not
@ -220,9 +231,5 @@ Future<List<int>> compile(InitializedCompilerState compilerState,
}
}
}
return summaryOnly
? result?.summary
: serializeComponent(result?.component,
filter: (library) => inputs.contains(library.importUri));
return component;
}

View file

@ -16,6 +16,7 @@ import 'package:args/args.dart';
import 'package:bazel_worker/bazel_worker.dart';
import 'package:build_integration/file_system/multi_root.dart';
import 'package:dev_compiler/src/kernel/target.dart';
import 'package:dev_compiler/src/flutter/track_widget_constructor_locations.dart';
import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
import 'package:kernel/ast.dart' show Component, Library;
import 'package:kernel/target/targets.dart';
@ -127,7 +128,8 @@ final summaryArgsParser = new ArgParser()
..addMultiOption('source')
..addOption('output')
..addFlag('reuse-compiler-result', defaultsTo: false)
..addFlag('use-incremental-compiler', defaultsTo: false);
..addFlag('use-incremental-compiler', defaultsTo: false)
..addFlag('track-kernel-creation', defaultsTo: false);
class ComputeKernelResult {
final bool succeeded;
@ -171,6 +173,13 @@ Future<ComputeKernelResult> computeKernel(List<String> args,
var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
var summaryOnly = parsedArgs['summary-only'] as bool;
var trackKernelCreation = parsedArgs['track-kernel-creation'] as bool;
if (summaryOnly && trackKernelCreation) {
throw new ArgumentError('error: --summary-only is not compatible with '
'--track-kernel-creation');
}
// TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
// compatible while we migrate existing clients of this tool.
var targetName =
@ -287,13 +296,23 @@ Future<ComputeKernelResult> computeKernel(List<String> args,
incrementalComponent.problemsAsJson = null;
incrementalComponent.mainMethod = null;
target.performOutlineTransformations(incrementalComponent);
} else if (trackKernelCreation) {
(new WidgetCreatorTracker()).transform(incrementalComponent);
}
return Future.value(fe.serializeComponent(incrementalComponent));
});
} else if (summaryOnly) {
kernel = await fe.compileSummary(state, sources, onDiagnostic);
} else {
kernel = await fe.compile(state, sources, onDiagnostic,
summaryOnly: summaryOnly);
Component component =
await fe.compileComponent(state, sources, onDiagnostic);
if (trackKernelCreation) {
(new WidgetCreatorTracker()).transform(component);
}
kernel = fe.serializeComponent(component,
filter: (library) => sources.contains(library.importUri));
}
if (kernel != null) {