@@ -11,42 +11,33 @@ use super::*;
1111#[ strum_discriminants( strum( serialize_all = "kebab-case" ) ) ]
1212pub ( crate ) enum Attribute < ' src > {
1313 Arg {
14- help : Option < StringLiteral > ,
15- long : Option < StringLiteral > ,
16- #[ serde( skip) ]
17- long_token : Option < Token < ' src > > ,
18- name : StringLiteral ,
19- #[ serde( skip) ]
20- name_token : Token < ' src > ,
21- #[ serde( skip) ]
22- pattern : Option < Pattern > ,
23- #[ serde( rename = "pattern" ) ]
24- pattern_literal : Option < StringLiteral > ,
25- short : Option < StringLiteral > ,
26- #[ serde( skip) ]
27- short_token : Option < Token < ' src > > ,
28- value : Option < StringLiteral > ,
14+ help : Option < StringLiteral < ' src > > ,
15+ long : Option < StringLiteral < ' src > > ,
16+ name : StringLiteral < ' src > ,
17+ pattern : Option < Pattern < ' src > > ,
18+ short : Option < StringLiteral < ' src > > ,
19+ value : Option < StringLiteral < ' src > > ,
2920 } ,
30- Confirm ( Option < StringLiteral > ) ,
21+ Confirm ( Option < StringLiteral < ' src > > ) ,
3122 Default ,
32- Doc ( Option < StringLiteral > ) ,
23+ Doc ( Option < StringLiteral < ' src > > ) ,
3324 ExitMessage ,
34- Extension ( StringLiteral ) ,
35- Group ( StringLiteral ) ,
25+ Extension ( StringLiteral < ' src > ) ,
26+ Group ( StringLiteral < ' src > ) ,
3627 Linux ,
3728 Macos ,
38- Metadata ( Vec < StringLiteral > ) ,
29+ Metadata ( Vec < StringLiteral < ' src > > ) ,
3930 NoCd ,
4031 NoExitMessage ,
4132 NoQuiet ,
4233 Openbsd ,
4334 Parallel ,
4435 PositionalArguments ,
4536 Private ,
46- Script ( Option < Interpreter < StringLiteral > > ) ,
37+ Script ( Option < Interpreter < StringLiteral < ' src > > > ) ,
4738 Unix ,
4839 Windows ,
49- WorkingDirectory ( StringLiteral ) ,
40+ WorkingDirectory ( StringLiteral < ' src > ) ,
5041}
5142
5243impl AttributeDiscriminant {
@@ -74,16 +65,38 @@ impl AttributeDiscriminant {
7465}
7566
7667impl < ' src > Attribute < ' src > {
68+ fn check_option_name (
69+ parameter : & StringLiteral < ' src > ,
70+ literal : & StringLiteral < ' src > ,
71+ ) -> CompileResult < ' src > {
72+ if literal. cooked . contains ( '=' ) {
73+ return Err (
74+ literal
75+ . token
76+ . error ( CompileErrorKind :: OptionNameContainsEqualSign {
77+ parameter : parameter. cooked . clone ( ) ,
78+ } ) ,
79+ ) ;
80+ }
81+
82+ if literal. cooked . is_empty ( ) {
83+ return Err ( literal. token . error ( CompileErrorKind :: OptionNameEmpty {
84+ parameter : parameter. cooked . clone ( ) ,
85+ } ) ) ;
86+ }
87+
88+ Ok ( ( ) )
89+ }
90+
7791 pub ( crate ) fn new (
7892 name : Name < ' src > ,
79- arguments : Vec < ( Token < ' src > , StringLiteral ) > ,
80- mut keyword_arguments : BTreeMap < & ' src str , ( Name < ' src > , Token < ' src > , StringLiteral ) > ,
93+ arguments : Vec < StringLiteral < ' src > > ,
94+ mut keyword_arguments : BTreeMap < & ' src str , ( Name < ' src > , StringLiteral < ' src > ) > ,
8195 ) -> CompileResult < ' src , Self > {
8296 let discriminant = name
8397 . lexeme ( )
8498 . parse :: < AttributeDiscriminant > ( )
85- . ok ( )
86- . ok_or_else ( || {
99+ . map_err ( |_| {
87100 name. error ( CompileErrorKind :: UnknownAttribute {
88101 attribute : name. lexeme ( ) ,
89102 } )
@@ -94,99 +107,68 @@ impl<'src> Attribute<'src> {
94107 if !range. contains ( & found) {
95108 return Err (
96109 name. error ( CompileErrorKind :: AttributeArgumentCountMismatch {
97- attribute : name. lexeme ( ) ,
110+ attribute : name,
98111 found,
99112 min : * range. start ( ) ,
100113 max : * range. end ( ) ,
101114 } ) ,
102115 ) ;
103116 }
104117
105- let ( tokens, arguments) : ( Vec < Token > , Vec < StringLiteral > ) = arguments. into_iter ( ) . unzip ( ) ;
106-
107118 let attribute = match discriminant {
108119 AttributeDiscriminant :: Arg => {
109120 let name = arguments. into_iter ( ) . next ( ) . unwrap ( ) ;
110- let name_token = tokens. into_iter ( ) . next ( ) . unwrap ( ) ;
111-
112- let ( long_token, long) =
113- if let Some ( ( _name, token, literal) ) = keyword_arguments. remove ( "long" ) {
114- if literal. cooked . contains ( '=' ) {
115- return Err ( token. error ( CompileErrorKind :: OptionNameContainsEqualSign {
116- parameter : name. cooked ,
117- } ) ) ;
118- }
119-
120- if literal. cooked . is_empty ( ) {
121- return Err ( token. error ( CompileErrorKind :: OptionNameEmpty {
122- parameter : name. cooked ,
123- } ) ) ;
124- }
125121
126- ( Some ( token) , Some ( literal) )
127- } else {
128- ( None , None )
129- } ;
130-
131- let ( short_token, short) =
132- if let Some ( ( _name, token, literal) ) = keyword_arguments. remove ( "short" ) {
133- if literal. cooked . contains ( '=' ) {
134- return Err ( token. error ( CompileErrorKind :: OptionNameContainsEqualSign {
135- parameter : name. cooked ,
136- } ) ) ;
137- }
122+ let long = keyword_arguments
123+ . remove ( "long" )
124+ . map ( |( _name, literal) | {
125+ Self :: check_option_name ( & name, & literal) ?;
126+ Ok ( literal)
127+ } )
128+ . transpose ( ) ?;
138129
139- if literal. cooked . is_empty ( ) {
140- return Err ( token. error ( CompileErrorKind :: OptionNameEmpty {
141- parameter : name. cooked ,
142- } ) ) ;
143- }
130+ let short = keyword_arguments
131+ . remove ( "short" )
132+ . map ( |( _name, literal) | {
133+ Self :: check_option_name ( & name, & literal) ?;
144134
145135 if literal. cooked . chars ( ) . count ( ) != 1 {
146- return Err (
147- token . error ( CompileErrorKind :: ShortOptionWithMultipleCharacters {
148- parameter : name. cooked ,
149- } ) ,
150- ) ;
136+ return Err ( literal . token . error (
137+ CompileErrorKind :: ShortOptionWithMultipleCharacters {
138+ parameter : name. cooked . clone ( ) ,
139+ } ,
140+ ) ) ;
151141 }
152142
153- ( Some ( token) , Some ( literal) )
154- } else {
155- ( None , None )
156- } ;
143+ Ok ( literal)
144+ } )
145+ . transpose ( ) ?;
157146
158- let ( pattern_literal , pattern) = keyword_arguments
147+ let pattern = keyword_arguments
159148 . remove ( "pattern" )
160- . map ( |( _name, token, literal) | {
161- let pattern = Pattern :: new ( token, & literal) ?;
162- Ok ( ( Some ( literal) , Some ( pattern) ) )
149+ . map ( |( _name, literal) | Pattern :: new ( & literal) )
150+ . transpose ( ) ?;
151+
152+ let value = keyword_arguments
153+ . remove ( "value" )
154+ . map ( |( name, literal) | {
155+ if long. is_none ( ) && short. is_none ( ) {
156+ return Err ( name. error ( CompileErrorKind :: ArgAttributeValueRequiresOption ) ) ;
157+ }
158+ Ok ( literal)
163159 } )
164- . transpose ( ) ?
165- . unwrap_or ( ( None , None ) ) ;
166-
167- let value = if let Some ( ( name, _token, literal) ) = keyword_arguments. remove ( "value" ) {
168- if long. is_none ( ) && short. is_none ( ) {
169- return Err ( name. error ( CompileErrorKind :: ArgAttributeValueRequiresOption ) ) ;
170- }
171- Some ( literal)
172- } else {
173- None
174- } ;
160+ . transpose ( ) ?;
175161
176162 let help = keyword_arguments
177163 . remove ( "help" )
178- . map ( |( _name, _token , literal) | literal) ;
164+ . map ( |( _name, literal) | literal) ;
179165
180166 Self :: Arg {
181167 help,
182168 long,
183- long_token,
184169 name,
185- name_token,
186170 pattern,
187- pattern_literal,
188171 short,
189- short_token,
190172 value,
191173 }
192174 }
@@ -220,7 +202,7 @@ impl<'src> Attribute<'src> {
220202 }
221203 } ;
222204
223- if let Some ( ( _name, ( keyword_name, _token , _literal) ) ) = keyword_arguments. into_iter ( ) . next ( ) {
205+ if let Some ( ( _name, ( keyword_name, _literal) ) ) = keyword_arguments. into_iter ( ) . next ( ) {
224206 return Err (
225207 keyword_name. error ( CompileErrorKind :: UnknownAttributeKeyword {
226208 attribute : name. lexeme ( ) ,
@@ -256,13 +238,9 @@ impl Display for Attribute<'_> {
256238 Self :: Arg {
257239 help,
258240 long,
259- long_token : _,
260241 name,
261- name_token : _,
262- pattern : _,
263- pattern_literal,
242+ pattern,
264243 short,
265- short_token : _,
266244 value,
267245 } => {
268246 write ! ( f, "({name}" ) ?;
@@ -275,8 +253,8 @@ impl Display for Attribute<'_> {
275253 write ! ( f, ", short={short}" ) ?;
276254 }
277255
278- if let Some ( pattern) = pattern_literal {
279- write ! ( f, ", pattern={pattern}" ) ?;
256+ if let Some ( pattern) = pattern {
257+ write ! ( f, ", pattern={}" , pattern . token . lexeme ( ) ) ?;
280258 }
281259
282260 if let Some ( value) = value {
0 commit comments