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