Skip to content

Commit 0001a42

Browse files
committed
fix: Fix lint completions not working for unclosed attributes
1 parent 03f6d92 commit 0001a42

File tree

3 files changed

+39
-25
lines changed

3 files changed

+39
-25
lines changed

crates/ide_completion/src/completions/attribute.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,12 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
3030
None => None,
3131
};
3232
match (name_ref, attribute.token_tree()) {
33-
(Some(path), Some(token_tree)) => match path.text().as_str() {
34-
"repr" => repr::complete_repr(acc, ctx, token_tree),
35-
"derive" => {
36-
derive::complete_derive(acc, ctx, &parse_tt_as_comma_sep_paths(token_tree)?)
37-
}
38-
"feature" => {
39-
lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(token_tree)?, FEATURES)
40-
}
33+
(Some(path), Some(tt)) if tt.l_paren_token().is_some() => match path.text().as_str() {
34+
"repr" => repr::complete_repr(acc, ctx, tt),
35+
"derive" => derive::complete_derive(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?),
36+
"feature" => lint::complete_lint(acc, ctx, &parse_tt_as_comma_sep_paths(tt)?, FEATURES),
4137
"allow" | "warn" | "deny" | "forbid" => {
42-
let existing_lints = parse_tt_as_comma_sep_paths(token_tree)?;
38+
let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
4339
lint::complete_lint(acc, ctx, &existing_lints, DEFAULT_LINTS);
4440
lint::complete_lint(acc, ctx, &existing_lints, CLIPPY_LINTS);
4541
lint::complete_lint(acc, ctx, &existing_lints, RUSTDOC_LINTS);
@@ -49,8 +45,8 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
4945
}
5046
_ => (),
5147
},
52-
(None, Some(_)) => (),
53-
_ => complete_new_attribute(acc, ctx, attribute),
48+
(_, Some(_)) => (),
49+
(_, None) => complete_new_attribute(acc, ctx, attribute),
5450
}
5551
Some(())
5652
}

crates/ide_completion/src/tests/attribute.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,20 @@ mod lint {
831831
r#"#[allow(rustdoc::bare_urls)] struct Test;"#,
832832
);
833833
}
834+
835+
#[test]
836+
fn lint_unclosed() {
837+
check_edit(
838+
"deprecated",
839+
r#"#[allow(dep$0 struct Test;"#,
840+
r#"#[allow(deprecated struct Test;"#,
841+
);
842+
check_edit(
843+
"bare_urls",
844+
r#"#[allow(rustdoc::$0 struct Test;"#,
845+
r#"#[allow(rustdoc::bare_urls struct Test;"#,
846+
);
847+
}
834848
}
835849

836850
mod repr {

crates/ide_db/src/helpers.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -305,20 +305,24 @@ pub fn lint_eq_or_in_group(lint: &str, lint_is: &str) -> bool {
305305
}
306306
}
307307

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

0 commit comments

Comments
 (0)