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_serialize::json::as_json;
16 use data::{VariableKind, Visibility};
18 use json_dumper::id_from_def_id;
20 use rls_data::{Analysis, Import, ImportKind, Def, DefKind, CratePreludeData};
23 // A dumper to dump a restricted set of JSON information, designed for use with
24 // libraries distributed without their source. Clients are likely to use type
25 // information here, and (for example) generate Rustdoc URLs, but don't need
26 // information for navigating the source of the crate.
27 // Relative to the regular JSON save-analysis info, this form is filtered to
28 // remove non-visible items.
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) = data.into() {
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(data.into());
83 fn inheritance(&mut self, data: InheritanceData) {
84 self.result.relations.push(data.into());
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 impl Into<Option<Import>> for UseData {
94 fn into(self) -> Option<Import> {
95 match self.visibility {
96 Visibility::Public => Some(Import {
97 kind: ImportKind::Use,
98 ref_id: self.mod_id.map(|id| id_from_def_id(id)),
101 value: String::new(),
107 impl Into<Option<Import>> for UseGlobData {
108 fn into(self) -> Option<Import> {
109 match self.visibility {
110 Visibility::Public => Some(Import {
111 kind: ImportKind::GlobUse,
114 name: "*".to_owned(),
115 value: self.names.join(", "),
122 impl Into<Option<Def>> for EnumData {
123 fn into(self) -> Option<Def> {
124 match self.visibility {
125 Visibility::Public => Some(Def {
127 id: id_from_def_id(self.id),
130 qualname: self.qualname,
133 children: self.variants.into_iter().map(|id| id_from_def_id(id)).collect(),
136 sig: Some(self.sig.into()),
144 impl Into<Option<Def>> for TupleVariantData {
145 fn into(self) -> Option<Def> {
147 kind: DefKind::Tuple,
148 id: id_from_def_id(self.id),
151 qualname: self.qualname,
153 parent: self.parent.map(|id| id_from_def_id(id)),
157 sig: Some(self.sig.into()),
162 impl Into<Option<Def>> for StructVariantData {
163 fn into(self) -> Option<Def> {
165 kind: DefKind::Struct,
166 id: id_from_def_id(self.id),
169 qualname: self.qualname,
171 parent: self.parent.map(|id| id_from_def_id(id)),
175 sig: Some(self.sig.into()),
180 impl Into<Option<Def>> for StructData {
181 fn into(self) -> Option<Def> {
182 match self.visibility {
183 Visibility::Public => Some(Def {
184 kind: DefKind::Struct,
185 id: id_from_def_id(self.id),
188 qualname: self.qualname,
191 children: self.fields.into_iter().map(|id| id_from_def_id(id)).collect(),
194 sig: Some(self.sig.into()),
201 impl Into<Option<Def>> for TraitData {
202 fn into(self) -> Option<Def> {
203 match self.visibility {
204 Visibility::Public => Some(Def {
205 kind: DefKind::Trait,
206 id: id_from_def_id(self.id),
209 qualname: self.qualname,
211 children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
215 sig: Some(self.sig.into()),
222 impl Into<Option<Def>> for FunctionData {
223 fn into(self) -> Option<Def> {
224 match self.visibility {
225 Visibility::Public => Some(Def {
226 kind: DefKind::Function,
227 id: id_from_def_id(self.id),
230 qualname: self.qualname,
233 parent: self.parent.map(|id| id_from_def_id(id)),
236 sig: Some(self.sig.into()),
243 impl Into<Option<Def>> for MethodData {
244 fn into(self) -> Option<Def> {
245 match self.visibility {
246 Visibility::Public => Some(Def {
247 kind: DefKind::Method,
248 id: id_from_def_id(self.id),
251 qualname: self.qualname,
254 parent: self.parent.map(|id| id_from_def_id(id)),
255 decl_id: self.decl_id.map(|id| id_from_def_id(id)),
257 sig: Some(self.sig.into()),
264 impl Into<Option<Def>> for MacroData {
265 fn into(self) -> Option<Def> {
267 kind: DefKind::Macro,
268 id: id_from_def_id(null_def_id()),
271 qualname: self.qualname,
272 value: String::new(),
282 impl Into<Option<Def>> for ModData {
283 fn into(self) -> Option<Def> {
284 match self.visibility {
285 Visibility::Public => Some(Def {
287 id: id_from_def_id(self.id),
290 qualname: self.qualname,
291 value: self.filename,
292 children: self.items.into_iter().map(|id| id_from_def_id(id)).collect(),
296 sig: Some(self.sig.into()),
303 impl Into<Option<Def>> for TypeDefData {
304 fn into(self) -> Option<Def> {
305 match self.visibility {
306 Visibility::Public => Some(Def {
308 id: id_from_def_id(self.id),
311 qualname: self.qualname,
314 parent: self.parent.map(|id| id_from_def_id(id)),
317 sig: self.sig.map(|s| s.into()),
325 impl Into<Option<Def>> for VariableData {
326 fn into(self) -> Option<Def> {
327 match self.visibility {
328 Visibility::Public => Some(Def {
329 kind: match self.kind {
330 VariableKind::Static => DefKind::Static,
331 VariableKind::Const => DefKind::Const,
332 VariableKind::Local => { return None }
333 VariableKind::Field => DefKind::Field,
335 id: id_from_def_id(self.id),
338 qualname: self.qualname,
341 parent: self.parent.map(|id| id_from_def_id(id)),
344 sig: self.sig.map(|s| s.into()),