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;
}
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!(

View file

@ -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(

View file

@ -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<Syntax
mod tests {
use super::{
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,
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_match_arm, unsafe_is_prev,
};
use crate::completion::test_utils::check_pattern_is_applicable;
@ -203,4 +211,14 @@ mod tests {
fn test_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);
}
}