From a2b4385f161134955fd729087f142d54c3a5e035 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Fri, 12 Jun 2020 00:17:30 +0200 Subject: Add few smoke tests for patterns and refactoring --- crates/ra_ide/src/completion/complete_keyword.rs | 8 +- crates/ra_ide/src/completion/completion_context.rs | 13 ++-- crates/ra_ide/src/completion/patterns.rs | 86 +++++++++++++++++++++- crates/ra_ide/src/completion/test_utils.rs | 14 ++++ 4 files changed, 111 insertions(+), 10 deletions(-) diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 50f003949..675991154 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -65,13 +65,13 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte add_keyword(ctx, acc, "use", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); add_keyword(ctx, acc, "impl", "impl $0 {}", ctx.is_new_item); add_keyword(ctx, acc, "trait", "impl $0 {}", ctx.is_new_item); - add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.after_unsafe); - add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.after_unsafe); - add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.after_unsafe); + add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); + add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); + add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !ctx.unsafe_is_prev); add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent); add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent); add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); - add_keyword(ctx, acc, "let", "let ", ctx.after_if || ctx.block_expr_parent); + add_keyword(ctx, acc, "let", "let ", ctx.if_is_prev || ctx.block_expr_parent); add_keyword(ctx, acc, "else", "else {$0}", ctx.after_if); add_keyword(ctx, acc, "else if", "else if $0 {}", ctx.after_if); add_keyword(ctx, acc, "mod", "mod $0 {}", ctx.is_new_item || ctx.block_expr_parent); diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index e579e2ee2..41aec5686 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -12,8 +12,8 @@ use ra_syntax::{ use ra_text_edit::Indel; use super::patterns::{ - goes_after_unsafe, has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, - has_ref_pat_parent, has_trait_as_prev_sibling, inside_trait, is_in_loop_body, + has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_ref_pat_parent, + has_trait_as_prev_sibling, if_is_prev, inside_trait, is_in_loop_body, unsafe_is_prev, }; use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; use test_utils::mark; @@ -64,7 +64,8 @@ pub(crate) struct CompletionContext<'a> { pub(super) is_path_type: bool, pub(super) has_type_args: bool, pub(super) attribute_under_caret: Option, - pub(super) after_unsafe: bool, + pub(super) unsafe_is_prev: bool, + pub(super) if_is_prev: bool, pub(super) block_expr_parent: bool, pub(super) bind_pat_parent: bool, pub(super) ref_pat_parent: bool, @@ -130,7 +131,7 @@ impl<'a> CompletionContext<'a> { has_type_args: false, dot_receiver_is_ambiguous_float_literal: false, attribute_under_caret: None, - after_unsafe: false, + unsafe_is_prev: false, in_loop_body: false, ref_pat_parent: false, bind_pat_parent: false, @@ -138,6 +139,7 @@ impl<'a> CompletionContext<'a> { inside_trait: false, trait_as_prev_sibling: false, impl_as_prev_sibling: false, + if_is_prev: false, }; let mut original_file = original_file.syntax().clone(); @@ -212,7 +214,8 @@ impl<'a> CompletionContext<'a> { let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased().unwrap(); let syntax_element = NodeOrToken::Token(fake_ident_token.clone()); self.block_expr_parent = has_block_expr_parent(syntax_element.clone()); - self.after_unsafe = goes_after_unsafe(syntax_element.clone()); + self.unsafe_is_prev = unsafe_is_prev(syntax_element.clone()); + self.if_is_prev = if_is_prev(syntax_element.clone()); self.bind_pat_parent = has_bind_pat_parent(syntax_element.clone()); self.ref_pat_parent = has_ref_pat_parent(syntax_element.clone()); self.in_loop_body = is_in_loop_body(syntax_element.clone()); diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs index 31d32ccd9..df2594152 100644 --- a/crates/ra_ide/src/completion/patterns.rs +++ b/crates/ra_ide/src/completion/patterns.rs @@ -22,7 +22,7 @@ pub(crate) fn has_ref_pat_parent(element: SyntaxElement) -> bool { element.ancestors().find(|it| it.kind() == REF_PAT).is_some() } -pub(crate) fn goes_after_unsafe(element: SyntaxElement) -> bool { +pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { element .into_token() .and_then(|it| previous_non_trivia_token(it)) @@ -30,6 +30,14 @@ pub(crate) fn goes_after_unsafe(element: SyntaxElement) -> bool { .is_some() } +pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { + element + .into_token() + .and_then(|it| previous_non_trivia_token(it)) + .filter(|it| it.kind() == IF_KW) + .is_some() +} + pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { not_same_range_ancestor(element).filter(|it| it.kind() == BLOCK_EXPR).is_some() } @@ -110,3 +118,79 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option + ", + unsafe_is_prev, + ); + } + + #[test] + fn test_if_is_prev() { + check_pattern_is_applicable( + r" + if l<|> + ", + if_is_prev, + ); + } + + #[test] + fn test_inside_trait() { + check_pattern_is_applicable( + r" + trait A { + fn<|> + } + ", + inside_trait, + ); + } + + #[test] + fn test_has_trait_as_prev_sibling() { + check_pattern_is_applicable( + r" + trait A w<|> { + } + ", + has_trait_as_prev_sibling, + ); + } + + #[test] + fn test_has_impl_as_prev_sibling() { + check_pattern_is_applicable( + r" + impl A w<|> { + } + ", + has_impl_as_prev_sibling, + ); + } + + #[test] + fn test_parent_block_expr() { + check_pattern_is_applicable( + r" + fn my_fn() { + let a = 2; + f<|> + } + ", + has_block_expr_parent, + ); + } +} diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs index bf22452a2..e9e89104e 100644 --- a/crates/ra_ide/src/completion/test_utils.rs +++ b/crates/ra_ide/src/completion/test_utils.rs @@ -5,6 +5,8 @@ use crate::{ mock_analysis::{analysis_and_position, single_file_with_position}, CompletionItem, }; +use hir::Semantics; +use ra_syntax::{AstNode, NodeOrToken, SyntaxElement, SyntaxToken}; pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec { do_completion_with_options(code, kind, &CompletionConfig::default()) @@ -27,3 +29,15 @@ pub(crate) fn do_completion_with_options( kind_completions.sort_by_key(|c| c.label().to_owned()); kind_completions } + +pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -> bool) { + let (analysis, pos) = single_file_with_position(code); + analysis + .with_db(|db| { + let sema = Semantics::new(db); + let original_file = sema.parse(pos.file_id); + let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap(); + assert!(check(NodeOrToken::Token(token))); + }) + .unwrap(); +} -- cgit v1.2.3