diff options
Diffstat (limited to 'crates/ra_ide_api/src/syntax_highlighting.rs')
-rw-r--r-- | crates/ra_ide_api/src/syntax_highlighting.rs | 92 |
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 @@ | |||
1 | use ra_syntax::{ast, AstNode,}; | ||
2 | use ra_db::SyntaxDatabase; | ||
3 | |||
4 | use crate::{ | ||
5 | FileId, Cancelable, HighlightedRange, | ||
6 | db::RootDatabase, | ||
7 | }; | ||
8 | |||
9 | pub(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)] | ||
35 | mod 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 | } | ||