Skip to content

Commit 938d1ba

Browse files
committed
Implement the kernel_generator API using fasta
BUG= [email protected] Review-Url: https://codereview.chromium.org/2856223003 .
1 parent 6ab17db commit 938d1ba

File tree

6 files changed

+170
-125
lines changed

6 files changed

+170
-125
lines changed

pkg/front_end/lib/compiler_options.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
library front_end.compiler_options;
66

7+
import 'dart:async';
78
import 'compilation_error.dart';
89
import 'file_system.dart';
910
import 'physical_file_system.dart';
11+
import 'src/simple_error.dart';
1012

1113
/// Default error handler used by [CompilerOptions.onError].
1214
void defaultErrorHandler(CompilationError error) => throw error;
@@ -134,3 +136,24 @@ class CompilerOptions {
134136
// SDK itself.
135137
List<Uri> additionalLibraries = [];
136138
}
139+
140+
Future<bool> validateOptions(CompilerOptions options) async {
141+
var fs = options.fileSystem;
142+
var root = options.sdkRoot;
143+
144+
bool _report(String msg) {
145+
options.onError(new SimpleError(msg));
146+
return false;
147+
}
148+
149+
if (root != null && !await fs.entityForUri(root).exists()) {
150+
return _report("SDK root directory not found: ${options.sdkRoot}");
151+
}
152+
153+
var summary = options.sdkSummary;
154+
if (summary != null && !await fs.entityForUri(summary).exists()) {
155+
return _report("SDK summary not found: ${options.sdkSummary}");
156+
}
157+
158+
return true;
159+
}

pkg/front_end/lib/kernel_generator.dart

Lines changed: 54 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@
55
/// Defines the front-end API for converting source code to Dart Kernel objects.
66
library front_end.kernel_generator;
77

8-
import 'compilation_error.dart';
98
import 'compiler_options.dart';
9+
import 'dart:async' show Future;
1010
import 'dart:async';
11-
12-
import 'package:analyzer/src/generated/source.dart' show SourceKind;
13-
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
14-
import 'package:analyzer/src/summary/package_bundle_reader.dart'
15-
show InSummarySource;
16-
// TODO(sigmund): move loader logic under front_end/lib/src/kernel/
17-
import 'package:analyzer/src/kernel/loader.dart';
18-
import 'package:kernel/kernel.dart';
19-
import 'package:source_span/source_span.dart' show SourceSpan;
11+
import 'src/fasta/dill/dill_target.dart' show DillTarget;
12+
import 'src/fasta/errors.dart' show InputError;
13+
import 'src/fasta/kernel/kernel_target.dart' show KernelTarget;
14+
import 'package:kernel/kernel.dart' show Program;
15+
import 'src/fasta/ticker.dart' show Ticker;
16+
import 'src/fasta/translate_uri.dart' show TranslateUri;
17+
import 'src/simple_error.dart';
2018

