OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #library('import_mapper'); |
| 6 |
| 7 #import('dart:io'); |
| 8 // TODO(rnystrom): This should be dart:json. |
| 9 #import('../../lib/json/json.dart'); |
| 10 #import('../../frog/lang.dart'); |
| 11 #import('../../frog/file_system.dart'); |
| 12 #import('../../frog/file_system_vm.dart'); |
| 13 |
| 14 typedef String ImportHook(ImportContext context, String name); |
| 15 |
| 16 /** |
| 17 * Provides contextual information about the current import and environment |
| 18 * that the import hook can use to resolve an import. |
| 19 */ |
| 20 class ImportContext { |
| 21 // TODO(rnystrom): Fill in context here as we figure out what we want. |
| 22 } |
| 23 |
| 24 /** The generated import map. */ |
| 25 Map<String, String> _importMap; |
| 26 |
| 27 ImportHook _hook; |
| 28 |
| 29 /** |
| 30 * Uses the given import hook to generate an import map for all of the |
| 31 * libraries used by a [entrypoint]. Returns the generated map object. |
| 32 */ |
| 33 Map<String, String> generateImportMap(String entrypoint, ImportHook hook) { |
| 34 _importMap = <String>{}; |
| 35 _hook = hook; |
| 36 |
| 37 // Initialize frog. |
| 38 final files = new VMFileSystem(); |
| 39 parseOptions('../../frog', ['', '', '--libdir=../../frog/lib'], files); |
| 40 initializeWorld(files); |
| 41 _importMap = {}; |
| 42 |
| 43 _walkLibrary(entrypoint); |
| 44 |
| 45 return _importMap; |
| 46 } |
| 47 |
| 48 /** |
| 49 * Uses the given import hook to generate an import map for all of the |
| 50 * libraries used by a given entrypoint. The entrypoint is assumed to be |
| 51 * provided as the first VM command line argument. |
| 52 * |
| 53 * Prints the import map data (a JSON object) to stdout. |
| 54 */ |
| 55 void printImportMap(ImportHook hook) { |
| 56 // The entrypoint of the library to generate an import map for. |
| 57 final argv = (new Options()).arguments; |
| 58 final entrypoint = argv[argv.length - 1]; |
| 59 |
| 60 final map = generateImportMap(entrypoint, hook); |
| 61 print(JSON.stringify(map)); |
| 62 } |
| 63 |
| 64 /** |
| 65 * Recursively traverses all of the `#import()` directives in the given library |
| 66 * entrypoint and runs the import hook on them. [entrypoint] should be a path |
| 67 * to a library file. |
| 68 */ |
| 69 void _walkLibrary(String entrypoint) { |
| 70 // TODO(rnystrom): Do more here when there's context we care about. |
| 71 final context = new ImportContext(); |
| 72 |
| 73 final text = _readFile(entrypoint); |
| 74 final source = new SourceFile(entrypoint, text); |
| 75 final parser = new Parser(source, diet: true); |
| 76 |
| 77 final definitions = parser.compilationUnit(); |
| 78 |
| 79 for (final definition in definitions) { |
| 80 // Only look at #import directives. |
| 81 if (definition is! DirectiveDefinition) continue; |
| 82 DirectiveDefinition directive = definition; |
| 83 if (directive.name.name != 'import') continue; |
| 84 |
| 85 // The first argument is expected to be a string literal. |
| 86 final name = directive.arguments[0].value.value.actualValue; |
| 87 |
| 88 // Only map a given import once. |
| 89 // TODO(rnystrom): Should invoke the hook again and ensure that it gets |
| 90 // the same result. It should be an error if the hook isn't |
| 91 // referentially transparent. |
| 92 if (!_importMap.containsKey(name)) { |
| 93 final uri = _hook(context, name); |
| 94 _importMap[name] = uri; |
| 95 |
| 96 // Recurse into this library. |
| 97 // TODO(rnystrom): Hackish. How should we handle corelib stuff? |
| 98 if (!uri.startsWith('dart:')) { |
| 99 _walkLibrary(_getFullPath(entrypoint, uri)); |
| 100 } |
| 101 } |
| 102 } |
| 103 } |
| 104 |
| 105 // TODO(rnystrom): Copied from frog/library.dart (makeFullPath). |
| 106 /** |
| 107 * Given the path to a library containing an #import() and the resolved URI for |
| 108 * that import, gives the full path to that library. |
| 109 */ |
| 110 String _getFullPath(String importingLibrary, String filename) { |
| 111 if (filename.startsWith('dart:')) return filename; |
| 112 // TODO(jmesserly): replace with node.js path.resolve |
| 113 if (filename.startsWith('/')) return filename; |
| 114 if (filename.startsWith('file:///')) return filename; |
| 115 if (filename.startsWith('http://')) return filename; |
| 116 if (const RegExp('^[a-zA-Z]:/').hasMatch(filename)) return filename; |
| 117 return joinPaths(dirname(importingLibrary), filename); |
| 118 } |
| 119 |
| 120 String _readFile(String filename) { |
| 121 // TODO(rnystrom): There must be an easier way than this. |
| 122 var file = (new File(filename)).openSync(); |
| 123 var length = file.lengthSync(); |
| 124 var buffer = new List<int>(length); |
| 125 var bytes = file.readListSync(buffer, 0, length); |
| 126 file.closeSync(); |
| 127 return new String.fromCharCodes(buffer); |
| 128 } |
OLD | NEW |