• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! A module for representations of starlark constructs
2 
3 mod glob;
4 mod label;
5 mod select;
6 mod select_dict;
7 mod select_list;
8 mod select_scalar;
9 mod select_set;
10 mod serialize;
11 mod target_compatible_with;
12 
13 use std::collections::BTreeSet as Set;
14 
15 use serde::{Serialize, Serializer};
16 use serde_starlark::{Error as StarlarkError, FunctionCall};
17 
18 pub(crate) use glob::*;
19 pub(crate) use label::*;
20 pub(crate) use select::*;
21 pub(crate) use select_dict::*;
22 pub(crate) use select_list::*;
23 pub(crate) use select_scalar::*;
24 pub(crate) use select_set::*;
25 pub(crate) use target_compatible_with::*;
26 
27 #[derive(Serialize)]
28 #[serde(untagged)]
29 pub(crate) enum Starlark {
30     Load(Load),
31     Package(Package),
32     PackageInfo(PackageInfo),
33     License(License),
34     ExportsFiles(ExportsFiles),
35     Filegroup(Filegroup),
36     Alias(Alias),
37     CargoBuildScript(CargoBuildScript),
38     #[serde(serialize_with = "serialize::rust_proc_macro")]
39     RustProcMacro(RustProcMacro),
40     #[serde(serialize_with = "serialize::rust_library")]
41     RustLibrary(RustLibrary),
42     #[serde(serialize_with = "serialize::rust_binary")]
43     RustBinary(RustBinary),
44 
45     #[serde(skip_serializing)]
46     Verbatim(String),
47 }
48 
49 pub(crate) struct Load {
50     pub(crate) bzl: String,
51     pub(crate) items: Set<String>,
52 }
53 
54 pub(crate) struct Package {
55     pub(crate) default_package_metadata: Set<Label>,
56     pub(crate) default_visibility: Set<String>,
57 }
58 
59 pub(crate) struct PackageInfo {
60     pub(crate) name: String,
61     pub(crate) package_name: String,
62     pub(crate) package_url: String,
63     pub(crate) package_version: String,
64 }
65 
66 pub(crate) struct License {
67     pub(crate) name: String,
68     pub(crate) license_kinds: Set<String>,
69     pub(crate) license_text: String,
70 }
71 
72 pub(crate) struct ExportsFiles {
73     pub(crate) paths: Set<String>,
74     pub(crate) globs: Glob,
75 }
76 
77 #[derive(Serialize)]
78 #[serde(rename = "filegroup")]
79 pub(crate) struct Filegroup {
80     pub(crate) name: String,
81     pub(crate) srcs: Glob,
82 }
83 
84 pub(crate) struct Alias {
85     pub(crate) rule: String,
86     pub(crate) name: String,
87     pub(crate) actual: Label,
88     pub(crate) tags: Set<String>,
89 }
90 
91 #[derive(Serialize)]
92 #[serde(rename = "cargo_build_script")]
93 pub(crate) struct CargoBuildScript {
94     pub(crate) name: String,
95     #[serde(skip_serializing_if = "SelectDict::is_empty")]
96     pub(crate) aliases: SelectDict<Label, String>,
97     #[serde(skip_serializing_if = "SelectDict::is_empty")]
98     pub(crate) build_script_env: SelectDict<String, String>,
99     #[serde(skip_serializing_if = "Data::is_empty")]
100     pub(crate) compile_data: Data,
101     #[serde(skip_serializing_if = "SelectSet::is_empty")]
102     pub(crate) crate_features: SelectSet<String>,
103     pub(crate) crate_name: String,
104     #[serde(skip_serializing_if = "Option::is_none")]
105     pub(crate) crate_root: Option<String>,
106     #[serde(skip_serializing_if = "Data::is_empty")]
107     pub(crate) data: Data,
108     #[serde(skip_serializing_if = "SelectSet::is_empty")]
109     pub(crate) deps: SelectSet<Label>,
110     #[serde(skip_serializing_if = "SelectSet::is_empty")]
111     pub(crate) link_deps: SelectSet<Label>,
112     pub(crate) edition: String,
113     #[serde(skip_serializing_if = "Option::is_none")]
114     pub(crate) linker_script: Option<String>,
115     #[serde(skip_serializing_if = "Option::is_none")]
116     pub(crate) links: Option<String>,
117     #[serde(skip_serializing_if = "SelectSet::is_empty")]
118     pub(crate) proc_macro_deps: SelectSet<Label>,
119     #[serde(skip_serializing_if = "SelectScalar::is_empty")]
120     pub(crate) rundir: SelectScalar<String>,
121     #[serde(skip_serializing_if = "SelectDict::is_empty")]
122     pub(crate) rustc_env: SelectDict<String, String>,
123     #[serde(skip_serializing_if = "SelectSet::is_empty")]
124     pub(crate) rustc_env_files: SelectSet<String>,
125     #[serde(skip_serializing_if = "SelectList::is_empty")]
126     pub(crate) rustc_flags: SelectList<String>,
127     pub(crate) srcs: Glob,
128     #[serde(skip_serializing_if = "Set::is_empty")]
129     pub(crate) tags: Set<String>,
130     #[serde(skip_serializing_if = "SelectSet::is_empty")]
131     pub(crate) tools: SelectSet<Label>,
132     #[serde(skip_serializing_if = "Set::is_empty")]
133     pub(crate) toolchains: Set<Label>,
134     pub(crate) version: String,
135     pub(crate) visibility: Set<String>,
136 }
137 
138 #[derive(Serialize)]
139 pub(crate) struct RustProcMacro {
140     pub(crate) name: String,
141     #[serde(skip_serializing_if = "SelectSet::is_empty")]
142     pub(crate) deps: SelectSet<Label>,
143     #[serde(skip_serializing_if = "SelectSet::is_empty")]
144     pub(crate) proc_macro_deps: SelectSet<Label>,
145     #[serde(skip_serializing_if = "SelectDict::is_empty")]
146     pub(crate) aliases: SelectDict<Label, String>,
147     #[serde(flatten)]
148     pub(crate) common: CommonAttrs,
149 }
150 
151 #[derive(Serialize)]
152 pub(crate) struct RustLibrary {
153     pub(crate) name: String,
154     #[serde(skip_serializing_if = "SelectSet::is_empty")]
155     pub(crate) deps: SelectSet<Label>,
156     #[serde(skip_serializing_if = "SelectSet::is_empty")]
157     pub(crate) proc_macro_deps: SelectSet<Label>,
158     #[serde(skip_serializing_if = "SelectDict::is_empty")]
159     pub(crate) aliases: SelectDict<Label, String>,
160     #[serde(flatten)]
161     pub(crate) common: CommonAttrs,
162     #[serde(skip_serializing_if = "std::ops::Not::not")]
163     pub(crate) disable_pipelining: bool,
164 }
165 
166 #[derive(Serialize)]
167 pub(crate) struct RustBinary {
168     pub(crate) name: String,
169     #[serde(skip_serializing_if = "SelectSet::is_empty")]
170     pub(crate) deps: SelectSet<Label>,
171     #[serde(skip_serializing_if = "SelectSet::is_empty")]
172     pub(crate) proc_macro_deps: SelectSet<Label>,
173     #[serde(skip_serializing_if = "SelectDict::is_empty")]
174     pub(crate) aliases: SelectDict<Label, String>,
175     #[serde(flatten)]
176     pub(crate) common: CommonAttrs,
177 }
178 
179 #[derive(Serialize)]
180 pub(crate) struct CommonAttrs {
181     #[serde(skip_serializing_if = "Data::is_empty")]
182     pub(crate) compile_data: Data,
183     #[serde(skip_serializing_if = "SelectSet::is_empty")]
184     pub(crate) crate_features: SelectSet<String>,
185     #[serde(skip_serializing_if = "Option::is_none")]
186     pub(crate) crate_root: Option<String>,
187     #[serde(skip_serializing_if = "Data::is_empty")]
188     pub(crate) data: Data,
189     pub(crate) edition: String,
190     #[serde(skip_serializing_if = "Option::is_none")]
191     pub(crate) linker_script: Option<String>,
192     #[serde(skip_serializing_if = "SelectDict::is_empty")]
193     pub(crate) rustc_env: SelectDict<String, String>,
194     #[serde(skip_serializing_if = "SelectSet::is_empty")]
195     pub(crate) rustc_env_files: SelectSet<String>,
196     #[serde(skip_serializing_if = "SelectList::is_empty")]
197     pub(crate) rustc_flags: SelectList<String>,
198     pub(crate) srcs: Glob,
199     #[serde(skip_serializing_if = "Set::is_empty")]
200     pub(crate) tags: Set<String>,
201     #[serde(skip_serializing_if = "Option::is_none")]
202     pub(crate) target_compatible_with: Option<TargetCompatibleWith>,
203     pub(crate) version: String,
204 }
205 
206 pub(crate) struct Data {
207     pub(crate) glob: Glob,
208     pub(crate) select: SelectSet<Label>,
209 }
210 
211 impl Package {
default_visibility_public(default_package_metadata: Set<Label>) -> Self212     pub(crate) fn default_visibility_public(default_package_metadata: Set<Label>) -> Self {
213         let mut default_visibility = Set::new();
214         default_visibility.insert("//visibility:public".to_owned());
215         Package {
216             default_package_metadata,
217             default_visibility,
218         }
219     }
220 }
221 
222 impl Serialize for Alias {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,223     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
224     where
225         S: Serializer,
226     {
227         // Output looks like:
228         //
229         //     rule(
230         //         name = "name",
231         //         actual = "actual",
232         //         tags = [
233         //            "tag1",
234         //            "tag2",
235         //         ],
236         //     )
237 
238         #[derive(Serialize)]
239         struct AliasInner<'a> {
240             pub(crate) name: &'a String,
241             pub(crate) actual: &'a Label,
242             pub(crate) tags: &'a Set<String>,
243         }
244 
245         FunctionCall::new(
246             &self.rule,
247             AliasInner {
248                 name: &self.name,
249                 actual: &self.actual,
250                 tags: &self.tags,
251             },
252         )
253         .serialize(serializer)
254     }
255 }
256 
serialize(starlark: &[Starlark]) -> Result<String, StarlarkError>257 pub(crate) fn serialize(starlark: &[Starlark]) -> Result<String, StarlarkError> {
258     let mut content = String::new();
259     for call in starlark {
260         if !content.is_empty() {
261             content.push('\n');
262         }
263         if let Starlark::Verbatim(comment) = call {
264             content.push_str(comment);
265         } else {
266             content.push_str(&serde_starlark::to_string(call)?);
267         }
268     }
269     Ok(content)
270 }
271