mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
More completion pattern tests
This commit is contained in:
parent
47ad752e6c
commit
e42c448077
2 changed files with 109 additions and 86 deletions
|
@ -39,8 +39,6 @@ pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Foo {}
|
|
||||||
|
|
||||||
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
|
||||||
if ctx.token.kind() == SyntaxKind::COMMENT {
|
if ctx.token.kind() == SyntaxKind::COMMENT {
|
||||||
cov_mark::hit!(no_keyword_completion_in_comments);
|
cov_mark::hit!(no_keyword_completion_in_comments);
|
||||||
|
|
|
@ -52,7 +52,7 @@ pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option<Immedi
|
||||||
let res = match_ast! {
|
let res = match_ast! {
|
||||||
match prev_sibling {
|
match prev_sibling {
|
||||||
ast::ExprStmt(it) => {
|
ast::ExprStmt(it) => {
|
||||||
let node = it.expr()?.syntax().clone();
|
let node = it.expr().filter(|_| it.semicolon_token().is_none())?.syntax().clone();
|
||||||
match_ast! {
|
match_ast! {
|
||||||
match node {
|
match node {
|
||||||
ast::IfExpr(_it) => ImmediatePrevSibling::IfExpr,
|
ast::IfExpr(_it) => ImmediatePrevSibling::IfExpr,
|
||||||
|
@ -149,59 +149,6 @@ fn maximize_name_ref(name_like: &ast::NameLike) -> Option<SyntaxNode> {
|
||||||
Some(node)
|
Some(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn check_location(code: &str, loc: ImmediateLocation) {
|
|
||||||
check_pattern_is_applicable(code, |e| {
|
|
||||||
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
|
|
||||||
assert_eq!(determine_location(name), Some(loc));
|
|
||||||
true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_trait_parent() {
|
|
||||||
check_location(r"trait A { f$0 }", ImmediateLocation::Trait);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_use_parent() {
|
|
||||||
check_location(r"use f$0", ImmediateLocation::Use);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_impl_parent() {
|
|
||||||
check_location(r"impl A { f$0 }", ImmediateLocation::Impl);
|
|
||||||
}
|
|
||||||
#[test]
|
|
||||||
fn test_has_field_list_parent() {
|
|
||||||
check_location(r"struct Foo { f$0 }", ImmediateLocation::RecordField);
|
|
||||||
check_location(r"struct Foo { f$0 pub f: i32}", ImmediateLocation::RecordField);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_block_expr_parent() {
|
|
||||||
check_location(r"fn my_fn() { let a = 2; f$0 }", ImmediateLocation::BlockExpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_ident_pat_parent() {
|
|
||||||
check_location(r"fn my_fn(m$0) {}", ImmediateLocation::IdentPat);
|
|
||||||
check_location(r"fn my_fn() { let m$0 }", ImmediateLocation::IdentPat);
|
|
||||||
check_location(r"fn my_fn(&m$0) {}", ImmediateLocation::IdentPat);
|
|
||||||
check_location(r"fn my_fn() { let &m$0 }", ImmediateLocation::IdentPat);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_ref_expr_parent() {
|
|
||||||
check_location(r"fn my_fn() { let x = &m$0 foo; }", ImmediateLocation::RefExpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_item_list_or_source_file_parent() {
|
|
||||||
check_location(r"i$0", ImmediateLocation::ItemList);
|
|
||||||
check_location(r"mod foo { f$0 }", ImmediateLocation::ItemList);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
|
pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
|
||||||
// Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
|
// Here we search `impl` keyword up through the all ancestors, unlike in `has_impl_parent`,
|
||||||
// where we only check the first parent with different text range.
|
// where we only check the first parent with different text range.
|
||||||
|
@ -251,36 +198,6 @@ fn test_for_is_prev2() {
|
||||||
check_pattern_is_applicable(r"for i i$0", for_is_prev2);
|
check_pattern_is_applicable(r"for i i$0", for_is_prev2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
fn check_prev_sibling(code: &str, sibling: impl Into<Option<ImmediatePrevSibling>>) {
|
|
||||||
check_pattern_is_applicable(code, |e| {
|
|
||||||
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
|
|
||||||
assert_eq!(determine_prev_sibling(name), sibling.into());
|
|
||||||
true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_impl_as_prev_sibling() {
|
|
||||||
check_prev_sibling(r"impl A w$0 ", ImmediatePrevSibling::ImplDefType);
|
|
||||||
check_prev_sibling(r"impl A w$0 {}", ImmediatePrevSibling::ImplDefType);
|
|
||||||
check_prev_sibling(r"impl A for A w$0 ", ImmediatePrevSibling::ImplDefType);
|
|
||||||
check_prev_sibling(r"impl A for A w$0 {}", ImmediatePrevSibling::ImplDefType);
|
|
||||||
check_prev_sibling(r"impl A for w$0 {}", None);
|
|
||||||
check_prev_sibling(r"impl A for w$0", None);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_trait_as_prev_sibling() {
|
|
||||||
check_prev_sibling(r"trait A w$0 ", ImmediatePrevSibling::TraitDefName);
|
|
||||||
check_prev_sibling(r"trait A w$0 {}", ImmediatePrevSibling::TraitDefName);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_has_if_expr_as_prev_sibling() {
|
|
||||||
check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
|
pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
|
||||||
element
|
element
|
||||||
.ancestors()
|
.ancestors()
|
||||||
|
@ -329,3 +246,111 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax
|
||||||
non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)
|
non_trivia_sibling(NodeOrToken::Node(prev_sibling_node), Direction::Prev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn check_location(code: &str, loc: impl Into<Option<ImmediateLocation>>) {
|
||||||
|
check_pattern_is_applicable(code, |e| {
|
||||||
|
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
|
||||||
|
assert_eq!(determine_location(name), loc.into());
|
||||||
|
true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_prev_sibling(code: &str, sibling: impl Into<Option<ImmediatePrevSibling>>) {
|
||||||
|
check_pattern_is_applicable(code, |e| {
|
||||||
|
let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike");
|
||||||
|
assert_eq!(determine_prev_sibling(name), sibling.into());
|
||||||
|
true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_trait_loc() {
|
||||||
|
check_location(r"trait A { f$0 }", ImmediateLocation::Trait);
|
||||||
|
check_location(r"trait A { #[attr] f$0 }", ImmediateLocation::Trait);
|
||||||
|
check_location(r"trait A { f$0 fn f() {} }", ImmediateLocation::Trait);
|
||||||
|
check_location(r"trait A { fn f() {} f$0 }", ImmediateLocation::Trait);
|
||||||
|
check_location(r"trait A$0 {}", None);
|
||||||
|
check_location(r"trait A { fn f$0 }", None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_impl_loc() {
|
||||||
|
check_location(r"impl A { f$0 }", ImmediateLocation::Impl);
|
||||||
|
check_location(r"impl A { #[attr] f$0 }", ImmediateLocation::Impl);
|
||||||
|
check_location(r"impl A { f$0 fn f() {} }", ImmediateLocation::Impl);
|
||||||
|
check_location(r"impl A { fn f() {} f$0 }", ImmediateLocation::Impl);
|
||||||
|
check_location(r"impl A$0 {}", None);
|
||||||
|
check_location(r"impl A { fn f$0 }", None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_use_loc() {
|
||||||
|
check_location(r"use f$0", ImmediateLocation::Use);
|
||||||
|
check_location(r"use f$0;", ImmediateLocation::Use);
|
||||||
|
check_location(r"use f::{f$0}", None);
|
||||||
|
check_location(r"use {f$0}", None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_record_field_loc() {
|
||||||
|
check_location(r"struct Foo { f$0 }", ImmediateLocation::RecordField);
|
||||||
|
check_location(r"struct Foo { f$0 pub f: i32}", ImmediateLocation::RecordField);
|
||||||
|
check_location(r"struct Foo { pub f: i32, f$0 }", ImmediateLocation::RecordField);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_block_expr_loc() {
|
||||||
|
check_location(r"fn my_fn() { let a = 2; f$0 }", ImmediateLocation::BlockExpr);
|
||||||
|
check_location(r"fn my_fn() { f$0 f }", ImmediateLocation::BlockExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ident_pat_loc() {
|
||||||
|
check_location(r"fn my_fn(m$0) {}", ImmediateLocation::IdentPat);
|
||||||
|
check_location(r"fn my_fn() { let m$0 }", ImmediateLocation::IdentPat);
|
||||||
|
check_location(r"fn my_fn(&m$0) {}", ImmediateLocation::IdentPat);
|
||||||
|
check_location(r"fn my_fn() { let &m$0 }", ImmediateLocation::IdentPat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ref_expr_loc() {
|
||||||
|
check_location(r"fn my_fn() { let x = &m$0 foo; }", ImmediateLocation::RefExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_item_list_loc() {
|
||||||
|
check_location(r"i$0", ImmediateLocation::ItemList);
|
||||||
|
check_location(r"#[attr] i$0", ImmediateLocation::ItemList);
|
||||||
|
check_location(r"fn f() {} i$0", ImmediateLocation::ItemList);
|
||||||
|
check_location(r"mod foo { f$0 }", ImmediateLocation::ItemList);
|
||||||
|
check_location(r"mod foo { #[attr] f$0 }", ImmediateLocation::ItemList);
|
||||||
|
check_location(r"mod foo { fn f() {} f$0 }", ImmediateLocation::ItemList);
|
||||||
|
check_location(r"mod foo$0 {}", None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_impl_prev_sibling() {
|
||||||
|
check_prev_sibling(r"impl A w$0 ", ImmediatePrevSibling::ImplDefType);
|
||||||
|
check_prev_sibling(r"impl A w$0 {}", ImmediatePrevSibling::ImplDefType);
|
||||||
|
check_prev_sibling(r"impl A for A w$0 ", ImmediatePrevSibling::ImplDefType);
|
||||||
|
check_prev_sibling(r"impl A for A w$0 {}", ImmediatePrevSibling::ImplDefType);
|
||||||
|
check_prev_sibling(r"impl A for w$0 {}", None);
|
||||||
|
check_prev_sibling(r"impl A for w$0", None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_trait_prev_sibling() {
|
||||||
|
check_prev_sibling(r"trait A w$0 ", ImmediatePrevSibling::TraitDefName);
|
||||||
|
check_prev_sibling(r"trait A w$0 {}", ImmediatePrevSibling::TraitDefName);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_if_expr_prev_sibling() {
|
||||||
|
check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr);
|
||||||
|
check_prev_sibling(r"fn foo() { if true {}; w$0", None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue