diff options
author | Kirill Bulatov <[email protected]> | 2019-07-19 22:20:09 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2019-07-20 21:45:26 +0100 |
commit | 201b344f2b0c9e84606115d135cd658d0a955d2c (patch) | |
tree | 1dc9c308c71ea4d2512d351de12933c6475abba8 /crates/ra_ide_api/src/inlay_hints.rs | |
parent | 761fc71083b9d810aa006210d6df2b0edf95cf33 (diff) |
Refactor server api
Diffstat (limited to 'crates/ra_ide_api/src/inlay_hints.rs')
-rw-r--r-- | crates/ra_ide_api/src/inlay_hints.rs | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs new file mode 100644 index 000000000..4d1df65d0 --- /dev/null +++ b/crates/ra_ide_api/src/inlay_hints.rs | |||
@@ -0,0 +1,110 @@ | |||
1 | use ra_syntax::{ | ||
2 | algo::visit::{visitor, Visitor}, | ||
3 | ast::{self, PatKind, TypeAscriptionOwner}, | ||
4 | AstNode, SmolStr, SourceFile, SyntaxNode, TextRange, | ||
5 | }; | ||
6 | |||
7 | #[derive(Debug, PartialEq, Eq)] | ||
8 | pub enum InlayKind { | ||
9 | LetBinding, | ||
10 | ClosureParameter, | ||
11 | } | ||
12 | |||
13 | #[derive(Debug)] | ||
14 | pub struct InlayHint { | ||
15 | pub range: TextRange, | ||
16 | pub text: SmolStr, | ||
17 | pub inlay_kind: InlayKind, | ||
18 | } | ||
19 | |||
20 | pub(crate) fn inlay_hints(file: &SourceFile) -> Vec<InlayHint> { | ||
21 | file.syntax().descendants().map(|node| get_inlay_hints(&node)).flatten().collect() | ||
22 | } | ||
23 | |||
24 | fn get_inlay_hints(node: &SyntaxNode) -> Vec<InlayHint> { | ||
25 | visitor() | ||
26 | .visit(|let_statement: ast::LetStmt| { | ||
27 | let let_syntax = let_statement.syntax(); | ||
28 | |||
29 | if let_statement.ascribed_type().is_some() { | ||
30 | return Vec::new(); | ||
31 | } | ||
32 | |||
33 | let pat_range = match let_statement.pat().map(|pat| pat.kind()) { | ||
34 | Some(PatKind::BindPat(bind_pat)) => bind_pat.syntax().text_range(), | ||
35 | Some(PatKind::TuplePat(tuple_pat)) => tuple_pat.syntax().text_range(), | ||
36 | _ => return Vec::new(), | ||
37 | }; | ||
38 | |||
39 | vec![InlayHint { | ||
40 | range: pat_range, | ||
41 | text: let_syntax.text().to_smol_string(), | ||
42 | inlay_kind: InlayKind::LetBinding, | ||
43 | }] | ||
44 | }) | ||
45 | .visit(|closure_parameter: ast::LambdaExpr| { | ||
46 | if let Some(param_list) = closure_parameter.param_list() { | ||
47 | param_list | ||
48 | .params() | ||
49 | .filter(|closure_param| closure_param.ascribed_type().is_none()) | ||
50 | .map(|closure_param| { | ||
51 | let closure_param_syntax = closure_param.syntax(); | ||
52 | InlayHint { | ||
53 | range: closure_param_syntax.text_range(), | ||
54 | text: closure_param_syntax.text().to_smol_string(), | ||
55 | inlay_kind: InlayKind::ClosureParameter, | ||
56 | } | ||
57 | }) | ||
58 | .collect() | ||
59 | } else { | ||
60 | Vec::new() | ||
61 | } | ||
62 | }) | ||
63 | .accept(&node) | ||
64 | .unwrap_or_else(Vec::new) | ||
65 | } | ||
66 | |||
67 | #[cfg(test)] | ||
68 | mod tests { | ||
69 | use super::*; | ||
70 | use insta::assert_debug_snapshot_matches; | ||
71 | |||
72 | #[test] | ||
73 | fn test_inlay_hints() { | ||
74 | let file = SourceFile::parse( | ||
75 | r#" | ||
76 | struct OuterStruct {} | ||
77 | |||
78 | fn main() { | ||
79 | struct InnerStruct {} | ||
80 | |||
81 | let test = 54; | ||
82 | let test = InnerStruct {}; | ||
83 | let test = OuterStruct {}; | ||
84 | let test = vec![222]; | ||
85 | let mut test = Vec::new(); | ||
86 | test.push(333); | ||
87 | let test = test.into_iter().map(|i| i * i).collect::<Vec<_>>(); | ||
88 | let mut test = 33; | ||
89 | let _ = 22; | ||
90 | let test: Vec<_> = (0..3).collect(); | ||
91 | |||
92 | let _ = (0..23).map(|i: u32| { | ||
93 | let i_squared = i * i; | ||
94 | i_squared | ||
95 | }); | ||
96 | |||
97 | let test: i32 = 33; | ||
98 | |||
99 | let (x, c) = (42, 'a'); | ||
100 | let test = (42, 'a'); | ||
101 | } | ||
102 | |||
103 | "#, | ||
104 | ) | ||
105 | .ok() | ||
106 | .unwrap(); | ||
107 | let hints = inlay_hints(&file); | ||
108 | assert_debug_snapshot_matches!("inlay_hints", hints); | ||
109 | } | ||
110 | } | ||