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