10
10
//! and harder to understand.
11
11
12
12
mod mbe;
13
+ mod builtin;
13
14
14
15
use std:: { iter, ops:: Range } ;
15
16
@@ -20,14 +21,15 @@ use stdx::format_to;
20
21
use syntax:: {
21
22
ast:: { self , edit:: IndentLevel } ,
22
23
AstNode ,
23
- SyntaxKind :: { EOF , IDENT , LIFETIME_IDENT } ,
24
+ SyntaxKind :: { COMMENT , EOF , IDENT , LIFETIME_IDENT } ,
24
25
SyntaxNode , T ,
25
26
} ;
26
27
27
28
use crate :: {
28
29
db:: DefDatabase , nameres:: ModuleSource , resolver:: HasResolver , test_db:: TestDB , AsMacroCall ,
29
30
} ;
30
31
32
+ #[ track_caller]
31
33
fn check ( ra_fixture : & str , mut expect : Expect ) {
32
34
let db = TestDB :: with_files ( ra_fixture) ;
33
35
let krate = db. crate_graph ( ) . iter ( ) . next ( ) . unwrap ( ) ;
@@ -44,37 +46,54 @@ fn check(ra_fixture: &str, mut expect: Expect) {
44
46
let mut expansions = Vec :: new ( ) ;
45
47
for macro_call in source_file. syntax ( ) . descendants ( ) . filter_map ( ast:: MacroCall :: cast) {
46
48
let macro_call = InFile :: new ( source. file_id , & macro_call) ;
49
+ let mut error = None ;
47
50
let macro_call_id = macro_call
48
51
. as_call_id_with_errors (
49
52
& db,
50
53
krate,
51
54
|path| resolver. resolve_path_as_macro ( & db, & path) ,
52
- & mut |err| panic ! ( "{}" , err) ,
55
+ & mut |err| error = Some ( err) ,
53
56
)
54
57
. unwrap ( )
55
58
. unwrap ( ) ;
56
59
let macro_file = MacroFile { macro_call_id } ;
57
- let expansion_result = db. parse_macro_expansion ( macro_file) ;
60
+ let mut expansion_result = db. parse_macro_expansion ( macro_file) ;
61
+ expansion_result. err = expansion_result. err . or ( error) ;
58
62
expansions. push ( ( macro_call. value . clone ( ) , expansion_result) ) ;
59
63
}
60
64
61
65
let mut expanded_text = source_file. to_string ( ) ;
62
66
for ( call, exp) in expansions. into_iter ( ) . rev ( ) {
67
+ let mut tree = false ;
68
+ let mut expect_errors = false ;
69
+ for comment in call. syntax ( ) . children_with_tokens ( ) . filter ( |it| it. kind ( ) == COMMENT ) {
70
+ tree |= comment. to_string ( ) . contains ( "+tree" ) ;
71
+ expect_errors |= comment. to_string ( ) . contains ( "+errors" ) ;
72
+ }
73
+
63
74
let mut expn_text = String :: new ( ) ;
64
75
if let Some ( err) = exp. err {
65
76
format_to ! ( expn_text, "/* error: {} */" , err) ;
66
77
}
67
78
if let Some ( ( parse, _token_map) ) = exp. value {
68
- assert ! (
69
- parse. errors( ) . is_empty( ) ,
70
- "parse errors in expansion: \n {:#?}" ,
71
- parse. errors( )
72
- ) ;
79
+ if expect_errors {
80
+ assert ! ( !parse. errors( ) . is_empty( ) , "no parse errors in expansion" ) ;
81
+ for e in parse. errors ( ) {
82
+ format_to ! ( expn_text, "/* parse error: {} */\n " , e) ;
83
+ }
84
+ } else {
85
+ assert ! (
86
+ parse. errors( ) . is_empty( ) ,
87
+ "parse errors in expansion: \n {:#?}" ,
88
+ parse. errors( )
89
+ ) ;
90
+ }
73
91
let pp = pretty_print_macro_expansion ( parse. syntax_node ( ) ) ;
74
92
let indent = IndentLevel :: from_node ( call. syntax ( ) ) ;
75
93
let pp = reindent ( indent, pp) ;
76
94
format_to ! ( expn_text, "{}" , pp) ;
77
- if call. to_string ( ) . contains ( "// +tree" ) {
95
+
96
+ if tree {
78
97
let tree = format ! ( "{:#?}" , parse. syntax_node( ) )
79
98
. split_inclusive ( "\n " )
80
99
. map ( |line| format ! ( "// {}" , line) )
@@ -129,6 +148,8 @@ fn pretty_print_macro_expansion(expn: SyntaxNode) -> String {
129
148
( T ! [ ->] , _) | ( _, T ! [ ->] ) => " " ,
130
149
( T ! [ &&] , _) | ( _, T ! [ &&] ) => " " ,
131
150
( T ! [ , ] , _) => " " ,
151
+ ( T ! [ : ] , IDENT | T ! [ '(' ] ) => " " ,
152
+ ( T ! [ : ] , _) if curr_kind. is_keyword ( ) => " " ,
132
153
( T ! [ fn ] , T ! [ '(' ] ) => "" ,
133
154
( T ! [ ']' ] , _) if curr_kind. is_keyword ( ) => " " ,
134
155
( T ! [ ']' ] , T ! [ #] ) => "\n " ,
0 commit comments