1
1
//! Builtin macro
2
- use crate :: { ast, name, AstId , BuiltinMacro , CrateId , MacroDefId } ;
2
+ use crate :: db:: AstDatabase ;
3
+ use crate :: {
4
+ ast:: { self , AstNode } ,
5
+ name, AstId , BuiltinMacro , CrateId , HirFileId , MacroCallId , MacroDefId , MacroFileKind ,
6
+ TextUnit ,
7
+ } ;
8
+
9
+ use crate :: quote;
3
10
4
11
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
5
12
pub enum BuiltinExpander {
6
- Line
13
+ Line ,
7
14
}
8
15
9
16
impl BuiltinExpander {
10
- pub fn expand ( & self , _tt : & tt:: Subtree ) -> Result < tt:: Subtree , mbe:: ExpandError > {
11
- Err ( mbe:: ExpandError :: UnexpectedToken )
17
+ pub fn expand (
18
+ & self ,
19
+ db : & dyn AstDatabase ,
20
+ id : MacroCallId ,
21
+ tt : & tt:: Subtree ,
22
+ ) -> Result < tt:: Subtree , mbe:: ExpandError > {
23
+ match self {
24
+ BuiltinExpander :: Line => line_expand ( db, id, tt) ,
25
+ }
12
26
}
13
27
}
14
28
@@ -18,9 +32,53 @@ pub fn find_builtin_macro(
18
32
ast_id : AstId < ast:: MacroCall > ,
19
33
) -> Option < MacroDefId > {
20
34
// FIXME: Better registering method
21
- if ident == & name:: LINE {
22
- Some ( MacroDefId :: BuiltinMacro ( BuiltinMacro { expander : BuiltinExpander :: Line , krate, ast_id } ) )
35
+ if ident == & name:: LINE_MACRO {
36
+ Some ( MacroDefId :: BuiltinMacro ( BuiltinMacro {
37
+ expander : BuiltinExpander :: Line ,
38
+ krate,
39
+ ast_id,
40
+ } ) )
23
41
} else {
24
42
None
25
43
}
26
44
}
45
+
46
+ fn to_line_number ( db : & dyn AstDatabase , file : HirFileId , pos : TextUnit ) -> usize {
47
+ // FIXME: Use expansion info
48
+ let file_id = file. original_file ( db) ;
49
+ let text = db. file_text ( file_id) ;
50
+ let mut line_num = 1 ;
51
+
52
+ // Count line end
53
+ for ( i, c) in text. chars ( ) . enumerate ( ) {
54
+ if i == pos. to_usize ( ) {
55
+ break ;
56
+ }
57
+ if c == '\n' {
58
+ line_num += 1 ;
59
+ }
60
+ }
61
+
62
+ line_num
63
+ }
64
+
65
+ fn line_expand (
66
+ db : & dyn AstDatabase ,
67
+ id : MacroCallId ,
68
+ _tt : & tt:: Subtree ,
69
+ ) -> Result < tt:: Subtree , mbe:: ExpandError > {
70
+ let loc = db. lookup_intern_macro ( id) ;
71
+ let macro_call = loc. ast_id . to_node ( db) ;
72
+
73
+ let arg = macro_call. token_tree ( ) . ok_or_else ( || mbe:: ExpandError :: UnexpectedToken ) ?;
74
+ let arg_start = arg. syntax ( ) . text_range ( ) . start ( ) ;
75
+
76
+ let file = id. as_file ( MacroFileKind :: Expr ) ;
77
+ let line_num = to_line_number ( db, file, arg_start) ;
78
+
79
+ let expanded = quote ! {
80
+ #line_num
81
+ } ;
82
+
83
+ Ok ( expanded)
84
+ }
0 commit comments