Skip to content

Commit e42c448

Browse files
committed
More completion pattern tests
1 parent 47ad752 commit e42c448

File tree

2 files changed

+109
-86
lines changed

2 files changed

+109
-86
lines changed

crates/ide_completion/src/completions/keyword.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
3939
}
4040
}
4141

42-
trait Foo {}
43-
4442
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
4543
if ctx.token.kind() == SyntaxKind::COMMENT {
4644
cov_mark::hit!(no_keyword_completion_in_comments);

crates/ide_completion/src/patterns.rs

Lines changed: 109 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi
5252
let res = match_ast! {
5353
match prev_sibling {
5454
ast::ExprStmt(it) => {
55-
let node = it.expr()?.syntax().clone();
55+
let node = it.expr().filter(|_| it.semicolon_token().is_none())?.syntax().clone();
5656
match_ast! {
5757
match node {
5858
ast::IfExpr(_it) => ImmediatePrevSibling::IfExpr,
@@ -149,59 +149,6 @@ fn maximize_name_ref(name_like: &ast::NameLike) -> Option<SyntaxNode> {
149149
Some(node)
150150
}
151151

152-
#[cfg(test)]
153-
fn check_location(code: &str, loc: ImmediateLocation) {
154-
check_pattern_is_applicable(code, |e| {
155-
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
156-
assert_eq!(determine_location(name), Some(loc));
157-
true
158-
});
159-
}
160-
161-
#[test]
162-
fn test_has_trait_parent() {
163-
check_location(r"trait A { f$0 }", ImmediateLocation::Trait);
164-
}
165-
166-
#[test]
167-
fn test_has_use_parent() {
168-
check_location(r"use f$0", ImmediateLocation::Use);
169-
}
170-
171-
#[test]
172-
fn test_has_impl_parent() {
173-
check_location(r"impl A { f$0 }", ImmediateLocation::Impl);
174-
}
175-
#[test]
176-
fn test_has_field_list_parent() {
177-
check_location(r"struct Foo { f$0 }", ImmediateLocation::RecordField);
178-
check_location(r"struct Foo { f$0 pub f: i32}", ImmediateLocation::RecordField);
179-
}
180-
181-
#[test]
182-
fn test_has_block_expr_parent() {
183-
check_location(r"fn my_fn() { let a = 2; f$0 }", ImmediateLocation::BlockExpr);
184-
}
185-
186-
#[test]
187-
fn test_has_ident_pat_parent() {
188-
check_location(r"fn my_fn(m$0) {}", ImmediateLocation::IdentPat);
189-
check_location(r"fn my_fn() { let m$0 }", ImmediateLocation::IdentPat);
190-
check_location(r"fn my_fn(&m$0) {}", ImmediateLocation::IdentPat);
191-
check_location(r"fn my_fn() { let &m$0 }", ImmediateLocation::IdentPat);
192-
}
193-
194-
#[test]
195-
fn test_has_ref_expr_parent() {
196-
check_location(r"fn my_fn() { let x = &m$0 foo; }", ImmediateLocation::RefExpr);
197-
}
198-
199-
#[test]
200-
fn test_has_item_list_or_source_file_parent() {
201-
check_location(r"i$0", ImmediateLocation::ItemList);
202-
check_location(r"mod foo { f$0 }", ImmediateLocation::ItemList);
203-
}
204-
205152
pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
206153
// Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
207154
// where we only check the first parent with different text range.
@@ -251,36 +198,6 @@ fn test_for_is_prev2() {
251198
check_pattern_is_applicable(r"for i i$0", for_is_prev2);
252199
}
253200

254-
#[cfg(test)]
255-
fn check_prev_sibling(code: &str, sibling: impl Into<Option<ImmediatePrevSibling>>) {
256-
check_pattern_is_applicable(code, |e| {
257-
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
258-
assert_eq!(determine_prev_sibling(name), sibling.into());
259-
true
260-
});
261-
}
262-
263-
#[test]
264-
fn test_has_impl_as_prev_sibling() {
265-
check_prev_sibling(r"impl A w$0 ", ImmediatePrevSibling::ImplDefType);
266-
check_prev_sibling(r"impl A w$0 {}", ImmediatePrevSibling::ImplDefType);
267-
check_prev_sibling(r"impl A for A w$0 ", ImmediatePrevSibling::ImplDefType);
268-
check_prev_sibling(r"impl A for A w$0 {}", ImmediatePrevSibling::ImplDefType);
269-
check_prev_sibling(r"impl A for w$0 {}", None);
270-
check_prev_sibling(r"impl A for w$0", None);
271-
}
272-
273-
#[test]
274-
fn test_has_trait_as_prev_sibling() {
275-
check_prev_sibling(r"trait A w$0 ", ImmediatePrevSibling::TraitDefName);
276-
check_prev_sibling(r"trait A w$0 {}", ImmediatePrevSibling::TraitDefName);
277-
}
278-
279-
#[test]
280-
fn test_has_if_expr_as_prev_sibling() {
281-
check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr);
282-
}
283-
284201
pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
285202
element
286203
.ancestors()
@@ -329,3 +246,111 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax
329246
non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)
330247
}
331248
}
249+
250+
#[cfg(test)]
251+
mod tests {
252+
use super::*;
253+
254+
fn check_location(code: &str, loc: impl Into<Option<ImmediateLocation>>) {
255+
check_pattern_is_applicable(code, |e| {
256+
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
257+
assert_eq!(determine_location(name), loc.into());
258+
true
259+
});
260+
}
261+
262+
fn check_prev_sibling(code: &str, sibling: impl Into<Option<ImmediatePrevSibling>>) {
263+
check_pattern_is_applicable(code, |e| {
264+
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
265+
assert_eq!(determine_prev_sibling(name), sibling.into());
266+
true
267+
});
268+
}
269+
270+
#[test]
271+
fn test_trait_loc() {
272+
check_location(r"trait A { f$0 }", ImmediateLocation::Trait);
273+
check_location(r"trait A { #[attr] f$0 }", ImmediateLocation::Trait);
274+
check_location(r"trait A { f$0 fn f() {} }", ImmediateLocation::Trait);
275+
check_location(r"trait A { fn f() {} f$0 }", ImmediateLocation::Trait);
276+
check_location(r"trait A$0 {}", None);
277+
check_location(r"trait A { fn f$0 }", None);
278+
}
279+
280+
#[test]
281+
fn test_impl_loc() {
282+
check_location(r"impl A { f$0 }", ImmediateLocation::Impl);
283+
check_location(r"impl A { #[attr] f$0 }", ImmediateLocation::Impl);
284+
check_location(r"impl A { f$0 fn f() {} }", ImmediateLocation::Impl);
285+
check_location(r"impl A { fn f() {} f$0 }", ImmediateLocation::Impl);
286+
check_location(r"impl A$0 {}", None);
287+
check_location(r"impl A { fn f$0 }", None);
288+
}
289+
290+
#[test]
291+
fn test_use_loc() {
292+
check_location(r"use f$0", ImmediateLocation::Use);
293+
check_location(r"use f$0;", ImmediateLocation::Use);
294+
check_location(r"use f::{f$0}", None);
295+
check_location(r"use {f$0}", None);
296+
}
297+
298+
#[test]
299+
fn test_record_field_loc() {
300+
check_location(r"struct Foo { f$0 }", ImmediateLocation::RecordField);
301+
check_location(r"struct Foo { f$0 pub f: i32}", ImmediateLocation::RecordField);
302+
check_location(r"struct Foo { pub f: i32, f$0 }", ImmediateLocation::RecordField);
303+
}
304+
305+
#[test]
306+
fn test_block_expr_loc() {
307+
check_location(r"fn my_fn() { let a = 2; f$0 }", ImmediateLocation::BlockExpr);
308+
check_location(r"fn my_fn() { f$0 f }", ImmediateLocation::BlockExpr);
309+
}
310+
311+
#[test]
312+
fn test_ident_pat_loc() {
313+
check_location(r"fn my_fn(m$0) {}", ImmediateLocation::IdentPat);
314+
check_location(r"fn my_fn() { let m$0 }", ImmediateLocation::IdentPat);
315+
check_location(r"fn my_fn(&m$0) {}", ImmediateLocation::IdentPat);
316+
check_location(r"fn my_fn() { let &m$0 }", ImmediateLocation::IdentPat);
317+
}
318+
319+
#[test]
320+
fn test_ref_expr_loc() {
321+
check_location(r"fn my_fn() { let x = &m$0 foo; }", ImmediateLocation::RefExpr);
322+
}
323+
324+
#[test]
325+
fn test_item_list_loc() {
326+
check_location(r"i$0", ImmediateLocation::ItemList);
327+
check_location(r"#[attr] i$0", ImmediateLocation::ItemList);
328+
check_location(r"fn f() {} i$0", ImmediateLocation::ItemList);
329+
check_location(r"mod foo { f$0 }", ImmediateLocation::ItemList);
330+
check_location(r"mod foo { #[attr] f$0 }", ImmediateLocation::ItemList);
331+
check_location(r"mod foo { fn f() {} f$0 }", ImmediateLocation::ItemList);
332+
check_location(r"mod foo$0 {}", None);
333+
}
334+
335+
#[test]
336+
fn test_impl_prev_sibling() {
337+
check_prev_sibling(r"impl A w$0 ", ImmediatePrevSibling::ImplDefType);
338+
check_prev_sibling(r"impl A w$0 {}", ImmediatePrevSibling::ImplDefType);
339+
check_prev_sibling(r"impl A for A w$0 ", ImmediatePrevSibling::ImplDefType);
340+
check_prev_sibling(r"impl A for A w$0 {}", ImmediatePrevSibling::ImplDefType);
341+
check_prev_sibling(r"impl A for w$0 {}", None);
342+
check_prev_sibling(r"impl A for w$0", None);
343+
}
344+
345+
#[test]
346+
fn test_trait_prev_sibling() {
347+
check_prev_sibling(r"trait A w$0 ", ImmediatePrevSibling::TraitDefName);
348+
check_prev_sibling(r"trait A w$0 {}", ImmediatePrevSibling::TraitDefName);
349+
}
350+
351+
#[test]
352+
fn test_if_expr_prev_sibling() {
353+
check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr);
354+
check_prev_sibling(r"fn foo() { if true {}; w$0", None);
355+
}
356+
}

0 commit comments

Comments
 (0)