From 912f38200fb6c8c6cea750a84c04de810992dec7 Mon Sep 17 00:00:00 2001 From: Mikhail Rakhmanov Date: Sat, 13 Jun 2020 10:43:39 +0200 Subject: Add keywords completions on source file position --- crates/ra_ide/src/completion/complete_keyword.rs | 115 ++++++++++++++++++--- crates/ra_ide/src/completion/completion_context.rs | 8 +- crates/ra_ide/src/completion/patterns.rs | 22 +++- 3 files changed, 124 insertions(+), 21 deletions(-) diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 025097e49..d016f0c7c 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs @@ -66,48 +66,83 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte return; } if ctx.unsafe_is_prev { - add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "fn", + "fn $0() {}", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); add_keyword( ctx, acc, "trait", "trait $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "impl", "impl $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); return; } - add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "fn", + "fn $0() {}", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); add_keyword( ctx, acc, "use", "use ", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "impl", "impl $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "trait", "trait $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "enum", + "enum $0 {}", + ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, + ); + add_keyword( + ctx, + acc, + "struct", + "struct $0 {}", + ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, + ); + add_keyword( + ctx, + acc, + "union", + "union $0 {}", + ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent, ); - add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); - add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); - add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !has_trait_or_impl_parent); add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm); add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm); add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); @@ -127,37 +162,58 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte acc, "mod", "mod $0 {}", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); - add_keyword(ctx, acc, "const", "const ", ctx.is_new_item || ctx.block_expr_parent); - add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); + add_keyword( + ctx, + acc, + "const", + "const ", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); + add_keyword( + ctx, + acc, + "type", + "type ", + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent, + ); add_keyword( ctx, acc, "static", "static ", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "extern", "extern ", - (ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent, + (ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent) + || ctx.block_expr_parent, ); add_keyword( ctx, acc, "unsafe", "unsafe ", - ctx.is_new_item || ctx.block_expr_parent || ctx.is_match_arm, + ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm, ); add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); - add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.has_trait_parent); + add_keyword( + ctx, + acc, + "pub", + "pub ", + ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent, + ); if !ctx.is_trivial_path { return; @@ -226,6 +282,31 @@ mod tests { ); } + #[test] + fn test_keywords_at_source_file_level() { + assert_debug_snapshot!( + get_keyword_completions(r"m<|>"), + @r###" + [ + "kw const", + "kw enum", + "kw extern", + "kw fn", + "kw impl", + "kw mod", + "kw pub", + "kw static", + "kw struct", + "kw trait", + "kw type", + "kw union", + "kw unsafe", + "kw use", + ] + "### + ); + } + #[test] fn test_keywords_in_function() { assert_debug_snapshot!( diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 2f96861ca..9f4c582d0 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -13,8 +13,8 @@ use ra_text_edit::Indel; use super::patterns::{ has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, - has_ref_parent, has_trait_as_prev_sibling, has_trait_parent, if_is_prev, is_in_loop_body, - is_match_arm, unsafe_is_prev, + has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling, + has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm, unsafe_is_prev, }; use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; use test_utils::mark; @@ -76,6 +76,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) trait_as_prev_sibling: bool, pub(super) impl_as_prev_sibling: bool, pub(super) is_match_arm: bool, + pub(super) has_item_list_or_source_file_parent: bool, } impl<'a> CompletionContext<'a> { @@ -145,6 +146,7 @@ impl<'a> CompletionContext<'a> { impl_as_prev_sibling: false, if_is_prev: false, is_match_arm: false, + has_item_list_or_source_file_parent: false, }; let mut original_file = original_file.syntax().clone(); @@ -229,6 +231,8 @@ impl<'a> CompletionContext<'a> { self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone()); self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone()); self.is_match_arm = is_match_arm(syntax_element.clone()); + self.has_item_list_or_source_file_parent = + has_item_list_or_source_file_parent(syntax_element.clone()); } fn fill( diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs index 464032cb4..fdcd3faa5 100644 --- a/crates/ra_ide/src/completion/patterns.rs +++ b/crates/ra_ide/src/completion/patterns.rs @@ -38,6 +38,14 @@ pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { .is_some() } +pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { + let ancestor = not_same_range_ancestor(element); + if !ancestor.is_some() { + return true; + } + ancestor.filter(|it| it.kind() == SOURCE_FILE || it.kind() == ITEM_LIST).is_some() +} + pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some() && previous_sibling_or_ancestor_sibling(element) @@ -139,8 +147,8 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option m<|> } }", is_match_arm); } + + #[test] + fn test_has_source_file_parent() { + check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); + } + + #[test] + fn test_has_item_list_parent() { + check_pattern_is_applicable(r"impl { f<|> }", has_item_list_or_source_file_parent); + } } -- cgit v1.2.3