aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api_light/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api_light/src/lib.rs')
-rw-r--r--crates/ra_ide_api_light/src/lib.rs140
1 files changed, 1 insertions, 139 deletions
diff --git a/crates/ra_ide_api_light/src/lib.rs b/crates/ra_ide_api_light/src/lib.rs
index f21a91e18..df7f144b6 100644
--- a/crates/ra_ide_api_light/src/lib.rs
+++ b/crates/ra_ide_api_light/src/lib.rs
@@ -4,147 +4,9 @@
4//! an edit or some auxiliary info. 4//! an edit or some auxiliary info.
5 5
6mod structure; 6mod structure;
7mod typing;
8 7
9use rustc_hash::FxHashSet; 8use ra_syntax::TextRange;
10use ra_text_edit::TextEditBuilder;
11use ra_syntax::{
12 SourceFile, SyntaxNode, TextRange, TextUnit, Direction,
13 algo::find_leaf_at_offset,
14 SyntaxKind::{self, *},
15 ast::{self, AstNode},
16};
17 9
18pub use crate::{ 10pub use crate::{
19 structure::{file_structure, StructureNode}, 11 structure::{file_structure, StructureNode},
20 typing::{on_enter, on_dot_typed, on_eq_typed},
21}; 12};
22
23#[derive(Debug)]
24pub struct LocalEdit {
25 pub label: String,
26 pub edit: ra_text_edit::TextEdit,
27 pub cursor_position: Option<TextUnit>,
28}
29
30#[derive(Debug)]
31pub struct HighlightedRange {
32 pub range: TextRange,
33 pub tag: &'static str,
34}
35
36#[derive(Debug, Copy, Clone)]
37pub enum Severity {
38 Error,
39 WeakWarning,
40}
41
42#[derive(Debug)]
43pub struct Diagnostic {
44 pub range: TextRange,
45 pub msg: String,
46 pub severity: Severity,
47 pub fix: Option<LocalEdit>,
48}
49
50pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
51 const BRACES: &[SyntaxKind] =
52 &[L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE];
53 let (brace_node, brace_idx) = find_leaf_at_offset(file.syntax(), offset)
54 .filter_map(|node| {
55 let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
56 Some((node, idx))
57 })
58 .next()?;
59 let parent = brace_node.parent()?;
60 let matching_kind = BRACES[brace_idx ^ 1];
61 let matching_node = parent.children().find(|node| node.kind() == matching_kind)?;
62 Some(matching_node.range().start())
63}
64
65pub fn highlight(root: &SyntaxNode) -> Vec<HighlightedRange> {
66 // Visited nodes to handle highlighting priorities
67 let mut highlighted = FxHashSet::default();
68 let mut res = Vec::new();
69 for node in root.descendants() {
70 if highlighted.contains(&node) {
71 continue;
72 }
73 let tag = match node.kind() {
74 COMMENT => "comment",
75 STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string",
76 ATTR => "attribute",
77 NAME_REF => "text",
78 NAME => "function",
79 INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal",
80 LIFETIME => "parameter",
81 k if k.is_keyword() => "keyword",
82 _ => {
83 if let Some(macro_call) = ast::MacroCall::cast(node) {
84 if let Some(path) = macro_call.path() {
85 if let Some(segment) = path.segment() {
86 if let Some(name_ref) = segment.name_ref() {
87 highlighted.insert(name_ref.syntax());
88 let range_start = name_ref.syntax().range().start();
89 let mut range_end = name_ref.syntax().range().end();
90 for sibling in path.syntax().siblings(Direction::Next) {
91 match sibling.kind() {
92 EXCL | IDENT => range_end = sibling.range().end(),
93 _ => (),
94 }
95 }
96 res.push(HighlightedRange {
97 range: TextRange::from_to(range_start, range_end),
98 tag: "macro",
99 })
100 }
101 }
102 }
103 }
104 continue;
105 }
106 };
107 res.push(HighlightedRange { range: node.range(), tag })
108 }
109 res
110}
111
112#[cfg(test)]
113mod tests {
114 use ra_syntax::AstNode;
115 use insta::assert_debug_snapshot_matches;
116
117 use test_utils::{add_cursor, assert_eq_text, extract_offset};
118
119 use super::*;
120
121 #[test]
122 fn test_highlighting() {
123 let file = SourceFile::parse(
124 r#"
125// comment
126fn main() {}
127 println!("Hello, {}!", 92);
128"#,
129 );
130 let hls = highlight(file.syntax());
131 assert_debug_snapshot_matches!("highlighting", hls);
132 }
133
134 #[test]
135 fn test_matching_brace() {
136 fn do_check(before: &str, after: &str) {
137 let (pos, before) = extract_offset(before);
138 let file = SourceFile::parse(&before);
139 let new_pos = match matching_brace(&file, pos) {
140 None => pos,
141 Some(pos) => pos,
142 };
143 let actual = add_cursor(&before, new_pos);
144 assert_eq_text!(after, &actual);
145 }
146
147 do_check("struct Foo { a: i32, }<|>", "struct Foo <|>{ a: i32, }");
148 }
149
150}