OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 library options; | |
6 | |
7 import 'package:args/args.dart'; | |
8 import 'package:path/path.dart'; | |
9 | |
10 import 'dart:io'; | |
11 | |
12 | |
13 const _BINARY_NAME = 'dartanalyzer'; | |
14 | |
15 /** | |
16 * Analyzer commandline configuration options. | |
17 */ | |
18 class CommandLineOptions { | |
19 | |
20 /** Batch mode (for unit testing) */ | |
21 final bool shouldBatch; | |
22 | |
23 /** Whether to use machine format for error display */ | |
24 final bool machineFormat; | |
25 | |
26 /** Whether to display version information */ | |
27 final bool displayVersion; | |
28 | |
29 /** Whether to report hints */ | |
30 final bool disableHints; | |
31 | |
32 /** Whether to ignore unrecognized flags */ | |
33 final bool ignoreUnrecognizedFlags; | |
34 | |
35 /** Whether to show performance statistics */ | |
36 final bool perf; | |
37 | |
38 /** Whether to show package: warnings */ | |
39 final bool showPackageWarnings; | |
40 | |
41 /** Whether to show SDK warnings */ | |
42 final bool showSdkWarnings; | |
43 | |
44 /** Whether to treat warnings as fatal */ | |
45 final bool warningsAreFatal; | |
46 | |
47 /** The path to the dart SDK */ | |
48 final String dartSdkPath; | |
49 | |
50 /** The path to the package root */ | |
51 final String packageRootPath; | |
52 | |
53 /** The source files to analyze */ | |
54 final List<String> sourceFiles; | |
55 | |
56 /** | |
57 * Initialize options from the given parsed [args]. | |
58 */ | |
59 CommandLineOptions._fromArgs(ArgResults args) | |
60 : shouldBatch = args['batch'], | |
61 machineFormat = args['machine'] || args['format'] == 'machine', | |
62 displayVersion = args['version'], | |
63 disableHints = args['no-hints'], | |
64 ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'], | |
65 perf = args['perf'], | |
66 showPackageWarnings = args['show-package-warnings'] || args['package-warni
ngs'], | |
67 showSdkWarnings = args['show-sdk-warnings'] || args['warnings'], | |
68 warningsAreFatal = args['fatal-warnings'], | |
69 dartSdkPath = args['dart-sdk'], | |
70 packageRootPath = args['package-root'], | |
71 sourceFiles = args.rest; | |
72 | |
73 /** | |
74 * Parse [args] into [CommandLineOptions] describing the specified | |
75 * analyzer options. In case of a format error, prints error and exists. | |
76 */ | |
77 static CommandLineOptions parse(List<String> args) { | |
78 CommandLineOptions options = _parse(args); | |
79 // check SDK | |
80 { | |
81 var sdkPath = options.dartSdkPath; | |
82 // check that SDK is specified | |
83 if (sdkPath == null) { | |
84 print('Usage: $_BINARY_NAME: no Dart SDK found.'); | |
85 exit(15); | |
86 } | |
87 // check that SDK is existing directory | |
88 if (!(new Directory(sdkPath)).existsSync()) { | |
89 print('Usage: $_BINARY_NAME: invalid Dart SDK path: $sdkPath'); | |
90 exit(15); | |
91 } | |
92 } | |
93 // OK | |
94 return options; | |
95 } | |
96 | |
97 static CommandLineOptions _parse(List<String> args) { | |
98 args = args.expand((String arg) => arg.split('=')).toList(); | |
99 var parser = new _CommandLineParser() | |
100 ..addFlag('batch', abbr: 'b', help: 'Run in batch mode', | |
101 defaultsTo: false, negatable: false) | |
102 ..addOption('dart-sdk', help: 'The path to the Dart SDK') | |
103 ..addOption('package-root', abbr: 'p', | |
104 help: 'The path to the package root') | |
105 ..addOption('format', | |
106 help: 'Specifies the format in which errors are displayed') | |
107 ..addFlag('machine', | |
108 help: 'Print errors in a format suitable for parsing (deprecated)', | |
109 defaultsTo: false, negatable: false) | |
110 ..addFlag('version', help: 'Print the analyzer version', | |
111 defaultsTo: false, negatable: false) | |
112 ..addFlag('no-hints', help: 'Do not show hint results', | |
113 defaultsTo: false, negatable: false) | |
114 ..addFlag('ignore-unrecognized-flags', | |
115 help: 'Ignore unrecognized command line flags', | |
116 defaultsTo: false, negatable: false) | |
117 ..addFlag('fatal-warnings', help: 'Treat non-type warnings as fatal', | |
118 defaultsTo: false, negatable: false) | |
119 ..addFlag('package-warnings', | |
120 help: 'Show warnings from package: imports', | |
121 defaultsTo: false, negatable: false) | |
122 ..addFlag('show-package-warnings', | |
123 help: 'Show warnings from package: imports (deprecated)', | |
124 defaultsTo: false, negatable: false) | |
125 ..addFlag('perf', | |
126 help: 'Show performance statistics', | |
127 defaultsTo: false, negatable: false) | |
128 ..addFlag('warnings', help: 'Show warnings from SDK imports', | |
129 defaultsTo: false, negatable: false) | |
130 ..addFlag('show-sdk-warnings', help: 'Show warnings from SDK imports (depr
ecated)', | |
131 defaultsTo: false, negatable: false) | |
132 ..addFlag('help', abbr: 'h', help: 'Display this help message', | |
133 defaultsTo: false, negatable: false); | |
134 | |
135 try { | |
136 // TODO(scheglov) https://code.google.com/p/dart/issues/detail?id=11061 | |
137 args = args.map((String arg) => arg == '-batch' ? '--batch' : arg).toList(
); | |
138 var results = parser.parse(args); | |
139 // help requests | |
140 if (results['help']) { | |
141 _showUsage(parser); | |
142 exit(0); | |
143 } | |
144 // batch mode and input files | |
145 if (results['batch']) { | |
146 if (results.rest.isNotEmpty) { | |
147 print('No source files expected in the batch mode.'); | |
148 _showUsage(parser); | |
149 exit(15); | |
150 } | |
151 } else if (results['version']) { | |
152 print('$_BINARY_NAME version ${_getVersion()}'); | |
153 exit(0); | |
154 } else { | |
155 if (results.rest.isEmpty) { | |
156 _showUsage(parser); | |
157 exit(15); | |
158 } | |
159 } | |
160 return new CommandLineOptions._fromArgs(results); | |
161 } on FormatException catch (e) { | |
162 print(e.message); | |
163 _showUsage(parser); | |
164 exit(15); | |
165 } | |
166 | |
167 } | |
168 | |
169 static _showUsage(parser) { | |
170 print('Usage: $_BINARY_NAME [options...] <libraries to analyze...>'); | |
171 print(parser.getUsage()); | |
172 print(''); | |
173 print('For more information, see http://www.dartlang.org/tools/analyzer.'); | |
174 } | |
175 | |
176 static String _getVersion() { | |
177 try { | |
178 String versionPath = join(dirname(Platform.script), '..', 'version');; | |
179 File versionFile = new File(versionPath); | |
180 return versionFile.readAsStringSync().trim(); | |
181 } catch (_) { | |
182 // This happens when the script is not running in the context of an SDK. | |
183 return "<unknown>"; | |
184 } | |
185 } | |
186 } | |
187 | |
188 /** | |
189 * Commandline argument parser. | |
190 * | |
191 * TODO(pquitslund): when the args package supports ignoring unrecognized | |
192 * options/flags, this class can be replaced with a simple [ArgParser] instance. | |
193 */ | |
194 class _CommandLineParser { | |
195 | |
196 final List<String> _knownFlags; | |
197 final ArgParser _parser; | |
198 | |
199 /** Creates a new command line parser */ | |
200 _CommandLineParser() | |
201 : _knownFlags = <String>[], | |
202 _parser = new ArgParser(); | |
203 | |
204 | |
205 /** | |
206 * Defines a flag. | |
207 * | |
208 * See [ArgParser.addFlag()]. | |
209 */ | |
210 void addFlag(String name, {String abbr, String help, bool defaultsTo: false, | |
211 bool negatable: true, void callback(bool value)}) { | |
212 _knownFlags.add(name); | |
213 _parser.addFlag(name, abbr: abbr, help: help, defaultsTo: defaultsTo, | |
214 negatable: negatable, callback: callback); | |
215 } | |
216 | |
217 /** | |
218 * Defines a value-taking option. | |
219 * | |
220 * See [ArgParser.addOption()]. | |
221 */ | |
222 void addOption(String name, {String abbr, String help, List<String> allowed, | |
223 Map<String, String> allowedHelp, String defaultsTo, | |
224 void callback(value), bool allowMultiple: false}) { | |
225 _knownFlags.add(name); | |
226 _parser.addOption(name, abbr: abbr, help: help, allowed: allowed, | |
227 allowedHelp: allowedHelp, defaultsTo: defaultsTo, callback: callback, | |
228 allowMultiple: allowMultiple); | |
229 } | |
230 | |
231 | |
232 /** | |
233 * Generates a string displaying usage information for the defined options. | |
234 * | |
235 * See [ArgParser.getUsage()]. | |
236 */ | |
237 String getUsage() => _parser.getUsage(); | |
238 | |
239 /** | |
240 * Parses [args], a list of command-line arguments, matches them against the | |
241 * flags and options defined by this parser, and returns the result. | |
242 * | |
243 * See [ArgParser]. | |
244 */ | |
245 ArgResults parse(List<String> args) => _parser.parse(_filterUnknowns(args)); | |
246 | |
247 List<String> _filterUnknowns(args) { | |
248 | |
249 // Only filter args if the ignore flag is specified. | |
250 if (!args.contains('--ignore-unrecognized-flags')) { | |
251 return args; | |
252 } | |
253 | |
254 //TODO(pquitslund): replace w/ the following once library skew issues are so
rted out | |
255 //return args.where((arg) => !arg.startsWith('--') || | |
256 // _knownFlags.contains(arg.substring(2))); | |
257 | |
258 // Filter all unrecognized flags and options. | |
259 var filtered = <String>[]; | |
260 for (var i=0; i < args.length; ++i) { | |
261 var arg = args[i]; | |
262 if (arg.startsWith('--') && arg.length > 2) { | |
263 if (!_knownFlags.contains(arg.substring(2))) { | |
264 print('remove: $arg'); | |
265 //"eat" params by advancing to the next flag/option | |
266 i = _getNextFlagIndex(args, i); | |
267 } else { | |
268 filtered.add(arg); | |
269 } | |
270 } else { | |
271 filtered.add(arg); | |
272 } | |
273 } | |
274 | |
275 return filtered; | |
276 } | |
277 | |
278 _getNextFlagIndex(args, i) { | |
279 for ( ; i < args.length; ++i) { | |
280 if (args[i].startsWith('--')) { | |
281 return i; | |
282 } | |
283 } | |
284 return i; | |
285 } | |
286 } | |
OLD | NEW |