mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
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>
This commit is contained in:
parent
d30deb58fe
commit
9f6b4255c2
@ -129,9 +129,8 @@ impl RawAttrs {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.chain(b.slice.iter().map(|it| {
|
.chain(b.slice.iter().map(|it| {
|
||||||
let mut it = it.clone();
|
let mut it = it.clone();
|
||||||
it.id.id = (it.id.ast_index() as u32 + last_ast_index)
|
let id = it.id.ast_index() as u32 + last_ast_index;
|
||||||
| ((it.id.cfg_attr_index().unwrap_or(0) as u32)
|
it.id = AttrId::new(id as usize, it.id.is_inner_attr());
|
||||||
<< AttrId::AST_INDEX_BITS);
|
|
||||||
it
|
it
|
||||||
}))
|
}))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
@ -175,25 +174,21 @@ pub struct AttrId {
|
|||||||
// FIXME: This only handles a single level of cfg_attr nesting
|
// FIXME: This only handles a single level of cfg_attr nesting
|
||||||
// that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again
|
// that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again
|
||||||
impl AttrId {
|
impl AttrId {
|
||||||
const CFG_ATTR_BITS: usize = 7;
|
|
||||||
const AST_INDEX_MASK: usize = 0x00FF_FFFF;
|
const AST_INDEX_MASK: usize = 0x00FF_FFFF;
|
||||||
const AST_INDEX_BITS: usize = Self::AST_INDEX_MASK.count_ones() as usize;
|
const INNER_ATTR_BIT: usize = 1 << 31;
|
||||||
const CFG_ATTR_SET_BITS: u32 = 1 << 31;
|
|
||||||
|
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 ast_index(&self) -> usize {
|
pub fn ast_index(&self) -> usize {
|
||||||
self.id as usize & Self::AST_INDEX_MASK
|
self.id as usize & Self::AST_INDEX_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cfg_attr_index(&self) -> Option<usize> {
|
pub fn is_inner_attr(&self) -> bool {
|
||||||
if self.id & Self::CFG_ATTR_SET_BITS == 0 {
|
(self.id as usize) & Self::INNER_ATTR_BIT != 0
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.id as usize >> Self::AST_INDEX_BITS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,10 +328,7 @@ impl Attr {
|
|||||||
None => return smallvec![self.clone()],
|
None => return smallvec![self.clone()],
|
||||||
};
|
};
|
||||||
let index = self.id;
|
let index = self.id;
|
||||||
let attrs = parts
|
let attrs = parts.filter_map(|attr| Attr::from_tt(db, attr, index));
|
||||||
.enumerate()
|
|
||||||
.take(1 << AttrId::CFG_ATTR_BITS)
|
|
||||||
.filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)));
|
|
||||||
|
|
||||||
let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
|
let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
|
||||||
let cfg = CfgExpr::parse(&cfg);
|
let cfg = CfgExpr::parse(&cfg);
|
||||||
@ -467,13 +459,18 @@ fn unescape(s: &str) -> Option<Cow<'_, str>> {
|
|||||||
pub fn collect_attrs(
|
pub fn collect_attrs(
|
||||||
owner: &dyn ast::HasAttrs,
|
owner: &dyn ast::HasAttrs,
|
||||||
) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
|
) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
|
||||||
let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
|
let inner_attrs =
|
||||||
let outer_attrs =
|
inner_attributes(owner.syntax()).into_iter().flatten().map(|attr| (attr, true));
|
||||||
ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
|
let outer_attrs = ast::AttrDocCommentIter::from_syntax_node(owner.syntax())
|
||||||
|
.filter(|el| match el {
|
||||||
Either::Left(attr) => attr.kind().is_outer(),
|
Either::Left(attr) => attr.kind().is_outer(),
|
||||||
Either::Right(comment) => comment.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(
|
fn inner_attributes(
|
||||||
|
@ -105,11 +105,13 @@ impl HasAttrs for crate::Crate {
|
|||||||
/// Resolves the item `link` points to in the scope of `def`.
|
/// Resolves the item `link` points to in the scope of `def`.
|
||||||
pub fn resolve_doc_path_on(
|
pub fn resolve_doc_path_on(
|
||||||
db: &dyn HirDatabase,
|
db: &dyn HirDatabase,
|
||||||
def: impl HasAttrs,
|
def: impl HasAttrs + Copy,
|
||||||
link: &str,
|
link: &str,
|
||||||
ns: Option<Namespace>,
|
ns: Option<Namespace>,
|
||||||
) -> Option<DocLinkDef> {
|
) -> 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_(
|
fn resolve_doc_path_on_(
|
||||||
@ -117,9 +119,18 @@ fn resolve_doc_path_on_(
|
|||||||
link: &str,
|
link: &str,
|
||||||
attr_id: AttrDefId,
|
attr_id: AttrDefId,
|
||||||
ns: Option<Namespace>,
|
ns: Option<Namespace>,
|
||||||
|
is_inner: bool,
|
||||||
) -> Option<DocLinkDef> {
|
) -> Option<DocLinkDef> {
|
||||||
let resolver = match attr_id {
|
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::FieldId(it) => it.parent.resolver(db),
|
||||||
AttrDefId::AdtId(it) => it.resolver(db),
|
AttrDefId::AdtId(it) => it.resolver(db),
|
||||||
AttrDefId::FunctionId(it) => it.resolver(db),
|
AttrDefId::FunctionId(it) => it.resolver(db),
|
||||||
|
@ -575,6 +575,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]
|
#[test]
|
||||||
fn rewrite_html_root_url() {
|
fn rewrite_html_root_url() {
|
||||||
check_rewrite(
|
check_rewrite(
|
||||||
@ -690,6 +724,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]
|
#[test]
|
||||||
fn rewrite_intra_doc_link_to_associated_item() {
|
fn rewrite_intra_doc_link_to_associated_item() {
|
||||||
check_rewrite(
|
check_rewrite(
|
||||||
|
@ -40,9 +40,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
|||||||
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||||
</style>
|
</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">//! 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="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>
|
<span class="keyword">pub</span> <span class="keyword">struct</span> <span class="struct declaration public">Struct</span><span class="semicolon">;</span>
|
||||||
|
@ -1072,9 +1072,9 @@ fn test_mod_hl_injection() {
|
|||||||
check_highlighting(
|
check_highlighting(
|
||||||
r##"
|
r##"
|
||||||
//- /foo.rs
|
//- /foo.rs
|
||||||
//! [Struct]
|
//! [foo::Struct]
|
||||||
//! This is an intra doc injection test for modules
|
//! This is an intra doc injection test for modules
|
||||||
//! [Struct]
|
//! [foo::Struct]
|
||||||
//! This is an intra doc injection test for modules
|
//! This is an intra doc injection test for modules
|
||||||
|
|
||||||
pub struct Struct;
|
pub struct Struct;
|
||||||
@ -1097,9 +1097,9 @@ mod foo;
|
|||||||
/// This is an intra doc injection test for modules
|
/// This is an intra doc injection test for modules
|
||||||
mod foo;
|
mod foo;
|
||||||
//- /foo.rs
|
//- /foo.rs
|
||||||
//! [Struct]
|
//! [foo::Struct]
|
||||||
//! This is an intra doc injection test for modules
|
//! This is an intra doc injection test for modules
|
||||||
//! [Struct]
|
//! [foo::Struct]
|
||||||
//! This is an intra doc injection test for modules
|
//! This is an intra doc injection test for modules
|
||||||
|
|
||||||
pub struct Struct;
|
pub struct Struct;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user