mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-04 02:39:32 +00:00
check module path inner or outer
Signed-off-by: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com>
This commit is contained in:
parent
ab4ba5cd29
commit
778322eb31
10 changed files with 256 additions and 130 deletions
|
@ -6,7 +6,7 @@
|
|||
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
|
||||
|
||||
use crate::RootDatabase;
|
||||
use crate::documentation::{Documentation, HasDocs};
|
||||
use crate::documentation::{DocsRangeMap, Documentation, HasDocs};
|
||||
use crate::famous_defs::FamousDefs;
|
||||
use arrayvec::ArrayVec;
|
||||
use either::Either;
|
||||
|
@ -21,7 +21,7 @@ use hir::{
|
|||
use span::Edition;
|
||||
use stdx::{format_to, impl_from};
|
||||
use syntax::{
|
||||
SyntaxKind, SyntaxNode, SyntaxToken,
|
||||
SyntaxKind, SyntaxNode, SyntaxToken, TextSize,
|
||||
ast::{self, AstNode},
|
||||
match_ast,
|
||||
};
|
||||
|
@ -210,29 +210,40 @@ impl Definition {
|
|||
famous_defs: Option<&FamousDefs<'_, '_>>,
|
||||
display_target: DisplayTarget,
|
||||
) -> Option<Documentation> {
|
||||
self.docs_with_rangemap(db, famous_defs, display_target).map(|(docs, _)| docs)
|
||||
}
|
||||
|
||||
pub fn docs_with_rangemap(
|
||||
&self,
|
||||
db: &RootDatabase,
|
||||
famous_defs: Option<&FamousDefs<'_, '_>>,
|
||||
display_target: DisplayTarget,
|
||||
) -> Option<(Documentation, Option<DocsRangeMap>)> {
|
||||
let docs = match self {
|
||||
Definition::Macro(it) => it.docs(db),
|
||||
Definition::Field(it) => it.docs(db),
|
||||
Definition::Module(it) => it.docs(db),
|
||||
Definition::Crate(it) => it.docs(db),
|
||||
Definition::Function(it) => it.docs(db),
|
||||
Definition::Adt(it) => it.docs(db),
|
||||
Definition::Variant(it) => it.docs(db),
|
||||
Definition::Const(it) => it.docs(db),
|
||||
Definition::Static(it) => it.docs(db),
|
||||
Definition::Trait(it) => it.docs(db),
|
||||
Definition::TraitAlias(it) => it.docs(db),
|
||||
Definition::Macro(it) => it.docs_with_rangemap(db),
|
||||
Definition::Field(it) => it.docs_with_rangemap(db),
|
||||
Definition::Module(it) => it.docs_with_rangemap(db),
|
||||
Definition::Crate(it) => it.docs_with_rangemap(db),
|
||||
Definition::Function(it) => it.docs_with_rangemap(db),
|
||||
Definition::Adt(it) => it.docs_with_rangemap(db),
|
||||
Definition::Variant(it) => it.docs_with_rangemap(db),
|
||||
Definition::Const(it) => it.docs_with_rangemap(db),
|
||||
Definition::Static(it) => it.docs_with_rangemap(db),
|
||||
Definition::Trait(it) => it.docs_with_rangemap(db),
|
||||
Definition::TraitAlias(it) => it.docs_with_rangemap(db),
|
||||
Definition::TypeAlias(it) => {
|
||||
it.docs(db).or_else(|| {
|
||||
it.docs_with_rangemap(db).or_else(|| {
|
||||
// docs are missing, try to fall back to the docs of the aliased item.
|
||||
let adt = it.ty(db).as_adt()?;
|
||||
let docs = adt.docs(db)?;
|
||||
let docs = format!(
|
||||
"*This is the documentation for* `{}`\n\n{}",
|
||||
adt.display(db, display_target),
|
||||
docs.as_str()
|
||||
let (docs, range_map) = adt.docs_with_rangemap(db)?;
|
||||
let header_docs = format!(
|
||||
"*This is the documentation for* `{}`\n\n",
|
||||
adt.display(db, display_target)
|
||||
);
|
||||
Some(Documentation::new(docs))
|
||||
let offset = TextSize::new(header_docs.len() as u32);
|
||||
let range_map = range_map.shift_docstring_line_range(offset);
|
||||
let docs = header_docs + docs.as_str();
|
||||
Some((Documentation::new(docs), range_map))
|
||||
})
|
||||
}
|
||||
Definition::BuiltinType(it) => {
|
||||
|
@ -241,17 +252,17 @@ impl Definition {
|
|||
let primitive_mod =
|
||||
format!("prim_{}", it.name().display(fd.0.db, display_target.edition));
|
||||
let doc_owner = find_std_module(fd, &primitive_mod, display_target.edition)?;
|
||||
doc_owner.docs(fd.0.db)
|
||||
doc_owner.docs_with_rangemap(fd.0.db)
|
||||
})
|
||||
}
|
||||
Definition::BuiltinLifetime(StaticLifetime) => None,
|
||||
Definition::Local(_) => None,
|
||||
Definition::SelfType(impl_def) => {
|
||||
impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))?
|
||||
impl_def.self_ty(db).as_adt().map(|adt| adt.docs_with_rangemap(db))?
|
||||
}
|
||||
Definition::GenericParam(_) => None,
|
||||
Definition::Label(_) => None,
|
||||
Definition::ExternCrateDecl(it) => it.docs(db),
|
||||
Definition::ExternCrateDecl(it) => it.docs_with_rangemap(db),
|
||||
|
||||
Definition::BuiltinAttr(it) => {
|
||||
let name = it.name(db);
|
||||
|
@ -276,7 +287,8 @@ impl Definition {
|
|||
name_value_str
|
||||
);
|
||||
}
|
||||
Some(Documentation::new(docs.replace('*', "\\*")))
|
||||
|
||||
return Some((Documentation::new(docs.replace('*', "\\*")), None));
|
||||
}
|
||||
Definition::ToolModule(_) => None,
|
||||
Definition::DeriveHelper(_) => None,
|
||||
|
@ -291,8 +303,9 @@ impl Definition {
|
|||
let trait_ = assoc.implemented_trait(db)?;
|
||||
let name = Some(assoc.name(db)?);
|
||||
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
|
||||
item.docs(db)
|
||||
item.docs_with_rangemap(db)
|
||||
})
|
||||
.map(|(docs, range_map)| (docs, Some(range_map)))
|
||||
}
|
||||
|
||||
pub fn label(&self, db: &RootDatabase, display_target: DisplayTarget) -> String {
|
||||
|
|
|
@ -34,11 +34,13 @@ impl From<Documentation> for String {
|
|||
|
||||
pub trait HasDocs: HasAttrs {
|
||||
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>;
|
||||
fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)>;
|
||||
fn resolve_doc_path(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
link: &str,
|
||||
ns: Option<hir::Namespace>,
|
||||
is_inner_doc: bool,
|
||||
) -> Option<hir::DocLinkDef>;
|
||||
}
|
||||
/// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree.
|
||||
|
@ -53,7 +55,7 @@ pub struct DocsRangeMap {
|
|||
|
||||
impl DocsRangeMap {
|
||||
/// Maps a [`TextRange`] relative to the documentation string back to its AST range
|
||||
pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> {
|
||||
pub fn map(&self, range: TextRange) -> Option<(InFile<TextRange>, AttrId)> {
|
||||
let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?;
|
||||
let (line_docs_range, idx, original_line_src_range) = self.mapping[found];
|
||||
if !line_docs_range.contains_range(range) {
|
||||
|
@ -71,7 +73,7 @@ impl DocsRangeMap {
|
|||
text_range.end() + original_line_src_range.start() + relative_range.start(),
|
||||
string.syntax().text_range().len().min(range.len()),
|
||||
);
|
||||
Some(InFile { file_id, value: range })
|
||||
Some((InFile { file_id, value: range }, idx))
|
||||
}
|
||||
Either::Right(comment) => {
|
||||
let text_range = comment.syntax().text_range();
|
||||
|
@ -82,10 +84,22 @@ impl DocsRangeMap {
|
|||
+ relative_range.start(),
|
||||
text_range.len().min(range.len()),
|
||||
);
|
||||
Some(InFile { file_id, value: range })
|
||||
Some((InFile { file_id, value: range }, idx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shift_docstring_line_range(self, offset: TextSize) -> DocsRangeMap {
|
||||
let mapping = self
|
||||
.mapping
|
||||
.into_iter()
|
||||
.map(|(buf_offset, id, base_offset)| {
|
||||
let buf_offset = buf_offset.checked_add(offset).unwrap();
|
||||
(buf_offset, id, base_offset)
|
||||
})
|
||||
.collect_vec();
|
||||
DocsRangeMap { source_map: self.source_map, mapping }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn docs_with_rangemap(
|
||||
|
@ -161,13 +175,20 @@ macro_rules! impl_has_docs {
|
|||
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
|
||||
docs_from_attrs(&self.attrs(db)).map(Documentation)
|
||||
}
|
||||
fn docs_with_rangemap(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
) -> Option<(Documentation, DocsRangeMap)> {
|
||||
docs_with_rangemap(db, &self.attrs(db))
|
||||
}
|
||||
fn resolve_doc_path(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
link: &str,
|
||||
ns: Option<hir::Namespace>
|
||||
ns: Option<hir::Namespace>,
|
||||
is_inner_doc: bool,
|
||||
) -> Option<hir::DocLinkDef> {
|
||||
resolve_doc_path_on(db, self, link, ns)
|
||||
resolve_doc_path_on(db, self, link, ns, is_inner_doc)
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
@ -184,13 +205,21 @@ macro_rules! impl_has_docs_enum {
|
|||
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
|
||||
hir::$enum::$variant(self).docs(db)
|
||||
}
|
||||
|
||||
fn docs_with_rangemap(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
) -> Option<(Documentation, DocsRangeMap)> {
|
||||
hir::$enum::$variant(self).docs_with_rangemap(db)
|
||||
}
|
||||
fn resolve_doc_path(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
link: &str,
|
||||
ns: Option<hir::Namespace>
|
||||
ns: Option<hir::Namespace>,
|
||||
is_inner_doc: bool,
|
||||
) -> Option<hir::DocLinkDef> {
|
||||
hir::$enum::$variant(self).resolve_doc_path(db, link, ns)
|
||||
hir::$enum::$variant(self).resolve_doc_path(db, link, ns, is_inner_doc)
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
@ -207,16 +236,25 @@ impl HasDocs for hir::AssocItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)> {
|
||||
match self {
|
||||
hir::AssocItem::Function(it) => it.docs_with_rangemap(db),
|
||||
hir::AssocItem::Const(it) => it.docs_with_rangemap(db),
|
||||
hir::AssocItem::TypeAlias(it) => it.docs_with_rangemap(db),
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_doc_path(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
link: &str,
|
||||
ns: Option<hir::Namespace>,
|
||||
is_inner_doc: bool,
|
||||
) -> Option<hir::DocLinkDef> {
|
||||
match self {
|
||||
hir::AssocItem::Function(it) => it.resolve_doc_path(db, link, ns),
|
||||
hir::AssocItem::Const(it) => it.resolve_doc_path(db, link, ns),
|
||||
hir::AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
|
||||
hir::AssocItem::Function(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
|
||||
hir::AssocItem::Const(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
|
||||
hir::AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,13 +276,36 @@ impl HasDocs for hir::ExternCrateDecl {
|
|||
}
|
||||
.map(Documentation::new)
|
||||
}
|
||||
|
||||
fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)> {
|
||||
let crate_docs = docs_with_rangemap(db, &self.resolved_crate(db)?.root_module().attrs(db));
|
||||
let decl_docs = docs_with_rangemap(db, &self.attrs(db));
|
||||
match (decl_docs, crate_docs) {
|
||||
(None, None) => None,
|
||||
(Some(decl_docs), None) => Some(decl_docs),
|
||||
(None, Some(crate_docs)) => Some(crate_docs),
|
||||
(
|
||||
Some((Documentation(mut decl_docs), mut decl_range_map)),
|
||||
Some((Documentation(crate_docs), crate_range_map)),
|
||||
) => {
|
||||
decl_docs.push('\n');
|
||||
decl_docs.push('\n');
|
||||
let offset = TextSize::new(decl_docs.len() as u32);
|
||||
decl_docs += &crate_docs;
|
||||
let crate_range_map = crate_range_map.shift_docstring_line_range(offset);
|
||||
decl_range_map.mapping.extend(crate_range_map.mapping);
|
||||
Some((Documentation(decl_docs), decl_range_map))
|
||||
}
|
||||
}
|
||||
}
|
||||
fn resolve_doc_path(
|
||||
self,
|
||||
db: &dyn HirDatabase,
|
||||
link: &str,
|
||||
ns: Option<hir::Namespace>,
|
||||
is_inner_doc: bool,
|
||||
) -> Option<hir::DocLinkDef> {
|
||||
resolve_doc_path_on(db, self, link, ns)
|
||||
resolve_doc_path_on(db, self, link, ns, is_inner_doc)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue