1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use rustc::hir::def_id::DefId;
14 use rustc_serialize::json::as_json;
17 use data::{VariableKind, Visibility, SigElement};
22 // A dumper to dump a restricted set of JSON information, designed for use with
23 // libraries distributed without their source. Clients are likely to use type
24 // information here, and (for example) generate Rustdoc URLs, but don't need
25 // information for navigating the source of the crate.
26 // Relative to the regular JSON save-analysis info, this form is filtered to
27 // remove non-visible items, but includes some extra info for items (e.g., the
28 // parent field for finding the struct to which a field belongs).
29 pub struct JsonApiDumper<'b, W: Write + 'b> {
34 impl<'b, W: Write> JsonApiDumper<'b, W> {
35 pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> {
36 JsonApiDumper { output: writer, result: Analysis::new() }
40 impl<'b, W: Write> Drop for JsonApiDumper<'b, W> {
42 if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
43 error!("Error writing output");
48 macro_rules! impl_fn {
49 ($fn_name: ident, $data_type: ident, $bucket: ident) => {
50 fn $fn_name(&mut self, data: $data_type) {
51 if let Some(datum) = From::from(data) {
52 self.result.$bucket.push(datum);
58 impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> {
59 fn crate_prelude(&mut self, data: CratePreludeData) {
60 self.result.prelude = Some(data)
63 impl_fn!(use_data, UseData, imports);
64 impl_fn!(use_glob, UseGlobData, imports);
66 impl_fn!(enum_data, EnumData, defs);
67 impl_fn!(tuple_variant, TupleVariantData, defs);
68 impl_fn!(struct_variant, StructVariantData, defs);
69 impl_fn!(struct_data, StructData, defs);
70 impl_fn!(trait_data, TraitData, defs);
71 impl_fn!(function, FunctionData, defs);
72 impl_fn!(method, MethodData, defs);
73 impl_fn!(macro_data, MacroData, defs);
74 impl_fn!(mod_data, ModData, defs);
75 impl_fn!(typedef, TypeDefData, defs);
76 impl_fn!(variable, VariableData, defs);
78 fn impl_data(&mut self, data: ImplData) {
79 if data.self_ref.is_some() {
80 self.result.relations.push(From::from(data));
83 fn inheritance(&mut self, data: InheritanceData) {
84 self.result.relations.push(From::from(data));
88 // FIXME methods. The defs have information about possible overriding and the
89 // refs have decl information (e.g., a trait method where we know the required
90 // method, but not the supplied method). In both cases, we are currently
93 #[derive(Debug, RustcEncodable)]
96 prelude: Option<CratePreludeData>,
99 relations: Vec<Relation>,
100 // These two fields are dummies so that clients can parse the two kinds of
101 // JSON data in the same way.
107 fn new() -> Analysis {
109 kind: Format::JsonApi,
120 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
121 // we use our own Id which is the same, but without the newtype.
122 #[derive(Debug, RustcEncodable)]
128 impl From<DefId> for Id {
129 fn from(id: DefId) -> Id {
131 krate: id.krate.as_u32(),
132 index: id.index.as_u32(),
137 #[derive(Debug, RustcEncodable)]
146 #[derive(Debug, RustcEncodable)]
152 impl From<UseData> for Option<Import> {
153 fn from(data: UseData) -> Option<Import> {
154 match data.visibility {
155 Visibility::Public => Some(Import {
156 kind: ImportKind::Use,
157 id: From::from(data.id),
160 value: String::new(),
166 impl From<UseGlobData> for Option<Import> {
167 fn from(data: UseGlobData) -> Option<Import> {
168 match data.visibility {
169 Visibility::Public => Some(Import {
170 kind: ImportKind::GlobUse,
171 id: From::from(data.id),
173 name: "*".to_owned(),
174 value: data.names.join(", "),
181 #[derive(Debug, RustcEncodable)]
193 sig: Option<JsonSignature>,
196 #[derive(Debug, RustcEncodable)]
198 // value = variant names
200 // value = enum name + variant name + types
202 // value = [enum name +] name + fields
206 // value = type + generics
208 // value = type + generics
214 // value = aliased type
216 // value = type and init expression (for all variable kinds).
222 impl From<EnumData> for Option<Def> {
223 fn from(data: EnumData) -> Option<Def> {
224 match data.visibility {
225 Visibility::Public => Some(Def {
227 id: From::from(data.id),
230 qualname: data.qualname,
233 children: data.variants.into_iter().map(|id| From::from(id)).collect(),
236 sig: Some(From::from(data.sig)),
243 impl From<TupleVariantData> for Option<Def> {
244 fn from(data: TupleVariantData) -> Option<Def> {
246 kind: DefKind::Tuple,
247 id: From::from(data.id),
250 qualname: data.qualname,
252 parent: data.parent.map(|id| From::from(id)),
256 sig: Some(From::from(data.sig)),
260 impl From<StructVariantData> for Option<Def> {
261 fn from(data: StructVariantData) -> Option<Def> {
263 kind: DefKind::Struct,
264 id: From::from(data.id),
267 qualname: data.qualname,
269 parent: data.parent.map(|id| From::from(id)),
273 sig: Some(From::from(data.sig)),
277 impl From<StructData> for Option<Def> {
278 fn from(data: StructData) -> Option<Def> {
279 match data.visibility {
280 Visibility::Public => Some(Def {
281 kind: DefKind::Struct,
282 id: From::from(data.id),
285 qualname: data.qualname,
288 children: data.fields.into_iter().map(|id| From::from(id)).collect(),
291 sig: Some(From::from(data.sig)),
297 impl From<TraitData> for Option<Def> {
298 fn from(data: TraitData) -> Option<Def> {
299 match data.visibility {
300 Visibility::Public => Some(Def {
301 kind: DefKind::Trait,
302 id: From::from(data.id),
305 qualname: data.qualname,
307 children: data.items.into_iter().map(|id| From::from(id)).collect(),
311 sig: Some(From::from(data.sig)),
317 impl From<FunctionData> for Option<Def> {
318 fn from(data: FunctionData) -> Option<Def> {
319 match data.visibility {
320 Visibility::Public => Some(Def {
321 kind: DefKind::Function,
322 id: From::from(data.id),
325 qualname: data.qualname,
328 parent: data.parent.map(|id| From::from(id)),
331 sig: Some(From::from(data.sig)),
337 impl From<MethodData> for Option<Def> {
338 fn from(data: MethodData) -> Option<Def> {
339 match data.visibility {
340 Visibility::Public => Some(Def {
341 kind: DefKind::Method,
342 id: From::from(data.id),
345 qualname: data.qualname,
348 parent: data.parent.map(|id| From::from(id)),
349 decl_id: data.decl_id.map(|id| From::from(id)),
351 sig: Some(From::from(data.sig)),
357 impl From<MacroData> for Option<Def> {
358 fn from(data: MacroData) -> Option<Def> {
360 kind: DefKind::Macro,
361 id: From::from(null_def_id()),
364 qualname: data.qualname,
365 value: String::new(),
374 impl From<ModData> for Option<Def> {
375 fn from(data:ModData) -> Option<Def> {
376 match data.visibility {
377 Visibility::Public => Some(Def {
379 id: From::from(data.id),
382 qualname: data.qualname,
383 value: data.filename,
384 children: data.items.into_iter().map(|id| From::from(id)).collect(),
388 sig: Some(From::from(data.sig)),
394 impl From<TypeDefData> for Option<Def> {
395 fn from(data: TypeDefData) -> Option<Def> {
396 match data.visibility {
397 Visibility::Public => Some(Def {
399 id: From::from(data.id),
402 qualname: data.qualname,
405 parent: data.parent.map(|id| From::from(id)),
408 sig: data.sig.map(|s| From::from(s)),
415 impl From<VariableData> for Option<Def> {
416 fn from(data: VariableData) -> Option<Def> {
417 match data.visibility {
418 Visibility::Public => Some(Def {
419 kind: match data.kind {
420 VariableKind::Static => DefKind::Static,
421 VariableKind::Const => DefKind::Const,
422 VariableKind::Local => { return None }
423 VariableKind::Field => DefKind::Field,
425 id: From::from(data.id),
428 qualname: data.qualname,
431 parent: data.parent.map(|id| From::from(id)),
434 sig: data.sig.map(|s| From::from(s)),
441 #[derive(Debug, RustcEncodable)]
449 #[derive(Debug, RustcEncodable)]
455 impl From<ImplData> for Relation {
456 fn from(data: ImplData) -> Relation {
459 kind: RelationKind::Impl,
460 from: From::from(data.self_ref.unwrap_or(null_def_id())),
461 to: From::from(data.trait_ref.unwrap_or(null_def_id())),
466 impl From<InheritanceData> for Relation {
467 fn from(data: InheritanceData) -> Relation {
470 kind: RelationKind::SuperTrait,
471 from: From::from(data.base_id),
472 to: From::from(data.deriv_id),
477 #[derive(Debug, RustcEncodable)]
478 pub struct JsonSignature {
483 defs: Vec<JsonSigElement>,
484 refs: Vec<JsonSigElement>,
487 impl From<Signature> for JsonSignature {
488 fn from(data: Signature) -> JsonSignature {
492 ident_start: data.ident_start,
493 ident_end: data.ident_end,
494 defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
495 refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
500 #[derive(Debug, RustcEncodable)]
501 pub struct JsonSigElement {
507 impl From<SigElement> for JsonSigElement {
508 fn from(data: SigElement) -> JsonSigElement {
510 id: From::from(data.id),