| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library kernel.treeshaker_dump; | 4 library kernel.treeshaker_dump; |
| 5 | 5 |
| 6 import 'dart:io'; | 6 import 'dart:io'; |
| 7 import 'package:kernel/kernel.dart'; | 7 import 'package:kernel/kernel.dart'; |
| 8 import 'package:kernel/transformations/treeshaker.dart'; | 8 import 'package:kernel/transformations/treeshaker.dart'; |
| 9 import 'package:args/args.dart'; | 9 import 'package:args/args.dart'; |
| 10 import 'package:path/path.dart' as pathlib; | 10 import 'package:path/path.dart' as pathlib; |
| 11 import 'package:kernel/text/ast_to_text.dart'; | 11 import 'package:kernel/text/ast_to_text.dart'; |
| 12 | 12 |
| 13 ArgParser parser = new ArgParser(allowTrailingOptions: true) | 13 ArgParser parser = new ArgParser(allowTrailingOptions: true) |
| 14 ..addFlag('used', help: 'Print used members', negatable: false) | 14 ..addFlag('used', help: 'Print used members', negatable: false) |
| 15 ..addFlag('unused', help: 'Print unused members', negatable: false) | 15 ..addFlag('unused', help: 'Print unused members', negatable: false) |
| 16 ..addFlag('instantiated', | 16 ..addFlag('instantiated', |
| 17 help: 'Print instantiated classes', negatable: false) | 17 help: 'Print instantiated classes', negatable: false) |
| 18 ..addFlag('types', help: 'Print classes used as a type', negatable: false) | 18 ..addFlag('types', help: 'Print classes used as a type', negatable: false) |
| 19 ..addFlag('summary', | 19 ..addFlag('summary', |
| 20 help: 'Print short summary of tree shaking results', defaultsTo: true) | 20 help: 'Print short summary of tree shaking results', defaultsTo: true) |
| 21 ..addFlag('diff', | 21 ..addFlag('diff', |
| 22 help: 'Print textual output before and after tree shaking.\n' | 22 help: 'Print textual output before and after tree shaking.\n' |
| 23 'Files are written to FILE.before.txt and FILE.after.txt', | 23 'Files are written to FILE.before.txt and FILE.after.txt', |
| 24 negatable: false) | 24 negatable: false) |
| 25 ..addOption('output', | 25 ..addOption('output', |
| 26 help: 'The --diff files are written to the given directory instead of ' | 26 help: 'The --diff files are written to the given directory instead of ' |
| 27 'the working directory'); | 27 'the working directory') |
| 28 ..addFlag('strong', help: 'Run the tree shaker in strong mode'); |
| 28 | 29 |
| 29 String usage = ''' | 30 String usage = ''' |
| 30 Usage: treeshaker_dump [options] FILE.dill | 31 Usage: treeshaker_dump [options] FILE.dill |
| 31 | 32 |
| 32 Runs tree shaking on the given program and prints information about the results. | 33 Runs tree shaking on the given program and prints information about the results. |
| 33 | 34 |
| 34 Example: | 35 Example: |
| 35 treeshaker_dump --instantiated foo.dill | 36 treeshaker_dump --instantiated foo.dill |
| 36 | 37 |
| 37 Example: | 38 Example: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 53 print('Exactly one file should be given.'); | 54 print('Exactly one file should be given.'); |
| 54 exit(1); | 55 exit(1); |
| 55 } | 56 } |
| 56 String filename = options.rest.single; | 57 String filename = options.rest.single; |
| 57 | 58 |
| 58 if (options['output'] != null && !options['diff']) { | 59 if (options['output'] != null && !options['diff']) { |
| 59 print('--output must be used with --diff'); | 60 print('--output must be used with --diff'); |
| 60 exit(1); | 61 exit(1); |
| 61 } | 62 } |
| 62 | 63 |
| 64 bool strong = options['strong']; |
| 65 |
| 63 Program program = loadProgramFromBinary(filename); | 66 Program program = loadProgramFromBinary(filename); |
| 64 TreeShaker shaker = new TreeShaker(program); | 67 TreeShaker shaker = new TreeShaker(program, strongMode: strong); |
| 65 int totalClasses = 0; | 68 int totalClasses = 0; |
| 66 int totalInstantiationCandidates = 0; | 69 int totalInstantiationCandidates = 0; |
| 67 int totalMembers = 0; | 70 int totalMembers = 0; |
| 68 int usedClasses = 0; | 71 int usedClasses = 0; |
| 69 int instantiatedClasses = 0; | 72 int instantiatedClasses = 0; |
| 70 int usedMembers = 0; | 73 int usedMembers = 0; |
| 71 | 74 |
| 72 void visitMember(Member member) { | 75 void visitMember(Member member) { |
| 73 if (member.isAbstract) return; // Abstract members are not relevant. | 76 if (member.isAbstract) return; // Abstract members are not relevant. |
| 74 ++totalMembers; | 77 ++totalMembers; |
| 75 bool isUsed = shaker.isMemberUsed(member); | 78 bool isUsed = shaker.isMemberBodyUsed(member); |
| 76 if (isUsed) { | 79 if (isUsed) { |
| 77 ++usedMembers; | 80 ++usedMembers; |
| 78 } | 81 } |
| 79 if (isUsed && options['used'] || !isUsed && options['unused']) { | 82 if (isUsed && options['used'] || !isUsed && options['unused']) { |
| 80 String prefix = (options['used'] && options['unused']) | 83 String prefix = (options['used'] && options['unused']) |
| 81 ? (isUsed ? 'USED ' : 'UNUSED ') | 84 ? (isUsed ? 'USED ' : 'UNUSED ') |
| 82 : ''; | 85 : ''; |
| 83 print('$prefix$member'); | 86 print('$prefix$member'); |
| 84 } | 87 } |
| 85 } | 88 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 120 |
| 118 if (options['diff']) { | 121 if (options['diff']) { |
| 119 String name = pathlib.basenameWithoutExtension(filename); | 122 String name = pathlib.basenameWithoutExtension(filename); |
| 120 String outputDir = options['output'] ?? ''; | 123 String outputDir = options['output'] ?? ''; |
| 121 String beforeFile = pathlib.join(outputDir, '$name.before.txt'); | 124 String beforeFile = pathlib.join(outputDir, '$name.before.txt'); |
| 122 String afterFile = pathlib.join(outputDir, '$name.after.txt'); | 125 String afterFile = pathlib.join(outputDir, '$name.after.txt'); |
| 123 NameSystem names = new NameSystem(); | 126 NameSystem names = new NameSystem(); |
| 124 StringBuffer before = new StringBuffer(); | 127 StringBuffer before = new StringBuffer(); |
| 125 new Printer(before, syntheticNames: names).writeProgramFile(program); | 128 new Printer(before, syntheticNames: names).writeProgramFile(program); |
| 126 new File(beforeFile).writeAsStringSync('$before'); | 129 new File(beforeFile).writeAsStringSync('$before'); |
| 127 new TreeShaker(program).transform(program); | 130 new TreeShaker(program, strongMode: strong).transform(program); |
| 128 StringBuffer after = new StringBuffer(); | 131 StringBuffer after = new StringBuffer(); |
| 129 new Printer(after, syntheticNames: names).writeProgramFile(program); | 132 new Printer(after, syntheticNames: names).writeProgramFile(program); |
| 130 new File(afterFile).writeAsStringSync('$after'); | 133 new File(afterFile).writeAsStringSync('$after'); |
| 131 print('Text written to $beforeFile and $afterFile'); | 134 print('Text written to $beforeFile and $afterFile'); |
| 132 } | 135 } |
| 133 } | 136 } |
| 134 | 137 |
| 135 String ratio(num x, num total) { | 138 String ratio(num x, num total) { |
| 136 return '$x / $total (${percent(x, total)})'; | 139 return '$x / $total (${percent(x, total)})'; |
| 137 } | 140 } |
| 138 | 141 |
| 139 String percent(num x, num total) { | 142 String percent(num x, num total) { |
| 140 return total == 0 ? '0%' : ((100 * x / total).toStringAsFixed(0) + '%'); | 143 return total == 0 ? '0%' : ((100 * x / total).toStringAsFixed(0) + '%'); |
| 141 } | 144 } |
| OLD | NEW |