Skip to content

Commit bca00ac

Browse files
bors[bot]Veykril
andauthored
Merge #9033
9033: Complete keywords in (Assoc)ItemList with leading attribute r=Veykril a=Veykril Fixes #7673 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 3a1598c + 1894db4 commit bca00ac

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

crates/ide_completion/src/completions/keyword.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,21 @@ fn quux() -> i32 {
394394
);
395395
}
396396

397+
#[test]
398+
fn test_keywords_in_impl_def_with_attr() {
399+
check(
400+
r"impl My { #[foo] $0 }",
401+
expect![[r#"
402+
kw fn
403+
kw const
404+
kw type
405+
kw unsafe
406+
kw pub(crate)
407+
kw pub
408+
"#]],
409+
);
410+
}
411+
397412
#[test]
398413
fn test_keywords_in_loop() {
399414
check(

crates/ide_completion/src/patterns.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ pub(crate) enum ImmediateLocation {
2525
}
2626

2727
pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation> {
28-
// First "expand" the element we are completing to its maximum so that we can check in what
29-
// context it immediately lies. This for example means if the token is a NameRef at the end of
30-
// a path, we want to look at where the path is in the tree.
28+
// First walk the element we are completing up to its highest node that has the same text range
29+
// as the element so that we can check in what context it immediately lies. We only do this for
30+
// NameRef -> Path as that's the only thing that makes sense to being "expanded" semantically.
31+
// We only wanna do this if the NameRef is the last segment of the path.
3132
let node = match tok.parent().and_then(ast::NameLike::cast)? {
3233
ast::NameLike::NameRef(name_ref) => {
3334
if let Some(segment) = name_ref.syntax().parent().and_then(ast::PathSegment::cast) {
@@ -47,7 +48,20 @@ pub(crate) fn determine_location(tok: SyntaxToken) -> Option<ImmediateLocation>
4748
it @ ast::NameLike::Name(_) | it @ ast::NameLike::Lifetime(_) => it.syntax().clone(),
4849
};
4950
let parent = match node.parent() {
50-
Some(parent) => parent,
51+
Some(parent) => match ast::MacroCall::cast(parent.clone()) {
52+
// When a path is being typed in an (Assoc)ItemList the parser will always emit a macro_call.
53+
// This is usually fine as the node expansion code above already accounts for that with
54+
// the ancestors call, but there is one exception to this which is that when an attribute
55+
// precedes it the code above will not walk the Path to the parent MacroCall as their ranges differ.
56+
Some(call)
57+
if call.excl_token().is_none()
58+
&& call.token_tree().is_none()
59+
&& call.semicolon_token().is_none() =>
60+
{
61+
call.syntax().parent()?
62+
}
63+
_ => parent,
64+
},
5165
// SourceFile
5266
None => {
5367
return match node.kind() {

0 commit comments

Comments
 (0)