|
34 | 34 | //! both occur before the crate is rendered.
|
35 | 35 | pub use self::ExternalLocation::*;
|
36 | 36 |
|
| 37 | +use std::ascii::OwnedAsciiExt; |
37 | 38 | use std::cell::RefCell;
|
38 | 39 | use std::cmp::Ordering;
|
39 | 40 | use std::collections::{HashMap, HashSet};
|
@@ -239,6 +240,51 @@ struct IndexItem {
|
239 | 240 | path: String,
|
240 | 241 | desc: String,
|
241 | 242 | parent: Option<ast::DefId>,
|
| 243 | + search_type: Option<IndexItemFunctionType>, |
| 244 | +} |
| 245 | + |
| 246 | +/// A type used for the search index. |
| 247 | +struct Type { |
| 248 | + name: Option<String>, |
| 249 | +} |
| 250 | + |
| 251 | +impl fmt::Display for Type { |
| 252 | + /// Formats type as {name: $name}. |
| 253 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 254 | + // Wrapping struct fmt should never call us when self.name is None, |
| 255 | + // but just to be safe we write `null` in that case. |
| 256 | + match self.name { |
| 257 | + Some(ref n) => write!(f, "{{\"name\":\"{}\"}}", n), |
| 258 | + None => write!(f, "null") |
| 259 | + } |
| 260 | + } |
| 261 | +} |
| 262 | + |
| 263 | +/// Full type of functions/methods in the search index. |
| 264 | +struct IndexItemFunctionType { |
| 265 | + inputs: Vec<Type>, |
| 266 | + output: Option<Type> |
| 267 | +} |
| 268 | + |
| 269 | +impl fmt::Display for IndexItemFunctionType { |
| 270 | + /// Formats a full fn type as a JSON {inputs: [Type], outputs: Type/null}. |
| 271 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 272 | + // If we couldn't figure out a type, just write `null`. |
| 273 | + if self.inputs.iter().any(|ref i| i.name.is_none()) || |
| 274 | + (self.output.is_some() && self.output.as_ref().unwrap().name.is_none()) { |
| 275 | + return write!(f, "null") |
| 276 | + } |
| 277 | + |
| 278 | + let inputs: Vec<String> = self.inputs.iter().map(|ref t| format!("{}", t)).collect(); |
| 279 | + try!(write!(f, "{{\"inputs\":[{}],\"output\":", inputs.connect(","))); |
| 280 | + |
| 281 | + match self.output { |
| 282 | + Some(ref t) => try!(write!(f, "{}", t)), |
| 283 | + None => try!(write!(f, "null")) |
| 284 | + }; |
| 285 | + |
| 286 | + Ok(try!(write!(f, "}}"))) |
| 287 | + } |
242 | 288 | }
|
243 | 289 |
|
244 | 290 | // TLS keys used to carry information around during rendering.
|
@@ -409,6 +455,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
|
409 | 455 | path: fqp[..fqp.len() - 1].connect("::"),
|
410 | 456 | desc: shorter(item.doc_value()).to_string(),
|
411 | 457 | parent: Some(did),
|
| 458 | + search_type: None, |
412 | 459 | });
|
413 | 460 | },
|
414 | 461 | None => {}
|
@@ -458,7 +505,11 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
|
458 | 505 | let pathid = *nodeid_to_pathid.get(&nodeid).unwrap();
|
459 | 506 | try!(write!(&mut w, ",{}", pathid));
|
460 | 507 | }
|
461 |
| - None => {} |
| 508 | + None => try!(write!(&mut w, ",null")) |
| 509 | + } |
| 510 | + match item.search_type { |
| 511 | + Some(ref t) => try!(write!(&mut w, ",{}", t)), |
| 512 | + None => try!(write!(&mut w, ",null")) |
462 | 513 | }
|
463 | 514 | try!(write!(&mut w, "]"));
|
464 | 515 | }
|
@@ -872,12 +923,21 @@ impl DocFolder for Cache {
|
872 | 923 |
|
873 | 924 | match parent {
|
874 | 925 | (parent, Some(path)) if is_method || (!self.privmod && !hidden_field) => {
|
| 926 | + // Needed to determine `self` type. |
| 927 | + let parent_basename = self.parent_stack.first().and_then(|parent| { |
| 928 | + match self.paths.get(parent) { |
| 929 | + Some(&(ref fqp, _)) => Some(fqp[fqp.len() - 1].clone()), |
| 930 | + _ => None |
| 931 | + } |
| 932 | + }); |
| 933 | + |
875 | 934 | self.search_index.push(IndexItem {
|
876 | 935 | ty: shortty(&item),
|
877 | 936 | name: s.to_string(),
|
878 | 937 | path: path.connect("::").to_string(),
|
879 | 938 | desc: shorter(item.doc_value()).to_string(),
|
880 | 939 | parent: parent,
|
| 940 | + search_type: get_index_search_type(&item, parent_basename), |
881 | 941 | });
|
882 | 942 | }
|
883 | 943 | (Some(parent), None) if is_method || (!self.privmod && !hidden_field)=> {
|
@@ -2307,6 +2367,52 @@ fn make_item_keywords(it: &clean::Item) -> String {
|
2307 | 2367 | format!("{}, {}", get_basic_keywords(), it.name.as_ref().unwrap())
|
2308 | 2368 | }
|
2309 | 2369 |
|
| 2370 | +fn get_index_search_type(item: &clean::Item, |
| 2371 | + parent: Option<String>) -> Option<IndexItemFunctionType> { |
| 2372 | + let decl = match item.inner { |
| 2373 | + clean::FunctionItem(ref f) => &f.decl, |
| 2374 | + clean::MethodItem(ref m) => &m.decl, |
| 2375 | + clean::TyMethodItem(ref m) => &m.decl, |
| 2376 | + _ => return None |
| 2377 | + }; |
| 2378 | + |
| 2379 | + let mut inputs = Vec::new(); |
| 2380 | + |
| 2381 | + // Consider `self` an argument as well. |
| 2382 | + if let Some(name) = parent { |
| 2383 | + inputs.push(Type { name: Some(name.into_ascii_lowercase()) }); |
| 2384 | + } |
| 2385 | + |
| 2386 | + inputs.extend(&mut decl.inputs.values.iter().map(|arg| { |
| 2387 | + get_index_type(&arg.type_) |
| 2388 | + })); |
| 2389 | + |
| 2390 | + let output = match decl.output { |
| 2391 | + clean::FunctionRetTy::Return(ref return_type) => Some(get_index_type(return_type)), |
| 2392 | + _ => None |
| 2393 | + }; |
| 2394 | + |
| 2395 | + Some(IndexItemFunctionType { inputs: inputs, output: output }) |
| 2396 | +} |
| 2397 | + |
| 2398 | +fn get_index_type(clean_type: &clean::Type) -> Type { |
| 2399 | + Type { name: get_index_type_name(clean_type).map(|s| s.into_ascii_lowercase()) } |
| 2400 | +} |
| 2401 | + |
| 2402 | +fn get_index_type_name(clean_type: &clean::Type) -> Option<String> { |
| 2403 | + match *clean_type { |
| 2404 | + clean::ResolvedPath { ref path, .. } => { |
| 2405 | + let segments = &path.segments; |
| 2406 | + Some(segments[segments.len() - 1].name.clone()) |
| 2407 | + }, |
| 2408 | + clean::Generic(ref s) => Some(s.clone()), |
| 2409 | + clean::Primitive(ref p) => Some(format!("{:?}", p)), |
| 2410 | + clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_), |
| 2411 | + // FIXME: add all from clean::Type. |
| 2412 | + _ => None |
| 2413 | + } |
| 2414 | +} |
| 2415 | + |
2310 | 2416 | pub fn cache() -> Arc<Cache> {
|
2311 | 2417 | CACHE_KEY.with(|c| c.borrow().clone())
|
2312 | 2418 | }
|
0 commit comments