| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env dart | |
| 2 | |
| 3 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 4 // for details. All rights reserved. Use of this source code is governed by a | |
| 5 // BSD-style license that can be found in the LICENSE file. | |
| 6 | |
| 7 import 'dart:convert'; | |
| 8 import 'dart:io'; | |
| 9 | |
| 10 import 'package:args/args.dart'; | |
| 11 import 'package:path/path.dart' as path; | |
| 12 | |
| 13 import 'package:analyzer_experimental/src/services/formatter_impl.dart'; | |
| 14 | |
| 15 | |
| 16 const BINARY_NAME = 'dartfmt'; | |
| 17 final dartFileRegExp = new RegExp(r'^[^.].*\.dart$', caseSensitive: false); | |
| 18 final argParser = _initArgParser(); | |
| 19 final defaultSelection = new Selection(-1, -1); | |
| 20 | |
| 21 var formatterSettings; | |
| 22 | |
| 23 bool machineFormat; | |
| 24 bool overwriteFileContents; | |
| 25 Selection selection; | |
| 26 const followLinks = false; | |
| 27 | |
| 28 | |
| 29 main(args) { | |
| 30 var options = argParser.parse(args); | |
| 31 if (options['help']) { | |
| 32 _printUsage(); | |
| 33 return; | |
| 34 } | |
| 35 | |
| 36 _readOptions(options); | |
| 37 | |
| 38 if (options.rest.isEmpty) { | |
| 39 _formatStdin(options); | |
| 40 } else { | |
| 41 _formatPaths(options.rest); | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 _readOptions(options) { | |
| 46 machineFormat = options['machine']; | |
| 47 overwriteFileContents = options['write']; | |
| 48 selection = _parseSelection(options['selection']); | |
| 49 formatterSettings = | |
| 50 new FormatterOptions(codeTransforms: options['transform']); | |
| 51 } | |
| 52 | |
| 53 Selection _parseSelection(selectionOption) { | |
| 54 if (selectionOption != null) { | |
| 55 var units = selectionOption.split(','); | |
| 56 if (units.length == 2) { | |
| 57 var offset = _toInt(units[0]); | |
| 58 var length = _toInt(units[1]); | |
| 59 if (offset != null && length != null) { | |
| 60 return new Selection(offset, length); | |
| 61 } | |
| 62 } | |
| 63 throw new FormatterException('Selections are specified as integer pairs ' | |
| 64 '(e.g., "(offset, length)".'); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 int _toInt(str) => int.parse(str, onError: (_) => null); | |
| 69 | |
| 70 _formatPaths(paths) { | |
| 71 paths.forEach((path) { | |
| 72 if (FileSystemEntity.isDirectorySync(path)) { | |
| 73 _formatDirectory(new Directory(path)); | |
| 74 } else { | |
| 75 _formatFile(new File(path)); | |
| 76 } | |
| 77 }); | |
| 78 } | |
| 79 | |
| 80 _formatResource(resource) { | |
| 81 if (resource is Directory) { | |
| 82 _formatDirectory(resource); | |
| 83 } else if (resource is File) { | |
| 84 _formatFile(resource); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 _formatDirectory(dir) => dir.listSync(followLinks: followLinks) | |
| 89 .forEach((resource) => _formatResource(resource)); | |
| 90 | |
| 91 _formatFile(file) { | |
| 92 if (_isDartFile(file)) { | |
| 93 try { | |
| 94 var buffer = new StringBuffer(); | |
| 95 var rawSource = file.readAsStringSync(); | |
| 96 var formatted = _formatCU(rawSource); | |
| 97 if (overwriteFileContents) { | |
| 98 file.writeAsStringSync(formatted); | |
| 99 } else { | |
| 100 print(formatted); | |
| 101 } | |
| 102 } catch (e) { | |
| 103 _log('Unable to format "${file.path}": $e'); | |
| 104 } | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 _isDartFile(file) => dartFileRegExp.hasMatch(path.basename(file.path)); | |
| 109 | |
| 110 _formatStdin(options) { | |
| 111 var input = new StringBuffer(); | |
| 112 stdin.transform(new Utf8Decoder()) | |
| 113 .listen((data) => input.write(data), | |
| 114 onError: (error) => _log('Error reading from stdin'), | |
| 115 onDone: () => print(_formatCU(input.toString()))); | |
| 116 } | |
| 117 | |
| 118 /// Initialize the arg parser instance. | |
| 119 ArgParser _initArgParser() { | |
| 120 // NOTE: these flags are placeholders only! | |
| 121 var parser = new ArgParser(); | |
| 122 parser.addFlag('write', abbr: 'w', negatable: false, | |
| 123 help: 'Write reformatted sources to files (overwriting contents). ' | |
| 124 'Do not print reformatted sources to standard output.'); | |
| 125 parser.addFlag('machine', abbr: 'm', negatable: false, | |
| 126 help: 'Produce output in a format suitable for parsing.'); | |
| 127 parser.addOption('selection', abbr: 's', | |
| 128 help: 'Specify selection information as an offset,length pair ' | |
| 129 '(e.g., -s "0,4").'); | |
| 130 parser.addFlag('transform', abbr: 't', negatable: true, | |
| 131 help: 'Perform code transformations.'); | |
| 132 parser.addFlag('help', abbr: 'h', negatable: false, | |
| 133 help: 'Print this usage information.'); | |
| 134 return parser; | |
| 135 } | |
| 136 | |
| 137 | |
| 138 /// Displays usage information. | |
| 139 _printUsage() { | |
| 140 var buffer = new StringBuffer(); | |
| 141 buffer..write('$BINARY_NAME formats Dart programs.') | |
| 142 ..write('\n\n') | |
| 143 ..write('Without an explicit path, $BINARY_NAME processes the standard ' | |
| 144 'input. Given a file, it operates on that file; given a ' | |
| 145 'directory, it operates on all .dart files in that directory, ' | |
| 146 'recursively. (Files starting with a period are ignored.) By ' | |
| 147 'default, $BINARY_NAME prints the reformatted sources to ' | |
| 148 'standard output.') | |
| 149 ..write('\n\n') | |
| 150 ..write('Supported flags are:') | |
| 151 ..write('Usage: $BINARY_NAME [flags] [path...]\n\n') | |
| 152 ..write('${argParser.getUsage()}\n\n'); | |
| 153 _log(buffer.toString()); | |
| 154 } | |
| 155 | |
| 156 /// Format the given [src] as a compilation unit. | |
| 157 String _formatCU(src) { | |
| 158 var formatResult = new CodeFormatter(formatterSettings).format( | |
| 159 CodeKind.COMPILATION_UNIT, src, selection: selection); | |
| 160 if (machineFormat) { | |
| 161 if (formatResult.selection == null) { | |
| 162 formatResult.selection = defaultSelection; | |
| 163 } | |
| 164 return _toJson(formatResult); | |
| 165 } | |
| 166 return formatResult.source; | |
| 167 } | |
| 168 | |
| 169 _toJson(formatResult) => | |
| 170 // Actual JSON format TBD | |
| 171 JSON.encode({'source': formatResult.source, | |
| 172 'selection': { | |
| 173 'offset': formatResult.selection.offset, | |
| 174 'length': formatResult.selection.length | |
| 175 } | |
| 176 }); | |
| 177 | |
| 178 /// Log the given [msg]. | |
| 179 _log(String msg) { | |
| 180 //TODO(pquitslund): add proper log support | |
| 181 print(msg); | |
| 182 } | |
| OLD | NEW |