]>
Commit | Line | Data |
---|---|---|
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 | ||
11 | use std::io::Write; | |
12 | ||
a7813a04 XL |
13 | use rustc_serialize::json::as_json; |
14 | ||
abe05a73 | 15 | use rls_data::{self, Analysis, CratePreludeData, Def, DefKind, Import, MacroRef, Ref, RefKind, |
2c00a5a8 | 16 | Relation, Impl}; |
3b2f2976 | 17 | use rls_data::config::Config; |
cc61c64b XL |
18 | use rls_span::{Column, Row}; |
19 | ||
ff7c6d11 XL |
20 | #[derive(Debug)] |
21 | pub struct Access { | |
22 | pub reachable: bool, | |
23 | pub public: bool, | |
24 | } | |
25 | ||
cc61c64b | 26 | pub struct JsonDumper<O: DumpOutput> { |
a7813a04 | 27 | result: Analysis, |
3b2f2976 | 28 | config: Config, |
cc61c64b | 29 | output: O, |
a7813a04 XL |
30 | } |
31 | ||
cc61c64b XL |
32 | pub trait DumpOutput { |
33 | fn dump(&mut self, result: &Analysis); | |
a7813a04 XL |
34 | } |
35 | ||
cc61c64b XL |
36 | pub struct WriteOutput<'b, W: Write + 'b> { |
37 | output: &'b mut W, | |
38 | } | |
39 | ||
40 | impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> { | |
41 | fn dump(&mut self, result: &Analysis) { | |
42 | if let Err(_) = write!(self.output, "{}", as_json(&result)) { | |
a7813a04 XL |
43 | error!("Error writing output"); |
44 | } | |
45 | } | |
46 | } | |
47 | ||
cc61c64b | 48 | pub struct CallbackOutput<'b> { |
8faf50e0 | 49 | callback: &'b mut dyn FnMut(&Analysis), |
cc61c64b XL |
50 | } |
51 | ||
52 | impl<'b> DumpOutput for CallbackOutput<'b> { | |
53 | fn dump(&mut self, result: &Analysis) { | |
54 | (self.callback)(result) | |
55 | } | |
56 | } | |
57 | ||
58 | impl<'b, W: Write> JsonDumper<WriteOutput<'b, W>> { | |
3b2f2976 XL |
59 | pub fn new(writer: &'b mut W, config: Config) -> JsonDumper<WriteOutput<'b, W>> { |
60 | JsonDumper { | |
61 | output: WriteOutput { output: writer }, | |
62 | config: config.clone(), | |
abe05a73 | 63 | result: Analysis::new(config), |
3b2f2976 | 64 | } |
cc61c64b XL |
65 | } |
66 | } | |
67 | ||
68 | impl<'b> JsonDumper<CallbackOutput<'b>> { | |
abe05a73 | 69 | pub fn with_callback( |
8faf50e0 | 70 | callback: &'b mut dyn FnMut(&Analysis), |
abe05a73 XL |
71 | config: Config, |
72 | ) -> JsonDumper<CallbackOutput<'b>> { | |
3b2f2976 XL |
73 | JsonDumper { |
74 | output: CallbackOutput { callback: callback }, | |
75 | config: config.clone(), | |
76 | result: Analysis::new(config), | |
77 | } | |
cc61c64b XL |
78 | } |
79 | } | |
80 | ||
81 | impl<O: DumpOutput> Drop for JsonDumper<O> { | |
82 | fn drop(&mut self) { | |
83 | self.output.dump(&self.result); | |
84 | } | |
85 | } | |
86 | ||
3b2f2976 XL |
87 | impl<'b, O: DumpOutput + 'b> JsonDumper<O> { |
88 | pub fn crate_prelude(&mut self, data: CratePreludeData) { | |
a7813a04 XL |
89 | self.result.prelude = Some(data) |
90 | } | |
91 | ||
3b2f2976 | 92 | pub fn macro_use(&mut self, data: MacroRef) { |
ff7c6d11 | 93 | if self.config.pub_only || self.config.reachable_only { |
3b2f2976 XL |
94 | return; |
95 | } | |
041b39d2 XL |
96 | self.result.macro_refs.push(data); |
97 | } | |
a7813a04 | 98 | |
ff7c6d11 XL |
99 | pub fn import(&mut self, access: &Access, import: Import) { |
100 | if !access.public && self.config.pub_only | |
101 | || !access.reachable && self.config.reachable_only { | |
3b2f2976 XL |
102 | return; |
103 | } | |
041b39d2 XL |
104 | self.result.imports.push(import); |
105 | } | |
a7813a04 | 106 | |
3b2f2976 | 107 | pub fn dump_ref(&mut self, data: Ref) { |
ff7c6d11 | 108 | if self.config.pub_only || self.config.reachable_only { |
3b2f2976 XL |
109 | return; |
110 | } | |
041b39d2 XL |
111 | self.result.refs.push(data); |
112 | } | |
3b2f2976 | 113 | |
ff7c6d11 XL |
114 | pub fn dump_def(&mut self, access: &Access, mut data: Def) { |
115 | if !access.public && self.config.pub_only | |
116 | || !access.reachable && self.config.reachable_only { | |
3b2f2976 XL |
117 | return; |
118 | } | |
041b39d2 | 119 | if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value { |
ff7c6d11 XL |
120 | // If the module is an out-of-line definition, then we'll make the |
121 | // definition the first character in the module's file and turn | |
476ff2be SL |
122 | // the declaration into a reference to it. |
123 | let rf = Ref { | |
124 | kind: RefKind::Mod, | |
041b39d2 XL |
125 | span: data.span, |
126 | ref_id: data.id, | |
476ff2be SL |
127 | }; |
128 | self.result.refs.push(rf); | |
041b39d2 XL |
129 | data.span = rls_data::SpanData { |
130 | file_name: data.value.clone().into(), | |
476ff2be SL |
131 | byte_start: 0, |
132 | byte_end: 0, | |
cc61c64b XL |
133 | line_start: Row::new_one_indexed(1), |
134 | line_end: Row::new_one_indexed(1), | |
135 | column_start: Column::new_one_indexed(1), | |
136 | column_end: Column::new_one_indexed(1), | |
476ff2be SL |
137 | } |
138 | } | |
041b39d2 | 139 | self.result.defs.push(data); |
476ff2be SL |
140 | } |
141 | ||
3b2f2976 | 142 | pub fn dump_relation(&mut self, data: Relation) { |
041b39d2 | 143 | self.result.relations.push(data); |
32a655c1 | 144 | } |
2c00a5a8 XL |
145 | |
146 | pub fn dump_impl(&mut self, data: Impl) { | |
147 | self.result.impls.push(data); | |
148 | } | |
32a655c1 | 149 | } |