Skip to content

Commit f46bc12

Browse files
committed
Add more patterns and keywords
1 parent eb4004f commit f46bc12

File tree

3 files changed

+59
-55
lines changed

3 files changed

+59
-55
lines changed

crates/ra_ide/src/completion/complete_keyword.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fn add_keyword(
6262
pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
6363
add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent);
6464
add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent);
65-
add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent);
65+
add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent);
6666
add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item);
6767
add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item);
6868
add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.after_unsafe);
@@ -72,7 +72,6 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
7272
add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent);
7373
add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent);
7474
add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent);
75-
add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent);
7675
add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if);
7776
add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if);
7877
add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent);
@@ -88,6 +87,8 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
8887
add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt);
8988
add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt);
9089
add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt);
90+
add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.inside_trait);
91+
add_keyword(ctx, acc, "where", "where ", ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling);
9192
complete_use_tree_keyword(acc, ctx);
9293

9394
let fn_def = match &ctx.function_syntax {

crates/ra_ide/src/completion/completion_context.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use ra_syntax::{
1212
use ra_text_edit::Indel;
1313

1414
use super::patterns::{
15-
goes_after_unsafe, has_bind_pat_parent, has_block_expr_parent, has_ref_pat_parent,
16-
is_in_loop_body,
15+
goes_after_unsafe, has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling,
16+
has_ref_pat_parent, has_trait_as_prev_sibling, inside_trait, is_in_loop_body,
1717
};
1818
use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
1919
use test_utils::mark;
@@ -69,6 +69,9 @@ pub(crate) struct CompletionContext<'a> {
6969
pub(super) bind_pat_parent: bool,
7070
pub(super) ref_pat_parent: bool,
7171
pub(super) in_loop_body: bool,
72+
pub(super) inside_trait: bool,
73+
pub(super) trait_as_prev_sibling: bool,
74+
pub(super) impl_as_prev_sibling: bool,
7275
}
7376

7477
impl<'a> CompletionContext<'a> {
@@ -132,6 +135,9 @@ impl<'a> CompletionContext<'a> {
132135
ref_pat_parent: false,
133136
bind_pat_parent: false,
134137
block_expr_parent: false,
138+
inside_trait: false,
139+
trait_as_prev_sibling: false,
140+
impl_as_prev_sibling: false,
135141
};
136142

137143
let mut original_file = original_file.syntax().clone();
@@ -210,6 +216,9 @@ impl<'a> CompletionContext<'a> {
210216
self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone());
211217
self.ref_pat_parent = has_ref_pat_parent(syntax_element.clone());
212218
self.in_loop_body = is_in_loop_body(syntax_element.clone());
219+
self.inside_trait = inside_trait(syntax_element.clone());
220+
self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone());
221+
self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());
213222
}
214223

