25
25
import static javax .lang .model .element .Modifier .PRIVATE ;
26
26
import static javax .lang .model .element .Modifier .PUBLIC ;
27
27
import static javax .lang .model .element .Modifier .STATIC ;
28
- import static net .jbock .compiler .Option .constructorArgumentsForJavadoc ;
29
28
30
29
final class Analyser {
31
30
@@ -56,6 +55,7 @@ final class Analyser {
56
55
private final MethodSpec readOption ;
57
56
private final MethodSpec checkConflict ;
58
57
private final MethodSpec readArgument ;
58
+ private final MethodSpec removeFirstFlag ;
59
59
60
60
private final FieldSpec longNames ;
61
61
private final FieldSpec shortNames ;
@@ -83,6 +83,7 @@ private Analyser(Constructor constructor) {
83
83
this .optionMapType = ParameterizedTypeName .get (ClassName .get (Map .class ),
84
84
option .optionClass , listOfArgumentType );
85
85
this .readArgument = readArgumentMethod ();
86
+ this .removeFirstFlag = removeFirstFlagMethod ();
86
87
this .optMap = FieldSpec .builder (optionMapType , "optMap" )
87
88
.addModifiers (PRIVATE , FINAL )
88
89
.build ();
@@ -95,7 +96,21 @@ private Analyser(Constructor constructor) {
95
96
this .readOption = readOptionMethod (keysClass , longNames , shortNames , option .optionClass );
96
97
this .checkConflict = checkConflictMethod (optionMapType , option .optionClass , optionTypeClass , optionType );
97
98
this .read = readMethod (keysClass , readOption , readArgument , optionMapType ,
98
- option .optionClass , optionType , optionTypeClass , checkConflict );
99
+ option .optionClass , optionType , optionTypeClass , checkConflict , removeFirstFlag );
100
+ }
101
+
102
+ private static MethodSpec removeFirstFlagMethod () {
103
+ ParameterSpec token = ParameterSpec .builder (STRING , "token" ).build ();
104
+ return MethodSpec .methodBuilder ("removeFirstFlag" )
105
+ .beginControlFlow ("if ($N.length() <= 2 || $N.startsWith($S))" ,
106
+ token , token , "--" )
107
+ .addStatement ("return null" )
108
+ .endControlFlow ()
109
+ .addStatement ("return $S + $N.substring(2)" , "-" , token )
110
+ .addParameter (token )
111
+ .addModifiers (PRIVATE , STATIC )
112
+ .returns (STRING )
113
+ .build ();
99
114
}
100
115
101
116
private static MethodSpec checkConflictMethod (TypeName optionMapType , ClassName optionClass ,
@@ -136,6 +151,7 @@ TypeSpec analyse() {
136
151
.addMethod (readOption )
137
152
.addMethod (readArgument )
138
153
.addMethod (checkConflict )
154
+ .addMethod (removeFirstFlag )
139
155
.addModifiers (PUBLIC , FINAL )
140
156
.build ();
141
157
}
@@ -177,21 +193,10 @@ private MethodSpec parseMethod() {
177
193
read , token , names , optMap , otherTokens , it )
178
194
.endControlFlow ()
179
195
.addStatement ("return new $T($N, $N, $N)" , binderClass , optMap , otherTokens , rest );
180
- TypeName originalClass = constructor .enclosingType ;
181
196
return MethodSpec .methodBuilder ("parse" )
182
197
.addParameter (ARGS )
183
198
.addCode (builder .build ())
184
199
.addException (IllegalArgumentException .class )
185
- .addJavadoc ("Parses the command line arguments and performs basic validation.\n " +
186
- "\n " +
187
- "@param args command line arguments\n " +
188
- "@throws $T if the input is invalid or ambiguous\n " +
189
- "@return a binder for constructing {@link $T}\n " +
190
- "\n " +
191
- "@see $T#$T($L)\n " ,
192
- IllegalArgumentException .class ,
193
- constructor .enclosingType ,
194
- originalClass , originalClass , constructorArgumentsForJavadoc (constructor ))
195
200
.returns (binderClass )
196
201
.addModifiers (PUBLIC , STATIC )
197
202
.build ();
@@ -267,7 +272,10 @@ private static MethodSpec readMethod(ClassName keysClass,
267
272
MethodSpec readArgument ,
268
273
TypeName optionMapType ,
269
274
ClassName optionClass ,
270
- FieldSpec optionType , ClassName optionTypeClass , MethodSpec checkConflict ) {
275
+ FieldSpec optionType ,
276
+ ClassName optionTypeClass ,
277
+ MethodSpec checkConflict ,
278
+ MethodSpec removeFirstFlag ) {
271
279
ParameterSpec names = ParameterSpec .builder (keysClass , "names" ).build ();
272
280
ParameterSpec optMap = ParameterSpec .builder (optionMapType , "optMap" ).build ();
273
281
ParameterSpec otherTokens = ParameterSpec .builder (STRING_LIST , "otherTokens" ).build ();
@@ -287,12 +295,23 @@ private static MethodSpec readMethod(ClassName keysClass,
287
295
.addStatement ("$N($N, $N, $N)" , checkConflict , optMap , option , token )
288
296
.addStatement ("$T $N = $N.computeIfAbsent($N, $N -> new $T<>())" ,
289
297
bucket .type , bucket , optMap , option , ignore , ArrayList .class )
290
- .beginControlFlow ("if ($N.$N == $T.$L)" , option , optionType , optionTypeClass , OptionType .FLAG )
291
- .add ("// add some non-null string to represent the flag\n " )
298
+ .beginControlFlow ("while ($N.$N == $T.$L)" , option , optionType , optionTypeClass , OptionType .FLAG )
292
299
.addStatement ("$N.add($S)" , bucket , "t" )
293
- .addStatement ("return" )
300
+ .addStatement ("$N = $N($N)" , token , removeFirstFlag , token )
301
+ .beginControlFlow ("if ($N == null)" , token )
302
+ .addStatement ("break" )
303
+ .endControlFlow ()
304
+ .addStatement ("$N = $N($N, $N)" , option , readOption , names , token )
305
+ .beginControlFlow ("if ($N == null)" , option )
306
+ .addStatement ("throw new $T($S)" , IllegalArgumentException .class ,
307
+ "invalid token" )
308
+ .endControlFlow ()
309
+ .addStatement ("$N = $N.computeIfAbsent($N, $N -> new $T<>())" ,
310
+ bucket , optMap , option , ignore , ArrayList .class )
294
311
.endControlFlow ()
295
- .addStatement ("$N.add($N($N, $N))" , bucket , readArgument , token , it );
312
+ .beginControlFlow ("if ($N.type != $T.$L)" , option , optionTypeClass , OptionType .FLAG )
313
+ .addStatement ("$N.add($N($N, $N))" , bucket , readArgument , token , it )
314
+ .endControlFlow ();
296
315
//@formatter:on
297
316
return MethodSpec .methodBuilder ("read" )
298
317
.addParameters (Arrays .asList (token , names , optMap , otherTokens , it ))
0 commit comments