]> git.proxmox.com Git - rustc.git/blob - src/librustc_save_analysis/json_api_dumper.rs
New upstream version 1.16.0+dfsg1
[rustc.git] / src / librustc_save_analysis / json_api_dumper.rs
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.
4 //
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.
10
11 use std::io::Write;
12
13 use rustc::hir::def_id::DefId;
14 use rustc_serialize::json::as_json;
15
16 use external_data::*;
17 use data::{VariableKind, Visibility, SigElement};
18 use dump::Dump;
19 use super::Format;
20
21
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> {
30 output: &'b mut W,
31 result: Analysis,
32 }
33
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() }
37 }
38 }
39
40 impl<'b, W: Write> Drop for JsonApiDumper<'b, W> {
41 fn drop(&mut self) {
42 if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
43 error!("Error writing output");
44 }
45 }
46 }
47
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);
53 }
54 }
55 }
56 }
57
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)
61 }
62
63 impl_fn!(use_data, UseData, imports);
64 impl_fn!(use_glob, UseGlobData, imports);
65
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);
77 }
78
79 // FIXME methods. The defs have information about possible overriding and the
80 // refs have decl information (e.g., a trait method where we know the required
81 // method, but not the supplied method). In both cases, we are currently
82 // ignoring it.
83
84 #[derive(Debug, RustcEncodable)]
85 struct Analysis {
86 kind: Format,
87 prelude: Option<CratePreludeData>,
88 imports: Vec<Import>,
89 defs: Vec<Def>,
90 // These two fields are dummies so that clients can parse the two kinds of
91 // JSON data in the same way.
92 refs: Vec<()>,
93 macro_refs: Vec<()>,
94 }
95
96 impl Analysis {
97 fn new() -> Analysis {
98 Analysis {
99 kind: Format::JsonApi,
100 prelude: None,
101 imports: vec![],
102 defs: vec![],
103 refs: vec![],
104 macro_refs: vec![],
105 }
106 }
107 }
108
109 // DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
110 // we use our own Id which is the same, but without the newtype.
111 #[derive(Debug, RustcEncodable)]
112 struct Id {
113 krate: u32,
114 index: u32,
115 }
116
117 impl From<DefId> for Id {
118 fn from(id: DefId) -> Id {
119 Id {
120 krate: id.krate.as_u32(),
121 index: id.index.as_u32(),
122 }
123 }
124 }
125
126 #[derive(Debug, RustcEncodable)]
127 struct Import {
128 kind: ImportKind,
129 id: Id,
130 span: SpanData,
131 name: String,
132 value: String,
133 }
134
135 #[derive(Debug, RustcEncodable)]
136 enum ImportKind {
137 Use,
138 GlobUse,
139 }
140
141 impl From<UseData> for Option<Import> {
142 fn from(data: UseData) -> Option<Import> {
143 match data.visibility {
144 Visibility::Public => Some(Import {
145 kind: ImportKind::Use,
146 id: From::from(data.id),
147 span: data.span,
148 name: data.name,
149 value: String::new(),
150 }),
151 _ => None,
152 }
153 }
154 }
155 impl From<UseGlobData> for Option<Import> {
156 fn from(data: UseGlobData) -> Option<Import> {
157 match data.visibility {
158 Visibility::Public => Some(Import {
159 kind: ImportKind::GlobUse,
160 id: From::from(data.id),
161 span: data.span,
162 name: "*".to_owned(),
163 value: data.names.join(", "),
164 }),
165 _ => None,
166 }
167 }
168 }
169
170 #[derive(Debug, RustcEncodable)]
171 struct Def {
172 kind: DefKind,
173 id: Id,
174 span: SpanData,
175 name: String,
176 qualname: String,
177 value: String,
178 parent: Option<Id>,
179 children: Vec<Id>,
180 decl_id: Option<Id>,
181 docs: String,
182 sig: Option<JsonSignature>,
183 }
184
185 #[derive(Debug, RustcEncodable)]
186 enum DefKind {
187 // value = variant names
188 Enum,
189 // value = enum name + variant name + types
190 Tuple,
191 // value = [enum name +] name + fields
192 Struct,
193 // value = signature
194 Trait,
195 // value = type + generics
196 Function,
197 // value = type + generics
198 Method,
199 // No id, no value.
200 Macro,
201 // value = file_name
202 Mod,
203 // value = aliased type
204 Type,
205 // value = type and init expression (for all variable kinds).
206 Static,
207 Const,
208 Field,
209 }
210
211 impl From<EnumData> for Option<Def> {
212 fn from(data: EnumData) -> Option<Def> {
213 match data.visibility {
214 Visibility::Public => Some(Def {
215 kind: DefKind::Enum,
216 id: From::from(data.id),
217 span: data.span,
218 name: data.name,
219 qualname: data.qualname,
220 value: data.value,
221 parent: None,
222 children: data.variants.into_iter().map(|id| From::from(id)).collect(),
223 decl_id: None,
224 docs: data.docs,
225 sig: Some(From::from(data.sig)),
226 }),
227 _ => None,
228 }
229 }
230 }
231
232 impl From<TupleVariantData> for Option<Def> {
233 fn from(data: TupleVariantData) -> Option<Def> {
234 Some(Def {
235 kind: DefKind::Tuple,
236 id: From::from(data.id),
237 span: data.span,
238 name: data.name,
239 qualname: data.qualname,
240 value: data.value,
241 parent: data.parent.map(|id| From::from(id)),
242 children: vec![],
243 decl_id: None,
244 docs: data.docs,
245 sig: Some(From::from(data.sig)),
246 })
247 }
248 }
249 impl From<StructVariantData> for Option<Def> {
250 fn from(data: StructVariantData) -> Option<Def> {
251 Some(Def {
252 kind: DefKind::Struct,
253 id: From::from(data.id),
254 span: data.span,
255 name: data.name,
256 qualname: data.qualname,
257 value: data.value,
258 parent: data.parent.map(|id| From::from(id)),
259 children: vec![],
260 decl_id: None,
261 docs: data.docs,
262 sig: Some(From::from(data.sig)),
263 })
264 }
265 }
266 impl From<StructData> for Option<Def> {
267 fn from(data: StructData) -> Option<Def> {
268 match data.visibility {
269 Visibility::Public => Some(Def {
270 kind: DefKind::Struct,
271 id: From::from(data.id),
272 span: data.span,
273 name: data.name,
274 qualname: data.qualname,
275 value: data.value,
276 parent: None,
277 children: data.fields.into_iter().map(|id| From::from(id)).collect(),
278 decl_id: None,
279 docs: data.docs,
280 sig: Some(From::from(data.sig)),
281 }),
282 _ => None,
283 }
284 }
285 }
286 impl From<TraitData> for Option<Def> {
287 fn from(data: TraitData) -> Option<Def> {
288 match data.visibility {
289 Visibility::Public => Some(Def {
290 kind: DefKind::Trait,
291 id: From::from(data.id),
292 span: data.span,
293 name: data.name,
294 qualname: data.qualname,
295 value: data.value,
296 children: data.items.into_iter().map(|id| From::from(id)).collect(),
297 parent: None,
298 decl_id: None,
299 docs: data.docs,
300 sig: Some(From::from(data.sig)),
301 }),
302 _ => None,
303 }
304 }
305 }
306 impl From<FunctionData> for Option<Def> {
307 fn from(data: FunctionData) -> Option<Def> {
308 match data.visibility {
309 Visibility::Public => Some(Def {
310 kind: DefKind::Function,
311 id: From::from(data.id),
312 span: data.span,
313 name: data.name,
314 qualname: data.qualname,
315 value: data.value,
316 children: vec![],
317 parent: data.parent.map(|id| From::from(id)),
318 decl_id: None,
319 docs: data.docs,
320 sig: Some(From::from(data.sig)),
321 }),
322 _ => None,
323 }
324 }
325 }
326 impl From<MethodData> for Option<Def> {
327 fn from(data: MethodData) -> Option<Def> {
328 match data.visibility {
329 Visibility::Public => Some(Def {
330 kind: DefKind::Method,
331 id: From::from(data.id),
332 span: data.span,
333 name: data.name,
334 qualname: data.qualname,
335 value: data.value,
336 children: vec![],
337 parent: data.parent.map(|id| From::from(id)),
338 decl_id: data.decl_id.map(|id| From::from(id)),
339 docs: data.docs,
340 sig: Some(From::from(data.sig)),
341 }),
342 _ => None,
343 }
344 }
345 }
346 impl From<MacroData> for Option<Def> {
347 fn from(data: MacroData) -> Option<Def> {
348 Some(Def {
349 kind: DefKind::Macro,
350 id: From::from(null_def_id()),
351 span: data.span,
352 name: data.name,
353 qualname: data.qualname,
354 value: String::new(),
355 children: vec![],
356 parent: None,
357 decl_id: None,
358 docs: data.docs,
359 sig: None,
360 })
361 }
362 }
363 impl From<ModData> for Option<Def> {
364 fn from(data:ModData) -> Option<Def> {
365 match data.visibility {
366 Visibility::Public => Some(Def {
367 kind: DefKind::Mod,
368 id: From::from(data.id),
369 span: data.span,
370 name: data.name,
371 qualname: data.qualname,
372 value: data.filename,
373 children: data.items.into_iter().map(|id| From::from(id)).collect(),
374 parent: None,
375 decl_id: None,
376 docs: data.docs,
377 sig: Some(From::from(data.sig)),
378 }),
379 _ => None,
380 }
381 }
382 }
383 impl From<TypeDefData> for Option<Def> {
384 fn from(data: TypeDefData) -> Option<Def> {
385 match data.visibility {
386 Visibility::Public => Some(Def {
387 kind: DefKind::Type,
388 id: From::from(data.id),
389 span: data.span,
390 name: data.name,
391 qualname: data.qualname,
392 value: data.value,
393 children: vec![],
394 parent: data.parent.map(|id| From::from(id)),
395 decl_id: None,
396 docs: String::new(),
397 sig: data.sig.map(|s| From::from(s)),
398 }),
399 _ => None,
400 }
401 }
402 }
403
404 impl From<VariableData> for Option<Def> {
405 fn from(data: VariableData) -> Option<Def> {
406 match data.visibility {
407 Visibility::Public => Some(Def {
408 kind: match data.kind {
409 VariableKind::Static => DefKind::Static,
410 VariableKind::Const => DefKind::Const,
411 VariableKind::Local => { return None }
412 VariableKind::Field => DefKind::Field,
413 },
414 id: From::from(data.id),
415 span: data.span,
416 name: data.name,
417 qualname: data.qualname,
418 value: data.value,
419 children: vec![],
420 parent: data.parent.map(|id| From::from(id)),
421 decl_id: None,
422 docs: data.docs,
423 sig: data.sig.map(|s| From::from(s)),
424 }),
425 _ => None,
426 }
427 }
428 }
429
430 #[derive(Debug, RustcEncodable)]
431 pub struct JsonSignature {
432 span: SpanData,
433 text: String,
434 ident_start: usize,
435 ident_end: usize,
436 defs: Vec<JsonSigElement>,
437 refs: Vec<JsonSigElement>,
438 }
439
440 impl From<Signature> for JsonSignature {
441 fn from(data: Signature) -> JsonSignature {
442 JsonSignature {
443 span: data.span,
444 text: data.text,
445 ident_start: data.ident_start,
446 ident_end: data.ident_end,
447 defs: data.defs.into_iter().map(|s| From::from(s)).collect(),
448 refs: data.refs.into_iter().map(|s| From::from(s)).collect(),
449 }
450 }
451 }
452
453 #[derive(Debug, RustcEncodable)]
454 pub struct JsonSigElement {
455 id: Id,
456 start: usize,
457 end: usize,
458 }
459
460 impl From<SigElement> for JsonSigElement {
461 fn from(data: SigElement) -> JsonSigElement {
462 JsonSigElement {
463 id: From::from(data.id),
464 start: data.start,
465 end: data.end,
466 }
467 }
468 }