11//! 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;
310
411#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
512pub enum BuiltinExpander {
6- Line
13+ Line ,
714}
815
916impl 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+ }
1226 }
1327}
1428
@@ -18,9 +32,53 @@ pub fn find_builtin_macro(
1832 ast_id : AstId < ast:: MacroCall > ,
1933) -> Option < MacroDefId > {
2034 // 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+ } ) )
2341 } else {
2442 None
2543 }
2644}
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