33using System ;
44using System . Collections . Generic ;
55using System . Collections . Immutable ;
6+ using System . Diagnostics ;
67using System . IO ;
78using System . Linq ;
89using System . Text ;
@@ -62,6 +63,56 @@ public CommandLineOptions(
6263 }
6364 }
6465
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+
65116 public static class CommandLineParser
66117 {
67118 private const string FileSwitch = "/file:" ;
@@ -71,10 +122,7 @@ public static class CommandLineParser
71122 private const string RuleEnabledSwitch1 = "/rule+:" ;
72123 private const string RuleEnabledSwitch2 = "/rule:" ;
73124 private const string RuleDisabledSwitch = "/rule-:" ;
74-
75- public static void PrintUsage ( )
76- {
77- Console . WriteLine (
125+ private const string Usage =
78126@"CodeFormatter [/file:<filename>] [/lang:<language>] [/c:<config>[,<config>...]>]
79127 [/copyright:<file> | /nocopyright] [/tables] [/nounicode]
80128 [/rule(+|-):rule1,rule2,...] [/verbose]
@@ -94,19 +142,24 @@ Use ConvertTests to convert MSTest tests to xUnit.
94142 /rule(+|-) - Enable (default) or disable the specified rule
95143 /rules - List the available rules
96144 /verbose - Verbose output
97- " ) ;
145+ " ;
146+
147+ public static void PrintUsage ( )
148+ {
149+ Console . WriteLine ( Usage ) ;
98150 }
99151
100152 public static bool TryParse ( string [ ] args , out CommandLineOptions options )
101153 {
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+ }
108158
159+ public static CommandLineParseResult Parse ( string [ ] args )
160+ {
109161 var comparer = StringComparer . OrdinalIgnoreCase ;
162+ var comparison = StringComparison . OrdinalIgnoreCase ;
110163 var formatTargets = new List < string > ( ) ;
111164 var fileNames = new List < string > ( ) ;
112165 var configBuilder = ImmutableArray . CreateBuilder < string [ ] > ( ) ;
@@ -116,7 +169,7 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
116169 var allowTables = false ;
117170 var verbose = false ;
118171
119- for ( int i = 1 ; i < args . Length ; i ++ )
172+ for ( int i = 0 ; i < args . Length ; i ++ )
120173 {
121174 string arg = args [ i ] ;
122175 if ( arg . StartsWith ( ConfigSwitch , StringComparison . OrdinalIgnoreCase ) )
@@ -134,10 +187,11 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
134187 }
135188 catch ( Exception ex )
136189 {
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 ) ;
141195 }
142196 }
143197 else if ( arg . StartsWith ( LanguageSwitch , StringComparison . OrdinalIgnoreCase ) )
@@ -156,19 +210,19 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
156210 {
157211 verbose = true ;
158212 }
159- else if ( comparer . Equals ( arg , FileSwitch ) )
213+ else if ( arg . StartsWith ( FileSwitch , comparison ) )
160214 {
161215 fileNames . Add ( arg . Substring ( FileSwitch . Length ) ) ;
162216 }
163- else if ( comparer . Equals ( arg , RuleEnabledSwitch1 ) )
217+ else if ( arg . StartsWith ( RuleEnabledSwitch1 , comparison ) )
164218 {
165219 UpdateRuleMap ( ref ruleMap , arg . Substring ( RuleEnabledSwitch1 . Length ) , enabled : true ) ;
166220 }
167- else if ( comparer . Equals ( arg , RuleEnabledSwitch2 ) )
221+ else if ( arg . StartsWith ( RuleEnabledSwitch2 , comparison ) )
168222 {
169223 UpdateRuleMap ( ref ruleMap , arg . Substring ( RuleEnabledSwitch2 . Length ) , enabled : true ) ;
170224 }
171- else if ( comparer . Equals ( arg , RuleDisabledSwitch ) )
225+ else if ( arg . StartsWith ( RuleDisabledSwitch , comparison ) )
172226 {
173227 UpdateRuleMap ( ref ruleMap , arg . Substring ( RuleDisabledSwitch . Length ) , enabled : false ) ;
174228 }
@@ -178,16 +232,20 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
178232 }
179233 else if ( comparer . Equals ( arg , "/rules" ) )
180234 {
181- options = CommandLineOptions . ListRules ;
182- return true ;
235+ return CommandLineParseResult . CreateSuccess ( CommandLineOptions . ListRules ) ;
183236 }
184237 else
185238 {
186239 formatTargets . Add ( arg ) ;
187240 }
188241 }
189242
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 (
191249 Operation . Format ,
192250 configBuilder . ToImmutableArray ( ) ,
193251 copyrightHeader ,
@@ -197,7 +255,7 @@ public static bool TryParse(string[] args, out CommandLineOptions options)
197255 language ,
198256 allowTables ,
199257 verbose ) ;
200- return true ;
258+ return CommandLineParseResult . CreateSuccess ( options ) ;
201259 }
202260
203261 private static void UpdateRuleMap ( ref ImmutableDictionary < string , bool > ruleMap , string data , bool enabled )
0 commit comments