diff options
| author | Hayashi Mikihiro <34ttrweoewiwe28@gmail.com> | 2025-03-28 23:50:26 +0900 |
|---|---|---|
| committer | Hayashi Mikihiro <34ttrweoewiwe28@gmail.com> | 2025-05-06 17:45:09 +0900 |
| commit | 546065a3150d4ae438e01c751bfcda6875e141d0 (patch) | |
| tree | da5da29860e548783a81c703d7c667054a9404c7 | |
| parent | bb584e87550e000a577a44f9a34bd71e07581e9e (diff) | |
| download | rust-546065a3150d4ae438e01c751bfcda6875e141d0.tar.gz rust-546065a3150d4ae438e01c751bfcda6875e141d0.zip | |
fix: resolve doc path if outer comments exist on module and replace from cfg_attr bit to doc_place bit
Signed-off-by: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com>
5 files changed, 99 insertions, 34 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs index bb17eb06276..b350a6f8ac0 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs @@ -129,9 +129,8 @@ impl RawAttrs { .cloned() .chain(b.slice.iter().map(|it| { let mut it = it.clone(); - it.id.id = (it.id.ast_index() as u32 + last_ast_index) - | ((it.id.cfg_attr_index().unwrap_or(0) as u32) - << AttrId::AST_INDEX_BITS); + let id = it.id.ast_index() as u32 + last_ast_index; + it.id = AttrId::new(id as usize, it.id.is_inner_attr()); it })) .collect::<Vec<_>>(); @@ -175,25 +174,21 @@ pub struct AttrId { // FIXME: This only handles a single level of cfg_attr nesting // that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again impl AttrId { - const CFG_ATTR_BITS: usize = 7; const AST_INDEX_MASK: usize = 0x00FF_FFFF; - const AST_INDEX_BITS: usize = Self::AST_INDEX_MASK.count_ones() as usize; - const CFG_ATTR_SET_BITS: u32 = 1 << 31; + const INNER_ATTR_BIT: usize = 1 << 31; - pub fn ast_index(&self) -> usize { - self.id as usize & Self::AST_INDEX_MASK + pub fn new(id: usize, is_inner: bool) -> Self { + let id = id & Self::AST_INDEX_MASK; + let id = if is_inner { id | Self::INNER_ATTR_BIT } else { id }; + Self { id: id as u32 } } - pub fn cfg_attr_index(&self) -> Option<usize> { - if self.id & Self::CFG_ATTR_SET_BITS == 0 { - None - } else { - Some(self.id as usize >> Self::AST_INDEX_BITS) - } + pub fn ast_index(&self) -> usize { + self.id as usize & Self::AST_INDEX_MASK } - pub fn with_cfg_attr(self, idx: usize) -> AttrId { - AttrId { id: self.id | ((idx as u32) << Self::AST_INDEX_BITS) | Self::CFG_ATTR_SET_BITS } + pub fn is_inner_attr(&self) -> bool { + (self.id as usize) & Self::INNER_ATTR_BIT != 0 } } @@ -333,10 +328,7 @@ impl Attr { None => return smallvec![self.clone()], }; let index = self.id; - let attrs = parts - .enumerate() - .take(1 << AttrId::CFG_ATTR_BITS) - .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx))); + let attrs = parts.filter_map(|attr| Attr::from_tt(db, attr, index)); let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg); let cfg = CfgExpr::parse(&cfg); @@ -467,13 +459,18 @@ fn unescape(s: &str) -> Option<Cow<'_, str>> { pub fn collect_attrs( owner: &dyn ast::HasAttrs, ) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> { - let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten(); - let outer_attrs = - ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el { + let inner_attrs = + inner_attributes(owner.syntax()).into_iter().flatten().map(|attr| (attr, true)); + let outer_attrs = ast::AttrDocCommentIter::from_syntax_node(owner.syntax()) + .filter(|el| match el { Either::Left(attr) => attr.kind().is_outer(), Either::Right(comment) => comment.is_outer(), - }); - outer_attrs.chain(inner_attrs).enumerate().map(|(id, attr)| (AttrId { id: id as u32 }, attr)) + }) + .map(|attr| (attr, false)); + outer_attrs + .chain(inner_attrs) + .enumerate() + .map(|(id, (attr, is_inner))| (AttrId::new(id, is_inner), attr)) } fn inner_attributes( diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 2d1727a6e90..38ba8d6a319 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -105,11 +105,13 @@ impl HasAttrs for crate::Crate { /// Resolves the item `link` points to in the scope of `def`. pub fn resolve_doc_path_on( db: &dyn HirDatabase, - def: impl HasAttrs, + def: impl HasAttrs + Copy, link: &str, ns: Option<Namespace>, ) -> Option<DocLinkDef> { - resolve_doc_path_on_(db, link, def.attr_id(), ns) + let is_inner = + def.attrs(db).by_key(&intern::sym::doc).attrs().all(|attr| attr.id.is_inner_attr()); + resolve_doc_path_on_(db, link, def.attr_id(), ns, is_inner) } fn resolve_doc_path_on_( @@ -117,9 +119,18 @@ fn resolve_doc_path_on_( link: &str, attr_id: AttrDefId, ns: Option<Namespace>, + is_inner: bool, ) -> Option<DocLinkDef> { let resolver = match attr_id { - AttrDefId::ModuleId(it) => it.resolver(db), + AttrDefId::ModuleId(it) => { + if is_inner { + it.resolver(db) + } else if let Some(parent) = Module::from(it).parent(db) { + parent.id.resolver(db) + } else { + it.resolver(db) + } + } AttrDefId::FieldId(it) => it.parent.resolver(db), AttrDefId::AdtId(it) => it.resolver(db), AttrDefId::FunctionId(it) => it.resolver(db), diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs index 91785be8d8b..6d56b98e57c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs @@ -576,6 +576,40 @@ struct S$0(i32); } #[test] +fn doc_links_module() { + check_doc_links( + r#" +/// [`M`] +/// [`M::f`] +mod M$0 { + //^ M + #![doc = "inner_item[`M::S`]"] + + pub fn f() {} + //^ M::f + pub struct S; + //^ M::S +} +"#, + ); + + check_doc_links( + r#" +mod M$0 { + //^ super::M + //! [`super::M`] + //! [`super::M::f`] + //! [`super::M::S`] + pub fn f() {} + //^ super::M::f + pub struct S; + //^ super::M::S +} +"#, + ); +} + +#[test] fn rewrite_html_root_url() { check_rewrite( r#" @@ -691,6 +725,29 @@ fn rewrite_intra_doc_link_with_anchor() { } #[test] +fn rewrite_module() { + check_rewrite( + r#" +//- /main.rs crate:foo +/// [Foo] +pub mod $0Foo{ +}; +"#, + expect"#]], + ); + + check_rewrite( + r#" +//- /main.rs crate:foo +pub mod $0Foo{ + //! [super::Foo] +}; +"#, + expect"#]], + ); +} + +#[test] fn rewrite_intra_doc_link_to_associated_item() { check_rewrite( r#" diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html index 9996a871580..75d96b422c1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html @@ -40,9 +40,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span> +<pre><code><span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[foo::Struct]</span> <span class="comment documentation">//! This is an intra doc injection test for modules</span> -<span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span> +<span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[foo::Struct]</span> <span class="comment documentation">//! This is an intra doc injection test for modules</span> <span class="keyword">pub</span> <span class="keyword">struct</span> <span class="struct declaration public">Struct</span><span class="semicolon">;</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index dd359326c61..a8d95309466 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -1072,9 +1072,9 @@ fn test_mod_hl_injection() { check_highlighting( r##" //- /foo.rs -//! [Struct] +//! [foo::Struct] //! This is an intra doc injection test for modules -//! [Struct] +//! [foo::Struct] //! This is an intra doc injection test for modules pub struct Struct; @@ -1097,9 +1097,9 @@ mod foo; /// This is an intra doc injection test for modules mod foo; //- /foo.rs -//! [Struct] +//! [foo::Struct] //! This is an intra doc injection test for modules -//! [Struct] +//! [foo::Struct] //! This is an intra doc injection test for modules pub struct Struct; |
