diff options
author | Edwin Cheng <[email protected]> | 2019-11-11 06:15:09 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-11-11 06:15:09 +0000 |
commit | c4aa8b63bcea5faa23da56b679cafbdbad6892f1 (patch) | |
tree | 759950e504bb0fa8115c85ea7e606e20c609f40c | |
parent | 1637a8a59071d8c7976ffc8d04edc5b7f54ae40b (diff) |
Add line macro and tests
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 70 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 2 |
3 files changed, 84 insertions, 7 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index e56b9356e..896bf2924 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -4810,3 +4810,22 @@ fn no_such_field_diagnostics() { | |||
4810 | "### | 4810 | "### |
4811 | ); | 4811 | ); |
4812 | } | 4812 | } |
4813 | |||
4814 | #[test] | ||
4815 | fn infer_builtin_macros_line() { | ||
4816 | assert_snapshot!( | ||
4817 | infer(r#" | ||
4818 | #[rustc_builtin_macro] | ||
4819 | macro_rules! line {() => {}} | ||
4820 | |||
4821 | fn main() { | ||
4822 | let x = line!(); | ||
4823 | } | ||
4824 | "#), | ||
4825 | @r###" | ||
4826 | ![0; 1) '6': i32 | ||
4827 | [64; 88) '{ ...!(); }': () | ||
4828 | [74; 75) 'x': i32 | ||
4829 | "### | ||
4830 | ); | ||
4831 | } | ||
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index dca2f17ef..acb62da27 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -1,14 +1,28 @@ | |||
1 | //! Builtin macro | 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 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 11 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
5 | pub enum BuiltinExpander { | 12 | pub enum BuiltinExpander { |
6 | Line | 13 | Line, |
7 | } | 14 | } |
8 | 15 | ||
9 | impl BuiltinExpander { | 16 | impl BuiltinExpander { |
10 | pub fn expand(&self, _tt: &tt::Subtree) -> Result<tt::Subtree, mbe::ExpandError> { | 17 | pub fn expand( |
11 | Err(mbe::ExpandError::UnexpectedToken) | 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 | ast_id: AstId<ast::MacroCall>, | 32 | ast_id: AstId<ast::MacroCall>, |
19 | ) -> Option<MacroDefId> { | 33 | ) -> Option<MacroDefId> { |
20 | // FIXME: Better registering method | 34 | // FIXME: Better registering method |
21 | if ident == &name::LINE { | 35 | if ident == &name::LINE_MACRO { |
22 | Some(MacroDefId::BuiltinMacro(BuiltinMacro { expander: BuiltinExpander::Line, krate, ast_id })) | 36 | Some(MacroDefId::BuiltinMacro(BuiltinMacro { |
37 | expander: BuiltinExpander::Line, | ||
38 | krate, | ||
39 | ast_id, | ||
40 | })) | ||
23 | } else { | 41 | } else { |
24 | None | 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 | } | ||
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 343c9e6bf..009ff5312 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -28,7 +28,7 @@ impl TokenExpander { | |||
28 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 28 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
29 | match self { | 29 | match self { |
30 | TokenExpander::MacroRules(it) => it.expand(tt), | 30 | TokenExpander::MacroRules(it) => it.expand(tt), |
31 | TokenExpander::Builtin(it) => it.expand(tt), | 31 | TokenExpander::Builtin(it) => it.expand(db, id, tt), |
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||