| Index: utils/import_mapper/import_mapper.dart
|
| diff --git a/utils/import_mapper/import_mapper.dart b/utils/import_mapper/import_mapper.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..381b79537c44eff03ea80915cd682472035fd84c
|
| --- /dev/null
|
| +++ b/utils/import_mapper/import_mapper.dart
|
| @@ -0,0 +1,128 @@
|
| +// Copyright (c) 2012, 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.
|
| +
|
| +#library('import_mapper');
|
| +
|
| +#import('dart:io');
|
| +// TODO(rnystrom): This should be dart:json.
|
| +#import('../../lib/json/json.dart');
|
| +#import('../../frog/lang.dart');
|
| +#import('../../frog/file_system.dart');
|
| +#import('../../frog/file_system_vm.dart');
|
| +
|
| +typedef String ImportHook(ImportContext context, String name);
|
| +
|
| +/**
|
| + * Provides contextual information about the current import and environment
|
| + * that the import hook can use to resolve an import.
|
| + */
|
| +class ImportContext {
|
| + // TODO(rnystrom): Fill in context here as we figure out what we want.
|
| +}
|
| +
|
| +/** The generated import map. */
|
| +Map<String, String> _importMap;
|
| +
|
| +ImportHook _hook;
|
| +
|
| +/**
|
| + * Uses the given import hook to generate an import map for all of the
|
| + * libraries used by a [entrypoint]. Returns the generated map object.
|
| + */
|
| +Map<String, String> generateImportMap(String entrypoint, ImportHook hook) {
|
| + _importMap = <String>{};
|
| + _hook = hook;
|
| +
|
| + // Initialize frog.
|
| + final files = new VMFileSystem();
|
| + parseOptions('../../frog', ['', '', '--libdir=../../frog/lib'], files);
|
| + initializeWorld(files);
|
| + _importMap = {};
|
| +
|
| + _walkLibrary(entrypoint);
|
| +
|
| + return _importMap;
|
| +}
|
| +
|
| +/**
|
| + * Uses the given import hook to generate an import map for all of the
|
| + * libraries used by a given entrypoint. The entrypoint is assumed to be
|
| + * provided as the first VM command line argument.
|
| + *
|
| + * Prints the import map data (a JSON object) to stdout.
|
| + */
|
| +void printImportMap(ImportHook hook) {
|
| + // The entrypoint of the library to generate an import map for.
|
| + final argv = (new Options()).arguments;
|
| + final entrypoint = argv[argv.length - 1];
|
| +
|
| + final map = generateImportMap(entrypoint, hook);
|
| + print(JSON.stringify(map));
|
| +}
|
| +
|
| +/**
|
| + * Recursively traverses all of the `#import()` directives in the given library
|
| + * entrypoint and runs the import hook on them. [entrypoint] should be a path
|
| + * to a library file.
|
| + */
|
| +void _walkLibrary(String entrypoint) {
|
| + // TODO(rnystrom): Do more here when there's context we care about.
|
| + final context = new ImportContext();
|
| +
|
| + final text = _readFile(entrypoint);
|
| + final source = new SourceFile(entrypoint, text);
|
| + final parser = new Parser(source, diet: true);
|
| +
|
| + final definitions = parser.compilationUnit();
|
| +
|
| + for (final definition in definitions) {
|
| + // Only look at #import directives.
|
| + if (definition is! DirectiveDefinition) continue;
|
| + DirectiveDefinition directive = definition;
|
| + if (directive.name.name != 'import') continue;
|
| +
|
| + // The first argument is expected to be a string literal.
|
| + final name = directive.arguments[0].value.value.actualValue;
|
| +
|
| + // Only map a given import once.
|
| + // TODO(rnystrom): Should invoke the hook again and ensure that it gets
|
| + // the same result. It should be an error if the hook isn't
|
| + // referentially transparent.
|
| + if (!_importMap.containsKey(name)) {
|
| + final uri = _hook(context, name);
|
| + _importMap[name] = uri;
|
| +
|
| + // Recurse into this library.
|
| + // TODO(rnystrom): Hackish. How should we handle corelib stuff?
|
| + if (!uri.startsWith('dart:')) {
|
| + _walkLibrary(_getFullPath(entrypoint, uri));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +// TODO(rnystrom): Copied from frog/library.dart (makeFullPath).
|
| +/**
|
| + * Given the path to a library containing an #import() and the resolved URI for
|
| + * that import, gives the full path to that library.
|
| + */
|
| +String _getFullPath(String importingLibrary, String filename) {
|
| + if (filename.startsWith('dart:')) return filename;
|
| + // TODO(jmesserly): replace with node.js path.resolve
|
| + if (filename.startsWith('/')) return filename;
|
| + if (filename.startsWith('file:///')) return filename;
|
| + if (filename.startsWith('http://')) return filename;
|
| + if (const RegExp('^[a-zA-Z]:/').hasMatch(filename)) return filename;
|
| + return joinPaths(dirname(importingLibrary), filename);
|
| +}
|
| +
|
| +String _readFile(String filename) {
|
| + // TODO(rnystrom): There must be an easier way than this.
|
| + var file = (new File(filename)).openSync();
|
| + var length = file.lengthSync();
|
| + var buffer = new List<int>(length);
|
| + var bytes = file.readListSync(buffer, 0, length);
|
| + file.closeSync();
|
| + return new String.fromCharCodes(buffer);
|
| +}
|
|
|