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