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 | 8 |
9 import 'dart:io'; | 9 import 'dart:io'; |
10 import 'dart:async'; | 10 import 'dart:async'; |
11 import 'dart:math' as math; | 11 import 'dart:math' as math; |
12 | 12 |
13 import 'package:analyzer/analyzer.dart'; | 13 import 'package:analyzer/analyzer.dart'; |
14 import 'package:analyzer/src/generated/sdk.dart'; | 14 import 'package:analyzer/src/generated/sdk.dart'; |
15 import 'package:path/path.dart' as path; | 15 import 'package:path/path.dart' as path; |
16 import 'package:front_end/src/fasta/compile_platform.dart' as | 16 import 'package:front_end/src/fasta/compile_platform.dart' as compile_platform; |
17 compile_platform; | 17 |
| 18 import 'package:front_end/src/fasta/outline.dart' show CompileTask; |
| 19 |
| 20 import 'package:front_end/src/fasta/compiler_command_line.dart' |
| 21 show CompilerCommandLine; |
| 22 |
| 23 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext; |
| 24 |
| 25 import 'package:front_end/src/fasta/ticker.dart' show Ticker; |
| 26 |
| 27 /// Set of input files that were read by this script to generate patched SDK. |
| 28 /// We will dump it out into the depfile for ninja to use. |
| 29 /// |
| 30 /// For more information see GN and Ninja references: |
| 31 /// https://chromium.googlesource.com/chromium/src/+/56807c6cb383140af0c03da8
f6731d77785d7160/tools/gn/docs/reference.md#depfile_string_File-name-for-input-d
ependencies-for-actions |
| 32 /// https://ninja-build.org/manual.html#_depfile |
| 33 /// |
| 34 final deps = new Set<String>(); |
| 35 |
| 36 /// Create [File] object from the given path and register it as a dependency. |
| 37 File getInputFile(String path, {canBeMissing: false}) { |
| 38 final file = new File(path); |
| 39 if (!file.existsSync()) { |
| 40 if (!canBeMissing) throw "patch_sdk.dart expects all inputs to exist"; |
| 41 return null; |
| 42 } |
| 43 deps.add(file.absolute.path); |
| 44 return file; |
| 45 } |
| 46 |
| 47 /// Read the given file synchronously as a string and register this path as |
| 48 /// a dependency. |
| 49 String readInputFile(String path, {canBeMissing: false}) => |
| 50 getInputFile(path, canBeMissing: canBeMissing)?.readAsStringSync(); |
18 | 51 |
19 Future main(List<String> argv) async { | 52 Future main(List<String> argv) async { |
20 var base = path.fromUri(Platform.script); | 53 var base = path.fromUri(Platform.script); |
21 var dartDir = path.dirname(path.dirname(path.absolute(base))); | 54 var dartDir = path.dirname(path.dirname(path.absolute(base))); |
22 | 55 |
23 if (argv.length != 5 || argv.first != 'vm') { | 56 if (argv.length != 5 || argv.first != 'vm') { |
24 final self = path.relative(base); | 57 final self = path.relative(base); |
25 print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); | 58 print('Usage: $self vm SDK_DIR PATCH_DIR OUTPUT_DIR PACKAGES'); |
26 | 59 |
27 final repositoryDir = path.relative(path.dirname(path.dirname(base))); | 60 final repositoryDir = path.relative(path.dirname(path.dirname(base))); |
28 final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); | 61 final sdkExample = path.relative(path.join(repositoryDir, 'sdk')); |
29 final patchExample = path.relative( | 62 final patchExample = path.relative( |
30 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); | 63 path.join(repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patch')); |
31 final outExample = path.relative(path.join(repositoryDir, 'out', 'DebugX64', | 64 final outExample = path.relative(path.join( |
32 'obj', 'gen', 'patched_sdk')); | 65 repositoryDir, 'out', 'DebugX64', 'obj', 'gen', 'patched_sdk')); |
33 print('For example:'); | 66 print('For example:'); |
34 print('\$ $self vm $sdkExample $patchExample $outExample'); | 67 print('\$ $self vm $sdkExample $patchExample $outExample'); |
35 | 68 |
36 exit(1); | 69 exit(1); |
37 } | 70 } |
38 | 71 |
39 var mode = argv[0]; | 72 var mode = argv[0]; |
| 73 assert(mode == "vm"); |
40 var input = argv[1]; | 74 var input = argv[1]; |
41 var sdkLibIn = path.join(input, 'lib'); | 75 var sdkLibIn = path.join(input, 'lib'); |
42 var patchIn = argv[2]; | 76 var patchIn = argv[2]; |
43 var outDir = argv[3]; | 77 var outDir = argv[3]; |
44 var sdkOut = path.join(outDir, 'lib'); | 78 var sdkOut = path.join(outDir, 'lib'); |
45 var packagesFile = argv[4]; | 79 var packagesFile = argv[4]; |
46 | 80 |
47 var privateIn = path.join(input, 'private'); | 81 var privateIn = path.join(input, 'private'); |
48 var INTERNAL_PATH = '_internal/compiler/js_lib/'; | 82 var INTERNAL_PATH = '_internal/compiler/js_lib/'; |
49 | 83 |
50 // Copy and patch libraries.dart and version | 84 // Copy and patch libraries.dart and version |
51 var libContents = new File(path.join(sdkLibIn, '_internal', | 85 var libContents = readInputFile(path.join( |
52 'sdk_library_metadata', 'lib', 'libraries.dart')).readAsStringSync(); | 86 sdkLibIn, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart')); |
53 if (mode == 'vm') { | 87 libContents = libContents.replaceAll( |
54 libContents = libContents.replaceAll( | 88 ' libraries = const {', |
55 ' libraries = const {', | 89 ''' libraries = const { |
56 ''' libraries = const { | |
57 | 90 |
58 "_builtin": const LibraryInfo( | 91 "_builtin": const LibraryInfo( |
59 "_builtin/_builtin.dart", | 92 "_builtin/_builtin.dart", |
60 categories: "Client,Server", | 93 categories: "Client,Server", |
61 implementation: true, | 94 implementation: true, |
62 documented: false, | 95 documented: false, |
63 platforms: VM_PLATFORM), | 96 platforms: VM_PLATFORM), |
64 | 97 |
65 "profiler": const LibraryInfo( | 98 "profiler": const LibraryInfo( |
66 "profiler/profiler.dart", | 99 "profiler/profiler.dart", |
67 maturity: Maturity.DEPRECATED, | 100 maturity: Maturity.DEPRECATED, |
68 documented: false), | 101 documented: false), |
69 | 102 |
70 "_vmservice": const LibraryInfo( | 103 "_vmservice": const LibraryInfo( |
71 "vmservice/vmservice.dart", | 104 "vmservice/vmservice.dart", |
72 implementation: true, | 105 implementation: true, |
73 documented: false, | 106 documented: false, |
74 platforms: VM_PLATFORM), | 107 platforms: VM_PLATFORM), |
75 | 108 |
76 "vmservice_io": const LibraryInfo( | 109 "vmservice_io": const LibraryInfo( |
77 "vmservice_io/vmservice_io.dart", | 110 "vmservice_io/vmservice_io.dart", |
78 implementation: true, | 111 implementation: true, |
79 documented: false, | 112 documented: false, |
80 platforms: VM_PLATFORM), | 113 platforms: VM_PLATFORM), |
81 | 114 |
82 '''); | 115 '''); |
83 } | |
84 _writeSync( | 116 _writeSync( |
85 path.join( | 117 path.join( |
86 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), | 118 sdkOut, '_internal', 'sdk_library_metadata', 'lib', 'libraries.dart'), |
87 libContents); | 119 libContents); |
88 if (mode == 'ddc') { | |
89 _writeSync(path.join(sdkOut, '..', 'version'), | |
90 new File(path.join(sdkLibIn, '..', 'version')).readAsStringSync()); | |
91 } | |
92 | 120 |
93 // Parse libraries.dart | 121 // Parse libraries.dart |
94 var sdkLibraries = _getSdkLibraries(libContents); | 122 var sdkLibraries = _getSdkLibraries(libContents); |
95 | 123 |
96 // Enumerate core libraries and apply patches | 124 // Enumerate core libraries and apply patches |
97 for (SdkLibrary library in sdkLibraries) { | 125 for (SdkLibrary library in sdkLibraries) { |
98 // TODO(jmesserly): analyzer does not handle the default case of | 126 if (library.isDart2JsLibrary) { |
99 // "both platforms" correctly, and treats it as being supported on neither. | |
100 // So instead we skip explicitly marked as either VM or dart2js libs. | |
101 if (mode == 'ddc' ? library.isVmLibrary : library.isDart2JsLibrary) { | |
102 continue; | 127 continue; |
103 } | 128 } |
104 | 129 |
105 var libraryOut = path.join(sdkLibIn, library.path); | 130 var libraryOut = path.join(sdkLibIn, library.path); |
106 var libraryIn; | 131 var libraryIn = libraryOut; |
107 if (mode == 'ddc' && library.path.contains(INTERNAL_PATH)) { | |
108 libraryIn = | |
109 path.join(privateIn, library.path.replaceAll(INTERNAL_PATH, '')); | |
110 } else { | |
111 libraryIn = libraryOut; | |
112 } | |
113 | 132 |
114 var libraryFile = new File(libraryIn); | 133 var libraryFile = getInputFile(libraryIn, canBeMissing: true); |
115 if (libraryFile.existsSync()) { | 134 if (libraryFile != null) { |
116 var outPaths = <String>[libraryOut]; | 135 var outPaths = <String>[libraryOut]; |
117 var libraryContents = libraryFile.readAsStringSync(); | 136 var libraryContents = libraryFile.readAsStringSync(); |
118 | 137 |
119 int inputModifyTime = | 138 int inputModifyTime = |
120 libraryFile.lastModifiedSync().millisecondsSinceEpoch; | 139 libraryFile.lastModifiedSync().millisecondsSinceEpoch; |
121 var partFiles = <File>[]; | 140 var partFiles = <File>[]; |
122 for (var part in parseDirectives(libraryContents).directives) { | 141 for (var part in parseDirectives(libraryContents).directives) { |
123 if (part is PartDirective) { | 142 if (part is PartDirective) { |
124 var partPath = part.uri.stringValue; | 143 var partPath = part.uri.stringValue; |
125 outPaths.add(path.join(path.dirname(libraryOut), partPath)); | 144 outPaths.add(path.join(path.dirname(libraryOut), partPath)); |
126 | 145 |
127 var partFile = new File(path.join(path.dirname(libraryIn), partPath)); | 146 var partFile = |
| 147 getInputFile(path.join(path.dirname(libraryIn), partPath)); |
128 partFiles.add(partFile); | 148 partFiles.add(partFile); |
129 inputModifyTime = math.max(inputModifyTime, | 149 inputModifyTime = math.max(inputModifyTime, |
130 partFile.lastModifiedSync().millisecondsSinceEpoch); | 150 partFile.lastModifiedSync().millisecondsSinceEpoch); |
131 } | 151 } |
132 } | 152 } |
133 | 153 |
134 // See if we can find a patch file. | 154 // See if we can find a patch file. |
135 var patchPath = path.join( | 155 var patchPath = path.join( |
136 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); | 156 patchIn, path.basenameWithoutExtension(libraryIn) + '_patch.dart'); |
137 | 157 |
138 var patchFile = new File(patchPath); | 158 var patchFile = getInputFile(patchPath, canBeMissing: true); |
139 bool patchExists = patchFile.existsSync(); | 159 if (patchFile != null) { |
140 if (patchExists) { | |
141 inputModifyTime = math.max(inputModifyTime, | 160 inputModifyTime = math.max(inputModifyTime, |
142 patchFile.lastModifiedSync().millisecondsSinceEpoch); | 161 patchFile.lastModifiedSync().millisecondsSinceEpoch); |
143 } | 162 } |
144 | 163 |
145 // Compute output paths | 164 // Compute output paths |
146 outPaths = outPaths | 165 outPaths = outPaths |
147 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) | 166 .map((p) => path.join(sdkOut, path.relative(p, from: sdkLibIn))) |
148 .toList(); | 167 .toList(); |
149 | 168 |
150 // Compare output modify time with input modify time. | 169 // Compare output modify time with input modify time. |
151 bool needsUpdate = false; | 170 bool needsUpdate = false; |
152 for (var outPath in outPaths) { | 171 for (var outPath in outPaths) { |
153 var outFile = new File(outPath); | 172 var outFile = new File(outPath); |
154 if (!outFile.existsSync() || | 173 if (!outFile.existsSync() || |
155 outFile.lastModifiedSync().millisecondsSinceEpoch < | 174 outFile.lastModifiedSync().millisecondsSinceEpoch < |
156 inputModifyTime) { | 175 inputModifyTime) { |
157 needsUpdate = true; | 176 needsUpdate = true; |
158 break; | 177 break; |
159 } | 178 } |
160 } | 179 } |
161 | 180 |
162 if (needsUpdate) { | 181 if (needsUpdate) { |
163 var contents = <String>[libraryContents]; | 182 var contents = <String>[libraryContents]; |
164 contents.addAll(partFiles.map((f) => f.readAsStringSync())); | 183 contents.addAll(partFiles.map((f) => f.readAsStringSync())); |
165 if (patchExists) { | 184 if (patchFile != null) { |
166 var patchContents = patchFile.readAsStringSync(); | 185 var patchContents = patchFile.readAsStringSync(); |
167 contents = _patchLibrary( | 186 contents = _patchLibrary(patchFile.path, contents, patchContents); |
168 patchFile.path, contents, patchContents); | |
169 } | 187 } |
170 | 188 |
171 for (var i = 0; i < outPaths.length; i++) { | 189 for (var i = 0; i < outPaths.length; i++) { |
172 _writeSync(outPaths[i], contents[i]); | 190 _writeSync(outPaths[i], contents[i]); |
173 } | 191 } |
174 } | 192 } |
175 } | 193 } |
176 } | 194 } |
177 | 195 |
178 if (mode == 'vm') { | 196 for (var tuple in [ |
179 for (var tuple in [['_builtin', 'builtin.dart']]) { | 197 ['_builtin', 'builtin.dart'] |
180 var vmLibrary = tuple[0]; | 198 ]) { |
181 var dartFile = tuple[1]; | 199 var vmLibrary = tuple[0]; |
| 200 var dartFile = tuple[1]; |
182 | 201 |
183 // The "dart:_builtin" library is only available for the DartVM. | 202 // The "dart:_builtin" library is only available for the DartVM. |
184 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); | 203 var builtinLibraryIn = path.join(dartDir, 'runtime', 'bin', dartFile); |
185 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); | 204 var builtinLibraryOut = path.join(sdkOut, vmLibrary, '${vmLibrary}.dart'); |
186 _writeSync(builtinLibraryOut, new File(builtinLibraryIn).readAsStringSync(
)); | 205 _writeSync(builtinLibraryOut, readInputFile(builtinLibraryIn)); |
187 } | 206 } |
188 | 207 |
189 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { | 208 for (var file in ['loader.dart', 'server.dart', 'vmservice_io.dart']) { |
190 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); | 209 var libraryIn = path.join(dartDir, 'runtime', 'bin', 'vmservice', file); |
191 var libraryOut = path.join(sdkOut, 'vmservice_io', file); | 210 var libraryOut = path.join(sdkOut, 'vmservice_io', file); |
192 _writeSync(libraryOut, new File(libraryIn).readAsStringSync()); | 211 _writeSync(libraryOut, readInputFile(libraryIn)); |
193 } | |
194 } | 212 } |
195 | 213 |
196 // TODO(kustermann): We suppress compiler hints/warnings/errors temporarily | 214 // TODO(kustermann): We suppress compiler hints/warnings/errors temporarily |
197 // because everyone building the `runtime` target will get these now. | 215 // because everyone building the `runtime` target will get these now. |
198 // We should remove the suppression again once the underlying issues have | 216 // We should remove the suppression again once the underlying issues have |
199 // been fixed (either in fasta or the dart files in the patched_sdk). | 217 // been fixed (either in fasta or the dart files in the patched_sdk). |
200 final capturedLines = <String>[]; | 218 final capturedLines = <String>[]; |
201 try { | 219 try { |
| 220 final platform = path.join(outDir, 'platform.dill'); |
| 221 |
202 await runZoned(() async { | 222 await runZoned(() async { |
203 await compile_platform.mainEntryPoint(<String>[ | 223 await compile_platform.mainEntryPoint(<String>[ |
204 '--packages', | 224 '--packages', |
205 new Uri.file(packagesFile).toString(), | 225 new Uri.file(packagesFile).toString(), |
206 new Uri.directory(outDir).toString(), | 226 new Uri.directory(outDir).toString(), |
207 path.join(outDir, 'platform.dill') | 227 platform, |
208 ]); | 228 ]); |
| 229 |
| 230 // platform.dill was generated, now generate platform.dill.d depfile |
| 231 // that captures all dependencies that participated in the generation. |
| 232 // There are two types of dependencies: |
| 233 // (1) all Dart sources that constitute this tool itself |
| 234 // (2) Dart SDK and patch sources. |
| 235 // We already collected all inputs from the second category in the deps |
| 236 // set. To collect inputs from the first category we actually use Fasta: |
| 237 // we ask Fasta to outline patch_sdk.dart and generate a depfile which |
| 238 // would list all the sources. |
| 239 final depfile = "${outDir}.d"; |
| 240 await CompilerCommandLine.withGlobalOptions("outline", [ |
| 241 '--packages', |
| 242 new Uri.file(packagesFile).toString(), |
| 243 '--platform', |
| 244 platform, // platform.dill that was just generated |
| 245 Platform.script.toString() // patch_sdk.dart |
| 246 ], (CompilerContext c) async { |
| 247 CompileTask task = |
| 248 new CompileTask(c, new Ticker(isVerbose: c.options.verbose)); |
| 249 final kernelTarget = await task.buildOutline(null); |
| 250 await kernelTarget.writeDepsFile( |
| 251 new Uri.file(platform), new Uri.file(depfile)); |
| 252 }); |
| 253 |
| 254 // Read depfile generated by Fasta and append deps that we have collected |
| 255 // during generation of patched_sdk to it. |
| 256 final list = new File(depfile).readAsStringSync().split(':'); |
| 257 assert(list.length == 2); |
| 258 deps.addAll(list[1].split(' ').where((str) => str.isNotEmpty)); |
| 259 assert(list[0] == 'patched_sdk/platform.dill'); |
| 260 new File(depfile).writeAsStringSync("${list[0]}: ${deps.join(' ')}\n"); |
209 }, zoneSpecification: new ZoneSpecification(print: (_, _2, _3, line) { | 261 }, zoneSpecification: new ZoneSpecification(print: (_, _2, _3, line) { |
210 capturedLines.add(line); | 262 capturedLines.add(line); |
211 })); | 263 })); |
212 } catch (_) { | 264 } catch (_) { |
213 for (final line in capturedLines) { | 265 for (final line in capturedLines) { |
214 print(line); | 266 print(line); |
215 } | 267 } |
216 rethrow; | 268 rethrow; |
217 } | 269 } |
218 } | 270 } |
(...skipping 18 matching lines...) Expand all Loading... |
237 /// | 289 /// |
238 /// This is purely a syntactic transformation. Unlike dart2js patch files, there | 290 /// This is purely a syntactic transformation. Unlike dart2js patch files, there |
239 /// is no semantic meaning given to the *_patch files, and they do not magically | 291 /// is no semantic meaning given to the *_patch files, and they do not magically |
240 /// get their own library scope, etc. | 292 /// get their own library scope, etc. |
241 /// | 293 /// |
242 /// Editorializing: the dart2js approach requires a Dart front end such as | 294 /// Editorializing: the dart2js approach requires a Dart front end such as |
243 /// package:analyzer to semantically model a feature beyond what is specified | 295 /// package:analyzer to semantically model a feature beyond what is specified |
244 /// in the Dart language. Since this feature is only for the convenience of | 296 /// in the Dart language. Since this feature is only for the convenience of |
245 /// writing the dart:* libraries, and not a tool given to Dart developers, it | 297 /// writing the dart:* libraries, and not a tool given to Dart developers, it |
246 /// seems like a non-ideal situation. Instead we keep the preprocessing simple. | 298 /// seems like a non-ideal situation. Instead we keep the preprocessing simple. |
247 List<String> _patchLibrary(String name, | 299 List<String> _patchLibrary( |
248 List<String> partsContents, | 300 String name, List<String> partsContents, String patchContents) { |
249 String patchContents) { | |
250 var results = <StringEditBuffer>[]; | 301 var results = <StringEditBuffer>[]; |
251 | 302 |
252 // Parse the patch first. We'll need to extract bits of this as we go through | 303 // Parse the patch first. We'll need to extract bits of this as we go through |
253 // the other files. | 304 // the other files. |
254 final patchFinder = new PatchFinder.parseAndVisit(name, patchContents); | 305 final patchFinder = new PatchFinder.parseAndVisit(name, patchContents); |
255 | 306 |
256 // Merge `external` declarations with the corresponding `@patch` code. | 307 // Merge `external` declarations with the corresponding `@patch` code. |
257 for (var partContent in partsContents) { | 308 for (var partContent in partsContents) { |
258 var partEdits = new StringEditBuffer(partContent); | 309 var partEdits = new StringEditBuffer(partContent); |
259 var partUnit = parseCompilationUnit(partContent); | 310 var partUnit = parseCompilationUnit(partContent); |
260 partUnit.accept(new PatchApplier(partEdits, patchFinder)); | 311 partUnit.accept(new PatchApplier(partEdits, patchFinder)); |
261 results.add(partEdits); | 312 results.add(partEdits); |
262 } | 313 } |
263 | 314 |
264 if (patchFinder.patches.length != patchFinder.applied.length) { | 315 if (patchFinder.patches.length != patchFinder.applied.length) { |
265 print('Some elements marked as @patch do not have corresponding elements:'); | 316 print('Some elements marked as @patch do not have corresponding elements:'); |
266 for (var patched in patchFinder.patches.keys) { | 317 for (var patched in patchFinder.patches.keys) { |
267 if (!patchFinder.applied.contains(patched)) { | 318 if (!patchFinder.applied.contains(patched)) { |
268 print('*** ${patched}'); | 319 print('*** ${patched}'); |
269 } | 320 } |
270 } | 321 } |
271 throw "Failed to apply all @patch-es"; | 322 throw "Failed to apply all @patch-es"; |
272 } | 323 } |
273 | 324 |
274 return new List<String>.from(results.map((e) => e.toString())); | 325 return new List<String>.from(results.map((e) => e.toString())); |
275 } | 326 } |
276 | 327 |
277 final String injectedCidFields = [ | 328 final String injectedCidFields = [ |
278 'Array', 'ExternalOneByteString', 'GrowableObjectArray', | 329 'Array', |
279 'ImmutableArray', 'OneByteString', 'TwoByteString', 'Bigint' | 330 'ExternalOneByteString', |
| 331 'GrowableObjectArray', |
| 332 'ImmutableArray', |
| 333 'OneByteString', |
| 334 'TwoByteString', |
| 335 'Bigint' |
280 ].map((name) => "static final int cid${name} = 0;").join('\n'); | 336 ].map((name) => "static final int cid${name} = 0;").join('\n'); |
281 | 337 |
282 /// Merge `@patch` declarations into `external` declarations. | 338 /// Merge `@patch` declarations into `external` declarations. |
283 class PatchApplier extends GeneralizingAstVisitor { | 339 class PatchApplier extends GeneralizingAstVisitor { |
284 final StringEditBuffer edits; | 340 final StringEditBuffer edits; |
285 final PatchFinder patch; | 341 final PatchFinder patch; |
286 | 342 |
287 bool _isLibrary = true; // until proven otherwise. | 343 bool _isLibrary = true; // until proven otherwise. |
288 | 344 |
289 PatchApplier(this.edits, this.patch); | 345 PatchApplier(this.edits, this.patch); |
290 | 346 |
291 @override | 347 @override |
292 visitCompilationUnit(CompilationUnit node) { | 348 visitCompilationUnit(CompilationUnit node) { |
293 super.visitCompilationUnit(node); | 349 super.visitCompilationUnit(node); |
294 if (_isLibrary) _mergeUnpatched(node); | 350 if (_isLibrary) _mergeUnpatched(node); |
295 } | 351 } |
296 | 352 |
297 void _merge(AstNode node, int pos) { | 353 void _merge(AstNode node, int pos) { |
298 var code = patch.contents.substring(node.offset, node.end); | 354 var code = patch.contents.substring(node.offset, node.end); |
299 | 355 |
300 // We inject a number of static fields into dart:internal.ClassID class. | 356 // We inject a number of static fields into dart:internal.ClassID class. |
301 // These fields represent various VM class ids and are only used to | 357 // These fields represent various VM class ids and are only used to |
302 // make core libraries compile. Kernel reader will actually ignore these | 358 // make core libraries compile. Kernel reader will actually ignore these |
303 // fields and instead inject concrete constants into this class. | 359 // fields and instead inject concrete constants into this class. |
304 if (node is ClassDeclaration && node.name.name == 'ClassID') { | 360 if (node is ClassDeclaration && node.name.name == 'ClassID') { |
305 code = code.replaceFirst( | 361 code = code.replaceFirst(new RegExp(r'}$'), injectedCidFields + '}'); |
306 new RegExp(r'}$'), injectedCidFields + '}'); | |
307 } | 362 } |
308 edits.insert(pos, '\n' + code); | 363 edits.insert(pos, '\n' + code); |
309 } | 364 } |
310 | 365 |
311 /// Merges directives and declarations that are not `@patch` into the library. | 366 /// Merges directives and declarations that are not `@patch` into the library. |
312 void _mergeUnpatched(CompilationUnit unit) { | 367 void _mergeUnpatched(CompilationUnit unit) { |
313 // Merge imports from the patch | 368 // Merge imports from the patch |
314 // TODO(jmesserly): remove duplicate imports | 369 // TODO(jmesserly): remove duplicate imports |
315 | 370 |
316 // To patch a library, we must have a library directive | 371 // To patch a library, we must have a library directive |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 var parent = node.parent; | 497 var parent = node.parent; |
443 var className = ''; | 498 var className = ''; |
444 if (parent is ClassDeclaration) { | 499 if (parent is ClassDeclaration) { |
445 className = parent.name.name + '.'; | 500 className = parent.name.name + '.'; |
446 } | 501 } |
447 var name = (node as dynamic).name; | 502 var name = (node as dynamic).name; |
448 name = (name != null ? name.name : ''); | 503 name = (name != null ? name.name : ''); |
449 | 504 |
450 var accessor = ''; | 505 var accessor = ''; |
451 if (node is MethodDeclaration) { | 506 if (node is MethodDeclaration) { |
452 if (node.isGetter) accessor = 'get:'; | 507 if (node.isGetter) |
| 508 accessor = 'get:'; |
453 else if (node.isSetter) accessor = 'set:'; | 509 else if (node.isSetter) accessor = 'set:'; |
454 } | 510 } |
455 return className + accessor + name; | 511 return className + accessor + name; |
456 } | 512 } |
457 | 513 |
458 bool _isPatch(AnnotatedNode node) => node.metadata.any(_isPatchAnnotation); | 514 bool _isPatch(AnnotatedNode node) => node.metadata.any(_isPatchAnnotation); |
459 | 515 |
460 bool _isPatchAnnotation(Annotation m) => | 516 bool _isPatchAnnotation(Annotation m) => |
461 m.name.name == 'patch' && m.constructorName == null && m.arguments == null; | 517 m.name.name == 'patch' && m.constructorName == null && m.arguments == null; |
462 | 518 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 if (diff != 0) return diff; | 607 if (diff != 0) return diff; |
552 return end - other.end; | 608 return end - other.end; |
553 } | 609 } |
554 } | 610 } |
555 | 611 |
556 List<SdkLibrary> _getSdkLibraries(String contents) { | 612 List<SdkLibrary> _getSdkLibraries(String contents) { |
557 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); | 613 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); |
558 parseCompilationUnit(contents).accept(libraryBuilder); | 614 parseCompilationUnit(contents).accept(libraryBuilder); |
559 return libraryBuilder.librariesMap.sdkLibraries; | 615 return libraryBuilder.librariesMap.sdkLibraries; |
560 } | 616 } |
OLD | NEW |