3
3
using System ;
4
4
using System . Collections . Generic ;
5
5
using System . Collections . Immutable ;
6
+ using System . Diagnostics ;
6
7
using System . IO ;
7
8
using System . Linq ;
8
9
using System . Text ;
@@ -62,6 +63,56 @@ public CommandLineOptions(
62
63
}
63
64
}
64
65
66
+ public sealed class CommandLineParseResult
67
+ {
68
+ private readonly CommandLineOptions _options ;
69
+ private readonly string _error ;
70
+
71
+ public bool IsSuccess
72
+ {
73
+ get { return _options != null ; }
74
+ }
75
+
76
+ public bool IsError
77
+ {
78
+ get { return ! IsSuccess ; }
79
+ }
80
+
81
+ public CommandLineOptions Options
82
+ {
83
+ get
84
+ {
85
+ Debug . Assert ( IsSuccess ) ;
86
+ return _options ;
87
+ }
88
+ }
89
+
90
+ public string Error
91
+ {
92
+ get
93
+ {
94
+ Debug . Assert ( IsError ) ;
95
+ return _error ;
96
+ }
97
+ }
98
+
99
+ private CommandLineParseResult ( CommandLineOptions options = null , string error = null )
100
+ {
101
+ _options = options ;
102
+ _error = error ;
103
+ }
104
+
105
+ public static CommandLineParseResult CreateSuccess ( CommandLineOptions options )
106
+ {
107
+ return new CommandLineParseResult ( options : options ) ;
108
+ }
109
+
110
+ public static CommandLineParseResult CreateError ( string error )
111
+ {
112
+ return new CommandLineParseResult ( error : error ) ;
113
+ }
114
+ }
115
+
65
116
public static class CommandLineParser
66
117
{
67
118
private const string FileSwitch = "/file:" ;
@@ -71,10 +122,7 @@ public static class CommandLineParser
71
122
private const string RuleEnabledSwitch1 = "/rule+:" ;
72
123
private const string RuleEnabledSwitch2 = "/rule:" ;
73
124
private const string RuleDisabledSwitch = "/rule-:" ;
74
-
75
- public static void PrintUsage ( )
76
- {
77
- Console . WriteLine (
125
+ private const string Usage =
78
126
@"CodeFormatter [/file:<filename>] [/lang:<language>] [/c:<config>[,<config>...]>]
79
127
[/copyright:<file> | /nocopyright] [/tables] [/nounicode]
80
128
[/rule(+|-):rule1,rule2,...] [/verbose]
@@ -94,19 +142,24 @@ Use ConvertTests to convert MSTest tests to xUnit.
94
142
/rule(+|-) - Enable (default) or disable the specified rule
95
143
/rules - List the available rules
96
144
/verbose - Verbose output
97
- " ) ;
145
+ " ;
146
+
147
+ public static void PrintUsage ( )
148
+ {
149
+ Console . WriteLine ( Usage ) ;
98
150
}
99
151
100
152
public static bool TryParse ( string [ ] args , out CommandLineOptions options )
101
153
{
102
- if ( args . Length < 1 )
103
- {
104
- PrintUsage ( ) ;
105
- options = null ;
106
- return false ;
107
- }
154
+ var result = Parse ( args ) ;
155
+ options = result . IsSuccess ? result . Options : null ;
156
+ return result . IsSuccess ;
157
+ }
108
158
159
+ public static CommandLineParseResult Parse ( string [ ] args )
160
+ {
109
161
var comparer = StringComparer . OrdinalIgnoreCase ;
162
+ var comparison = StringComparison . OrdinalIgnoreCase ;
110
163
var formatTargets = new List < string > ( ) ;
111
164
var fileNames = new List < string > ( ) ;
112
165
var configBuilder = ImmutableArray . CreateBuilder < string [ ] > ( ) ;
@@ -116,7 +169,7 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
116
169
var allowTables = false ;
117
170
var verbose = false ;
118
171
119
- for ( int i = 1 ; i < args . Length ; i ++ )
172
+ for ( int i = 0 ; i < args . Length ; i ++ )
120
173
{
121
174
string arg = args [ i ] ;
122
175
if ( arg . StartsWith ( ConfigSwitch , StringComparison . OrdinalIgnoreCase ) )
@@ -134,10 +187,11 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
134
187
}
135
188
catch ( Exception ex )
136
189
{
137
- Console . Error . WriteLine ( "Could not read {0}" , fileName ) ;
138
- Console . Error . WriteLine ( ex . Message ) ;
139
- options = null ;
140
- return false ;
190
+ string error = string . Format ( "Could not read {0}{1}{2}" ,
191
+ fileName ,
192
+ Environment . NewLine ,
193
+ ex . Message ) ;
194
+ return CommandLineParseResult . CreateError ( error ) ;
141
195
}
142
196
}
143
197
else if ( arg . StartsWith ( LanguageSwitch , StringComparison . OrdinalIgnoreCase ) )
@@ -156,19 +210,19 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
156
210
{
157
211
verbose = true ;
158
212
}
159
- else if ( comparer . Equals ( arg , FileSwitch ) )
213
+ else if ( arg . StartsWith ( FileSwitch , comparison ) )
160
214
{
161
215
fileNames . Add ( arg . Substring ( FileSwitch . Length ) ) ;
162
216
}
163
- else if ( comparer . Equals ( arg , RuleEnabledSwitch1 ) )
217
+ else if ( arg . StartsWith ( RuleEnabledSwitch1 , comparison ) )
164
218
{
165
219
UpdateRuleMap ( ref ruleMap , arg . Substring ( RuleEnabledSwitch1 . Length ) , enabled : true ) ;
166
220
}
167
- else if ( comparer . Equals ( arg , RuleEnabledSwitch2 ) )
221
+ else if ( arg . StartsWith ( RuleEnabledSwitch2 , comparison ) )
168
222
{
169
223
UpdateRuleMap ( ref ruleMap , arg . Substring ( RuleEnabledSwitch2 . Length ) , enabled : true ) ;
170
224
}
171
- else if ( comparer . Equals ( arg , RuleDisabledSwitch ) )
225
+ else if ( arg . StartsWith ( RuleDisabledSwitch , comparison ) )
172
226
{
173
227
UpdateRuleMap ( ref ruleMap , arg . Substring ( RuleDisabledSwitch . Length ) , enabled : false ) ;
174
228
}
@@ -178,16 +232,20 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
178
232
}
179
233
else if ( comparer . Equals ( arg , "/rules" ) )
180
234
{
181
- options = CommandLineOptions . ListRules ;
182
- return true ;
235
+ return CommandLineParseResult . CreateSuccess ( CommandLineOptions . ListRules ) ;
183
236
}
184
237
else
185
238
{
186
239
formatTargets . Add ( arg ) ;
187
240
}
188
241
}
189
242
190
- options = new CommandLineOptions (
243
+ if ( formatTargets . Count == 0 )
244
+ {
245
+ return CommandLineParseResult . CreateError ( "Must specify at least one project / solution / rsp to format" ) ;
246
+ }
247
+
248
+ var options = new CommandLineOptions (
191
249
Operation . Format ,
192
250
configBuilder . ToImmutableArray ( ) ,
193
251
copyrightHeader ,
@@ -197,7 +255,7 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
197
255
language ,
198
256
allowTables ,
199
257
verbose ) ;
200
- return true ;
258
+ return CommandLineParseResult . CreateSuccess ( options ) ;
201
259
}
202
260
203
261
private static void UpdateRuleMap ( ref ImmutableDictionary < string , bool > ruleMap , string data , bool enabled )
0 commit comments