mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Add keywords completions on source file position
This commit is contained in:
parent
16bbf4ab7f
commit
912f38200f
3 changed files with 124 additions and 21 deletions
|
@ -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!(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue