Respect item type in documentation lookup
Sometimes, there might be multiple items with the same name, for example std::u8 is both a module and a primitive. Previously, we could not determine which one Source::load_doc would return. With this patch, we add the ty parameter that can be used to filter by the item type.
This commit is contained in:
parent
c672a65d59
commit
5b2003b979
@ -10,6 +10,8 @@ SPDX-License-Identifier: MIT
|
||||
- Improve handling of different items with same name:
|
||||
- Add the item type to the item list if multiple matches are found in the
|
||||
search index.
|
||||
- Respect the item type when opening the documentation for an item that has
|
||||
been found in the search index.
|
||||
|
||||
## v0.2.0 (2020-08-11)
|
||||
|
||||
|
@ -40,7 +40,13 @@ impl fmt::Display for IndexItem {
|
||||
if self.description.is_empty() {
|
||||
write!(f, "{} ({})", &self.name, self.ty.name())
|
||||
} else {
|
||||
write!(f, "{} ({}): {}", &self.name, self.ty.name(), &self.description)
|
||||
write!(
|
||||
f,
|
||||
"{} ({}): {}",
|
||||
&self.name,
|
||||
self.ty.name(),
|
||||
&self.description
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
33
src/main.rs
33
src/main.rs
@ -46,7 +46,7 @@ fn main() -> anyhow::Result<()> {
|
||||
|
||||
let args = args::Args::load()?;
|
||||
let sources = load_sources(&args.source_paths, !args.no_default_sources)?;
|
||||
let doc = if let Some(doc) = find_doc(&sources, &args.keyword)? {
|
||||
let doc = if let Some(doc) = find_doc(&sources, &args.keyword, None)? {
|
||||
Some(doc)
|
||||
} else if !args.no_search {
|
||||
search_doc(&sources, &args.keyword)?
|
||||
@ -130,10 +130,11 @@ fn get_sysroot() -> Option<path::PathBuf> {
|
||||
fn find_doc(
|
||||
sources: &[Box<dyn source::Source>],
|
||||
name: &doc::Name,
|
||||
ty: Option<doc::ItemType>,
|
||||
) -> anyhow::Result<Option<doc::Doc>> {
|
||||
let fqn = name.clone().into();
|
||||
for source in sources {
|
||||
if let Some(doc) = source.find_doc(&fqn)? {
|
||||
if let Some(doc) = source.find_doc(&fqn, ty)? {
|
||||
return Ok(Some(doc));
|
||||
}
|
||||
}
|
||||
@ -150,7 +151,7 @@ fn search_doc(
|
||||
if let Some(item) = search_item(sources, name)? {
|
||||
use anyhow::Context;
|
||||
|
||||
let doc = find_doc(sources, &item.name)?
|
||||
let doc = find_doc(sources, &item.name, Some(item.ty))?
|
||||
.with_context(|| format!("Could not find documentation for {}", &item.name))?;
|
||||
Ok(Some(doc))
|
||||
} else {
|
||||
@ -242,26 +243,32 @@ mod tests {
|
||||
let path = ensure_docs();
|
||||
let sources = vec![source::get_source(path).unwrap()];
|
||||
|
||||
assert!(super::find_doc(&sources, &"kuchiki".to_owned().into())
|
||||
.unwrap()
|
||||
.is_some());
|
||||
assert!(
|
||||
super::find_doc(&sources, &"kuchiki::NodeRef".to_owned().into())
|
||||
super::find_doc(&sources, &"kuchiki".to_owned().into(), None)
|
||||
.unwrap()
|
||||
.is_some()
|
||||
);
|
||||
assert!(
|
||||
super::find_doc(&sources, &"kuchiki::NodeDataRef::as_node".to_owned().into())
|
||||
super::find_doc(&sources, &"kuchiki::NodeRef".to_owned().into(), None)
|
||||
.unwrap()
|
||||
.is_some()
|
||||
);
|
||||
assert!(super::find_doc(
|
||||
&sources,
|
||||
&"kuchiki::NodeDataRef::as_node".to_owned().into(),
|
||||
None
|
||||
)
|
||||
.unwrap()
|
||||
.is_some());
|
||||
assert!(
|
||||
super::find_doc(&sources, &"kuchiki::traits".to_owned().into(), None)
|
||||
.unwrap()
|
||||
.is_some()
|
||||
);
|
||||
assert!(
|
||||
super::find_doc(&sources, &"kuchiki::traits".to_owned().into())
|
||||
super::find_doc(&sources, &"kachiki".to_owned().into(), None)
|
||||
.unwrap()
|
||||
.is_some()
|
||||
.is_none()
|
||||
);
|
||||
assert!(super::find_doc(&sources, &"kachiki".to_owned().into())
|
||||
.unwrap()
|
||||
.is_none());
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,11 @@ use crate::parser;
|
||||
|
||||
/// Documentation source, for example a local directory.
|
||||
pub trait Source {
|
||||
fn find_doc(&self, name: &doc::Fqn) -> anyhow::Result<Option<doc::Doc>>;
|
||||
fn find_doc(
|
||||
&self,
|
||||
name: &doc::Fqn,
|
||||
ty: Option<doc::ItemType>,
|
||||
) -> anyhow::Result<Option<doc::Doc>>;
|
||||
fn load_index(&self) -> anyhow::Result<Option<index::Index>>;
|
||||
}
|
||||
|
||||
@ -34,6 +38,31 @@ impl DirSource {
|
||||
Self { path }
|
||||
}
|
||||
|
||||
fn find_doc_html(
|
||||
&self,
|
||||
path: &path::Path,
|
||||
name: &doc::Fqn,
|
||||
ty: Option<doc::ItemType>,
|
||||
) -> anyhow::Result<Option<doc::Doc>> {
|
||||
if let Some(ty) = ty {
|
||||
match ty {
|
||||
doc::ItemType::Module => self.get_module(&path, name),
|
||||
doc::ItemType::StructField
|
||||
| doc::ItemType::Variant
|
||||
| doc::ItemType::AssocType
|
||||
| doc::ItemType::AssocConst
|
||||
| doc::ItemType::Method => self.get_member(&path, name),
|
||||
_ => self.get_item(&path, name),
|
||||
}
|
||||
} else {
|
||||
self.get_item(&path, name)
|
||||
.transpose()
|
||||
.or_else(|| self.get_module(&path, name).transpose())
|
||||
.or_else(|| self.get_member(&path, name).transpose())
|
||||
.transpose()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_crate(&self, name: &str) -> Option<path::PathBuf> {
|
||||
log::info!(
|
||||
"Searching crate '{}' in dir source '{}'",
|
||||
@ -124,19 +153,18 @@ impl DirSource {
|
||||
}
|
||||
|
||||
impl Source for DirSource {
|
||||
fn find_doc(&self, name: &doc::Fqn) -> anyhow::Result<Option<doc::Doc>> {
|
||||
fn find_doc(
|
||||
&self,
|
||||
name: &doc::Fqn,
|
||||
ty: Option<doc::ItemType>,
|
||||
) -> anyhow::Result<Option<doc::Doc>> {
|
||||
log::info!(
|
||||
"Searching documentation for '{}' in dir source '{}'",
|
||||
name,
|
||||
self.path.display()
|
||||
);
|
||||
if let Some(crate_path) = self.get_crate(name.krate()) {
|
||||
let doc = self
|
||||
.get_item(&crate_path, name)
|
||||
.transpose()
|
||||
.or_else(|| self.get_module(&crate_path, name).transpose())
|
||||
.or_else(|| self.get_member(&crate_path, name).transpose())
|
||||
.transpose()?;
|
||||
let doc = self.find_doc_html(&crate_path, name, ty)?;
|
||||
if doc.is_some() {
|
||||
log::info!(
|
||||
"Found documentation for '{}' in dir source '{}'",
|
||||
|
Loading…
Reference in New Issue
Block a user