@@ -6,7 +6,7 @@ use crate::{
6
6
7
7
use base_db:: FileId ;
8
8
use either:: Either ;
9
- use mbe:: parse_to_token_tree;
9
+ use mbe:: { parse_to_token_tree, ExpandResult } ;
10
10
use parser:: FragmentKind ;
11
11
use syntax:: ast:: { self , AstToken } ;
12
12
@@ -28,7 +28,7 @@ macro_rules! register_builtin {
28
28
db: & dyn AstDatabase ,
29
29
id: LazyMacroId ,
30
30
tt: & tt:: Subtree ,
31
- ) -> Result <tt:: Subtree , mbe :: ExpandError > {
31
+ ) -> ExpandResult <tt:: Subtree > {
32
32
let expander = match * self {
33
33
$( BuiltinFnLikeExpander :: $kind => $expand, ) *
34
34
} ;
@@ -42,7 +42,7 @@ macro_rules! register_builtin {
42
42
db: & dyn AstDatabase ,
43
43
arg_id: EagerMacroId ,
44
44
tt: & tt:: Subtree ,
45
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe :: ExpandError > {
45
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
46
46
let expander = match * self {
47
47
$( EagerExpander :: $e_kind => $e_expand, ) *
48
48
} ;
@@ -109,25 +109,28 @@ fn line_expand(
109
109
_db : & dyn AstDatabase ,
110
110
_id : LazyMacroId ,
111
111
_tt : & tt:: Subtree ,
112
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
112
+ ) -> ExpandResult < tt:: Subtree > {
113
113
// dummy implementation for type-checking purposes
114
114
let line_num = 0 ;
115
115
let expanded = quote ! {
116
116
#line_num
117
117
} ;
118
118
119
- Ok ( expanded)
119
+ ExpandResult :: ok ( expanded)
120
120
}
121
121
122
122
fn stringify_expand (
123
123
db : & dyn AstDatabase ,
124
124
id : LazyMacroId ,
125
125
_tt : & tt:: Subtree ,
126
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
126
+ ) -> ExpandResult < tt:: Subtree > {
127
127
let loc = db. lookup_intern_macro ( id) ;
128
128
129
129
let macro_content = {
130
- let arg = loc. kind . arg ( db) . ok_or_else ( || mbe:: ExpandError :: UnexpectedToken ) ?;
130
+ let arg = match loc. kind . arg ( db) {
131
+ Some ( arg) => arg,
132
+ None => return ExpandResult :: only_err ( mbe:: ExpandError :: UnexpectedToken ) ,
133
+ } ;
131
134
let macro_args = arg;
132
135
let text = macro_args. text ( ) ;
133
136
let without_parens = TextSize :: of ( '(' ) ..text. len ( ) - TextSize :: of ( ')' ) ;
@@ -138,28 +141,28 @@ fn stringify_expand(
138
141
#macro_content
139
142
} ;
140
143
141
- Ok ( expanded)
144
+ ExpandResult :: ok ( expanded)
142
145
}
143
146
144
147
fn column_expand (
145
148
_db : & dyn AstDatabase ,
146
149
_id : LazyMacroId ,
147
150
_tt : & tt:: Subtree ,
148
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
151
+ ) -> ExpandResult < tt:: Subtree > {
149
152
// dummy implementation for type-checking purposes
150
153
let col_num = 0 ;
151
154
let expanded = quote ! {
152
155
#col_num
153
156
} ;
154
157
155
- Ok ( expanded)
158
+ ExpandResult :: ok ( expanded)
156
159
}
157
160
158
161
fn assert_expand (
159
162
_db : & dyn AstDatabase ,
160
163
_id : LazyMacroId ,
161
164
tt : & tt:: Subtree ,
162
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
165
+ ) -> ExpandResult < tt:: Subtree > {
163
166
// A hacky implementation for goto def and hover
164
167
// We expand `assert!(cond, arg1, arg2)` to
165
168
// ```
@@ -191,14 +194,14 @@ fn assert_expand(
191
194
let expanded = quote ! {
192
195
{ { ( ##arg_tts) ; } }
193
196
} ;
194
- Ok ( expanded)
197
+ ExpandResult :: ok ( expanded)
195
198
}
196
199
197
200
fn file_expand (
198
201
_db : & dyn AstDatabase ,
199
202
_id : LazyMacroId ,
200
203
_tt : & tt:: Subtree ,
201
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
204
+ ) -> ExpandResult < tt:: Subtree > {
202
205
// FIXME: RA purposefully lacks knowledge of absolute file names
203
206
// so just return "".
204
207
let file_name = "" ;
@@ -207,31 +210,33 @@ fn file_expand(
207
210
#file_name
208
211
} ;
209
212
210
- Ok ( expanded)
213
+ ExpandResult :: ok ( expanded)
211
214
}
212
215
213
216
fn compile_error_expand (
214
217
_db : & dyn AstDatabase ,
215
218
_id : LazyMacroId ,
216
219
tt : & tt:: Subtree ,
217
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
220
+ ) -> ExpandResult < tt:: Subtree > {
218
221
if tt. count ( ) == 1 {
219
222
if let tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( it) ) = & tt. token_trees [ 0 ] {
220
223
let s = it. text . as_str ( ) ;
221
224
if s. contains ( '"' ) {
222
- return Ok ( quote ! { loop { #it } } ) ;
225
+ return ExpandResult :: ok ( quote ! { loop { #it } } ) ;
223
226
}
224
227
} ;
225
228
}
226
229
227
- Err ( mbe:: ExpandError :: BindingError ( "Must be a string" . into ( ) ) )
230
+ ExpandResult :: only_err ( mbe:: ExpandError :: BindingError (
231
+ "`compile_error!` argument be a string" . into ( ) ,
232
+ ) )
228
233
}
229
234
230
235
fn format_args_expand (
231
236
_db : & dyn AstDatabase ,
232
237
_id : LazyMacroId ,
233
238
tt : & tt:: Subtree ,
234
- ) -> Result < tt:: Subtree , mbe :: ExpandError > {
239
+ ) -> ExpandResult < tt:: Subtree > {
235
240
// We expand `format_args!("", a1, a2)` to
236
241
// ```
237
242
// std::fmt::Arguments::new_v1(&[], &[
@@ -257,7 +262,7 @@ fn format_args_expand(
257
262
args. push ( current) ;
258
263
}
259
264
if args. is_empty ( ) {
260
- return Err ( mbe:: ExpandError :: NoMatchingRule ) ;
265
+ return ExpandResult :: only_err ( mbe:: ExpandError :: NoMatchingRule ) ;
261
266
}
262
267
let _format_string = args. remove ( 0 ) ;
263
268
let arg_tts = args. into_iter ( ) . flat_map ( |arg| {
@@ -266,7 +271,7 @@ fn format_args_expand(
266
271
let expanded = quote ! {
267
272
std:: fmt:: Arguments :: new_v1( & [ ] , & [ ##arg_tts] )
268
273
} ;
269
- Ok ( expanded)
274
+ ExpandResult :: ok ( expanded)
270
275
}
271
276
272
277
fn unquote_str ( lit : & tt:: Literal ) -> Option < String > {
@@ -279,19 +284,24 @@ fn concat_expand(
279
284
_db : & dyn AstDatabase ,
280
285
_arg_id : EagerMacroId ,
281
286
tt : & tt:: Subtree ,
282
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe :: ExpandError > {
287
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
283
288
let mut text = String :: new ( ) ;
284
289
for ( i, t) in tt. token_trees . iter ( ) . enumerate ( ) {
285
290
match t {
286
291
tt:: TokenTree :: Leaf ( tt:: Leaf :: Literal ( it) ) if i % 2 == 0 => {
287
- text += & unquote_str ( & it) . ok_or_else ( || mbe:: ExpandError :: ConversionError ) ?;
292
+ text += & match unquote_str ( & it) {
293
+ Some ( s) => s,
294
+ None => {
295
+ return ExpandResult :: only_err ( mbe:: ExpandError :: ConversionError ) ;
296
+ }
297
+ } ;
288
298
}
289
299
tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( punct) ) if i % 2 == 1 && punct. char == ',' => ( ) ,
290
- _ => return Err ( mbe:: ExpandError :: UnexpectedToken ) ,
300
+ _ => return ExpandResult :: only_err ( mbe:: ExpandError :: UnexpectedToken ) ,
291
301
}
292
302
}
293
303
294
- Ok ( ( quote ! ( #text) , FragmentKind :: Expr ) )
304
+ ExpandResult :: ok ( Some ( ( quote ! ( #text) , FragmentKind :: Expr ) ) )
295
305
}
296
306
297
307
fn relative_file (
@@ -324,26 +334,35 @@ fn include_expand(
324
334
db : & dyn AstDatabase ,
325
335
arg_id : EagerMacroId ,
326
336
tt : & tt:: Subtree ,
327
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe:: ExpandError > {
328
- let path = parse_string ( tt) ?;
329
- let file_id = relative_file ( db, arg_id. into ( ) , & path, false )
330
- . ok_or_else ( || mbe:: ExpandError :: ConversionError ) ?;
331
-
332
- // FIXME:
333
- // Handle include as expression
334
- let res = parse_to_token_tree ( & db. file_text ( file_id) )
335
- . ok_or_else ( || mbe:: ExpandError :: ConversionError ) ?
336
- . 0 ;
337
-
338
- Ok ( ( res, FragmentKind :: Items ) )
337
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
338
+ let res = ( || {
339
+ let path = parse_string ( tt) ?;
340
+ let file_id = relative_file ( db, arg_id. into ( ) , & path, false )
341
+ . ok_or_else ( || mbe:: ExpandError :: ConversionError ) ?;
342
+
343
+ Ok ( parse_to_token_tree ( & db. file_text ( file_id) )
344
+ . ok_or_else ( || mbe:: ExpandError :: ConversionError ) ?
345
+ . 0 )
346
+ } ) ( ) ;
347
+
348
+ match res {
349
+ Ok ( res) => {
350
+ // FIXME:
351
+ // Handle include as expression
352
+ ExpandResult :: ok ( Some ( ( res, FragmentKind :: Items ) ) )
353
+ }
354
+ Err ( e) => ExpandResult :: only_err ( e) ,
355
+ }
339
356
}
340
357
341
358
fn include_bytes_expand (
342
359
_db : & dyn AstDatabase ,
343
360
_arg_id : EagerMacroId ,
344
361
tt : & tt:: Subtree ,
345
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe:: ExpandError > {
346
- let _path = parse_string ( tt) ?;
362
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
363
+ if let Err ( e) = parse_string ( tt) {
364
+ return ExpandResult :: only_err ( e) ;
365
+ }
347
366
348
367
// FIXME: actually read the file here if the user asked for macro expansion
349
368
let res = tt:: Subtree {
@@ -353,15 +372,18 @@ fn include_bytes_expand(
353
372
id: tt:: TokenId :: unspecified( ) ,
354
373
} ) ) ] ,
355
374
} ;
356
- Ok ( ( res, FragmentKind :: Expr ) )
375
+ ExpandResult :: ok ( Some ( ( res, FragmentKind :: Expr ) ) )
357
376
}
358
377
359
378
fn include_str_expand (
360
379
db : & dyn AstDatabase ,
361
380
arg_id : EagerMacroId ,
362
381
tt : & tt:: Subtree ,
363
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe:: ExpandError > {
364
- let path = parse_string ( tt) ?;
382
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
383
+ let path = match parse_string ( tt) {
384
+ Ok ( it) => it,
385
+ Err ( e) => return ExpandResult :: only_err ( e) ,
386
+ } ;
365
387
366
388
// FIXME: we're not able to read excluded files (which is most of them because
367
389
// it's unusual to `include_str!` a Rust file), but we can return an empty string.
@@ -370,14 +392,14 @@ fn include_str_expand(
370
392
let file_id = match relative_file ( db, arg_id. into ( ) , & path, true ) {
371
393
Some ( file_id) => file_id,
372
394
None => {
373
- return Ok ( ( quote ! ( "" ) , FragmentKind :: Expr ) ) ;
395
+ return ExpandResult :: ok ( Some ( ( quote ! ( "" ) , FragmentKind :: Expr ) ) ) ;
374
396
}
375
397
} ;
376
398
377
399
let text = db. file_text ( file_id) ;
378
400
let text = & * text;
379
401
380
- Ok ( ( quote ! ( #text) , FragmentKind :: Expr ) )
402
+ ExpandResult :: ok ( Some ( ( quote ! ( #text) , FragmentKind :: Expr ) ) )
381
403
}
382
404
383
405
fn get_env_inner ( db : & dyn AstDatabase , arg_id : EagerMacroId , key : & str ) -> Option < String > {
@@ -389,8 +411,11 @@ fn env_expand(
389
411
db : & dyn AstDatabase ,
390
412
arg_id : EagerMacroId ,
391
413
tt : & tt:: Subtree ,
392
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe:: ExpandError > {
393
- let key = parse_string ( tt) ?;
414
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
415
+ let key = match parse_string ( tt) {
416
+ Ok ( it) => it,
417
+ Err ( e) => return ExpandResult :: only_err ( e) ,
418
+ } ;
394
419
395
420
// FIXME:
396
421
// If the environment variable is not defined int rustc, then a compilation error will be emitted.
@@ -402,21 +427,25 @@ fn env_expand(
402
427
let s = get_env_inner ( db, arg_id, & key) . unwrap_or_else ( || "__RA_UNIMPLEMENTED__" . to_string ( ) ) ;
403
428
let expanded = quote ! { #s } ;
404
429
405
- Ok ( ( expanded, FragmentKind :: Expr ) )
430
+ ExpandResult :: ok ( Some ( ( expanded, FragmentKind :: Expr ) ) )
406
431
}
407
432
408
433
fn option_env_expand (
409
434
db : & dyn AstDatabase ,
410
435
arg_id : EagerMacroId ,
411
436
tt : & tt:: Subtree ,
412
- ) -> Result < ( tt:: Subtree , FragmentKind ) , mbe:: ExpandError > {
413
- let key = parse_string ( tt) ?;
437
+ ) -> ExpandResult < Option < ( tt:: Subtree , FragmentKind ) > > {
438
+ let key = match parse_string ( tt) {
439
+ Ok ( it) => it,
440
+ Err ( e) => return ExpandResult :: only_err ( e) ,
441
+ } ;
442
+
414
443
let expanded = match get_env_inner ( db, arg_id, & key) {
415
444
None => quote ! { std:: option:: Option :: None :: <& str > } ,
416
445
Some ( s) => quote ! { std:: option:: Some ( #s) } ,
417
446
} ;
418
447
419
- Ok ( ( expanded, FragmentKind :: Expr ) )
448
+ ExpandResult :: ok ( Some ( ( expanded, FragmentKind :: Expr ) ) )
420
449
}
421
450
422
451
#[ cfg( test) ]
@@ -485,7 +514,7 @@ mod tests {
485
514
}
486
515
} ) ;
487
516
488
- let ( subtree, fragment) = expander. expand ( & db, arg_id, & parsed_args) . unwrap ( ) ;
517
+ let ( subtree, fragment) = expander. expand ( & db, arg_id, & parsed_args) . value . unwrap ( ) ;
489
518
let eager = EagerCallLoc {
490
519
def,
491
520
fragment,
0 commit comments