Skip to content

Commit

Permalink
Support type search for arguments and returned types
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeGomez committed Mar 16, 2020
1 parent 59f4ba9 commit b9167e6
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 103 deletions.
20 changes: 20 additions & 0 deletions src/librustdoc/clean/mod.rs
Expand Up @@ -1078,6 +1078,26 @@ impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
}
}

impl Clean<TypeKind> for hir::def::DefKind {
fn clean(&self, _: &DocContext<'_>) -> TypeKind {
match *self {
hir::def::DefKind::Mod => TypeKind::Module,
hir::def::DefKind::Struct => TypeKind::Struct,
hir::def::DefKind::Union => TypeKind::Union,
hir::def::DefKind::Enum => TypeKind::Enum,
hir::def::DefKind::Trait => TypeKind::Trait,
hir::def::DefKind::TyAlias => TypeKind::Typedef,
hir::def::DefKind::ForeignTy => TypeKind::Foreign,
hir::def::DefKind::TraitAlias => TypeKind::TraitAlias,
hir::def::DefKind::Fn => TypeKind::Function,
hir::def::DefKind::Const => TypeKind::Const,
hir::def::DefKind::Static => TypeKind::Static,
hir::def::DefKind::Macro(_) => TypeKind::Macro,
_ => TypeKind::Foreign,
}
}
}

