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