aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src/syntax_highlighting.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api/src/syntax_highlighting.rs')
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs92
1 files changed, 92 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
new file mode 100644
index 000000000..cb19e9515
--- /dev/null
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -0,0 +1,92 @@
1use ra_syntax::{ast, AstNode,};
2use ra_db::SyntaxDatabase;
3
4use crate::{
5 FileId, Cancelable, HighlightedRange,
6 db::RootDatabase,
7};
8
9pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
10 let source_file = db.source_file(file_id);
11 let mut res = ra_ide_api_light::highlight(source_file.syntax());
12 for macro_call in source_file
13 .syntax()
14 .descendants()
15 .filter_map(ast::MacroCall::cast)
16 {
17 if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) {
18 let mapped_ranges = ra_ide_api_light::highlight(&exp.syntax())
19 .into_iter()
20 .filter_map(|r| {
21 let mapped_range = exp.map_range_back(r.range)?;
22 let res = HighlightedRange {
23 range: mapped_range + off,
24 tag: r.tag,
25 };
26 Some(res)
27 });
28 res.extend(mapped_ranges);
29 }
30 }
31 Ok(res)
32}
33
34#[cfg(test)]
35mod tests {
36 use crate::mock_analysis::single_file;
37 use test_utils::assert_eq_dbg;
38
39 #[test]
40 fn highlights_code_inside_macros() {
41 let (analysis, file_id) = single_file(
42 "
43 fn main() {
44 ctry!({ let x = 92; x});
45 vec![{ let x = 92; x}];
46 }
47 ",
48 );
49 let highlights = analysis.highlight(file_id).unwrap();
50 assert_eq_dbg(
51 r#"[HighlightedRange { range: [13; 15), tag: "keyword" },
52 HighlightedRange { range: [16; 20), tag: "function" },
53 HighlightedRange { range: [41; 46), tag: "macro" },
54 HighlightedRange { range: [49; 52), tag: "keyword" },
55 HighlightedRange { range: [57; 59), tag: "literal" },
56 HighlightedRange { range: [82; 86), tag: "macro" },
57 HighlightedRange { range: [89; 92), tag: "keyword" },
58 HighlightedRange { range: [97; 99), tag: "literal" },
59 HighlightedRange { range: [49; 52), tag: "keyword" },
60 HighlightedRange { range: [53; 54), tag: "function" },
61 HighlightedRange { range: [57; 59), tag: "literal" },
62 HighlightedRange { range: [61; 62), tag: "text" },
63 HighlightedRange { range: [89; 92), tag: "keyword" },
64 HighlightedRange { range: [93; 94), tag: "function" },
65 HighlightedRange { range: [97; 99), tag: "literal" },
66 HighlightedRange { range: [101; 102), tag: "text" }]"#,
67 &highlights,
68 )
69 }
70
71 // FIXME: this test is not really necessary: artifact of the inital hacky
72 // macros implementation.
73 #[test]
74 fn highlight_query_group_macro() {
75 let (analysis, file_id) = single_file(
76 "
77 salsa::query_group! {
78 pub trait HirDatabase: SyntaxDatabase {}
79 }
80 ",
81 );
82 let highlights = analysis.highlight(file_id).unwrap();
83 assert_eq_dbg(
84 r#"[HighlightedRange { range: [20; 32), tag: "macro" },
85 HighlightedRange { range: [13; 18), tag: "text" },
86 HighlightedRange { range: [51; 54), tag: "keyword" },
87 HighlightedRange { range: [55; 60), tag: "keyword" },
88 HighlightedRange { range: [61; 72), tag: "function" }]"#,
89 &highlights,
90 )
91 }
92}