mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 01:17:27 +00:00
Allow hints after 'fn' keyword if it's an impl trait block
This commit is contained in:
parent
8f303daf45
commit
6f573bd84f
3 changed files with 37 additions and 4 deletions
|
@ -18,8 +18,9 @@ use crate::{
|
||||||
patterns::{
|
patterns::{
|
||||||
fn_is_prev, for_is_prev2, has_bind_pat_parent, has_block_expr_parent,
|
fn_is_prev, for_is_prev2, has_bind_pat_parent, has_block_expr_parent,
|
||||||
has_field_list_parent, has_impl_as_prev_sibling, has_impl_parent,
|
has_field_list_parent, has_impl_as_prev_sibling, has_impl_parent,
|
||||||
has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
|
has_impl_trait_parent, has_item_list_or_source_file_parent, has_ref_parent,
|
||||||
has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm, unsafe_is_prev,
|
has_trait_as_prev_sibling, has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm,
|
||||||
|
unsafe_is_prev,
|
||||||
},
|
},
|
||||||
CompletionConfig,
|
CompletionConfig,
|
||||||
},
|
},
|
||||||
|
@ -86,6 +87,7 @@ pub(crate) struct CompletionContext<'a> {
|
||||||
pub(super) in_loop_body: bool,
|
pub(super) in_loop_body: bool,
|
||||||
pub(super) has_trait_parent: bool,
|
pub(super) has_trait_parent: bool,
|
||||||
pub(super) has_impl_parent: bool,
|
pub(super) has_impl_parent: bool,
|
||||||
|
pub(super) has_impl_trait_parent: bool,
|
||||||
pub(super) has_field_list_parent: bool,
|
pub(super) has_field_list_parent: bool,
|
||||||
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,
|
||||||
|
@ -170,6 +172,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
block_expr_parent: false,
|
block_expr_parent: false,
|
||||||
has_trait_parent: false,
|
has_trait_parent: false,
|
||||||
has_impl_parent: false,
|
has_impl_parent: false,
|
||||||
|
has_impl_trait_parent: false,
|
||||||
has_field_list_parent: false,
|
has_field_list_parent: false,
|
||||||
trait_as_prev_sibling: false,
|
trait_as_prev_sibling: false,
|
||||||
impl_as_prev_sibling: false,
|
impl_as_prev_sibling: false,
|
||||||
|
@ -228,9 +231,10 @@ impl<'a> CompletionContext<'a> {
|
||||||
/// Checks whether completions in that particular case don't make much sense.
|
/// Checks whether completions in that particular case don't make much sense.
|
||||||
/// Examples:
|
/// Examples:
|
||||||
/// - `fn <|>` -- we expect function name, it's unlikely that "hint" will be helpful.
|
/// - `fn <|>` -- we expect function name, it's unlikely that "hint" will be helpful.
|
||||||
|
/// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names.
|
||||||
/// - `for _ i<|>` -- obviously, it'll be "in" keyword.
|
/// - `for _ i<|>` -- obviously, it'll be "in" keyword.
|
||||||
pub(crate) fn no_completion_required(&self) -> bool {
|
pub(crate) fn no_completion_required(&self) -> bool {
|
||||||
self.fn_is_prev || self.for_is_prev2
|
(self.fn_is_prev && !self.has_impl_trait_parent) || self.for_is_prev2
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The range of the identifier that is being completed.
|
/// The range of the identifier that is being completed.
|
||||||
|
@ -256,6 +260,7 @@ impl<'a> CompletionContext<'a> {
|
||||||
self.in_loop_body = is_in_loop_body(syntax_element.clone());
|
self.in_loop_body = is_in_loop_body(syntax_element.clone());
|
||||||
self.has_trait_parent = has_trait_parent(syntax_element.clone());
|
self.has_trait_parent = has_trait_parent(syntax_element.clone());
|
||||||
self.has_impl_parent = has_impl_parent(syntax_element.clone());
|
self.has_impl_parent = has_impl_parent(syntax_element.clone());
|
||||||
|
self.has_impl_trait_parent = has_impl_trait_parent(syntax_element.clone());
|
||||||
self.has_field_list_parent = has_field_list_parent(syntax_element.clone());
|
self.has_field_list_parent = has_field_list_parent(syntax_element.clone());
|
||||||
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());
|
||||||
|
|
|
@ -9,7 +9,7 @@ use syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::completion::test_utils::check_pattern_is_applicable;
|
use crate::completion::test_utils::{check_pattern_is_applicable, check_pattern_is_not_applicable};
|
||||||
|
|
||||||
pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
|
pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
|
||||||
not_same_range_ancestor(element)
|
not_same_range_ancestor(element)
|
||||||
|
@ -34,6 +34,22 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool {
|
||||||
fn test_has_impl_parent() {
|
fn test_has_impl_parent() {
|
||||||
check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent);
|
check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn has_impl_trait_parent(element: SyntaxElement) -> bool {
|
||||||
|
not_same_range_ancestor(element)
|
||||||
|
.filter(|it| it.kind() == ASSOC_ITEM_LIST)
|
||||||
|
.and_then(|it| it.parent())
|
||||||
|
.filter(|it| it.kind() == IMPL)
|
||||||
|
.map(|it| ast::Impl::cast(it).unwrap())
|
||||||
|
.map(|it| it.trait_().is_some())
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test_has_impl_trait_parent() {
|
||||||
|
check_pattern_is_applicable(r"impl Foo for Bar { f<|> }", has_impl_trait_parent);
|
||||||
|
check_pattern_is_not_applicable(r"impl A { f<|> }", has_impl_trait_parent);
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool {
|
pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool {
|
||||||
not_same_range_ancestor(element).filter(|it| it.kind() == RECORD_FIELD_LIST).is_some()
|
not_same_range_ancestor(element).filter(|it| it.kind() == RECORD_FIELD_LIST).is_some()
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,18 @@ pub(crate) fn check_pattern_is_applicable(code: &str, check: fn(SyntaxElement) -
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn check_pattern_is_not_applicable(code: &str, check: fn(SyntaxElement) -> bool) {
|
||||||
|
let (analysis, pos) = fixture::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();
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_all_completion_items(
|
pub(crate) fn get_all_completion_items(
|
||||||
config: CompletionConfig,
|
config: CompletionConfig,
|
||||||
code: &str,
|
code: &str,
|
||||||
|
|
Loading…
Reference in a new issue