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:math' as math; | 10 import 'dart:math' as math; |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 // the other files. | 257 // the other files. |
258 final patchFinder = new PatchFinder.parseAndVisit(name, patchContents); | 258 final patchFinder = new PatchFinder.parseAndVisit(name, patchContents); |
259 | 259 |
260 // Merge `external` declarations with the corresponding `@patch` code. | 260 // Merge `external` declarations with the corresponding `@patch` code. |
261 for (var partContent in partsContents) { | 261 for (var partContent in partsContents) { |
262 var partEdits = new StringEditBuffer(partContent); | 262 var partEdits = new StringEditBuffer(partContent); |
263 var partUnit = parseCompilationUnit(partContent); | 263 var partUnit = parseCompilationUnit(partContent); |
264 partUnit.accept(new PatchApplier(partEdits, patchFinder)); | 264 partUnit.accept(new PatchApplier(partEdits, patchFinder)); |
265 results.add(partEdits); | 265 results.add(partEdits); |
266 } | 266 } |
| 267 |
| 268 if (patchFinder.patches.length != patchFinder.applied.length) { |
| 269 print('Some elements marked as @patch do not have corresponding elements:'); |
| 270 for (var patched in patchFinder.patches.keys) { |
| 271 if (!patchFinder.applied.contains(patched)) { |
| 272 print('*** ${patched}'); |
| 273 } |
| 274 } |
| 275 throw "Failed to apply all @patch-es"; |
| 276 } |
| 277 |
267 return new List<String>.from(results.map((e) => e.toString())); | 278 return new List<String>.from(results.map((e) => e.toString())); |
268 } | 279 } |
269 | 280 |
270 /// Merge `@patch` declarations into `external` declarations. | 281 /// Merge `@patch` declarations into `external` declarations. |
271 class PatchApplier extends GeneralizingAstVisitor { | 282 class PatchApplier extends GeneralizingAstVisitor { |
272 final StringEditBuffer edits; | 283 final StringEditBuffer edits; |
273 final PatchFinder patch; | 284 final PatchFinder patch; |
274 | 285 |
275 bool _isLibrary = true; // until proven otherwise. | 286 bool _isLibrary = true; // until proven otherwise. |
276 | 287 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 for (var member in mergeMembers) { | 347 for (var member in mergeMembers) { |
337 var code = patch.contents.substring(member.offset, member.end); | 348 var code = patch.contents.substring(member.offset, member.end); |
338 edits.insert(pos, '\n\n ' + code); | 349 edits.insert(pos, '\n\n ' + code); |
339 } | 350 } |
340 } | 351 } |
341 | 352 |
342 void _maybePatch(AstNode node) { | 353 void _maybePatch(AstNode node) { |
343 if (node is FieldDeclaration) return; | 354 if (node is FieldDeclaration) return; |
344 | 355 |
345 var externalKeyword = (node as dynamic).externalKeyword; | 356 var externalKeyword = (node as dynamic).externalKeyword; |
346 if (externalKeyword == null) return; | |
347 | 357 |
348 var name = _qualifiedName(node); | 358 var name = _qualifiedName(node); |
349 var patchNode = patch.patches[name]; | 359 var patchNode = patch.patches[name]; |
350 if (patchNode == null) { | 360 if (patchNode == null) { |
351 print('warning: patch not found for $name: $node'); | 361 if (externalKeyword != null) { |
| 362 print('warning: patch not found for $name: $node'); |
| 363 } |
352 return; | 364 return; |
353 } | 365 } |
| 366 patch.applied.add(name); |
354 | 367 |
355 Annotation patchMeta = patchNode.metadata.lastWhere(_isPatchAnnotation); | 368 Annotation patchMeta = patchNode.metadata.lastWhere(_isPatchAnnotation); |
356 int start = patchMeta.endToken.next.offset; | 369 int start = patchMeta.endToken.next.offset; |
357 var code = patch.contents.substring(start, patchNode.end); | 370 var code = patch.contents.substring(start, patchNode.end); |
358 | 371 |
359 // For some node like static fields, the node's offset doesn't include | 372 // For some node like static fields, the node's offset doesn't include |
360 // the external keyword. Also starting from the keyword lets us preserve | 373 // the external keyword. Also starting from the keyword lets us preserve |
361 // documentation comments. | 374 // documentation comments. |
362 edits.replace(externalKeyword.offset, node.end, code); | 375 edits.replace(externalKeyword?.offset ?? node.offset, node.end, code); |
363 } | 376 } |
364 } | 377 } |
365 | 378 |
366 class PatchFinder extends GeneralizingAstVisitor { | 379 class PatchFinder extends GeneralizingAstVisitor { |
367 final String contents; | 380 final String contents; |
368 final CompilationUnit unit; | 381 final CompilationUnit unit; |
369 | 382 |
370 final Map patches = <String, Declaration>{}; | 383 final Map patches = <String, Declaration>{}; |
371 final Map mergeMembers = <String, List<ClassMember>>{}; | 384 final Map mergeMembers = <String, List<ClassMember>>{}; |
372 final List mergeDeclarations = <CompilationUnitMember>[]; | 385 final List mergeDeclarations = <CompilationUnitMember>[]; |
| 386 final Set<String> applied = new Set<String>(); |
373 | 387 |
374 PatchFinder.parseAndVisit(String name, String contents) | 388 PatchFinder.parseAndVisit(String name, String contents) |
375 : contents = contents, | 389 : contents = contents, |
376 unit = parseCompilationUnit(contents, name: name) { | 390 unit = parseCompilationUnit(contents, name: name) { |
377 visitCompilationUnit(unit); | 391 visitCompilationUnit(unit); |
378 } | 392 } |
379 | 393 |
380 @override | 394 @override |
381 visitCompilationUnitMember(CompilationUnitMember node) { | 395 visitCompilationUnitMember(CompilationUnitMember node) { |
382 mergeDeclarations.add(node); | 396 mergeDeclarations.add(node); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 if (diff != 0) return diff; | 541 if (diff != 0) return diff; |
528 return end - other.end; | 542 return end - other.end; |
529 } | 543 } |
530 } | 544 } |
531 | 545 |
532 List<SdkLibrary> _getSdkLibraries(String contents) { | 546 List<SdkLibrary> _getSdkLibraries(String contents) { |
533 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); | 547 var libraryBuilder = new SdkLibrariesReader_LibraryBuilder(true); |
534 parseCompilationUnit(contents).accept(libraryBuilder); | 548 parseCompilationUnit(contents).accept(libraryBuilder); |
535 return libraryBuilder.librariesMap.sdkLibraries; | 549 return libraryBuilder.librariesMap.sdkLibraries; |
536 } | 550 } |
OLD | NEW |