Skip to content

Commit

Permalink
Merge #10956 #10986
Browse files Browse the repository at this point in the history
10956: minor: Bump deps r=Veykril a=lnicola

bors r+

10986: fix: Fix lint completions not working for unclosed attributes r=Veykril a=Veykril

Fixes #10682
Uses keywords and nested `TokenTree`s as a heuristic to figure out when to stop parsing in case the attribute is unclosed which should work pretty well as attributes are usually followed by either of those.
bors r+

Co-authored-by: Laurențiu Nicola <lnicola@dend.ro>
Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
  • Loading branch information
3 people committed Dec 11, 2021
3 parents 9946def + 9a624ab + 0001a42 commit 48cd733
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 36 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/ide_assists/src/handlers/extract_function.rs
Expand Up @@ -480,7 +480,7 @@ impl FunctionBody {
.statements()
.map(|stmt| stmt.syntax().text_range())
.filter(|&stmt| selected.intersect(stmt).filter(|it| !it.is_empty()).is_some())
.fold1(|acc, stmt| acc.cover(stmt));
.reduce(|acc, stmt| acc.cover(stmt));
if let Some(tail_range) = parent
.tail_expr()
.map(|it| it.syntax().text_range())
Expand Down
3 changes: 1 addition & 2 deletions crates/ide_assists/src/handlers/unmerge_use.rs
@@ -1,4 +1,3 @@
use itertools::Itertools;
use syntax::{
ast::{self, make, HasVisibility},
ted::{self, Position},
Expand Down Expand Up @@ -70,7 +69,7 @@ fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
.filter_map(ast::UseTree::cast)
.filter_map(|t| t.path());

let final_path = paths.fold1(|prev, next| make::path_concat(next, prev))?;
let final_path = paths.reduce(|prev, next| make::path_concat(next, prev))?;
if final_path.segment().map_or(false, |it| it.self_token().is_some()) {
final_path.qualifier()
} else {
Expand Down
18 changes: 7 additions & 11 deletions crates/ide_completion/src/completions/attribute.rs
Expand Up @@ -30,16 +30,12 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
None => None,
};
match (name_ref, attribute.token_tree()) {
(Some(path), Some(token_tree)) => match path.text().as_str() {
"repr" => repr::complete_repr(acc, ctx, token_tree),
"derive" => {
derive::complete_derive(acc, ctx, &parse_tt_as_comma_sep_paths(token_tree)?)
}
"feature" => {
lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(token_tree)?, FEATURES)
}
(Some(path), Some(tt)) if tt.l_paren_token().is_some() => match path.text().as_str() {
"repr" => repr::complete_repr(acc, ctx, tt),
"derive" => derive::complete_derive(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?),
"feature" => lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?, FEATURES),
"allow" | "warn" | "deny" | "forbid" => {
let existing_lints = parse_tt_as_comma_sep_paths(token_tree)?;
let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
lint::complete_lint(acc, ctx, &existing_lints, DEFAULT_LINTS);
lint::complete_lint(acc, ctx, &existing_lints, CLIPPY_LINTS);
lint::complete_lint(acc, ctx, &existing_lints, RUSTDOC_LINTS);
Expand All @@ -49,8 +45,8 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
}
_ => (),
},
(None, Some(_)) => (),
_ => complete_new_attribute(acc, ctx, attribute),
(_, Some(_)) => (),
(_, None) => complete_new_attribute(acc, ctx, attribute),
}
Some(())
}
Expand Down
14 changes: 14 additions & 0 deletions crates/ide_completion/src/tests/attribute.rs
Expand Up @@ -831,6 +831,20 @@ mod lint {
r#"#[allow(rustdoc::bare_urls)] struct Test;"#,
);
}

#[test]
fn lint_unclosed() {
check_edit(
"deprecated",
r#"#[allow(dep$0 struct Test;"#,
r#"#[allow(deprecated struct Test;"#,
);
check_edit(
"bare_urls",
r#"#[allow(rustdoc::$0 struct Test;"#,
r#"#[allow(rustdoc::bare_urls struct Test;"#,
);
}
}

mod repr {
Expand Down
32 changes: 18 additions & 14 deletions crates/ide_db/src/helpers.rs
Expand Up @@ -305,20 +305,24 @@ pub fn lint_eq_or_in_group(lint: &str, lint_is: &str) -> bool {
}
}

/// Parses the input token tree as comma separated paths.
/// Parses the input token tree as comma separated plain paths.
pub fn parse_tt_as_comma_sep_paths(input: ast::TokenTree) -> Option<Vec<ast::Path>> {
let r_paren = input.r_paren_token()?;
let tokens = input
.syntax()
.children_with_tokens()
.skip(1)
.take_while(|it| it.as_token() != Some(&r_paren));
let r_paren = input.r_paren_token();
let tokens =
input.syntax().children_with_tokens().skip(1).map_while(|it| match it.into_token() {
// seeing a keyword means the attribute is unclosed so stop parsing here
Some(tok) if tok.kind().is_keyword() => None,
// don't include the right token tree parenthesis if it exists
tok @ Some(_) if tok == r_paren => None,
// only nodes that we can find are other TokenTrees, those are unexpected in this parse though
None => None,
Some(tok) => Some(tok),
});
let input_expressions = tokens.into_iter().group_by(|tok| tok.kind() == T![,]);
Some(
input_expressions
.into_iter()
.filter_map(|(is_sep, group)| (!is_sep).then(|| group))
.filter_map(|mut tokens| ast::Path::parse(&tokens.join("")).ok())
.collect::<Vec<ast::Path>>(),
)
let paths = input_expressions
.into_iter()
.filter_map(|(is_sep, group)| (!is_sep).then(|| group))
.filter_map(|mut tokens| ast::Path::parse(&tokens.join("")).ok())
.collect();
Some(paths)
}

0 comments on commit 48cd733

Please sign in to comment.