diff options
Diffstat (limited to 'crates/libeditor')
-rw-r--r-- | crates/libeditor/src/code_actions.rs | 18 | ||||
-rw-r--r-- | crates/libeditor/src/completion.rs | 31 | ||||
-rw-r--r-- | crates/libeditor/src/lib.rs | 21 | ||||
-rw-r--r-- | crates/libeditor/tests/test.rs | 22 |
4 files changed, 74 insertions, 18 deletions
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs index b3305be2a..f53a8f9c6 100644 --- a/crates/libeditor/src/code_actions.rs +++ b/crates/libeditor/src/code_actions.rs | |||
@@ -3,7 +3,7 @@ use std::{ | |||
3 | }; | 3 | }; |
4 | 4 | ||
5 | use libsyntax2::{ | 5 | use libsyntax2::{ |
6 | File, | 6 | File, TextUnit, |
7 | ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, | 7 | ast::{self, AstNode, AttrsOwner, TypeParamsOwner, NameOwner}, |
8 | SyntaxKind::COMMA, | 8 | SyntaxKind::COMMA, |
9 | SyntaxNodeRef, | 9 | SyntaxNodeRef, |
@@ -13,7 +13,7 @@ use libsyntax2::{ | |||
13 | }, | 13 | }, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use {TextUnit, EditBuilder, Edit}; | 16 | use {EditBuilder, Edit, find_node_at_offset}; |
17 | 17 | ||
18 | #[derive(Debug)] | 18 | #[derive(Debug)] |
19 | pub struct ActionResult { | 19 | pub struct ActionResult { |
@@ -39,7 +39,7 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() | |||
39 | } | 39 | } |
40 | 40 | ||
41 | pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { | 41 | pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { |
42 | let nominal = find_node::<ast::NominalDef>(file.syntax(), offset)?; | 42 | let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; |
43 | Some(move || { | 43 | Some(move || { |
44 | let derive_attr = nominal | 44 | let derive_attr = nominal |
45 | .attrs() | 45 | .attrs() |
@@ -66,7 +66,7 @@ pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() | |||
66 | } | 66 | } |
67 | 67 | ||
68 | pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { | 68 | pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { |
69 | let nominal = find_node::<ast::NominalDef>(file.syntax(), offset)?; | 69 | let nominal = find_node_at_offset::<ast::NominalDef>(file.syntax(), offset)?; |
70 | let name = nominal.name()?; | 70 | let name = nominal.name()?; |
71 | 71 | ||
72 | Some(move || { | 72 | Some(move || { |
@@ -105,16 +105,6 @@ fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<Synta | |||
105 | .find(|node| !node.kind().is_trivia()) | 105 | .find(|node| !node.kind().is_trivia()) |
106 | } | 106 | } |
107 | 107 | ||
108 | pub fn find_node<'a, N: AstNode<'a>>(syntax: SyntaxNodeRef<'a>, offset: TextUnit) -> Option<N> { | ||
109 | let leaves = find_leaf_at_offset(syntax, offset); | ||
110 | let leaf = leaves.clone() | ||
111 | .find(|leaf| !leaf.kind().is_trivia()) | ||
112 | .or_else(|| leaves.right_biased())?; | ||
113 | ancestors(leaf) | ||
114 | .filter_map(N::cast) | ||
115 | .next() | ||
116 | } | ||
117 | |||
118 | fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) { | 108 | fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) { |
119 | buf.push_str(bra); | 109 | buf.push_str(bra); |
120 | let mut first = true; | 110 | let mut first = true; |
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs new file mode 100644 index 000000000..cf61ec784 --- /dev/null +++ b/crates/libeditor/src/completion.rs | |||
@@ -0,0 +1,31 @@ | |||
1 | use libsyntax2::{ | ||
2 | File, TextUnit, | ||
3 | ast, | ||
4 | algo::find_leaf_at_offset, | ||
5 | }; | ||
6 | |||
7 | use { | ||
8 | AtomEdit, find_node_at_offset, | ||
9 | }; | ||
10 | |||
11 | #[derive(Debug)] | ||
12 | pub struct CompletionItem { | ||
13 | name: String, | ||
14 | } | ||
15 | |||
16 | pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionItem>> { | ||
17 | // Insert a fake ident to get a valid parse tree | ||
18 | let file = { | ||
19 | let edit = AtomEdit::insert(offset, "intellijRulezz".to_string()); | ||
20 | // Don't bother with completion if incremental reparse fails | ||
21 | file.incremental_reparse(&edit)? | ||
22 | }; | ||
23 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?; | ||
24 | Some(complete(name_ref)) | ||
25 | } | ||
26 | |||
27 | fn complete(name_ref: ast::NameRef) -> Vec<CompletionItem> { | ||
28 | vec![CompletionItem { | ||
29 | name: "foo".to_string() | ||
30 | }] | ||
31 | } | ||
diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index 55302265f..60489f7e3 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs | |||
@@ -8,11 +8,12 @@ mod line_index; | |||
8 | mod edit; | 8 | mod edit; |
9 | mod code_actions; | 9 | mod code_actions; |
10 | mod typing; | 10 | mod typing; |
11 | mod completion; | ||
11 | 12 | ||
12 | use libsyntax2::{ | 13 | use libsyntax2::{ |
13 | File, TextUnit, TextRange, | 14 | File, TextUnit, TextRange, SyntaxNodeRef, |
14 | ast::{AstNode, NameOwner}, | 15 | ast::{AstNode, NameOwner}, |
15 | algo::{walk, find_leaf_at_offset}, | 16 | algo::{walk, find_leaf_at_offset, ancestors}, |
16 | SyntaxKind::{self, *}, | 17 | SyntaxKind::{self, *}, |
17 | }; | 18 | }; |
18 | pub use libsyntax2::AtomEdit; | 19 | pub use libsyntax2::AtomEdit; |
@@ -22,10 +23,11 @@ pub use self::{ | |||
22 | symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, | 23 | symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, |
23 | edit::{EditBuilder, Edit}, | 24 | edit::{EditBuilder, Edit}, |
24 | code_actions::{ | 25 | code_actions::{ |
25 | ActionResult, find_node, | 26 | ActionResult, |
26 | flip_comma, add_derive, add_impl, | 27 | flip_comma, add_derive, add_impl, |
27 | }, | 28 | }, |
28 | typing::join_lines, | 29 | typing::join_lines, |
30 | completion::scope_completion, | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | #[derive(Debug)] | 33 | #[derive(Debug)] |
@@ -138,3 +140,16 @@ pub fn runnables(file: &File) -> Vec<Runnable> { | |||
138 | }) | 140 | }) |
139 | .collect() | 141 | .collect() |
140 | } | 142 | } |
143 | |||
144 | pub fn find_node_at_offset<'a, N: AstNode<'a>>( | ||
145 | syntax: SyntaxNodeRef<'a>, | ||
146 | offset: TextUnit, | ||
147 | ) -> Option<N> { | ||
148 | let leaves = find_leaf_at_offset(syntax, offset); | ||
149 | let leaf = leaves.clone() | ||
150 | .find(|leaf| !leaf.kind().is_trivia()) | ||
151 | .or_else(|| leaves.right_biased())?; | ||
152 | ancestors(leaf) | ||
153 | .filter_map(N::cast) | ||
154 | .next() | ||
155 | } | ||
diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs index c8882c94d..9d59f4cdf 100644 --- a/crates/libeditor/tests/test.rs +++ b/crates/libeditor/tests/test.rs | |||
@@ -9,7 +9,7 @@ use libeditor::{ | |||
9 | ActionResult, | 9 | ActionResult, |
10 | highlight, runnables, extend_selection, file_structure, | 10 | highlight, runnables, extend_selection, file_structure, |
11 | flip_comma, add_derive, add_impl, matching_brace, | 11 | flip_comma, add_derive, add_impl, matching_brace, |
12 | join_lines, | 12 | join_lines, scope_completion, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[test] | 15 | #[test] |
@@ -244,6 +244,26 @@ struct Foo { f: u32 } | |||
244 | "); | 244 | "); |
245 | } | 245 | } |
246 | 246 | ||
247 | // #[test] | ||
248 | // fn test_completion() { | ||
249 | // fn do_check(code: &str, expected_completions: &str) { | ||
250 | // let (off, code) = extract_offset(&code); | ||
251 | // let file = file(&code); | ||
252 | // let completions = scope_completion(&file, off).unwrap(); | ||
253 | // assert_eq_dbg(expected_completions, &completions); | ||
254 | // } | ||
255 | |||
256 | // do_check(r" | ||
257 | // fn foo(foo: i32) { | ||
258 | // let bar = 92; | ||
259 | // 1 + <|> | ||
260 | // } | ||
261 | // ", r#" | ||
262 | // CompletionItem { name: "bar" }, | ||
263 | // CompletionItem { name: "foo" }, | ||
264 | // "#); | ||
265 | // } | ||
266 | |||
247 | fn file(text: &str) -> File { | 267 | fn file(text: &str) -> File { |
248 | File::parse(text) | 268 | File::parse(text) |
249 | } | 269 | } |