215224
fn fill(

crates/ra_ide/src/completion/patterns.rs

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,48 +3,47 @@ use ra_syntax::{
33
ast::{self, LoopBodyOwner},
44
match_ast, AstNode, Direction, NodeOrToken, SyntaxElement,
55
SyntaxKind::*,
6-
SyntaxNode,
6+
SyntaxNode, SyntaxToken,
77
};
88

99
pub(crate) fn inside_impl(element: SyntaxElement) -> bool {
10-
let node = match element {
11-
NodeOrToken::Node(node) => node,
12-
NodeOrToken::Token(token) => token.parent(),
13-
};
14-
node.ancestors().find(|it| it.kind() == IMPL_DEF).is_some()
10+
element.ancestors().find(|it| it.kind() == IMPL_DEF).is_some()
11+
}
12+
13+
pub(crate) fn inside_trait(element: SyntaxElement) -> bool {
14+
element.ancestors().find(|it| it.kind() == TRAIT_DEF).is_some()
1515
}
1616

1717
pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool {
18-
let node = match element {
19-
NodeOrToken::Node(node) => node,
20-
NodeOrToken::Token(token) => token.parent(),
21-
};
22-
node.ancestors().find(|it| it.kind() == BIND_PAT).is_some()
18+
element.ancestors().find(|it| it.kind() == BIND_PAT).is_some()
2319
}
2420

2521
pub(crate) fn has_ref_pat_parent(element: SyntaxElement) -> bool {
26-
let node = match element {
27-
NodeOrToken::Node(node) => node,
28-
NodeOrToken::Token(token) => token.parent(),
29-
};
30-
node.ancestors().find(|it| it.kind() == REF_PAT).is_some()
22+
element.ancestors().find(|it| it.kind() == REF_PAT).is_some()
3123
}
3224

3325
pub(crate) fn goes_after_unsafe(element: SyntaxElement) -> bool {
34-
if let Some(token) = previous_non_triva_element(element).and_then(|it| it.into_token()) {
35-
if token.kind() == UNSAFE_KW {
36-
return true;
37-
}
38-
}
39-
false
26+
element
27+
.into_token()
28+
.and_then(|it| previous_non_trivia_token(it))
29+
.filter(|it| it.kind() == UNSAFE_KW)
30+
.is_some()
4031
}
4132

4233
pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool {
43-
not_same_range_parent(element).filter(|it| it.kind() == BLOCK_EXPR).is_some()
34+
not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some()
4435
}
4536

4637
pub(crate) fn has_item_list_parent(element: SyntaxElement) -> bool {
47-
not_same_range_parent(element).filter(|it| it.kind() == ITEM_LIST).is_some()
38+
not_same_range_ancestor(element).filter(|it| it.kind() == ITEM_LIST).is_some()
39+
}
40+
41+
pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool {
42+
previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == TRAIT_DEF).is_some()
43+
}
44+
45+
pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool {
46+
previous_sibling_or_ancestor_sibling(element).filter(|it| it.kind() == IMPL_DEF).is_some()
4847
}
4948

5049
pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
@@ -73,20 +72,30 @@ pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
7372
false
7473
}
7574

76-
fn not_same_range_parent(element: SyntaxElement) -> Option<SyntaxNode> {
77-
let node = match element {
78-
NodeOrToken::Node(node) => node,
79-
NodeOrToken::Token(token) => token.parent(),
80-
};
81-
let range = node.text_range();
82-
node.ancestors().take_while(|it| it.text_range() == range).last().and_then(|it| it.parent())
75+
fn not_same_range_ancestor(element: SyntaxElement) -> Option<SyntaxNode> {
76+
element
77+
.ancestors()
78+
.take_while(|it| it.text_range() == element.text_range())
79+
.last()
80+
.and_then(|it| it.parent())
8381
}
8482

85-
fn previous_non_triva_element(element: SyntaxElement) -> Option<SyntaxElement> {
86-
// trying to get first non triva sibling if we have one
83+
fn previous_non_trivia_token(token: SyntaxToken) -> Option<SyntaxToken> {
84+
let mut token = token.prev_token();
85+
while let Some(inner) = token.clone() {
86+
if !inner.kind().is_trivia() {
87+
return Some(inner);
88+
} else {
89+
token = inner.prev_token();
90+
}
91+
}
92+
None
93+
}
94+
95+
fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<SyntaxElement> {
8796
let token_sibling = non_trivia_sibling(element.clone(), Direction::Prev);
88-
let mut wrapped = if let Some(sibling) = token_sibling {
89-
sibling
97+
if let Some(sibling) = token_sibling {
98+
Some(sibling)
9099
} else {
91100
// if not trying to find first ancestor which has such a sibling
92101
let node = match element {
@@ -98,21 +107,6 @@ fn previous_non_triva_element(element: SyntaxElement) -> Option<SyntaxElement> {
98107
let prev_sibling_node = top_node.ancestors().find(|it| {
99108
non_trivia_sibling(NodeOrToken::Node(it.to_owned()), Direction::Prev).is_some()
100109
})?;
101-
non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)?
102-
};
103-
// TODO: Check if this can be simplified
104-
// Matklad: I think you can avoid this loop if you use SyntaxToken::prev_token -- unlike prev_sibling_or_token, it works across parents.
105-
// traversing the tree down to get the last token or node, i.e. the closest one
106-
loop {
107-
if let Some(token) = wrapped.as_token() {
108-
return Some(NodeOrToken::Token(token.clone()));
109-
} else {
110-
let new = wrapped.as_node().and_then(|n| n.last_child_or_token());
111-
if new.is_some() {
112-
wrapped = new.unwrap().clone();
113-
} else {
114-
return Some(wrapped);
115-
}
116-
}
110+
non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)
117111
}
118112
}

0 commit comments

Comments
 (0)