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};
21 use rls_data::{SpanData, CratePreludeData};
24 // A dumper to dump a restricted set of JSON information, designed for use with
25 // libraries distributed without their source. Clients are likely to use type
26 // information here, and (for example) generate Rustdoc URLs, but don't need
27 // information for navigating the source of the crate.
28 // Relative to the regular JSON save-analysis info, this form is filtered to
29 // remove non-visible items, but includes some extra info for items (e.g., the
30 // parent field for finding the struct to which a field belongs).
31 pub struct JsonApiDumper<'b, W: Write + 'b> {
36 impl<'b, W: Write> JsonApiDumper<'b, W> {
37 pub fn new(writer: &'b mut W) -> JsonApiDumper<'b, W> {
38 JsonApiDumper { output: writer, result: Analysis::new() }
42 impl<'b, W: Write> Drop for JsonApiDumper<'b, W> {
44 if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
45 error!("Error writing output");
50 macro_rules! impl_fn {
51 ($fn_name: ident, $data_type: ident, $bucket: ident) => {
52 fn $fn_name(&mut self, data: $data_type) {
53 if let Some(datum) = From::from(data) {
54 self.result.$bucket.push(datum);
60 impl<'b, W: Write + 'b> Dump for JsonApiDumper<'b, W> {
61 fn crate_prelude(&mut self, data: CratePreludeData) {
62 self.result.prelude = Some(data)
65 impl_fn!(use_data, UseData, imports);
66 impl_fn!(use_glob, UseGlobData, imports);
68 impl_fn!(enum_data, EnumData, defs);
69 impl_fn!(tuple_variant, TupleVariantData, defs);
70 impl_fn!(struct_variant, StructVariantData, defs);
71 impl_fn!(struct_data, StructData, defs);
72 impl_fn!(trait_data, TraitData, defs);
73 impl_fn!(function, FunctionData, defs);
74 impl_fn!(method, MethodData, defs);
75 impl_fn!(macro_data, MacroData, defs);
76 impl_fn!(mod_data, ModData, defs);
77 impl_fn!(typedef, TypeDefData, defs);
78 impl_fn!(variable, VariableData, defs);
80 fn impl_data(&mut self, data: ImplData) {
81 if data.self_ref.is_some() {
82 self.result.relations.push(From::from(data));
85 fn inheritance(&mut self, data: InheritanceData) {
86 self.result.relations.push(From::from(data));
90 // FIXME methods. The defs have information about possible overriding and the
91 // refs have decl information (e.g., a trait method where we know the required
92 // method, but not the supplied method). In both cases, we are currently
95 #[derive(Debug, RustcEncodable)]
98 prelude: Option<CratePreludeData>,
101 relations: Vec<Relation>,
102 // These two fields are dummies so that clients can parse the two kinds of
103 // JSON data in the same way.
109 fn new() -> Analysis {
111 kind: Format::JsonApi,
122 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
123 // we use our own Id which is the same, but without the newtype.
124 #[derive(Debug, RustcEncodable)]
130 impl From<DefId> for Id {
131 fn from(id: DefId) -> Id {
133 krate: id.krate.as_u32(),
134 index: id.index.as_u32(),
139 #[derive(Debug, RustcEncodable)]
148 #[derive(Debug, RustcEncodable)]
154 impl From<UseData> for Option<Import> {
155 fn from(data: UseData) -> Option<Import> {
156 match data.visibility {
157 Visibility::Public => Some(Import {
158 kind: ImportKind::Use,
159 id: From::from(data.id),
162 value: String::new(),
168 impl From<UseGlobData> for Option<Import> {
169 fn from(data: UseGlobData) -> Option<Import> {
170 match data.visibility {
171 Visibility::Public => Some(Import {
172 kind: ImportKind::GlobUse,
173 id: From::from(data.id),
175 name: "*".to_owned(),
176 value: data.names.join(", "),
183 #[derive(Debug, RustcEncodable)]
195 sig: Option<JsonSignature>,
198 #[derive(Debug, RustcEncodable)]
200 // value = variant names
202 // value = enum name + variant name + types
204 // value = [enum name +] name + fields
208 // value = type + generics
210 // value = type + generics
216 // value = aliased type
218 // value = type and init expression (for all variable kinds).
224 impl From<EnumData> for Option<Def> {
225 fn from(data: EnumData) -> Option<Def> {
226 match data.visibility {
227 Visibility::Public => Some(Def {
229 id: From::from(data.id),
232 qualname: data.qualname,
235 children: data.variants.into_iter().map(|id| From::from(id)).collect(),
238 sig: Some(From::from(data.sig)),
245 impl From<TupleVariantData> for Option<Def> {
246 fn from(data: TupleVariantData) -> Option<Def> {
248 kind: DefKind::Tuple,
249 id: From::from(data.id),
252 qualname: data.qualname,
254 parent: data.parent.map(|id| From::from(id)),
258 sig: Some(From::from(data.sig)),
262 impl From<StructVariantData> for Option<Def> {
263 fn from(data: StructVariantData) -> Option<Def> {
265 kind: DefKind::Struct,
266 id: From::from(data.id),
269 qualname: data.qualname,
271 parent: data.parent.map(|id| From::from(id)),
275 sig: Some(From::from(data.sig)),
279 impl From<StructData> for Option<Def> {
280 fn from(data: StructData) -> Option<Def> {
281 match data.visibility {
282 Visibility::Public => Some(Def {
283 kind: DefKind::Struct,
284 id: From::from(data.id),
287 qualname: data.qualname,
290 children: data.fields.into_iter().map(|id| From::from(id)).collect(),
293 sig: Some(From::from(data.sig)),
299 impl From<TraitData> for Option<Def> {
300 fn from(data: TraitData) -> Option<Def> {
301 match data.visibility {
302 Visibility::Public => Some(Def {
303 kind: DefKind::Trait,
304 id: From::from(data.id),
307 qualname: data.qualname,
309 children: data.items.into_iter().map(|id| From::from(id)).collect(),
313 sig: Some(From::from(data.sig)),
319 impl From<FunctionData> for Option<Def> {
320 fn from(data: FunctionData) -> Option<Def> {
321 match data.visibility {
322 Visibility::Public => Some(Def {
323 kind: DefKind::Function,
324 id: From::from(data.id),
327 qualname: data.qualname,
330 parent: data.parent.map(|id| From::from(id)),
333 sig: Some(From::from(data.sig)),
339 impl From<MethodData> for Option<Def> {
340 fn from(data: MethodData) -> Option<Def> {
341 match data.visibility {
342 Visibility::Public => Some(Def {
343 kind: DefKind::Method,
344 id: From::from(data.id),
347 qualname: data.qualname,
350 parent: data.parent.map(|id| From::from(id)),
351 decl_id: data.decl_id.map(|id| From::from(id)),
353 sig: Some(From::from(data.sig)),
359 impl From<MacroData> for Option<Def> {
360 fn from(data: MacroData) -> Option<Def> {
362 kind: DefKind::Macro,
363 id: From::from(null_def_id()),
366 qualname: data.qualname,
367 value: String::new(),
376 impl From<ModData> for Option<Def> {
377 fn from(data:ModData) -> Option<Def> {
378 match data.visibility {
379 Visibility::Public => Some(Def {
381 id: From::from(data.id),
384 qualname: data.qualname,
385 value: data.filename,
386 children: data.items.into_iter().map(|id| From::from(id)).collect(),
390 sig: Some(From::from(data.sig)),
396 impl From<TypeDefData> for Option<Def> {
397 fn from(data: TypeDefData) -> Option<Def> {
398 match data.visibility {
399 Visibility::Public => Some(Def {
401 id: From::from(data.id),
404 qualname: data.qualname,
407 parent: data.parent.map(|id| From::from(id)),
410 sig: data.sig.map(|s| From::from(s)),
417 impl From<VariableData> for Option<Def> {
418 fn from(data: VariableData) -> Option<Def> {
419 match data.visibility {
420 Visibility::Public => Some(Def {
421 kind: match data.kind {
422 VariableKind::Static => DefKind::Static,
423 VariableKind::Const => DefKind::Const,
424 VariableKind::Local => { return None }
425 VariableKind::Field => DefKind::Field,
427 id: From::from(data.id),
430 qualname: data.qualname,
433 parent: data.parent.map(|id| From::from(id)),
436 sig: data.sig.map(|s| From::from(s)),
443 #[derive(Debug, RustcEncodable)]
451 #[derive(Debug, RustcEncodable)]
457 impl From<ImplData> for Relation {
458 fn from(data: ImplData) -> Relation {
461 kind: RelationKind::Impl,
462 from: From::from(data.self_ref.unwrap_or(null_def_id())),
463 to: From::from(data.trait_ref.unwrap_or(null_def_id())),
468 impl From<InheritanceData> for Relation {
469 fn from(data: InheritanceData) -> Relation {
472 kind: RelationKind::SuperTrait,
473 from: From::from(data.base_id),
474 to: From::from(data.deriv_id),
479 #[derive(Debug, RustcEncodable)]
480 pub struct JsonSignature {
485 defs: Vec<JsonSigElement>,
486 refs: Vec<JsonSigElement>,
489 impl From<Signature> for JsonSignature {
490 fn from(data: Signature) -> JsonSignature {
494 ident_start: data.ident_start,
495 ident_end: data.ident_end,
496 defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
497 refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
502 #[derive(Debug, RustcEncodable)]
503 pub struct JsonSigElement {
509 impl From<SigElement> for JsonSigElement {
510 fn from(data: SigElement) -> JsonSigElement {
512 id: From::from(data.id),