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; |
} |