impl Clean<Item> for hir::TraitItem<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let inner = match self.kind {
Expand Down
14 changes: 7 additions & 7 deletions src/librustdoc/clean/types.rs
Expand Up @@ -836,26 +836,26 @@ pub struct Method {
pub decl: FnDecl,
pub header: hir::FnHeader,
pub defaultness: Option<hir::Defaultness>,
pub all_types: Vec<Type>,
pub ret_types: Vec<Type>,
pub all_types: Vec<(Type, TypeKind)>,
pub ret_types: Vec<(Type, TypeKind)>,
}

#[derive(Clone, Debug)]
pub struct TyMethod {
pub header: hir::FnHeader,
pub decl: FnDecl,
pub generics: Generics,
pub all_types: Vec<Type>,
pub ret_types: Vec<Type>,
pub all_types: Vec<(Type, TypeKind)>,
pub ret_types: Vec<(Type, TypeKind)>,
}

#[derive(Clone, Debug)]
pub struct Function {
pub decl: FnDecl,
pub generics: Generics,
pub header: hir::FnHeader,
pub all_types: Vec<Type>,
pub ret_types: Vec<Type>,
pub all_types: Vec<(Type, TypeKind)>,
pub ret_types: Vec<(Type, TypeKind)>,
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
Expand Down Expand Up @@ -1042,7 +1042,7 @@ pub enum PrimitiveType {
Never,
}

#[derive(Clone, Copy, Debug)]
#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)]
pub enum TypeKind {
Enum,
Function,
Expand Down
40 changes: 31 additions & 9 deletions src/librustdoc/clean/utils.rs
Expand Up @@ -184,7 +184,7 @@ pub fn get_real_types(
arg: &Type,
cx: &DocContext<'_>,
recurse: i32,
) -> FxHashSet<Type> {
) -> FxHashSet<(Type, TypeKind)> {
let arg_s = arg.print().to_string();
let mut res = FxHashSet::default();
if recurse >= 10 {
Expand All @@ -209,7 +209,11 @@ pub fn get_real_types(
if !adds.is_empty() {
res.extend(adds);
} else if !ty.is_full_generic() {
res.insert(ty);
if let Some(did) = ty.def_id() {
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
res.insert((ty, kind));
}
}
}
}
}
Expand All @@ -225,22 +229,32 @@ pub fn get_real_types(
if !adds.is_empty() {
res.extend(adds);
} else if !ty.is_full_generic() {
res.insert(ty.clone());
if let Some(did) = ty.def_id() {
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
res.insert((ty.clone(), kind));
}
}
}
}
}
}
} else {
res.insert(arg.clone());
if let Some(did) = arg.def_id() {
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
res.insert((arg.clone(), kind));
}
}
if let Some(gens) = arg.generics() {
for gen in gens.iter() {
if gen.is_full_generic() {
let adds = get_real_types(generics, gen, cx, recurse + 1);
if !adds.is_empty() {
res.extend(adds);
}
} else {
res.insert(gen.clone());
} else if let Some(did) = gen.def_id() {
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
res.insert((gen.clone(), kind));
}
}
}
}
Expand All @@ -256,7 +270,7 @@ pub fn get_all_types(
generics: &Generics,
decl: &FnDecl,
cx: &DocContext<'_>,
) -> (Vec<Type>, Vec<Type>) {
) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) {
let mut all_types = FxHashSet::default();
for arg in decl.inputs.values.iter() {
if arg.type_.is_self_type() {
Expand All @@ -266,15 +280,23 @@ pub fn get_all_types(
if !args.is_empty() {
all_types.extend(args);
} else {
all_types.insert(arg.type_.clone());
if let Some(did) = arg.type_.def_id() {
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
all_types.insert((arg.type_.clone(), kind));
}
}
}
}

let ret_types = match decl.output {
FnRetTy::Return(ref return_type) => {
let mut ret = get_real_types(generics, &return_type, cx, 0);
if ret.is_empty() {
ret.insert(return_type.clone());
if let Some(did) = return_type.def_id() {
if let Some(kind) = cx.tcx.def_kind(did).clean(cx) {
ret.insert((return_type.clone(), kind));
}
}
}
ret.into_iter().collect()
}
Expand Down
69 changes: 62 additions & 7 deletions src/librustdoc/html/render.rs
Expand Up @@ -58,7 +58,7 @@ use rustc_span::symbol::{sym, Symbol};
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};

use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy};
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
use crate::config::{OutputFormat, RenderOptions};
use crate::docfs::{DocFS, ErrorStorage, PathError};
use crate::doctree;
Expand Down Expand Up @@ -303,8 +303,10 @@ impl Serialize for IndexItem {
/// A type used for the search index.
#[derive(Debug)]
struct Type {
ty: Option<DefId>,
idx: Option<usize>,
name: Option<String>,
generics: Option<Vec<String>>,
generics: Option<Vec<Generic>>,
}

impl Serialize for Type {
Expand All @@ -314,7 +316,11 @@ impl Serialize for Type {
{
if let Some(name) = &self.name {
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element(&name)?;
if let Some(id) = self.idx {
seq.serialize_element(&id)?;
} else {
seq.serialize_element(&name)?;
}
if let Some(generics) = &self.generics {
seq.serialize_element(&generics)?;
}
Expand All @@ -325,11 +331,32 @@ impl Serialize for Type {
}
}

/// A type used for the search index.
#[derive(Debug)]
struct Generic {
name: String,
defid: Option<DefId>,
idx: Option<usize>,
}

impl Serialize for Generic {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if let Some(id) = self.idx {
serializer.serialize_some(&id)
} else {
serializer.serialize_some(&self.name)
}
}
}

/// Full type of functions/methods in the search index.
#[derive(Debug)]
struct IndexItemFunctionType {
inputs: Vec<Type>,
output: Option<Vec<Type>>,
inputs: Vec<TypeWithKind>,
output: Option<Vec<TypeWithKind>>,
}

impl Serialize for IndexItemFunctionType {
Expand All @@ -340,8 +367,8 @@ impl Serialize for IndexItemFunctionType {
// If we couldn't figure out a type, just write `null`.
let mut iter = self.inputs.iter();
if match self.output {
Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()),
None => iter.any(|ref i| i.name.is_none()),
Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()),
None => iter.any(|ref i| i.ty.name.is_none()),
} {
serializer.serialize_none()
} else {
Expand All @@ -359,6 +386,34 @@ impl Serialize for IndexItemFunctionType {
}
}

#[derive(Debug)]
pub struct TypeWithKind {
ty: Type,
kind: TypeKind,
}

impl From<(Type, TypeKind)> for TypeWithKind {
fn from(x: (Type, TypeKind)) -> TypeWithKind {
TypeWithKind {
ty: x.0,
kind: x.1,
}
}
}

impl Serialize for TypeWithKind {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(None)?;
seq.serialize_element(&self.ty.name)?;
let x: ItemType = self.kind.into();
seq.serialize_element(&x)?;
seq.end()
}
}

thread_local!(static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
thread_local!(pub static CURRENT_DEPTH: Cell<usize> = Cell::new(0));

Expand Down
47 changes: 29 additions & 18 deletions src/librustdoc/html/render/cache.rs
Expand Up @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf};
use serde::Serialize;

use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType};
use super::{RenderInfo, Type};
use super::{Generic, RenderInfo, Type, TypeWithKind};

/// Indicates where an external crate can be found.
pub enum ExternalLocation {
Expand Down Expand Up @@ -588,19 +588,22 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
let mut lastpathid = 0usize;

for item in search_index {
item.parent_idx = item.parent.map(|defid| {
if defid_to_pathid.contains_key(&defid) {
*defid_to_pathid.get(&defid).expect("no pathid")
} else {
let pathid = lastpathid;
defid_to_pathid.insert(defid, pathid);
lastpathid += 1;
item.parent_idx = item.parent.and_then(|defid| {
if defid_to_pathid.contains_key(&defid) {
defid_to_pathid.get(&defid).map(|x| *x)
} else {
let pathid = lastpathid;
defid_to_pathid.insert(defid, pathid);
lastpathid += 1;

let &(ref fqp, short) = paths.get(&defid).unwrap();
if let Some(&(ref fqp, short)) = paths.get(&defid) {
crate_paths.push((short, fqp.last().unwrap().clone()));
pathid
Some(pathid)
} else {
None
}
});
}
});

// Omit the parent path if it is same to that of the prior item.
if lastpath == item.path {
Expand Down Expand Up @@ -647,12 +650,15 @@ fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {
_ => return None,
};

let inputs =
all_types.iter().map(|arg| get_index_type(&arg)).filter(|a| a.name.is_some()).collect();
let inputs = all_types
.iter()
.map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
.filter(|a| a.ty.name.is_some())
.collect();
let output = ret_types
.iter()
.map(|arg| get_index_type(&arg))
.filter(|a| a.name.is_some())
.map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind)))
.filter(|a| a.ty.name.is_some())
.collect::<Vec<_>>();
let output = if output.is_empty() { None } else { Some(output) };

Expand All @@ -661,6 +667,8 @@ fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> {

fn get_index_type(clean_type: &clean::Type) -> Type {
let t = Type {
ty: clean_type.def_id(),
idx: None,
name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()),
generics: get_generics(clean_type),
};
Expand All @@ -685,12 +693,15 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
}
}

fn get_generics(clean_type: &clean::Type) -> Option<Vec<String>> {
fn get_generics(clean_type: &clean::Type) -> Option<Vec<Generic>> {
clean_type.generics().and_then(|types| {
let r = types
.iter()
.filter_map(|t| get_index_type_name(t, false))
.map(|s| s.to_ascii_lowercase())
.filter_map(|t| if let Some(name) = get_index_type_name(t, false) {
Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None })
} else {
None
})
.collect::<Vec<_>>();
if r.is_empty() { None } else { Some(r) }
})
Expand Down

0 comments on commit b9167e6

Please sign in to comment.