Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir-expand/src/attrs.rs | 22 | ||||
| -rw-r--r-- | crates/hir-expand/src/db.rs | 2 | ||||
| -rw-r--r-- | crates/ide-completion/src/tests/attribute.rs | 19 |
3 files changed, 38 insertions, 5 deletions
diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index 395b997972..896baacf04 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -375,12 +375,28 @@ impl AttrId { /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due /// to `cfg_attr`) and its [`ast::Meta`]. + /// + /// Assumes that the attribute syntax node was present in the + /// original file (not speculatively expanded macro output). pub fn find_attr_range_with_source( self, db: &dyn ExpandDatabase, krate: Crate, owner: &dyn ast::HasAttrs, ) -> (ast::Attr, ast::Meta) { + self.find_attr_range_with_source_opt(db, krate, owner).unwrap_or_else(|| { + panic!("used an incorrect `AttrId`; crate={krate:?}, attr_id={self:?}"); + }) + } + + /// Returns the containing `ast::Attr` (note that it may contain other attributes as well due + /// to `cfg_attr`) and its [`ast::Meta`]. + pub(crate) fn find_attr_range_with_source_opt( + self, + db: &dyn ExpandDatabase, + krate: Crate, + owner: &dyn ast::HasAttrs, + ) -> Option<(ast::Attr, ast::Meta)> { let cfg_options = OnceCell::new(); let mut index = 0; let result = collect_item_tree_attrs( @@ -395,10 +411,8 @@ impl AttrId { }, ); match result { - Some(Either::Left(it)) => it, - _ => { - panic!("used an incorrect `AttrId`; crate={krate:?}, attr_id={self:?}"); - } + Some(Either::Left(it)) => Some(it), + _ => None, } } diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 87abee94cb..90e4e0086e 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -217,7 +217,7 @@ pub fn expand_speculative( // then try finding a token id for our token if it is inside this input subtree. let item = ast::Item::cast(speculative_args.clone())?; let (_, meta) = - attr_ids.invoc_attr().find_attr_range_with_source(db, loc.krate, &item); + attr_ids.invoc_attr().find_attr_range_with_source_opt(db, loc.krate, &item)?; if let ast::Meta::TokenTreeMeta(meta) = meta && let Some(tt) = meta.token_tree() { diff --git a/crates/ide-completion/src/tests/attribute.rs b/crates/ide-completion/src/tests/attribute.rs index 6dcd4f9cdd..300ea9bb11 100644 --- a/crates/ide-completion/src/tests/attribute.rs +++ b/crates/ide-completion/src/tests/attribute.rs @@ -1047,6 +1047,25 @@ mod cfg { } #[test] + fn inside_cfg_attr_gating_attr_macro() { + check( + r#" +//- proc_macros: identity +//- /main.rs cfg:feature=on +#[cfg_attr(feat$0ure = "on", proc_macros::identity)] +fn f() {} +"#, + expect![[r#" + ba all + ba any + ba feature + ba not + ba true + "#]], + ); + } + + #[test] fn complete_key_attr() { check_edit( "test", |