2119
/// Generates a kernel representation of the program whose main library is in
2220
/// the given [source].
@@ -37,18 +35,54 @@ import 'package:source_span/source_span.dart' show SourceSpan;
3735
/// take the place of Dart source code (since the Dart source code is still
3836
/// needed to access the contents of method bodies).
3937
Future<Program> kernelForProgram(Uri source, CompilerOptions options) async {
40-
var loader = await _createLoader(options, entry: source);
38+
var fs = options.fileSystem;
39+
40+
report(String msg) {
41+
options.onError(new SimpleError(msg));
42+
return null;
43+
}
4144

42-
if (options.compileSdk) {
43-
options.additionalLibraries.forEach(loader.loadLibrary);
45+
if (!await fs.entityForUri(source).exists()) {
46+
return report("Entry-point file not found: $source");
4447
}
4548

46-
// TODO(sigmund): merge what we have in loadEverything and the logic below in
47-
// kernelForBuildUnit so there is a single place where we crawl for
48-
// dependencies.
49-
loader.loadProgram(source, compileSdk: options.compileSdk);
50-
_reportErrors(loader.errors, options.onError);
51-
return loader.program;
49+
if (!await validateOptions(options)) return null;
50+
51+
try {
52+
TranslateUri uriTranslator =
53+
await TranslateUri.parse(null, options.packagesFileUri);
54+
55+
var dillTarget =
56+
new DillTarget(new Ticker(isVerbose: false), uriTranslator);
57+
var summary = options.sdkSummary;
58+
if (summary != null) dillTarget.read(summary);
59+
60+
var kernelTarget =
61+
new KernelTarget(dillTarget, uriTranslator, options.strongMode);
62+
kernelTarget.read(source);
63+
64+
await dillTarget.writeOutline(null);
65+
await kernelTarget.writeOutline(null);
66+
Program program = await kernelTarget.writeProgram(null);
67+
68+
if (kernelTarget.errors.isNotEmpty) {
69+
kernelTarget.errors.forEach((e) => report('$e'));
70+
return null;
71+
}
72+
73+
if (program.mainMethod == null) {
74+
return report("No 'main' method found.");
75+
}
76+
77+
if (!options.compileSdk) {
78+
// TODO(sigmund): ensure that the result is not including
79+
// sources for the sdk, only external references.
80+
}
81+
return program;
82+
} on InputError catch (e) {
83+
options.onError(new SimpleError(e.format()));
84+
return null;
85+
}
5286
}
5387

5488
/// Generates a kernel representation for a build unit.
@@ -86,103 +120,5 @@ Future<Program> kernelForProgram(Uri source, CompilerOptions options) async {
86120
/// obtained from?
87121
Future<Program> kernelForBuildUnit(
88122
List<Uri> sources, CompilerOptions options) async {
89-
var program = new Program();
90-
var loader = await _createLoader(options, program: program);
91-
var context = loader.context;
92-
93-
// Process every library in the build unit.
94-
for (var uri in sources) {
95-
var source = context.sourceFactory.forUri2(uri);
96-
// We ignore part files, those are handled by their enclosing library.
97-
if (context.computeKindOf(source) == SourceKind.PART) {
98-
// TODO(sigmund): record it and ensure that this part is within a provided
99-
// library.
100-
continue;
101-
}
102-
loader.loadLibrary(uri);
103-
}
104-
105-
// Check whether all dependencies were included in [sources].
106-
// TODO(sigmund): we should look for dependencies using import, export, and
107-
// part directives intead of relying on the dartk-loader. In particular, if a
108-
// library is imported but not used, the logic below will not detect it.
109-
for (int i = 0; i < program.libraries.length; ++i) {
110-
// Note: we don't use a for-in loop because program.libraries grows as
111-
// the loader processes libraries.
112-
var lib = program.libraries[i];
113-
var source = context.sourceFactory.forUri2(lib.importUri);
114-
if (source is InSummarySource) continue;
115-
if (options.chaseDependencies) {
116-
loader.ensureLibraryIsLoaded(lib);
117-
} else if (lib.isExternal) {
118-
// Default behavior: the build should be hermetic and all dependencies
119-
// should be listed.
120-
options.onError(new _DartkError('hermetic build error: '
121-
'no source or summary was given for ${lib.importUri}'));
122-
}
123-
}
124-
125-
_reportErrors(loader.errors, options.onError);
126-
return program;
127-
}
128-
129-
/// Create a [DartLoader] using the provided [options].
130-
///
131-
/// If [options] contain no configuration to resolve `.packages`, the [entry]
132-
/// file will be used to search for a `.packages` file.
133-
Future<DartLoader> _createLoader(CompilerOptions options,
134-
{Program program, Uri entry}) async {
135-
var kernelOptions = _convertOptions(options);
136-
var packages = await createPackages(_uriToPath(options.packagesFileUri),
137-
discoveryPath: entry?.path);
138-
var loader =
139-
new DartLoader(program ?? new Program(), kernelOptions, packages);
140-
var patchPaths = <String, List<String>>{};
141-
142-
// TODO(sigmund,paulberry): use ProcessedOptions so that we can resolve the
143-
// URIs correctly even if sdkRoot is inferred and not specified explicitly.
144-
String resolve(Uri patch) => _uriToPath(options.sdkRoot.resolveUri(patch));
145-
146-
options.targetPatches.forEach((uri, patches) {
147-
patchPaths['$uri'] = patches.map(resolve).toList();
148-
});
149-
AnalysisOptionsImpl analysisOptions = loader.context.analysisOptions;
150-
analysisOptions.patchPaths = patchPaths;
151-
return loader;
152-
}
153-
154-
DartOptions _convertOptions(CompilerOptions options) {
155-
return new DartOptions(
156-
strongMode: options.strongMode,
157-
sdk: _uriToPath(options.sdkRoot),
158-
// TODO(sigmund): make it possible to use summaries and still compile the
159-
// sdk sources.
160-
sdkSummary: options.compileSdk ? null : _uriToPath(options.sdkSummary),
161-
packagePath: _uriToPath(options.packagesFileUri),
162-
customUriMappings: options.uriOverride,
163-
declaredVariables: options.declaredVariables);
164-
}
165-
166-
void _reportErrors(List errors, ErrorHandler onError) {
167-
if (onError == null) return;
168-
for (var error in errors) {
169-
onError(new _DartkError(error));
170-
}
171-
}
172-
173-
String _uriToPath(Uri uri) {
174-
if (uri == null) return null;
175-
if (uri.scheme != 'file') {
176-
throw new StateError('Only file URIs are supported: $uri');
177-
}
178-
return uri.toFilePath();
179-
}
180-
181-
// TODO(sigmund): delete this class. Dartk should not format errors itself, we
182-
// should just pass them along.
183-
class _DartkError implements CompilationError {
184-
String get correction => null;
185-
SourceSpan get span => null;
186-
final String message;
187-
_DartkError(this.message);
123+
throw new UnimplementedError("kernel for build-unit is not implemented");
188124
}

pkg/front_end/lib/src/fasta/fasta.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,6 @@ Future<CompilationResult> parseScript(
173173
formatUnexpected(patchedSdk, -1, "Patched sdk directory not found."));
174174
}
175175

176-
Target target = getTarget("vm", new TargetFlags(strongMode: false));
177-
178176
Program program;
179177
try {
180178
TranslateUri uriTranslator = await TranslateUri.parse(null, packages);
@@ -201,6 +199,7 @@ Future<CompilationResult> parseScript(
201199
}
202200

203201
// Perform target-specific transformations.
202+
Target target = getTarget("vm", new TargetFlags(strongMode: false));
204203
target.performModularTransformations(program);
205204
target.performGlobalTransformations(program);
206205

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import 'package:front_end/compilation_error.dart';
2+
3+
import 'package:source_span/source_span.dart' show SourceSpan;
4+
5+
/// An error that only contains a message and no error location.
6+
class SimpleError implements CompilationError {
7+
String get correction => null;
8+
SourceSpan get span => null;
9+
final String message;
10+
SimpleError(this.message);
11+
}

pkg/front_end/test/subpackage_relationships_test.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ main() async {
2323
/// re-export stuff in lib/src.
2424
/// TODO(paulberry): remove dependencies on analyzer.
2525
final subpackageRules = {
26-
'lib': new SubpackageRules(
27-
mayImportAnalyzer: true,
28-
allowedDependencies: ['lib/src', 'lib/src/base']),
26+
'lib': new SubpackageRules(mayImportAnalyzer: true, allowedDependencies: [
27+
'lib/src',
28+
'lib/src/base',
29+
'lib/src/fasta',
30+
'lib/src/fasta/dill',
31+
'lib/src/fasta/kernel'
32+
]),
2933
'lib/src': new SubpackageRules(mayImportAnalyzer: true, allowedDependencies: [
3034
'lib',
3135
'lib/src/base',

pkg/front_end/tool/perf.dart

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,24 @@ import 'package:analyzer/file_system/physical_file_system.dart'
1616
import 'package:analyzer/source/package_map_resolver.dart';
1717
import 'package:analyzer/src/context/builder.dart';
1818
import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
19+
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
1920
import 'package:analyzer/src/generated/parser.dart';
2021
import 'package:analyzer/src/generated/source.dart';
2122
import 'package:analyzer/src/generated/source_io.dart';
23+
import 'package:analyzer/src/kernel/loader.dart';
2224
import 'package:analyzer/src/summary/format.dart';
2325
import 'package:analyzer/src/summary/idl.dart';
2426
import 'package:analyzer/src/summary/link.dart';
2527
import 'package:analyzer/src/summary/summarize_ast.dart';
28+
import 'package:front_end/compilation_error.dart';
2629
import 'package:front_end/compiler_options.dart';
27-
import 'package:front_end/kernel_generator.dart';
2830
import 'package:front_end/src/scanner/reader.dart';
2931
import 'package:front_end/src/scanner/scanner.dart';
3032
import 'package:front_end/src/scanner/token.dart';
3133
import 'package:kernel/kernel.dart' hide Source;
3234
import 'package:package_config/discovery.dart';
3335
import 'package:path/path.dart' as path;
36+
import 'package:source_span/source_span.dart' show SourceSpan;
3437

3538
main(List<String> args) async {
3639
// TODO(sigmund): provide sdk folder as well.
@@ -133,13 +136,82 @@ Future<Program> generateKernel(Uri entryUri,
133136
} else {
134137
options.sdkRoot = _sdkUri;
135138
}
136-
Program program = await kernelForProgram(entryUri, options);
139+
Program program = await _kernelForProgramViaDartk(entryUri, options);
137140
dartkTimer.stop();
138141
var suffix = useSdkSummary ? '_sum' : '';
139142
report('kernel_gen_e2e${suffix}', dartkTimer.elapsedMicroseconds);
140143
return program;
141144
}
142145

146+
_kernelForProgramViaDartk(Uri source, CompilerOptions options) async {
147+
var loader = await _createLoader(options, entry: source);
148+
if (options.compileSdk) {
149+
options.additionalLibraries.forEach(loader.loadLibrary);
150+
}
151+
loader.loadProgram(source, compileSdk: options.compileSdk);
152+
_reportErrors(loader.errors, options.onError);
153+
return loader.program;
154+
}
155+
156+
/// Create a [DartLoader] using the provided [options].
157+
///
158+
/// If [options] contain no configuration to resolve `.packages`, the [entry]
159+
/// file will be used to search for a `.packages` file.
160+
Future<DartLoader> _createLoader(CompilerOptions options,
161+
{Program program, Uri entry}) async {
162+
var kernelOptions = _convertOptions(options);
163+
var packages = await createPackages(_uriToPath(options.packagesFileUri),
164+
discoveryPath: entry?.path);
165+
var loader =
166+
new DartLoader(program ?? new Program(), kernelOptions, packages);
167+
var patchPaths = <String, List<String>>{};
168+
169+
// TODO(sigmund,paulberry): use ProcessedOptions so that we can resolve the
170+
// URIs correctly even if sdkRoot is inferred and not specified explicitly.
171+
String resolve(Uri patch) => _uriToPath(options.sdkRoot.resolveUri(patch));
172+
173+
options.targetPatches.forEach((uri, patches) {
174+
patchPaths['$uri'] = patches.map(resolve).toList();
175+
});
176+
AnalysisOptionsImpl analysisOptions = loader.context.analysisOptions;
177+
analysisOptions.patchPaths = patchPaths;
178+
return loader;
179+
}
180+
181+
DartOptions _convertOptions(CompilerOptions options) {
182+
return new DartOptions(
183+
strongMode: options.strongMode,
184+
sdk: _uriToPath(options.sdkRoot),
185+
// TODO(sigmund): make it possible to use summaries and still compile the
186+
// sdk sources.
187+
sdkSummary: options.compileSdk ? null : _uriToPath(options.sdkSummary),
188+
packagePath: _uriToPath(options.packagesFileUri),
189+
customUriMappings: options.uriOverride,
190+
declaredVariables: options.declaredVariables);
191+
}
192+
193+
String _uriToPath(Uri uri) {
194+
if (uri == null) return null;
195+
if (uri.scheme != 'file') {
196+
throw new StateError('Only file URIs are supported: $uri');
197+
}
198+
return uri.toFilePath();
199+
}
200+
201+
void _reportErrors(List errors, ErrorHandler onError) {
202+
if (onError == null) return;
203+
for (var error in errors) {
204+
onError(new _DartkError(error));
205+
}
206+
}
207+
208+
class _DartkError implements CompilationError {
209+
String get correction => null;
210+
SourceSpan get span => null;
211+
final String message;
212+
_DartkError(this.message);
213+
}
214+
143215
/// Generates unlinkmed summaries for all files in [files], and returns them in
144216
/// an [_UnlinkedSummaries] container.
145217
_UnlinkedSummaries generateUnlinkedSummaries(Set<Source> files) {

0 commit comments

Comments
 (0)