Add keywords completions on source file position

This commit is contained in:
Mikhail Rakhmanov 2020-06-13 10:43:39 +02:00
parent 16bbf4ab7f
commit 912f38200f
3 changed files with 124 additions and 21 deletions

View file

@ -66,48 +66,83 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
return; return;
} }
if ctx.unsafe_is_prev { 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( add_keyword(
ctx, ctx,
acc, acc,
"trait", "trait",
"trait $0 {}", "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( add_keyword(
ctx, ctx,
acc, acc,
"impl", "impl",
"impl $0 {}", "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; 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( add_keyword(
ctx, ctx,
acc, acc,
"use", "use",
"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( add_keyword(
ctx, ctx,
acc, acc,
"impl", "impl",
"impl $0 {}", "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( add_keyword(
ctx, ctx,
acc, acc,
"trait", "trait",
"trait $0 {}", "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, "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, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm);
add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); 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, acc,
"mod", "mod",
"mod $0 {}", "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, "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(
add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); 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( add_keyword(
ctx, ctx,
acc, acc,
"static", "static",
"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( add_keyword(
ctx, ctx,
acc, acc,
"extern", "extern",
"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( add_keyword(
ctx, ctx,
acc, acc,
"unsafe", "unsafe",
"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, "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, "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, "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, "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 { if !ctx.is_trivial_path {
return; 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] #[test]
fn test_keywords_in_function() { fn test_keywords_in_function() {
assert_debug_snapshot!( assert_debug_snapshot!(

View file

@ -13,8 +13,8 @@ use ra_text_edit::Indel;
use super::patterns::{ use super::patterns::{
has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, 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, has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
is_match_arm, unsafe_is_prev, 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 crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
use test_utils::mark; use test_utils::mark;
@ -76,6 +76,7 @@ pub(crate) struct CompletionContext<'a> {
pub(super) trait_as_prev_sibling: bool, pub(super) trait_as_prev_sibling: bool,
pub(super) impl_as_prev_sibling: bool, pub(super) impl_as_prev_sibling: bool,
pub(super) is_match_arm: bool, pub(super) is_match_arm: bool,
pub(super) has_item_list_or_source_file_parent: bool,
} }
impl<'a> CompletionContext<'a> { impl<'a> CompletionContext<'a> {
@ -145,6 +146,7 @@ impl<'a> CompletionContext<'a> {
impl_as_prev_sibling: false, impl_as_prev_sibling: false,
if_is_prev: false, if_is_prev: false,
is_match_arm: false, is_match_arm: false,
has_item_list_or_source_file_parent: false,
}; };
let mut original_file = original_file.syntax().clone(); 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.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.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());
self.is_match_arm = is_match_arm(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( fn fill(

View file

@ -38,6 +38,14 @@ pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool {
.is_some() .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 { pub(crate) fn is_match_arm(element: SyntaxElement) -> bool {
not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some() not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some()
&& previous_sibling_or_ancestor_sibling(element) && previous_sibling_or_ancestor_sibling(element)
@ -139,8 +147,8 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax
mod tests { mod tests {
use super::{ use super::{
has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, 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_match_arm, has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
unsafe_is_prev, has_trait_parent, if_is_prev, is_match_arm, unsafe_is_prev,
}; };
use crate::completion::test_utils::check_pattern_is_applicable; use crate::completion::test_utils::check_pattern_is_applicable;
@ -203,4 +211,14 @@ mod tests {
fn test_is_match_arm() { fn test_is_match_arm() {
check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm); check_pattern_is_applicable(r"fn my_fn() { match () { () => 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);
}
} }