Import item types from librustdoc
Previously, our ItemType enum only had three values: Module, Item and Member. With this patch we import the ItemType variants from librustdoc (see html/item_type.rs) for better compatibility and easier parsing.
This commit is contained in:
parent
bb3b361d02
commit
f799d860ca
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -480,6 +480,7 @@ dependencies = [
|
||||
"pager 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_tuple 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -537,6 +538,16 @@ dependencies = [
|
||||
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_tuple"
|
||||
version = "0.5.0"
|
||||
@ -812,6 +823,7 @@ dependencies = [
|
||||
"checksum serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
|
||||
"checksum serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
|
||||
"checksum serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)" = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3"
|
||||
"checksum serde_repr 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76"
|
||||
"checksum serde_tuple 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427"
|
||||
"checksum serde_tuple_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e"
|
||||
"checksum servo_arc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432"
|
||||
|
@ -18,6 +18,7 @@ html2text = "0.1.12"
|
||||
kuchiki = "0.8.0"
|
||||
pager = "0.15.0"
|
||||
serde_json = "1.0.56"
|
||||
serde_repr = "0.1.6"
|
||||
serde_tuple = "0.5.0"
|
||||
termion = "1.5.5"
|
||||
|
||||
|
109
src/doc.rs
109
src/doc.rs
@ -21,12 +21,35 @@ pub struct Name {
|
||||
#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Fqn(Name);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, serde_repr::Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum ItemType {
|
||||
Crate,
|
||||
Module,
|
||||
Item,
|
||||
Member,
|
||||
Module = 0,
|
||||
ExternCrate = 1,
|
||||
Import = 2,
|
||||
Struct = 3,
|
||||
Enum = 4,
|
||||
Function = 5,
|
||||
Typedef = 6,
|
||||
Static = 7,
|
||||
Trait = 8,
|
||||
Impl = 9,
|
||||
TyMethod = 10,
|
||||
Method = 11,
|
||||
StructField = 12,
|
||||
Variant = 13,
|
||||
Macro = 14,
|
||||
Primitive = 15,
|
||||
AssocType = 16,
|
||||
Constant = 17,
|
||||
AssocConst = 18,
|
||||
Union = 19,
|
||||
ForeignType = 20,
|
||||
Keyword = 21,
|
||||
OpaqueTy = 22,
|
||||
ProcAttribute = 23,
|
||||
ProcDerive = 24,
|
||||
TraitAlias = 25,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
@ -143,10 +166,6 @@ 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)
|
||||
}
|
||||
@ -188,6 +207,42 @@ impl ops::Deref for Fqn {
|
||||
}
|
||||
}
|
||||
|
||||
impl str::FromStr for ItemType {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"mod" => Ok(ItemType::Module),
|
||||
"externcrate" => Ok(ItemType::ExternCrate),
|
||||
"import" => Ok(ItemType::Import),
|
||||
"struct" => Ok(ItemType::Struct),
|
||||
"union" => Ok(ItemType::Union),
|
||||
"enum" => Ok(ItemType::Enum),
|
||||
"fn" => Ok(ItemType::Function),
|
||||
"type" => Ok(ItemType::Typedef),
|
||||
"static" => Ok(ItemType::Static),
|
||||
"trait" => Ok(ItemType::Trait),
|
||||
"impl" => Ok(ItemType::Impl),
|
||||
"tymethod" => Ok(ItemType::TyMethod),
|
||||
"method" => Ok(ItemType::Method),
|
||||
"structfield" => Ok(ItemType::StructField),
|
||||
"variant" => Ok(ItemType::Variant),
|
||||
"macro" => Ok(ItemType::Macro),
|
||||
"primitive" => Ok(ItemType::Primitive),
|
||||
"associatedtype" => Ok(ItemType::AssocType),
|
||||
"constant" => Ok(ItemType::Constant),
|
||||
"associatedconstant" => Ok(ItemType::AssocConst),
|
||||
"foreigntype" => Ok(ItemType::ForeignType),
|
||||
"keyword" => Ok(ItemType::Keyword),
|
||||
"opaque" => Ok(ItemType::OpaqueTy),
|
||||
"attr" => Ok(ItemType::ProcAttribute),
|
||||
"derive" => Ok(ItemType::ProcDerive),
|
||||
"traitalias" => Ok(ItemType::TraitAlias),
|
||||
_ => Err(anyhow::anyhow!("Unsupported item type: {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Crate {
|
||||
pub fn new(name: String, path: path::PathBuf) -> Self {
|
||||
Crate { name, path }
|
||||
@ -198,10 +253,12 @@ 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);
|
||||
let file_name = path.file_name().unwrap().to_str().unwrap();
|
||||
let item_type: ItemType = file_name.splitn(2, '.').next().unwrap().parse()?;
|
||||
return Ok(Some(Item::new(
|
||||
name.clone(),
|
||||
self.path.join(path),
|
||||
ItemType::Item,
|
||||
item_type,
|
||||
)));
|
||||
}
|
||||
}
|
||||
@ -221,12 +278,7 @@ impl Crate {
|
||||
};
|
||||
let path = self.path.join(module_path).join("index.html");
|
||||
if path.is_file() {
|
||||
let item_type = if name.is_crate() {
|
||||
ItemType::Crate
|
||||
} else {
|
||||
ItemType::Module
|
||||
};
|
||||
Some(Item::new(name.clone(), path, item_type))
|
||||
Some(Item::new(name.clone(), path, ItemType::Module))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -240,7 +292,7 @@ impl Crate {
|
||||
// TODO: error
|
||||
self.find_item(&parent)
|
||||
.unwrap()
|
||||
.and_then(|i| i.find_member(name.last()))
|
||||
.and_then(|i| i.find_member(name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -254,23 +306,20 @@ impl Item {
|
||||
|
||||
pub fn load_doc(&self) -> anyhow::Result<Doc> {
|
||||
match self.ty {
|
||||
ItemType::Member => parser::parse_member_doc(&self.path, &self.name),
|
||||
ItemType::Module | ItemType::Crate => parser::parse_module_doc(&self.path, &self.name),
|
||||
ItemType::Item => parser::parse_item_doc(&self.path, &self.name),
|
||||
ItemType::TyMethod
|
||||
| ItemType::Method
|
||||
| ItemType::StructField
|
||||
| ItemType::Variant
|
||||
| ItemType::AssocType
|
||||
| ItemType::AssocConst => parser::parse_member_doc(&self.path, &self.name),
|
||||
ItemType::Module => parser::parse_module_doc(&self.path, &self.name),
|
||||
_ => parser::parse_item_doc(&self.path, &self.name),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_member(&self, name: &str) -> Option<Item> {
|
||||
pub fn find_member(&self, name: &Fqn) -> Option<Item> {
|
||||
// TODO: error handling
|
||||
if parser::find_member(&self.path, name).unwrap() {
|
||||
Some(Item::new(
|
||||
self.name.child(name),
|
||||
self.path.clone(),
|
||||
ItemType::Member,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
parser::find_member(&self.path, name).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
21
src/index.rs
21
src/index.rs
@ -57,9 +57,9 @@ struct CrateData {
|
||||
paths: Vec<(usize, String)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, serde_tuple::Deserialize_tuple)]
|
||||
#[derive(Debug, PartialEq, serde_tuple::Deserialize_tuple)]
|
||||
struct ItemData {
|
||||
ty: usize,
|
||||
ty: doc::ItemType,
|
||||
name: String,
|
||||
path: String,
|
||||
desc: String,
|
||||
@ -122,8 +122,7 @@ impl Index {
|
||||
&item.path
|
||||
};
|
||||
|
||||
if item.ty == 16 {
|
||||
// Skip associated types (== item type 16)
|
||||
if item.ty == doc::ItemType::AssocType {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -152,6 +151,7 @@ impl Index {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{CrateData, Data, ItemData};
|
||||
use crate::doc::ItemType;
|
||||
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
@ -174,11 +174,14 @@ mod tests {
|
||||
fn test_one_item() {
|
||||
let mut expected: Data = Default::default();
|
||||
let mut krate: CrateData = Default::default();
|
||||
let mut item: ItemData = Default::default();
|
||||
item.name = "name".to_owned();
|
||||
item.path = "path".to_owned();
|
||||
item.desc = "desc".to_owned();
|
||||
krate.items.push(item);
|
||||
krate.items.push(ItemData {
|
||||
ty: ItemType::Module,
|
||||
name: "name".to_owned(),
|
||||
path: "path".to_owned(),
|
||||
desc: "desc".to_owned(),
|
||||
parent: None,
|
||||
_ignored: Default::default(),
|
||||
});
|
||||
expected.crates.insert("test".to_owned(), krate);
|
||||
let actual: Data = serde_json::from_str(
|
||||
"{\"test\": {\"i\": [[0, \"name\", \"path\", \"desc\", null, null]], \"p\": []}}",
|
||||
|
@ -37,9 +37,26 @@ pub fn find_item<P: AsRef<path::Path>>(path: P, item: &str) -> anyhow::Result<Op
|
||||
Ok(item)
|
||||
}
|
||||
|
||||
pub fn find_member<P: AsRef<path::Path>>(path: P, item: &str) -> anyhow::Result<bool> {
|
||||
let document = parse_file(path)?;
|
||||
Ok(get_member(&document, item)?.is_some())
|
||||
pub fn find_member<P: AsRef<path::Path>>(
|
||||
path: P,
|
||||
name: &doc::Fqn,
|
||||
) -> anyhow::Result<Option<doc::Item>> {
|
||||
let document = parse_file(path.as_ref())?;
|
||||
if let Some(member) = get_member(&document, name.last())? {
|
||||
let parent = member
|
||||
.as_node()
|
||||
.parent()
|
||||
.context("Member element does not have a parent")?;
|
||||
if let Some(parent_id) = get_attribute(parent.as_element().unwrap(), "id") {
|
||||
let item_type: doc::ItemType = parent_id.splitn(2, '.').next().unwrap().parse()?;
|
||||
return Ok(Some(doc::Item::new(
|
||||
name.clone(),
|
||||
path.as_ref().to_owned(),
|
||||
item_type,
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn select(
|
||||
@ -154,11 +171,7 @@ fn get_member(
|
||||
document: &kuchiki::NodeRef,
|
||||
name: &str,
|
||||
) -> anyhow::Result<Option<kuchiki::NodeDataRef<kuchiki::ElementData>>> {
|
||||
document
|
||||
.select(&format!("#{}\\.v", name))
|
||||
.ok()
|
||||
.context("Could not select member by id")
|
||||
.map(|mut i| i.next())
|
||||
select_first(document, &format!("#{}\\.v", name))
|
||||
}
|
||||
|
||||
fn get_attribute(element: &kuchiki::ElementData, name: &str) -> Option<String> {
|
||||
|
Loading…
Reference in New Issue
Block a user