aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand/src/builtin_macro.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_expand/src/builtin_macro.rs')
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs80
1 files changed, 80 insertions, 0 deletions
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
new file mode 100644
index 000000000..97fb0cb55
--- /dev/null
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -0,0 +1,80 @@
1//! Builtin macro
2use crate::db::AstDatabase;
3use crate::{
4 ast::{self, AstNode},
5 name, AstId, CrateId, HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind,
6 TextUnit,
7};
8
9use crate::quote;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum BuiltinExpander {
13 Line,
14}
15
16impl BuiltinExpander {
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 }
26 }
27}
28
29pub fn find_builtin_macro(
30 ident: &name::Name,
31 krate: CrateId,
32 ast_id: AstId<ast::MacroCall>,
33) -> Option<MacroDefId> {
34 // FIXME: Better registering method
35 if ident == &name::LINE_MACRO {
36 Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Line) })
37 } else {
38 None
39 }
40}
41
42fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize {
43 // FIXME: Use expansion info
44 let file_id = file.original_file(db);
45 let text = db.file_text(file_id);
46 let mut line_num = 1;
47
48 // Count line end
49 for (i, c) in text.chars().enumerate() {
50 if i == pos.to_usize() {
51 break;
52 }
53 if c == '\n' {
54 line_num += 1;
55 }
56 }
57
58 line_num
59}
60
61fn line_expand(
62 db: &dyn AstDatabase,
63 id: MacroCallId,
64 _tt: &tt::Subtree,
65) -> Result<tt::Subtree, mbe::ExpandError> {
66 let loc = db.lookup_intern_macro(id);
67 let macro_call = loc.ast_id.to_node(db);
68
69 let arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?;
70 let arg_start = arg.syntax().text_range().start();
71
72 let file = id.as_file(MacroFileKind::Expr);
73 let line_num = to_line_number(db, file, arg_start);
74
75 let expanded = quote! {
76 #line_num
77 };
78
79 Ok(expanded)
80}