Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/context/analysis.rs')
-rw-r--r--crates/ide-completion/src/context/analysis.rs46
1 files changed, 36 insertions, 10 deletions
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index a3494b964f..2a293313f2 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -284,9 +284,12 @@ fn expand(
};
// Expand pseudo-derive expansion aka `derive(Debug$0)`
- if let Some((orig_attr, spec_attr)) = attrs {
+ if let Some((orig_attr, spec_attr)) = attrs
+ && let Some(orig_meta) = orig_attr.meta()
+ {
+ // FIXME: Support speculative expansion with `cfg_attr`.
if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_tokens))) = (
- sema.expand_derive_as_pseudo_attr_macro(&orig_attr),
+ sema.expand_derive_as_pseudo_attr_macro(&orig_meta),
sema.speculative_expand_derive_as_pseudo_attr_macro(
&orig_attr,
&spec_attr,
@@ -463,7 +466,9 @@ fn analyze<'db>(
}
// Overwrite the path kind for derives
- if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
+ if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx
+ && let Some(origin_meta) = origin_attr.meta()
+ {
if let Some(ast::NameLike::NameRef(name_ref)) =
find_node_at_offset(&file_with_fake_ident, offset)
{
@@ -473,7 +478,7 @@ fn analyze<'db>(
if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind {
path_ctx.kind = PathKind::Derive {
existing_derives: sema
- .resolve_derive_macro(&origin_attr)
+ .resolve_derive_macro(&origin_meta)
.into_iter()
.flatten()
.flatten()
@@ -498,7 +503,7 @@ fn analyze<'db>(
let token = syntax::algo::skip_trivia_token(self_token.clone(), Direction::Prev)?;
let p = token.parent()?;
if p.kind() == SyntaxKind::TOKEN_TREE
- && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
+ && p.ancestors().any(|it| it.kind() == SyntaxKind::TOKEN_TREE_META)
{
let colon_prefix = previous_non_trivia_token(self_token.clone())
.is_some_and(|it| T![:] == it.kind());
@@ -506,7 +511,7 @@ fn analyze<'db>(
CompletionAnalysis::UnexpandedAttrTT {
fake_attribute_under_caret: fake_ident_token
.parent_ancestors()
- .find_map(ast::Attr::cast),
+ .find_map(ast::TokenTreeMeta::cast),
colon_prefix,
extern_crate: p.ancestors().find_map(ast::ExternCrate::cast),
}
@@ -525,6 +530,13 @@ fn analyze<'db>(
} else {
return None;
}
+ } else if find_node_at_offset::<ast::CfgPredicate>(
+ &speculative_file,
+ speculative_offset,
+ )
+ .is_some()
+ {
+ CompletionAnalysis::CfgPredicate
} else {
return None;
}
@@ -827,6 +839,19 @@ fn expected_type_and_name<'db>(
.map(|c| (Some(c.return_type()), None))
.unwrap_or((None, None))
},
+ ast::Variant(it) => {
+ let is_simple_field = |field: ast::TupleField| {
+ let Some(ty) = field.ty() else { return true };
+ matches!(ty, ast::Type::PathType(_)) && ty.generic_arg_list().is_none()
+ };
+ let is_simple_variant = matches!(
+ it.field_list(),
+ Some(ast::FieldList::TupleFieldList(list))
+ if list.syntax().children_with_tokens().all(|it| it.kind() != T![,])
+ && list.fields().next().is_none_or(is_simple_field)
+ );
+ (None, it.name().filter(|_| is_simple_variant).map(NameOrNameRef::Name))
+ },
ast::Stmt(_) => (None, None),
ast::Item(_) => (None, None),
_ => {
@@ -1265,15 +1290,14 @@ fn classify_name_ref<'db>(
let original = ast::Static::cast(name.syntax().parent()?)?;
TypeLocation::TypeAscription(TypeAscriptionTarget::Const(original.body()))
},
- ast::RetType(it) => {
- it.thin_arrow_token()?;
+ ast::RetType(_) => {
let parent = match ast::Fn::cast(parent.parent()?) {
Some(it) => it.param_list(),
None => ast::ClosureExpr::cast(parent.parent()?)?.param_list(),
};
let parent = find_opt_node_in_file(original_file, parent)?.syntax().parent()?;
- TypeLocation::TypeAscription(TypeAscriptionTarget::RetType(match_ast! {
+ let body = match_ast! {
match parent {
ast::ClosureExpr(it) => {
it.body()
@@ -1283,7 +1307,9 @@ fn classify_name_ref<'db>(
},
_ => return None,
}
- }))
+ };
+ let item = ast::Fn::cast(parent);
+ TypeLocation::TypeAscription(TypeAscriptionTarget::RetType { body, item })
},
ast::Param(it) => {
it.colon_token()?;