Store item type for items
Previously, we assumed that we only have to differentiate between items (= elements with their own documentation file) and members (= elements described in the documentation file of their parent). But this model was too simple. For example, there are big differences in the structure of a module and a struct documentation file. Therefore we introduce a new enum, ItemType, that stores the type of an item. This allows us to drop the member field of the Item struct and to add the name of the member to the full name of the item.
This commit is contained in:
parent
9613235ccc
commit
60cb034c5a
55
src/doc.rs
55
src/doc.rs
@ -21,6 +21,14 @@ pub struct Name {
|
||||
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Fqn(Name);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum ItemType {
|
||||
Crate,
|
||||
Module,
|
||||
Item,
|
||||
Member,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Crate {
|
||||
pub name: String,
|
||||
@ -29,9 +37,9 @@ pub struct Crate {
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Item {
|
||||
pub path: path::PathBuf,
|
||||
pub name: Fqn,
|
||||
pub member: Option<String>,
|
||||
pub ty: ItemType,
|
||||
pub path: path::PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@ -135,6 +143,10 @@ impl Fqn {
|
||||
self.first()
|
||||
}
|
||||
|
||||
pub fn is_crate(&self) -> bool {
|
||||
self.0.is_singleton()
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<Self> {
|
||||
self.0.parent().map(From::from)
|
||||
}
|
||||
@ -186,7 +198,11 @@ impl Crate {
|
||||
if let Some(local_name) = name.rest() {
|
||||
if let Some(path) = parser::find_item(self.path.join("all.html"), local_name)? {
|
||||
let path = path::PathBuf::from(path);
|
||||
return Ok(Some(Item::new(name.clone(), self.path.join(path), None)));
|
||||
return Ok(Some(Item::new(
|
||||
name.clone(),
|
||||
self.path.join(path),
|
||||
ItemType::Item,
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -205,7 +221,12 @@ impl Crate {
|
||||
};
|
||||
let path = self.path.join(module_path).join("index.html");
|
||||
if path.is_file() {
|
||||
Some(Item::new(name.clone(), path, None))
|
||||
let item_type = if name.is_crate() {
|
||||
ItemType::Crate
|
||||
} else {
|
||||
ItemType::Module
|
||||
};
|
||||
Some(Item::new(name.clone(), path, item_type))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -215,15 +236,11 @@ impl Crate {
|
||||
}
|
||||
|
||||
pub fn find_member(&self, name: &Fqn) -> Option<Item> {
|
||||
if self.name == name.krate() {
|
||||
if let Some(parent) = name.parent() {
|
||||
// TODO: error
|
||||
self.find_item(&parent)
|
||||
.unwrap()
|
||||
.and_then(|i| i.find_member(name.last()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
if let Some(parent) = name.parent() {
|
||||
// TODO: error
|
||||
self.find_item(&parent)
|
||||
.unwrap()
|
||||
.and_then(|i| i.find_member(name.last()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -231,13 +248,13 @@ impl Crate {
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn new(name: Fqn, path: path::PathBuf, member: Option<String>) -> Self {
|
||||
Item { path, member, name }
|
||||
pub fn new(name: Fqn, path: path::PathBuf, ty: ItemType) -> Self {
|
||||
Item { name, ty, path }
|
||||
}
|
||||
|
||||
pub fn load_doc(&self) -> anyhow::Result<Doc> {
|
||||
if let Some(member) = &self.member {
|
||||
parser::parse_member_doc(&self.path, &self.name, member)
|
||||
if self.ty == ItemType::Member {
|
||||
parser::parse_member_doc(&self.path, &self.name)
|
||||
} else {
|
||||
parser::parse_item_doc(&self.path, &self.name)
|
||||
}
|
||||
@ -247,9 +264,9 @@ impl Item {
|
||||
// TODO: error handling
|
||||
if parser::find_member(&self.path, name).unwrap() {
|
||||
Some(Item::new(
|
||||
self.name.clone(),
|
||||
self.name.child(name),
|
||||
self.path.clone(),
|
||||
Some(name.to_owned()),
|
||||
ItemType::Member,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
@ -96,19 +96,18 @@ pub fn parse_item_doc<P: AsRef<path::Path>>(path: P, name: &doc::Fqn) -> anyhow:
|
||||
|
||||
pub fn parse_member_doc<P: AsRef<path::Path>>(
|
||||
path: P,
|
||||
item: &doc::Fqn,
|
||||
name: &str,
|
||||
name: &doc::Fqn,
|
||||
) -> anyhow::Result<doc::Doc> {
|
||||
let document = parse_file(path)?;
|
||||
let member =
|
||||
get_member(&document, name)?.with_context(|| format!("Could not find member {}", name))?;
|
||||
let member = get_member(&document, name.last())?
|
||||
.with_context(|| format!("Could not find member {}", name))?;
|
||||
let heading = member
|
||||
.as_node()
|
||||
.parent()
|
||||
.with_context(|| format!("The member {} does not have a parent", name))?;
|
||||
let docblock = heading.next_sibling();
|
||||
|
||||
let mut doc = doc::Doc::new(item.child(name));
|
||||
let mut doc = doc::Doc::new(name.clone());
|
||||
doc.definition = Some(get_html(member.as_node())?);
|
||||
doc.description = docblock.map(|n| get_html(&n)).transpose()?;
|
||||
Ok(doc)
|
||||
@ -190,10 +189,10 @@ mod tests {
|
||||
fn test_parse_member_doc() {
|
||||
let path = crate::tests::ensure_docs();
|
||||
let path = path.join("kuchiki").join("struct.NodeDataRef.html");
|
||||
let name: doc::Fqn = "kuchiki::NodeDataRef".to_owned().into();
|
||||
let doc = super::parse_member_doc(&path, &name, "as_node").unwrap();
|
||||
let name: doc::Fqn = "kuchiki::NodeDataRef::as_node".to_owned().into();
|
||||
let doc = super::parse_member_doc(&path, &name).unwrap();
|
||||
|
||||
assert_eq!(name.child("as_node"), doc.name);
|
||||
assert_eq!(name, doc.name);
|
||||
assert!(doc.title.is_none());
|
||||
assert_eq!(
|
||||
"<code id=\"as_node.v\">\
|
||||
|
Loading…
Reference in New Issue
Block a user