mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 14:03:35 +00:00
Restrict completions inside visibility modifiers
This commit is contained in:
parent
ea105f9396
commit
f6cb42fdb8
7 changed files with 53 additions and 9 deletions
|
@ -39,10 +39,16 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||||
let has_block_expr_parent = ctx.has_block_expr_parent();
|
let has_block_expr_parent = ctx.has_block_expr_parent();
|
||||||
let expects_item = ctx.expects_item();
|
let expects_item = ctx.expects_item();
|
||||||
|
|
||||||
|
if let Some(ImmediateLocation::Visibility(vis)) = &ctx.completion_location {
|
||||||
|
if vis.in_token().is_none() {
|
||||||
|
add_keyword("in", "in");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ctx.has_impl_or_trait_prev_sibling() {
|
if ctx.has_impl_or_trait_prev_sibling() {
|
||||||
add_keyword("where", "where ");
|
add_keyword("where", "where");
|
||||||
if ctx.has_impl_prev_sibling() {
|
if ctx.has_impl_prev_sibling() {
|
||||||
add_keyword("for", "for ");
|
add_keyword("for", "for");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -62,12 +68,12 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||||
if !ctx.has_visibility_prev_sibling()
|
if !ctx.has_visibility_prev_sibling()
|
||||||
&& (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
|
&& (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
|
||||||
{
|
{
|
||||||
add_keyword("pub(crate)", "pub(crate) ");
|
add_keyword("pub(crate)", "pub(crate)");
|
||||||
add_keyword("pub", "pub ");
|
add_keyword("pub", "pub");
|
||||||
}
|
}
|
||||||
|
|
||||||
if expects_item || expects_assoc_item || has_block_expr_parent {
|
if expects_item || expects_assoc_item || has_block_expr_parent {
|
||||||
add_keyword("unsafe", "unsafe ");
|
add_keyword("unsafe", "unsafe");
|
||||||
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
add_keyword("fn", "fn $1($2) {\n $0\n}");
|
||||||
add_keyword("const", "const $0");
|
add_keyword("const", "const $0");
|
||||||
add_keyword("type", "type $0");
|
add_keyword("type", "type $0");
|
||||||
|
@ -110,7 +116,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
|
if ctx.previous_token_is(T![if]) || ctx.previous_token_is(T![while]) || has_block_expr_parent {
|
||||||
add_keyword("let", "let ");
|
add_keyword("let", "let");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.after_if() {
|
if ctx.after_if() {
|
||||||
|
|
|
@ -24,6 +24,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
|
std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
|
||||||
|
if let Some(ImmediateLocation::Visibility(_)) = ctx.completion_location {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ctx.expects_item() || ctx.expects_assoc_item() {
|
if ctx.expects_item() || ctx.expects_assoc_item() {
|
||||||
// only show macros in {Assoc}ItemList
|
// only show macros in {Assoc}ItemList
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub(crate) enum ImmediateLocation {
|
||||||
Attribute(ast::Attr),
|
Attribute(ast::Attr),
|
||||||
// Fake file ast node
|
// Fake file ast node
|
||||||
ModDeclaration(ast::Module),
|
ModDeclaration(ast::Module),
|
||||||
|
Visibility(ast::Visibility),
|
||||||
// Original file ast node
|
// Original file ast node
|
||||||
MethodCall {
|
MethodCall {
|
||||||
receiver: Option<ast::Expr>,
|
receiver: Option<ast::Expr>,
|
||||||
|
@ -246,6 +247,8 @@ pub(crate) fn determine_location(
|
||||||
.and_then(|r| find_node_with_range(original_file, r)),
|
.and_then(|r| find_node_with_range(original_file, r)),
|
||||||
has_parens: it.arg_list().map_or(false, |it| it.l_paren_token().is_some())
|
has_parens: it.arg_list().map_or(false, |it| it.l_paren_token().is_some())
|
||||||
},
|
},
|
||||||
|
ast::Visibility(it) => it.pub_token()
|
||||||
|
.and_then(|t| (t.text_range().end() < offset).then(|| ImmediateLocation::Visibility(it)))?,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,10 +9,10 @@ mod item_list;
|
||||||
mod item;
|
mod item;
|
||||||
mod pattern;
|
mod pattern;
|
||||||
mod predicate;
|
mod predicate;
|
||||||
|
mod sourcegen;
|
||||||
mod type_pos;
|
mod type_pos;
|
||||||
mod use_tree;
|
mod use_tree;
|
||||||
|
mod visibility;
|
||||||
mod sourcegen;
|
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
|
24
crates/ide_completion/src/tests/visibility.rs
Normal file
24
crates/ide_completion/src/tests/visibility.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//! Completion tests for visibility modifiers.
|
||||||
|
use expect_test::{expect, Expect};
|
||||||
|
|
||||||
|
use crate::tests::completion_list;
|
||||||
|
|
||||||
|
fn check(ra_fixture: &str, expect: Expect) {
|
||||||
|
let actual = completion_list(ra_fixture);
|
||||||
|
expect.assert_eq(&actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_pub() {
|
||||||
|
check(
|
||||||
|
r#"
|
||||||
|
pub($0)
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
kw in
|
||||||
|
kw self
|
||||||
|
kw super
|
||||||
|
kw crate
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
|
@ -162,7 +162,7 @@ fn opt_visibility(p: &mut Parser) -> bool {
|
||||||
// test pub_parens_typepath
|
// test pub_parens_typepath
|
||||||
// struct B(pub (super::A));
|
// struct B(pub (super::A));
|
||||||
// struct B(pub (crate::A,));
|
// struct B(pub (crate::A,));
|
||||||
T![crate] | T![self] | T![super] if p.nth(2) != T![:] => {
|
T![crate] | T![self] | T![super] | T![ident] if p.nth(2) != T![:] => {
|
||||||
p.bump_any();
|
p.bump_any();
|
||||||
let path_m = p.start();
|
let path_m = p.start();
|
||||||
let path_segment_m = p.start();
|
let path_segment_m = p.start();
|
||||||
|
|
|
@ -211,6 +211,14 @@ fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<Syntax
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) {
|
fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) {
|
||||||
|
if vis.in_token().is_none() {
|
||||||
|
if vis.path().and_then(|p| p.as_single_name_ref()).and_then(|n| n.ident_token()).is_some() {
|
||||||
|
errors.push(SyntaxError::new(
|
||||||
|
"incorrect visibility restriction",
|
||||||
|
vis.syntax.text_range(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
let parent = match vis.syntax().parent() {
|
let parent = match vis.syntax().parent() {
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
None => return,
|
None => return,
|
||||||
|
|
Loading…
Reference in a new issue