mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Merge #9651
9651: Restrict completions inside visibility modifiers r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
33972da625
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 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() {
|
||||
add_keyword("where", "where ");
|
||||
add_keyword("where", "where");
|
||||
if ctx.has_impl_prev_sibling() {
|
||||
add_keyword("for", "for ");
|
||||
add_keyword("for", "for");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -62,12 +68,12 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
|
|||
if !ctx.has_visibility_prev_sibling()
|
||||
&& (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
|
||||
{
|
||||
add_keyword("pub(crate)", "pub(crate) ");
|
||||
add_keyword("pub", "pub ");
|
||||
add_keyword("pub(crate)", "pub(crate)");
|
||||
add_keyword("pub", "pub");
|
||||
}
|
||||
|
||||
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("const", "const $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 {
|
||||
add_keyword("let", "let ");
|
||||
add_keyword("let", "let");
|
||||
}
|
||||
|
||||
if ctx.after_if() {
|
||||
|
|
|
@ -24,6 +24,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
|
|||
return;
|
||||
}
|
||||
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() {
|
||||
// only show macros in {Assoc}ItemList
|
||||
|
|
|
@ -41,6 +41,7 @@ pub(crate) enum ImmediateLocation {
|
|||
Attribute(ast::Attr),
|
||||
// Fake file ast node
|
||||
ModDeclaration(ast::Module),
|
||||
Visibility(ast::Visibility),
|
||||
// Original file ast node
|
||||
MethodCall {
|
||||
receiver: Option<ast::Expr>,
|
||||
|
@ -246,6 +247,8 @@ pub(crate) fn determine_location(
|
|||
.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())
|
||||
},
|
||||
ast::Visibility(it) => it.pub_token()
|
||||
.and_then(|t| (t.text_range().end() < offset).then(|| ImmediateLocation::Visibility(it)))?,
|
||||
_ => return None,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,10 +9,10 @@ mod item_list;
|
|||
mod item;
|
||||
mod pattern;
|
||||
mod predicate;
|
||||
mod sourcegen;
|
||||
mod type_pos;
|
||||
mod use_tree;
|
||||
|
||||
mod sourcegen;
|
||||
mod visibility;
|
||||
|
||||
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
|
||||
// struct B(pub (super::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();
|
||||
let path_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>) {
|
||||
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() {
|
||||
Some(it) => it,
|
||||
None => return,
|
||||
|
|
Loading…
Reference in a new issue