use rustc::metadata::cstore;
use rustc::metadata::csearch;
use rustc::metadata::decoder;
+use rustc::middle::ty;
use std::strbuf::StrBuf;
pub attrs: Vec<Attribute> ,
pub inner: ItemEnum,
pub visibility: Option<Visibility>,
- pub id: ast::NodeId,
+ pub def_id: ast::DefId,
}
impl Item {
attrs: self.attrs.clean(),
source: where.clean(),
visibility: self.vis.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
inner: ModuleItem(Module {
is_crate: self.is_crate,
items: items.iter()
#[deriving(Clone, Encodable, Decodable)]
pub struct TyParam {
pub name: StrBuf,
- pub id: ast::NodeId,
+ pub did: ast::DefId,
pub bounds: Vec<TyParamBound>,
}
fn clean(&self) -> TyParam {
TyParam {
name: self.ident.clean(),
- id: self.id,
+ did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
bounds: self.bounds.clean().move_iter().collect(),
}
}
}
+impl Clean<TyParam> for ty::TypeParameterDef {
+ fn clean(&self) -> TyParam {
+ let cx = super::ctxtkey.get().unwrap();
+ cx.external_typarams.borrow_mut().get_mut_ref().insert(self.def_id,
+ self.ident.clean());
+ TyParam {
+ name: self.ident.clean(),
+ did: self.def_id,
+ bounds: self.bounds.clean(),
+ }
+ }
+}
+
#[deriving(Clone, Encodable, Decodable)]
pub enum TyParamBound {
RegionBound,
}
}
+fn external_path(name: &str) -> Path {
+ Path {
+ global: false,
+ segments: vec![PathSegment {
+ name: name.to_strbuf(),
+ lifetimes: Vec::new(),
+ types: Vec::new(),
+ }]
+ }
+}
+
+impl Clean<TyParamBound> for ty::BuiltinBound {
+ fn clean(&self) -> TyParamBound {
+ let cx = super::ctxtkey.get().unwrap();
+ let tcx = match cx.maybe_typed {
+ core::Typed(ref tcx) => tcx,
+ core::NotTyped(_) => return RegionBound,
+ };
+ let (did, path) = match *self {
+ ty::BoundStatic => return RegionBound,
+ ty::BoundSend =>
+ (tcx.lang_items.send_trait().unwrap(), external_path("Send")),
+ ty::BoundSized =>
+ (tcx.lang_items.sized_trait().unwrap(), external_path("Sized")),
+ ty::BoundCopy =>
+ (tcx.lang_items.copy_trait().unwrap(), external_path("Copy")),
+ ty::BoundShare =>
+ (tcx.lang_items.share_trait().unwrap(), external_path("Share")),
+ };
+ let fqn = csearch::get_item_path(tcx, did);
+ let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf()).collect();
+ cx.external_paths.borrow_mut().get_mut_ref().insert(did,
+ (fqn, TypeTrait));
+ TraitBound(ResolvedPath {
+ path: path,
+ typarams: None,
+ did: did,
+ })
+ }
+}
+
+impl Clean<TyParamBound> for ty::TraitRef {
+ fn clean(&self) -> TyParamBound {
+ let cx = super::ctxtkey.get().unwrap();
+ let tcx = match cx.maybe_typed {
+ core::Typed(ref tcx) => tcx,
+ core::NotTyped(_) => return RegionBound,
+ };
+ let fqn = csearch::get_item_path(tcx, self.def_id);
+ let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf())
+ .collect::<Vec<StrBuf>>();
+ let path = external_path(fqn.last().unwrap().as_slice());
+ cx.external_paths.borrow_mut().get_mut_ref().insert(self.def_id,
+ (fqn, TypeTrait));
+ TraitBound(ResolvedPath {
+ path: path,
+ typarams: None,
+ did: self.def_id,
+ })
+ }
+}
+
+impl Clean<Vec<TyParamBound>> for ty::ParamBounds {
+ fn clean(&self) -> Vec<TyParamBound> {
+ let mut v = Vec::new();
+ for b in self.builtin_bounds.iter() {
+ if b != ty::BoundSized {
+ v.push(b.clean());
+ }
+ }
+ for t in self.trait_bounds.iter() {
+ v.push(t.clean());
+ }
+ return v;
+ }
+}
+
+impl Clean<Option<Vec<TyParamBound>>> for ty::substs {
+ fn clean(&self) -> Option<Vec<TyParamBound>> {
+ let mut v = Vec::new();
+ match self.regions {
+ ty::NonerasedRegions(..) => v.push(RegionBound),
+ ty::ErasedRegions => {}
+ }
+ v.extend(self.tps.iter().map(|t| TraitBound(t.clean())));
+
+ if v.len() > 0 {Some(v)} else {None}
+ }
+}
+
#[deriving(Clone, Encodable, Decodable)]
pub struct Lifetime(StrBuf);
}
}
+impl Clean<Lifetime> for ty::RegionParameterDef {
+ fn clean(&self) -> Lifetime {
+ Lifetime(token::get_name(self.name).get().to_strbuf())
+ }
+}
+
+impl Clean<Option<Lifetime>> for ty::Region {
+ fn clean(&self) -> Option<Lifetime> {
+ match *self {
+ ty::ReStatic => Some(Lifetime("static".to_strbuf())),
+ ty::ReLateBound(_, ty::BrNamed(_, name)) =>
+ Some(Lifetime(token::get_name(name).get().to_strbuf())),
+
+ ty::ReLateBound(..) |
+ ty::ReEarlyBound(..) |
+ ty::ReFree(..) |
+ ty::ReScope(..) |
+ ty::ReInfer(..) |
+ ty::ReEmpty(..) => None
+ }
+ }
+}
+
// maybe use a Generic enum and use ~[Generic]?
#[deriving(Clone, Encodable, Decodable)]
pub struct Generics {
}
}
+impl Clean<Generics> for ty::Generics {
+ fn clean(&self) -> Generics {
+ Generics {
+ lifetimes: self.region_param_defs.clean(),
+ type_params: self.type_param_defs.clean(),
+ }
+ }
+}
+
#[deriving(Clone, Encodable, Decodable)]
pub struct Method {
pub generics: Generics,
name: Some(self.ident.clean()),
attrs: self.attrs.clean().move_iter().collect(),
source: self.span.clean(),
- id: self.id.clone(),
+ def_id: ast_util::local_def(self.id.clone()),
visibility: self.vis.clean(),
inner: MethodItem(Method {
generics: self.generics.clean(),
- self_: self.explicit_self.clean(),
+ self_: self.explicit_self.node.clean(),
fn_style: self.fn_style.clone(),
decl: decl,
}),
name: Some(self.ident.clean()),
attrs: self.attrs.clean().move_iter().collect(),
source: self.span.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: None,
inner: TyMethodItem(TyMethod {
fn_style: self.fn_style.clone(),
decl: decl,
- self_: self.explicit_self.clean(),
+ self_: self.explicit_self.node.clean(),
generics: self.generics.clean(),
}),
}
SelfOwned,
}
-impl Clean<SelfTy> for ast::ExplicitSelf {
+impl Clean<SelfTy> for ast::ExplicitSelf_ {
fn clean(&self) -> SelfTy {
- match self.node {
+ match *self {
ast::SelfStatic => SelfStatic,
ast::SelfValue => SelfValue,
ast::SelfUniq => SelfOwned,
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
inner: FunctionItem(Function {
decl: self.decl.clean(),
generics: self.generics.clean(),
impl Clean<ClosureDecl> for ast::ClosureTy {
fn clean(&self) -> ClosureDecl {
ClosureDecl {
- lifetimes: self.lifetimes.clean().move_iter().collect(),
+ lifetimes: self.lifetimes.clean(),
decl: self.decl.clean(),
onceness: self.onceness,
fn_style: self.fn_style,
}
}
+impl Clean<FnDecl> for ty::FnSig {
+ fn clean(&self) -> FnDecl {
+ FnDecl {
+ output: self.output.clean(),
+ cf: Return,
+ attrs: Vec::new(), // FIXME: this is likely wrong
+ inputs: Arguments {
+ values: self.inputs.iter().map(|t| {
+ Argument {
+ type_: t.clean(),
+ id: 0,
+ name: "".to_strbuf(), // FIXME: where are the names?
+ }
+ }).collect(),
+ },
+ }
+ }
+}
+
#[deriving(Clone, Encodable, Decodable)]
pub struct Argument {
pub type_: Type,
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
inner: TraitItem(Trait {
methods: self.methods.clean(),
}
}
+impl Clean<TraitMethod> for ty::Method {
+ fn clean(&self) -> TraitMethod {
+ let m = if self.provided_source.is_some() {Provided} else {Required};
+ let cx = super::ctxtkey.get().unwrap();
+ let tcx = match cx.maybe_typed {
+ core::Typed(ref tcx) => tcx,
+ core::NotTyped(_) => fail!(),
+ };
+ let mut attrs = Vec::new();
+ csearch::get_item_attrs(&tcx.sess.cstore, self.def_id, |v| {
+ attrs.extend(v.move_iter().map(|i| i.clean()));
+ });
+ let (self_, sig) = match self.explicit_self {
+ ast::SelfStatic => (ast::SelfStatic.clean(), self.fty.sig.clone()),
+ s => {
+ let sig = ty::FnSig {
+ inputs: Vec::from_slice(self.fty.sig.inputs.slice_from(1)),
+ ..self.fty.sig.clone()
+ };
+ let s = match s {
+ ast::SelfRegion(..) => {
+ match ty::get(*self.fty.sig.inputs.get(0)).sty {
+ ty::ty_rptr(r, mt) => {
+ SelfBorrowed(r.clean(), mt.mutbl.clean())
+ }
+ _ => s.clean(),
+ }
+ }
+ s => s.clean(),
+ };
+ (s, sig)
+ }
+ };
+ m(Item {
+ name: Some(self.ident.clean()),
+ visibility: Some(ast::Inherited),
+ def_id: self.def_id,
+ attrs: attrs,
+ source: Span {
+ filename: "".to_strbuf(),
+ loline: 0, locol: 0, hiline: 0, hicol: 0,
+ },
+ inner: TyMethodItem(TyMethod {
+ fn_style: self.fty.fn_style,
+ generics: self.generics.clean(),
+ self_: self_,
+ decl: sig.clean(),
+ })
+ })
+ }
+}
+
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
/// it does not preserve mutability or boxes.
TyParamBinder(ast::NodeId),
/// For parameterized types, so the consumer of the JSON don't go looking
/// for types which don't exist anywhere.
- Generic(ast::NodeId),
+ Generic(ast::DefId),
/// For references to self
- Self(ast::NodeId),
+ Self(ast::DefId),
/// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
Primitive(ast::PrimTy),
Closure(Box<ClosureDecl>, Option<Lifetime>),
}
}
+impl Clean<Type> for ty::t {
+ fn clean(&self) -> Type {
+ match ty::get(*self).sty {
+ ty::ty_nil => Unit,
+ ty::ty_bot => Bottom,
+ ty::ty_bool => Bool,
+ ty::ty_char => Primitive(ast::TyChar),
+ ty::ty_int(t) => Primitive(ast::TyInt(t)),
+ ty::ty_uint(u) => Primitive(ast::TyUint(u)),
+ ty::ty_float(f) => Primitive(ast::TyFloat(f)),
+ ty::ty_box(t) => Managed(box t.clean()),
+ ty::ty_uniq(t) => Unique(box t.clean()),
+ ty::ty_str => String,
+ ty::ty_vec(mt, None) => Vector(box mt.ty.clean()),
+ ty::ty_vec(mt, Some(i)) => FixedVector(box mt.ty.clean(),
+ format_strbuf!("{}", i)),
+ ty::ty_ptr(mt) => RawPointer(mt.mutbl.clean(), box mt.ty.clean()),
+ ty::ty_rptr(r, mt) => BorrowedRef {
+ lifetime: r.clean(),
+ mutability: mt.mutbl.clean(),
+ type_: box mt.ty.clean(),
+ },
+ ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl {
+ fn_style: fty.fn_style,
+ generics: Generics {
+ lifetimes: Vec::new(), type_params: Vec::new()
+ },
+ decl: fty.sig.clean(),
+ abi: fty.abi.to_str().to_strbuf(),
+ }),
+ ty::ty_closure(ref fty) => {
+ let decl = box ClosureDecl {
+ lifetimes: Vec::new(), // FIXME: this looks wrong...
+ decl: fty.sig.clean(),
+ onceness: fty.onceness,
+ fn_style: fty.fn_style,
+ bounds: fty.bounds.iter().map(|i| i.clean()).collect(),
+ };
+ match fty.store {
+ ty::UniqTraitStore => Proc(decl),
+ ty::RegionTraitStore(ref r, _) => Closure(decl, r.clean()),
+ }
+ }
+ ty::ty_struct(did, ref substs) |
+ ty::ty_enum(did, ref substs) |
+ ty::ty_trait(box ty::TyTrait { def_id: did, ref substs, .. }) => {
+ let cx = super::ctxtkey.get().unwrap();
+ let tcx = match cx.maybe_typed {
+ core::Typed(ref tycx) => tycx,
+ core::NotTyped(_) => fail!(),
+ };
+ let fqn = csearch::get_item_path(tcx, did);
+ let fqn: Vec<StrBuf> = fqn.move_iter().map(|i| {
+ i.to_str().to_strbuf()
+ }).collect();
+ let mut path = external_path(fqn.last().unwrap().to_str());
+ let kind = match ty::get(*self).sty {
+ ty::ty_struct(..) => TypeStruct,
+ ty::ty_trait(..) => TypeTrait,
+ _ => TypeEnum,
+ };
+ path.segments.get_mut(0).lifetimes = match substs.regions {
+ ty::ErasedRegions => Vec::new(),
+ ty::NonerasedRegions(ref v) => {
+ v.iter().filter_map(|v| v.clean()).collect()
+ }
+ };
+ path.segments.get_mut(0).types = substs.tps.clean();
+ cx.external_paths.borrow_mut().get_mut_ref().insert(did,
+ (fqn, kind));
+ ResolvedPath {
+ path: path,
+ typarams: None,
+ did: did,
+ }
+ }
+ ty::ty_tup(ref t) => Tuple(t.iter().map(|t| t.clean()).collect()),
+
+ ty::ty_param(ref p) => Generic(p.def_id),
+ ty::ty_self(did) => Self(did),
+
+ ty::ty_infer(..) => fail!("ty_infer"),
+ ty::ty_err => fail!("ty_err"),
+ }
+ }
+}
+
#[deriving(Clone, Encodable, Decodable)]
pub enum StructField {
HiddenStructField, // inserted later by strip passes
attrs: self.node.attrs.clean().move_iter().collect(),
source: self.span.clean(),
visibility: Some(vis),
- id: self.node.id,
+ def_id: ast_util::local_def(self.node.id),
inner: StructFieldItem(TypedStructField(self.node.ty.clean())),
}
}
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
inner: StructItem(Struct {
struct_type: self.struct_type,
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
inner: EnumItem(Enum {
variants: self.variants.clean(),
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: self.vis.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
inner: VariantItem(Variant {
kind: self.kind.clean(),
}),
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
- id: self.id.clone(),
+ def_id: ast_util::local_def(self.id.clone()),
visibility: self.vis.clean(),
inner: TypedefItem(Typedef {
type_: self.ty.clean(),
name: Some(self.name.clean()),
attrs: self.attrs.clean(),
source: self.where.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
inner: StaticItem(Static {
type_: self.type_.clean(),
name: None,
attrs: self.attrs.clean(),
source: self.where.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
inner: ImplItem(Impl {
generics: self.generics.clean(),
name: None,
attrs: self.attrs.clean().move_iter().collect(),
source: self.span.clean(),
- id: 0,
+ def_id: ast_util::local_def(0),
visibility: self.vis.clean(),
inner: ViewItemItem(ViewItem {
inner: self.node.clean()
name: Some(self.ident.clean()),
attrs: self.attrs.clean().move_iter().collect(),
source: self.span.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
visibility: self.vis.clean(),
inner: inner,
}
}
/// Given a Type, resolve it using the def_map
-fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound> >,
+fn resolve_type(path: Path, tpbs: Option<Vec<TyParamBound>>,
id: ast::NodeId) -> Type {
let cx = super::ctxtkey.get().unwrap();
let tycx = match cx.maybe_typed {
};
match def {
- ast::DefSelfTy(i) => return Self(i),
+ ast::DefSelfTy(i) => return Self(ast_util::local_def(i)),
ast::DefPrimTy(p) => match p {
ast::TyStr => return String,
ast::TyBool => return Bool,
_ => return Primitive(p)
},
- ast::DefTyParam(i, _) => return Generic(i.node),
+ ast::DefTyParam(i, _) => return Generic(i),
ast::DefTyParamBinder(i) => return TyParamBinder(i),
_ => {}
};
let fqn = fqn.move_iter().map(|i| i.to_str().to_strbuf()).collect();
debug!("recording {} => {}", did, fqn);
cx.external_paths.borrow_mut().get_mut_ref().insert(did, (fqn, kind));
+ match kind {
+ TypeTrait => {
+ let t = build_external_trait(tcx, did);
+ cx.external_traits.borrow_mut().get_mut_ref().insert(did, t);
+ }
+ _ => {}
+ }
return did;
}
+fn build_external_trait(tcx: &ty::ctxt, did: ast::DefId) -> Trait {
+ let def = csearch::get_trait_def(tcx, did);
+ let methods = ty::trait_methods(tcx, did);
+ Trait {
+ generics: def.generics.clean(),
+ methods: methods.iter().map(|i| i.clean()).collect(),
+ parents: Vec::new(), // FIXME: this is likely wrong
+ }
+}
+
fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
ImportSource {
path: path,
attrs: self.attrs.clean(),
source: self.where.clean(),
visibility: ast::Public.clean(),
- id: self.id,
+ def_id: ast_util::local_def(self.id),
inner: MacroItem(Macro {
source: self.where.to_src(),
}),