| Index: pkg/compiler/samples/jsonify/jsonify.dart
|
| diff --git a/pkg/compiler/samples/jsonify/jsonify.dart b/pkg/compiler/samples/jsonify/jsonify.dart
|
| index a84cb043ea79570b6ddbc0c341769e66a8ef3629..4d3d8b93717cf8379d1403dbc0b21d3aa7e0a1d6 100644
|
| --- a/pkg/compiler/samples/jsonify/jsonify.dart
|
| +++ b/pkg/compiler/samples/jsonify/jsonify.dart
|
| @@ -2,108 +2,268 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| +// TODO(sigmund): eventually this file should move under site/try, or get
|
| +// deleted once we have direct coverage for incrementality in our tests.
|
| +
|
| +// TODO(sigmund): simplify this file as much as possible. This file illustrates
|
| +// how we can access different modules of our frontend compiler. Currently it
|
| +// requires a lot of setup and in some cases it illustrates how encapsulation is
|
| +// not respected between compiler tasks. Eventually all the _Fake* classes below
|
| +// should disappear. We should also consider exposing the subset of the
|
| +// functionality used below as it's own library in the future.
|
| +
|
| import 'dart:async';
|
| -import 'dart:convert';
|
| import 'dart:io';
|
| -import 'dart:mirrors';
|
| +import 'dart:convert';
|
|
|
| import 'package:sdk_library_metadata/libraries.dart' show libraries;
|
|
|
| -import '../../lib/src/filenames.dart';
|
| -import '../../lib/src/mirrors/analyze.dart' show analyze;
|
| -import '../../lib/src/mirrors/dart2js_mirrors.dart' show BackDoor;
|
| -import '../../lib/src/source_file_provider.dart';
|
| -import '../../lib/src/util/uri_extras.dart';
|
| +import 'package:compiler/compiler_new.dart' show CompilerInput;
|
| +import 'package:compiler/src/common/backend_api.dart' show Backend;
|
| +import 'package:compiler/src/compiler.dart' show Compiler;
|
| +import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
|
| +import 'package:compiler/src/diagnostics/spannable.dart';
|
| +import 'package:compiler/src/elements/elements.dart';
|
| +import 'package:compiler/src/environment.dart';
|
| +import 'package:compiler/src/id_generator.dart';
|
| +import 'package:compiler/src/io/source_file.dart';
|
| +import 'package:compiler/src/library_loader.dart';
|
| +import 'package:compiler/src/options.dart';
|
| +import 'package:compiler/src/parser/diet_parser_task.dart';
|
| +import 'package:compiler/src/parser/element_listener.dart' show ScannerOptions;
|
| +import 'package:compiler/src/patch_parser.dart';
|
| +import 'package:compiler/src/platform_configuration.dart' as platform;
|
| +import 'package:compiler/src/resolved_uri_translator.dart';
|
| +import 'package:compiler/src/scanner/scanner_task.dart';
|
| +import 'package:compiler/src/script.dart';
|
| +import 'package:compiler/src/serialization/serialization.dart'
|
| + show LibraryDeserializer;
|
| +import 'package:compiler/src/serialization/task.dart';
|
| +import 'package:compiler/src/source_file_provider.dart';
|
| +import 'package:compiler/src/util/uri_extras.dart' show relativize;
|
|
|
| -const DART2JS = '../../lib/src/dart2js.dart';
|
| -const DART2JS_MIRROR = '../../lib/src/mirrors/dart2js_mirror.dart';
|
| -const SDK_ROOT = '../../../../sdk/';
|
| +Uri sdkRoot = Uri.base.resolveUri(Platform.script).resolve('../../../../');
|
|
|
| -bool isPublicDart2jsLibrary(String name) {
|
| - return !name.startsWith('_') && libraries[name].isDart2jsLibrary;
|
| +main(List<String> arguments) async {
|
| + if (arguments.length == 0) {
|
| + print('usage: jsonify.dart <out-path>');
|
| + exit(1);
|
| + }
|
| +
|
| + var out = arguments[0];
|
| + List<Uri> sdkFiles = await collectSdkFiles();
|
| + new File(out).writeAsStringSync(emitSdkAsJson(sdkFiles));
|
| }
|
|
|
| -var handler;
|
| -RandomAccessFile output;
|
| -Uri outputUri;
|
| -Uri sdkRoot;
|
| -const bool outputJson =
|
| - const bool.fromEnvironment('outputJson', defaultValue: false);
|
| +/// Collects a list of files that are part of the SDK.
|
| +Future<List<Uri>> collectSdkFiles() async {
|
| + var loader = await createLoader();
|
| + var libs = <LibraryElement>[];
|
| + for (var uri in dartColonLibraries) {
|
| + libs.add(await loader.loadLibrary(uri));
|
| + }
|
|
|
| -main(List<String> arguments) {
|
| - handler = new FormattingDiagnosticHandler()..throwOnError = true;
|
| + var files = <Uri>[];
|
| + // Include all units transitively reachable from dart:* libraries.
|
| + crawlLibraries(libs, (lib) => files.addAll(_unitsOf(lib)));
|
|
|
| - outputUri = handler.provider.cwd.resolve(nativeToUriPath(arguments.first));
|
| - output = new File(arguments.first).openSync(mode: FileMode.WRITE);
|
| + // Include all patch files.
|
| + libraries.forEach((name, info) {
|
| + var patch = info.dart2jsPatchPath;
|
| + if (patch != null) files.add(sdkRoot.resolve('sdk/lib/$patch'));
|
| + });
|
|
|
| - Uri myLocation = handler.provider.cwd.resolveUri(Platform.script);
|
| + // Include the platform specs.
|
| + ["client", "server", "shared"]
|
| + .forEach((f) => files.add(sdkRoot.resolve('sdk/lib/dart_$f.platform')));
|
|
|
| - Uri packageRoot = handler.provider.cwd.resolve(Platform.packageRoot);
|
| + return files;
|
| +}
|
|
|
| - Uri libraryRoot = myLocation.resolve(SDK_ROOT);
|
| +/// Creates a string that encodes the contents of the sdk libraries in json.
|
| +///
|
| +/// The keys of the json file are sdk-relative paths to source files, and the
|
| +/// values are the contents of the file.
|
| +String emitSdkAsJson(List<Uri> paths) {
|
| + var map = <String, String>{};
|
| + for (var uri in paths) {
|
| + String filename = relativize(sdkRoot, uri, false);
|
| + var contents = new File.fromUri(uri).readAsStringSync();
|
| + map['sdk:/$filename'] = contents;
|
| + }
|
| + return JSON.encode(map);
|
| +}
|
|
|
| - sdkRoot = libraryRoot.resolve('../');
|
| +/// Returns the resource URI for every compilation unit in [lib].
|
| +Iterable<Uri> _unitsOf(LibraryElement lib) =>
|
| + lib.compilationUnits.map((unit) => unit.script.resourceUri);
|
|
|
| - // Get the names of public dart2js libraries.
|
| - Iterable<String> names = libraries.keys.where(isPublicDart2jsLibrary);
|
| +/// Provides a list of dart:* uris for all dart libraries declared in the
|
| +/// sdk_library_metadata.
|
| +List<Uri> get dartColonLibraries {
|
| + isPublicDart2jsLibrary(String name) =>
|
| + !name.startsWith('_') && libraries[name].isDart2jsLibrary;
|
|
|
| - // Turn the names into uris by prepending dart: to them.
|
| - List<Uri> uris = names.map((String name) => Uri.parse('dart:$name')).toList();
|
| + // Get the names of public dart2js libraries and turn them into URIs.
|
| + return libraries.keys
|
| + .where(isPublicDart2jsLibrary)
|
| + .map((name) => Uri.parse('dart:$name'))
|
| + .toList();
|
| +}
|
|
|
| - analyze(uris, libraryRoot, packageRoot, handler.provider, handler)
|
| - .then(jsonify);
|
| +/// Helper function to crawls imports and exports in [libs], and apply [action]
|
| +/// once on each library that was found.
|
| +void crawlLibraries(List<LibraryElement> libs, void action(LibraryElement l)) {
|
| + var seen = new Set();
|
| + helper(lib) {
|
| + if (!seen.add(lib)) return;
|
| + helper(lib.implementation);
|
| + action(lib);
|
| + lib.imports.forEach((i) => helper(i.importedLibrary));
|
| + lib.exports.forEach((i) => helper(i.exportedLibrary));
|
| + }
|
| + libs.forEach(helper);
|
| }
|
|
|
| -jsonify(MirrorSystem mirrors) {
|
| - var map = <String, String>{};
|
| - List<Future> futures = <Future>[];
|
| +// ----------------------------------------------------------------------------
|
| +// Anything below this line illustrates how to directly use
|
| +// modules of the compiler. We expected this to become simpler as we make
|
| +// progress refactoring the codebase.
|
|
|
| - Future mapUri(Uri uri) {
|
| - String filename = relativize(sdkRoot, uri, false);
|
| - return handler.provider.readStringFromUri(uri).then((contents) {
|
| - map['sdk:/$filename'] = contents;
|
| - });
|
| +var ids = new IdGenerator();
|
| +var scriptLoader;
|
| +var loader;
|
| +var patchParser;
|
| +
|
| +/// Uses internal dart2js APIs to create a library loader.
|
| +Future<LibraryLoaderTask> createLoader() async {
|
| + var inputProvider = new CompilerSourceFileProvider();
|
| + var compiler = new _FakeCompiler();
|
| + var dietParser = new DietParserTask(compiler, const _ParserOptions(), ids,
|
| + compiler.backend, compiler.reporter);
|
| + var scanner = new _Scanner(new ScannerTask(compiler, dietParser));
|
| + Uri platformConfig = Uri.base
|
| + .resolveUri(Platform.script)
|
| + .resolve('../../../../sdk/lib/dart_shared.platform');
|
| + var sdkLibraries = await platform.load(platformConfig, inputProvider);
|
| + loader = new LibraryLoaderTask(
|
| + compiler,
|
| + new ResolvedUriTranslator(sdkLibraries, new _FakeReporter()),
|
| + scriptLoader = new _ScriptLoader(inputProvider),
|
| + scanner,
|
| + new _FakeDeserializer(),
|
| + new _Listener(),
|
| + const _EmptyEnvironment());
|
| + patchParser = new PatchParserTask(compiler, const _ParserOptions());
|
| + return loader;
|
| +}
|
| +
|
| +/// Uses internal dart2js APIs to create a diet parser and scanner.
|
| +
|
| +class _FakeCompiler implements Compiler {
|
| + final _FakeOptions options = new _FakeOptions();
|
| + final reporter = new _FakeReporter();
|
| + final backend = new _FakeBackend();
|
| + final enqueuer = new _FakeEnqueuer();
|
| + final patchVersion = null;
|
| + final idGenerator = ids;
|
| + final parsingContext = new _FakeParsingContext();
|
| + onLibraryCreated(_) => print("remove this!");
|
| + readScript(u, [s]) => scriptLoader.readScript(u, s);
|
| +}
|
| +
|
| +class _FakeEnqueuer {
|
| + final resolution = new _FakeResolutionEnqueuer();
|
| +}
|
| +
|
| +class _FakeResolutionEnqueuer {
|
| + addDeferredAction(a, f) {}
|
| +}
|
| +
|
| +class _FakeBackend implements Backend {
|
| + bool canLibraryUseNative(LibraryElement library) => true;
|
| +}
|
| +
|
| +class _FakeParsingContext {
|
| + getScannerOptionsFor(element) => const ScannerOptions(canUseNative: true);
|
| +}
|
| +
|
| +class _FakeReporter implements DiagnosticReporter {
|
| + final _FakeOptions options = new _FakeOptions();
|
| + withCurrentElement(e, f) => f();
|
| + log(m) {}
|
| + reportWarningMessage(s, m, [a]) {
|
| + print('warning: $s $m $a');
|
| }
|
|
|
| - mirrors.libraries.forEach((_, LibraryMirror library) {
|
| - BackDoor.compilationUnitsOf(library).forEach((compilationUnit) {
|
| - futures.add(mapUri(compilationUnit.uri));
|
| - });
|
| - });
|
| + reportHintMessage(s, m, [a]) {
|
| + print('hint: $s $m $a');
|
| + }
|
|
|
| - libraries.forEach((name, info) {
|
| - var patch = info.dart2jsPatchPath;
|
| - if (patch != null) {
|
| - futures.add(mapUri(sdkRoot.resolve('sdk/lib/$patch')));
|
| - }
|
| - });
|
| + reportErrorMessage(s, m, [a]) {
|
| + print('error: $s $m $a');
|
| + }
|
| +}
|
| +
|
| +class _FakeOptions {
|
| + final bool verbose = false;
|
| + final bool preserveComments = false;
|
| + final bool suppressHints = true;
|
| +}
|
| +
|
| +class _FakeDeserializer implements LibraryDeserializer {
|
| + Future<LibraryElement> readLibrary(Uri uri) async => null;
|
| +}
|
|
|
| - for (String filename in [
|
| - "dart_client.platform",
|
| - "dart_server.platform",
|
| - "dart_shared.platform"
|
| - ]) {
|
| - futures.add(mapUri(sdkRoot.resolve('sdk/lib/$filename')));
|
| +class _ScriptLoader implements ScriptLoader {
|
| + CompilerInput inputProvider;
|
| +
|
| + _ScriptLoader(this.inputProvider);
|
| +
|
| + Future<Script> readScript(Uri uri, [Spannable spannable]) async {
|
| + if (!uri.isAbsolute) throw 'Relative URI $uri provided to readScript.';
|
| + if (uri.scheme == 'packages') throw 'package:* URIs are not supported.';
|
| + if (uri.scheme == 'dart-ext') return new Script.synthetic(uri);
|
| + return new Script(uri, uri, await _readFile(uri));
|
| }
|
|
|
| - Future.wait(futures).then((_) {
|
| - if (outputJson) {
|
| - output.writeStringSync(JSON.encode(map));
|
| - } else {
|
| - output.writeStringSync('''
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| + Future<SourceFile> _readFile(Uri uri) async {
|
| + var data = await inputProvider.readFromUri(uri);
|
| + if (data is List<int>) return new Utf8BytesSourceFile(uri, data);
|
| + if (data is String) return new StringSourceFile.fromUri(uri, data);
|
| + throw "Expected a 'String' or a 'List<int>' from the input "
|
| + "provider, but got: ${data.runtimeType}.";
|
| + }
|
| +}
|
|
|
| -// DO NOT EDIT.
|
| -// This file is generated by jsonify.dart.
|
| +class _Scanner implements ElementScanner {
|
| + ScannerTask scanner;
|
| + _Scanner(this.scanner);
|
| + void scanLibrary(LibraryElement library) => scanner.scanLibrary(library);
|
| + void scanUnit(CompilationUnitElement unit) => scanner.scan(unit);
|
| +}
|
|
|
| -library dart.sdk_sources;
|
| +class _Listener implements LibraryLoaderListener {
|
| + _Listener();
|
| + Future onLibrariesLoaded(LoadedLibraries results) async {}
|
| + void onLibraryCreated(LibraryElement library) {}
|
| + Future onLibraryScanned(LibraryElement library, LibraryLoader loader) async {
|
| + if (library.isPatched) return;
|
| + var path = libraries[library.canonicalUri.path]?.dart2jsPatchPath;
|
| + if (path == null) return;
|
| + await patchParser.patchLibrary(
|
| + loader, sdkRoot.resolve('sdk/lib/$path'), library);
|
| + }
|
| +}
|
|
|
| -const Map<String, String> SDK_SOURCES = const <String, String>''');
|
| - output.writeStringSync(JSON.encode(map).replaceAll(r'$', r'\$'));
|
| - output.writeStringSync(';\n');
|
| - }
|
| - output.closeSync();
|
| - });
|
| +class _EmptyEnvironment implements Environment {
|
| + const _EmptyEnvironment();
|
| + valueOf(k) => null;
|
| +}
|
| +
|
| +class _ParserOptions implements ParserOptions {
|
| + const _ParserOptions();
|
| +
|
| + bool get enableConditionalDirectives => false;
|
| + bool get enableGenericMethodSyntax => false;
|
| }
|
|
|