aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libeditor')
-rw-r--r--crates/libeditor/src/code_actions.rs18
-rw-r--r--crates/libeditor/src/completion.rs31
-rw-r--r--crates/libeditor/src/lib.rs21
-rw-r--r--crates/libeditor/tests/test.rs22
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
5use libsyntax2::{ 5use 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
16use {TextUnit, EditBuilder, Edit}; 16use {EditBuilder, Edit, find_node_at_offset};
17 17
18#[derive(Debug)] 18#[derive(Debug)]
19pub struct ActionResult { 19pub struct ActionResult {
@@ -39,7 +39,7 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce()
39} 39}
40 40
41pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { 41pub 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
68pub fn add_impl<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { 68pub 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
108pub 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
118fn comma_list(buf: &mut String, bra: &str, ket: &str, items: impl Iterator<Item=impl fmt::Display>) { 108fn 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 @@
1use libsyntax2::{
2 File, TextUnit,
3 ast,
4 algo::find_leaf_at_offset,
5};
6
7use {
8 AtomEdit, find_node_at_offset,
9};
10
11#[derive(Debug)]
12pub struct CompletionItem {
13 name: String,
14}
15
16pub 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
27fn 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;
8mod edit; 8mod edit;
9mod code_actions; 9mod code_actions;
10mod typing; 10mod typing;
11mod completion;
11 12
12use libsyntax2::{ 13use 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};
18pub use libsyntax2::AtomEdit; 19pub 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
144pub 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
247fn file(text: &str) -> File { 267fn file(text: &str) -> File {
248 File::parse(text) 268 File::parse(text)
249} 269}