OLD | NEW |
---|---|
1 #!/usr/bin/env dart | 1 #!/usr/bin/env dart |
2 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 /// Command line tool to merge the SDK libraries and our patch files. | 6 /// Command line tool to merge the SDK libraries and our patch files. |
7 /// This is currently designed as an offline tool, but we could automate it. | 7 /// This is currently designed as an offline tool, but we could automate it. |
8 library dev_compiler.tool.patch_sdk; | 8 library dev_compiler.tool.patch_sdk; |
9 | 9 |
10 import 'dart:io'; | 10 import 'dart:io'; |
11 | 11 |
12 import 'package:analyzer/analyzer.dart'; | 12 import 'package:analyzer/analyzer.dart'; |
13 import 'package:analyzer/src/generated/sdk.dart'; | |
13 import 'package:path/path.dart' as path; | 14 import 'package:path/path.dart' as path; |
14 | 15 |
15 import 'input_sdk/lib/_internal/libraries.dart' as sdk; | 16 void main(List<String> argv) { |
Jennifer Messerly
2015/03/19 22:57:34
These changes aren't really needed, but they let p
| |
17 if (argv.length < 2) { | |
18 var self = path.relative(Platform.script.path); | |
19 var toolDir = path.relative(path.dirname(Platform.script.path)); | |
16 | 20 |
17 void main(List<String> argv) { | 21 var inputExample = path.join(toolDir, 'input_sdk'); |
18 var toolDir = path.relative(path.dirname(Platform.script.path)); | 22 var outExample = path.relative( |
19 var sdkLibIn = path.join(toolDir, 'input_sdk', 'lib'); | 23 path.normalize(path.join(toolDir, '..', 'test', 'generated_sdk'))); |
20 var patchIn = path.join(toolDir, 'input_sdk', 'patch'); | 24 |
21 var privateIn = path.join(toolDir, 'input_sdk', 'private'); | 25 print('Usage: $self INPUT_DIR OUTPUT_DIR'); |
22 var sdkOut = | 26 print('For example:'); |
23 path.normalize(path.join(toolDir, '..', 'test', 'generated_sdk', 'lib')); | 27 print('\$ $self $inputExample $outExample'); |
28 | |
29 inputExample = path.join(toolDir, 'min_sdk'); | |
30 outExample = path.join(toolDir, 'out', 'min_sdk'); | |
31 print('\$ $self $inputExample $outExample'); | |
32 exit(1); | |
33 } | |
34 | |
35 var input = argv[0]; | |
36 var sdkLibIn = path.join(input, 'lib'); | |
37 var patchIn = path.join(input, 'patch'); | |
38 var privateIn = path.join(input, 'private'); | |
39 var sdkOut = path.join(argv[1], 'lib'); | |
24 var privateLibOut = | 40 var privateLibOut = |
25 path.normalize(path.join(sdkOut, '_internal', 'compiler', 'js_lib')); | 41 path.normalize(path.join(sdkOut, '_internal', 'compiler', 'js_lib')); |
26 | 42 |
27 var INTERNAL_PATH = '_internal/compiler/js_lib/'; | 43 var INTERNAL_PATH = '_internal/compiler/js_lib/'; |
28 | 44 |
29 if (argv.isNotEmpty) { | |
30 print('Usage: ${path.relative(Platform.script.path)}\n'); | |
31 print('input SDK directory: $sdkLibIn'); | |
32 // We can freely make changes to these two. | |
33 print('input private libs directory: $privateIn'); | |
34 print('input patch directory: $patchIn'); | |
35 print('output SDK directory: $sdkOut'); | |
36 exit(1); | |
37 } | |
38 | |
39 // Copy libraries.dart and version | 45 // Copy libraries.dart and version |
40 _writeSync(path.join(sdkOut, '_internal', 'libraries.dart'), | 46 var libContents = new File(path.join(sdkLibIn, '_internal', 'libraries.dart')) |
41 new File(path.join(sdkLibIn, '_internal', 'libraries.dart')) | 47 .readAsStringSync(); |
42 .readAsStringSync()); | 48 _writeSync(path.join(sdkOut, '_internal', 'libraries.dart'), libContents); |
43 _writeSync(path.join(sdkOut, '..', 'version'), | 49 _writeSync(path.join(sdkOut, '..', 'version'), |
44 new File(path.join(sdkLibIn, '..', 'version')).readAsStringSync()); | 50 new File(path.join(sdkLibIn, '..', 'version')).readAsStringSync()); |
45 | 51 |
52 // Parse libraries.dart | |
53 var sdkLibraries = _getSdkLibraries(libContents); | |
54 | |
46 // Enumerate core libraries and apply patches | 55 // Enumerate core libraries and apply patches |
47 for (var library in sdk.LIBRARIES.values) { | 56 for (SdkLibrary library in sdkLibraries) { |
48 if (library.platforms & sdk.DART2JS_PLATFORM == 0) continue; | 57 // TODO(jmesserly): analyzer does not handle the default case of |
58 // "both platforms" correctly, and treats it as being supported on neither. | |
59 // So instead we skip explicitly marked as VM libs. | |
60 if (library.isVmLibrary) continue; | |
49 | 61 |
50 var libraryOut = path.join(sdkLibIn, library.path); | 62 var libraryOut = path.join(sdkLibIn, library.path); |
51 var libraryIn; | 63 var libraryIn; |
52 if (library.path.contains(INTERNAL_PATH)) { | 64 if (library.path.contains(INTERNAL_PATH)) { |
53 libraryIn = | 65 libraryIn = |
54 path.join(privateIn, library.path.replaceAll(INTERNAL_PATH, '')); | 66 path.join(privateIn, library.path.replaceAll(INTERNAL_PATH, '')); |
55 } else { | 67 } else { |
56 libraryIn = libraryOut; | 68 libraryIn = libraryOut; |
57 } | 69 } |
58 | 70 |
59 var libraryFile = new File(libraryIn); | 71 var libraryFile = new File(libraryIn); |
60 if (libraryFile.existsSync()) { | 72 if (libraryFile.existsSync()) { |
61 var contents = <String>[]; | 73 var contents = <String>[]; |
62 var paths = <String>[]; | 74 var paths = <String>[]; |
63 var libraryContents = libraryFile.readAsStringSync(); | 75 var libraryContents = libraryFile.readAsStringSync(); |
64 paths.add(libraryOut); | 76 paths.add(libraryOut); |
65 contents.add(libraryContents); | 77 contents.add(libraryContents); |
66 for (var part in parseDirectives(libraryContents).directives) { | 78 for (var part in parseDirectives(libraryContents).directives) { |
67 if (part is PartDirective) { | 79 if (part is PartDirective) { |
68 var partPath = part.uri.stringValue; | 80 var partPath = part.uri.stringValue; |
69 paths.add(path.join(path.dirname(libraryOut), partPath)); | 81 paths.add(path.join(path.dirname(libraryOut), partPath)); |
70 contents.add(new File(path.join(path.dirname(libraryIn), partPath)) | 82 contents.add(new File(path.join(path.dirname(libraryIn), partPath)) |
71 .readAsStringSync()); | 83 .readAsStringSync()); |
72 } | 84 } |
73 } | 85 } |
74 | 86 |
75 if (library.dart2jsPatchPath != null) { | 87 // See if we can find a patch file. |
76 var patchPath = path.join( | 88 var patchPath = path.join( |
77 patchIn, library.dart2jsPatchPath.replaceAll(INTERNAL_PATH, '')); | 89 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); |
90 | |
91 if (new File(patchPath).existsSync()) { | |
78 var patchContents = new File(patchPath).readAsStringSync(); | 92 var patchContents = new File(patchPath).readAsStringSync(); |
79 | |
80 contents = _patchLibrary(contents, patchContents); | 93 contents = _patchLibrary(contents, patchContents); |
81 } | 94 } |
82 for (var i = 0; i < paths.length; i++) { | 95 for (var i = 0; i < paths.length; i++) { |
83 var outPath = | 96 var outPath = |
84 path.join(sdkOut, path.relative(paths[i], from: sdkLibIn)); | 97 path.join(sdkOut, path.relative(paths[i], from: sdkLibIn)); |
85 _writeSync(outPath, contents[i]); | 98 _writeSync(outPath, contents[i]); |
86 } | 99 } |
87 } | 100 } |
88 } | 101 } |
89 } | 102 } |
90 | 103 |
91 /// Writes a file, creating the directory if needed. | 104 /// Writes a file, creating the directory if needed. |
92 void _writeSync(String filePath, String contents) { | 105 void _writeSync(String filePath, String contents) { |
93 print('Writing $filePath'); | |
94 | |
95 var outDir = new Directory(path.dirname(filePath)); | 106 var outDir = new Directory(path.dirname(filePath)); |
96 if (!outDir.existsSync()) outDir.createSync(recursive: true); | 107 if (!outDir.existsSync()) outDir.createSync(recursive: true); |
97 | 108 |
98 new File(filePath).writeAsStringSync(contents); | 109 new File(filePath).writeAsStringSync(contents); |
99 } | 110 } |
100 | 111 |
101 /// Merges dart:* library code with code from *_patch.dart file. | 112 /// Merges dart:* library code with code from *_patch.dart file. |
102 /// | 113 /// |
103 /// Takes a list of the library's parts contents, with the main library contents | 114 /// Takes a list of the library's parts contents, with the main library contents |
104 /// first in the list, and the contents of the patch file. | 115 /// first in the list, and the contents of the patch file. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 } | 201 } |
191 | 202 |
192 void _maybePatch(AstNode node) { | 203 void _maybePatch(AstNode node) { |
193 if (node is FieldDeclaration) return; | 204 if (node is FieldDeclaration) return; |
194 | 205 |
195 var externalKeyword = (node as dynamic).externalKeyword; | 206 var externalKeyword = (node as dynamic).externalKeyword; |
196 if (externalKeyword == null) return; | 207 if (externalKeyword == null) return; |
197 | 208 |
198 var name = _qualifiedName(node); | 209 var name = _qualifiedName(node); |
199 var patchNode = patch.patches[name]; | 210 var patchNode = patch.patches[name]; |
200 if (patchNode == null) throw 'patch not found for $name: $node'; | 211 if (patchNode == null) { |
212 print('warning: patch not found for $name: $node'); | |
213 return; | |
214 } | |
201 | 215 |
202 Annotation patchMeta = patchNode.metadata.lastWhere(_isPatchAnnotation); | 216 Annotation patchMeta = patchNode.metadata.lastWhere(_isPatchAnnotation); |
203 int start = patchMeta.endToken.next.offset; | 217 int start = patchMeta.endToken.next.offset; |
204 var code = patch.contents.substring(start, patchNode.end); | 218 var code = patch.contents.substring(start, patchNode.end); |
205 | 219 |
206 // For some node like static fields, the node's offset doesn't include | 220 // For some node like static fields, the node's offset doesn't include |
207 // the external keyword. Also starting from the keyword lets us preserve | 221 // the external keyword. Also starting from the keyword lets us preserve |
208 // documentation comments. | 222 // documentation comments. |
209 edits.replace(externalKeyword.offset, node.end, code); | 223 edits.replace(externalKeyword.offset, node.end, code); |
210 } | 224 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 patches[_qualifiedName(node)] = node; | 265 patches[_qualifiedName(node)] = node; |
252 } else { | 266 } else { |
253 mergeDeclarations.add(node); | 267 mergeDeclarations.add(node); |
254 } | 268 } |
255 } | 269 } |
256 | 270 |
257 @override visitFunctionBody(node) {} // skip method bodies | 271 @override visitFunctionBody(node) {} // skip method bodies |
258 } | 272 } |
259 | 273 |
260 String _qualifiedName(Declaration node) { | 274 String _qualifiedName(Declaration node) { |
261 assert(node is MethodDeclaration || | |
262 node is FunctionDeclaration || | |
263 node is ConstructorDeclaration); | |
264 | |
265 var parent = node.parent; | 275 var parent = node.parent; |
266 var className = ''; | 276 var className = ''; |
267 if (parent is ClassDeclaration) { | 277 if (parent is ClassDeclaration) { |
268 className = parent.name.name + '.'; | 278 className = parent.name.name + '.'; |
269 } | 279 } |
270 var name = (node as dynamic).name; | 280 var name = (node as dynamic).name; |
271 return className + (name != null ? name.name : ''); | 281 return className + (name != null ? name.name : ''); |
272 } | 282 } |
273 | 283 |
274 bool _isPatch(AnnotatedNode node) => node.metadata.any(_isPatchAnnotation); | 284 bool _isPatch(AnnotatedNode node) => node.metadata.any(_isPatchAnnotation); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
361 int get length => end - begin; | 371 int get length => end - begin; |
362 | 372 |
363 String toString() => '(Edit @ $begin,$end: "$replace")'; | 373 String toString() => '(Edit @ $begin,$end: "$replace")'; |
364 | 374 |
365 int compareTo(_StringEdit other) { | 375 int compareTo(_StringEdit other) { |
366 int diff = begin - other.begin; | 376 int diff = begin - other.begin; |
367 if (diff != 0) return diff; | 377 if (diff != 0) return diff; |
368 return end - other.end; | 378 return end - other.end; |
369 } | 379 } |
370 } | 380 } |
381 | |
382 List<SdkLibrary> _getSdkLibraries(String contents) { | |
383 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); | |
384 parseCompilationUnit(contents).accept(libraryBuilder); | |
385 return libraryBuilder.librariesMap.sdkLibraries; | |
386 } | |
OLD | NEW |