Skip to content

Commit 778322e

Browse files
committed
check module path inner or outer
Signed-off-by: Hayashi Mikihiro <34ttrweoewiwe28@gmail.com>
1 parent ab4ba5c commit 778322e

File tree

10 files changed

+256
-130
lines changed

10 files changed

+256
-130
lines changed

crates/hir/src/attrs.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -108,22 +108,21 @@ pub fn resolve_doc_path_on(
108108
def: impl HasAttrs + Copy,
109109
link: &str,
110110
ns: Option<Namespace>,
111+
is_inner_doc: bool,
111112
) -> Option<DocLinkDef> {
112-
let is_inner =
113-
def.attrs(db).by_key(&intern::sym::doc).attrs().all(|attr| attr.id.is_inner_attr());
114-
resolve_doc_path_on_(db, link, def.attr_id(), ns, is_inner)
113+
resolve_doc_path_on_(db, link, def.attr_id(), ns, is_inner_doc)
115114
}
116115

117116
fn resolve_doc_path_on_(
118117
db: &dyn HirDatabase,
119118
link: &str,
120119
attr_id: AttrDefId,
121120
ns: Option<Namespace>,
122-
is_inner: bool,
121+
is_inner_doc: bool,
123122
) -> Option<DocLinkDef> {
124123
let resolver = match attr_id {
125124
AttrDefId::ModuleId(it) => {
126-
if is_inner {
125+
if is_inner_doc {
127126
it.resolver(db)
128127
} else if let Some(parent) = Module::from(it).parent(db) {
129128
parent.id.resolver(db)

crates/ide-db/src/defs.rs

+38-25
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
77

88
use crate::RootDatabase;
9-
use crate::documentation::{Documentation, HasDocs};
9+
use crate::documentation::{DocsRangeMap, Documentation, HasDocs};
1010
use crate::famous_defs::FamousDefs;
1111
use arrayvec::ArrayVec;
1212
use either::Either;
@@ -21,7 +21,7 @@ use hir::{
2121
use span::Edition;
2222
use stdx::{format_to, impl_from};
2323
use syntax::{
24-
SyntaxKind, SyntaxNode, SyntaxToken,
24+
SyntaxKind, SyntaxNode, SyntaxToken, TextSize,
2525
ast::{self, AstNode},
2626
match_ast,
2727
};
@@ -210,29 +210,40 @@ impl Definition {
210210
famous_defs: Option<&FamousDefs<'_, '_>>,
211211
display_target: DisplayTarget,
212212
) -> Option<Documentation> {
213+
self.docs_with_rangemap(db, famous_defs, display_target).map(|(docs, _)| docs)
214+
}
215+
216+
pub fn docs_with_rangemap(
217+
&self,
218+
db: &RootDatabase,
219+
famous_defs: Option<&FamousDefs<'_, '_>>,
220+
display_target: DisplayTarget,
221+
) -> Option<(Documentation, Option<DocsRangeMap>)> {
213222
let docs = match self {
214-
Definition::Macro(it) => it.docs(db),
215-
Definition::Field(it) => it.docs(db),
216-
Definition::Module(it) => it.docs(db),
217-
Definition::Crate(it) => it.docs(db),
218-
Definition::Function(it) => it.docs(db),
219-
Definition::Adt(it) => it.docs(db),
220-
Definition::Variant(it) => it.docs(db),
221-
Definition::Const(it) => it.docs(db),
222-
Definition::Static(it) => it.docs(db),
223-
Definition::Trait(it) => it.docs(db),
224-
Definition::TraitAlias(it) => it.docs(db),
223+
Definition::Macro(it) => it.docs_with_rangemap(db),
224+
Definition::Field(it) => it.docs_with_rangemap(db),
225+
Definition::Module(it) => it.docs_with_rangemap(db),
226+
Definition::Crate(it) => it.docs_with_rangemap(db),
227+
Definition::Function(it) => it.docs_with_rangemap(db),
228+
Definition::Adt(it) => it.docs_with_rangemap(db),
229+
Definition::Variant(it) => it.docs_with_rangemap(db),
230+
Definition::Const(it) => it.docs_with_rangemap(db),
231+
Definition::Static(it) => it.docs_with_rangemap(db),
232+
Definition::Trait(it) => it.docs_with_rangemap(db),
233+
Definition::TraitAlias(it) => it.docs_with_rangemap(db),
225234
Definition::TypeAlias(it) => {
226-
it.docs(db).or_else(|| {
235+
it.docs_with_rangemap(db).or_else(|| {
227236
// docs are missing, try to fall back to the docs of the aliased item.
228237
let adt = it.ty(db).as_adt()?;
229-
let docs = adt.docs(db)?;
230-
let docs = format!(
231-
"*This is the documentation for* `{}`\n\n{}",
232-
adt.display(db, display_target),
233-
docs.as_str()
238+
let (docs, range_map) = adt.docs_with_rangemap(db)?;
239+
let header_docs = format!(
240+
"*This is the documentation for* `{}`\n\n",
241+
adt.display(db, display_target)
234242
);
235-
Some(Documentation::new(docs))
243+
let offset = TextSize::new(header_docs.len() as u32);
244+
let range_map = range_map.shift_docstring_line_range(offset);
245+
let docs = header_docs + docs.as_str();
246+
Some((Documentation::new(docs), range_map))
236247
})
237248
}
238249
Definition::BuiltinType(it) => {
@@ -241,17 +252,17 @@ impl Definition {
241252
let primitive_mod =
242253
format!("prim_{}", it.name().display(fd.0.db, display_target.edition));
243254
let doc_owner = find_std_module(fd, &primitive_mod, display_target.edition)?;
244-
doc_owner.docs(fd.0.db)
255+
doc_owner.docs_with_rangemap(fd.0.db)
245256
})
246257
}
247258
Definition::BuiltinLifetime(StaticLifetime) => None,
248259
Definition::Local(_) => None,
249260
Definition::SelfType(impl_def) => {
250-
impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))?
261+
impl_def.self_ty(db).as_adt().map(|adt| adt.docs_with_rangemap(db))?
251262
}
252263
Definition::GenericParam(_) => None,
253264
Definition::Label(_) => None,
254-
Definition::ExternCrateDecl(it) => it.docs(db),
265+
Definition::ExternCrateDecl(it) => it.docs_with_rangemap(db),
255266

256267
Definition::BuiltinAttr(it) => {
257268
let name = it.name(db);
@@ -276,7 +287,8 @@ impl Definition {
276287
name_value_str
277288
);
278289
}
279-
Some(Documentation::new(docs.replace('*', "\\*")))
290+
291+
return Some((Documentation::new(docs.replace('*', "\\*")), None));
280292
}
281293
Definition::ToolModule(_) => None,
282294
Definition::DeriveHelper(_) => None,
@@ -291,8 +303,9 @@ impl Definition {
291303
let trait_ = assoc.implemented_trait(db)?;
292304
let name = Some(assoc.name(db)?);
293305
let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
294-
item.docs(db)
306+
item.docs_with_rangemap(db)
295307
})
308+
.map(|(docs, range_map)| (docs, Some(range_map)))
296309
}
297310

298311
pub fn label(&self, db: &RootDatabase, display_target: DisplayTarget) -> String {

crates/ide-db/src/documentation.rs

+72-11
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ impl From<Documentation> for String {
3434

3535
pub trait HasDocs: HasAttrs {
3636
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>;
37+
fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)>;
3738
fn resolve_doc_path(
3839
self,
3940
db: &dyn HirDatabase,
4041
link: &str,
4142
ns: Option<hir::Namespace>,
43+
is_inner_doc: bool,
4244
) -> Option<hir::DocLinkDef>;
4345
}
4446
/// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree.
@@ -53,7 +55,7 @@ pub struct DocsRangeMap {
5355

5456
impl DocsRangeMap {
5557
/// Maps a [`TextRange`] relative to the documentation string back to its AST range
56-
pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> {
58+
pub fn map(&self, range: TextRange) -> Option<(InFile<TextRange>, AttrId)> {
5759
let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?;
5860
let (line_docs_range, idx, original_line_src_range) = self.mapping[found];
5961
if !line_docs_range.contains_range(range) {
@@ -71,7 +73,7 @@ impl DocsRangeMap {
7173
text_range.end() + original_line_src_range.start() + relative_range.start(),
7274
string.syntax().text_range().len().min(range.len()),
7375
);
74-
Some(InFile { file_id, value: range })
76+
Some((InFile { file_id, value: range }, idx))
7577
}
7678
Either::Right(comment) => {
7779
let text_range = comment.syntax().text_range();
@@ -82,10 +84,22 @@ impl DocsRangeMap {
8284
+ relative_range.start(),
8385
text_range.len().min(range.len()),
8486
);
85-
Some(InFile { file_id, value: range })
87+
Some((InFile { file_id, value: range }, idx))
8688
}
8789
}
8890
}
91+
92+
pub fn shift_docstring_line_range(self, offset: TextSize) -> DocsRangeMap {
93+
let mapping = self
94+
.mapping
95+
.into_iter()
96+
.map(|(buf_offset, id, base_offset)| {
97+
let buf_offset = buf_offset.checked_add(offset).unwrap();
98+
(buf_offset, id, base_offset)
99+
})
100+
.collect_vec();
101+
DocsRangeMap { source_map: self.source_map, mapping }
102+
}
89103
}
90104

91105
pub fn docs_with_rangemap(
@@ -161,13 +175,20 @@ macro_rules! impl_has_docs {
161175
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
162176
docs_from_attrs(&self.attrs(db)).map(Documentation)
163177
}
178+
fn docs_with_rangemap(
179+
self,
180+
db: &dyn HirDatabase,
181+
) -> Option<(Documentation, DocsRangeMap)> {
182+
docs_with_rangemap(db, &self.attrs(db))
183+
}
164184
fn resolve_doc_path(
165185
self,
166186
db: &dyn HirDatabase,
167187
link: &str,
168-
ns: Option<hir::Namespace>
188+
ns: Option<hir::Namespace>,
189+
is_inner_doc: bool,
169190
) -> Option<hir::DocLinkDef> {
170-
resolve_doc_path_on(db, self, link, ns)
191+
resolve_doc_path_on(db, self, link, ns, is_inner_doc)
171192
}
172193
}
173194
)*};
@@ -184,13 +205,21 @@ macro_rules! impl_has_docs_enum {
184205
fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
185206
hir::$enum::$variant(self).docs(db)
186207
}
208+
209+
fn docs_with_rangemap(
210+
self,
211+
db: &dyn HirDatabase,
212+
) -> Option<(Documentation, DocsRangeMap)> {
213+
hir::$enum::$variant(self).docs_with_rangemap(db)
214+
}
187215
fn resolve_doc_path(
188216
self,
189217
db: &dyn HirDatabase,
190218
link: &str,
191-
ns: Option<hir::Namespace>
219+
ns: Option<hir::Namespace>,
220+
is_inner_doc: bool,
192221
) -> Option<hir::DocLinkDef> {
193-
hir::$enum::$variant(self).resolve_doc_path(db, link, ns)
222+
hir::$enum::$variant(self).resolve_doc_path(db, link, ns, is_inner_doc)
194223
}
195224
}
196225
)*};
@@ -207,16 +236,25 @@ impl HasDocs for hir::AssocItem {
207236
}
208237
}
209238

239+
fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)> {
240+
match self {
241+
hir::AssocItem::Function(it) => it.docs_with_rangemap(db),
242+
hir::AssocItem::Const(it) => it.docs_with_rangemap(db),
243+
hir::AssocItem::TypeAlias(it) => it.docs_with_rangemap(db),
244+
}
245+
}
246+
210247
fn resolve_doc_path(
211248
self,
212249
db: &dyn HirDatabase,
213250
link: &str,
214251
ns: Option<hir::Namespace>,
252+
is_inner_doc: bool,
215253
) -> Option<hir::DocLinkDef> {
216254
match self {
217-
hir::AssocItem::Function(it) => it.resolve_doc_path(db, link, ns),
218-
hir::AssocItem::Const(it) => it.resolve_doc_path(db, link, ns),
219-
hir::AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
255+
hir::AssocItem::Function(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
256+
hir::AssocItem::Const(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
257+
hir::AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
220258
}
221259
}
222260
}
@@ -238,13 +276,36 @@ impl HasDocs for hir::ExternCrateDecl {
238276
}
239277
.map(Documentation::new)
240278
}
279+
280+
fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)> {
281+
let crate_docs = docs_with_rangemap(db, &self.resolved_crate(db)?.root_module().attrs(db));
282+
let decl_docs = docs_with_rangemap(db, &self.attrs(db));
283+
match (decl_docs, crate_docs) {
284+
(None, None) => None,
285+
(Some(decl_docs), None) => Some(decl_docs),
286+
(None, Some(crate_docs)) => Some(crate_docs),
287+
(
288+
Some((Documentation(mut decl_docs), mut decl_range_map)),
289+
Some((Documentation(crate_docs), crate_range_map)),
290+
) => {
291+
decl_docs.push('\n');
292+
decl_docs.push('\n');
293+
let offset = TextSize::new(decl_docs.len() as u32);
294+
decl_docs += &crate_docs;
295+
let crate_range_map = crate_range_map.shift_docstring_line_range(offset);
296+
decl_range_map.mapping.extend(crate_range_map.mapping);
297+
Some((Documentation(decl_docs), decl_range_map))
298+
}
299+
}
300+
}
241301
fn resolve_doc_path(
242302
self,
243303
db: &dyn HirDatabase,
244304
link: &str,
245305
ns: Option<hir::Namespace>,
306+
is_inner_doc: bool,
246307
) -> Option<hir::DocLinkDef> {
247-
resolve_doc_path_on(db, self, link, ns)
308+
resolve_doc_path_on(db, self, link, ns, is_inner_doc)
248309
}
249310
}
250311

0 commit comments

Comments
 (0)