1use std::cmp::Ordering;
2
3use {
4 std::rc::Rc,
5 crate::{
6 makepad_live_id::*,
7 makepad_live_tokenizer::{live_error_origin, LiveErrorOrigin},
8 live_ptr::{LiveFileId, LivePtr, LiveFileGeneration},
9 live_error::{LiveError},
10 live_document::{LiveOriginal, LiveExpanded},
11 live_node::{LiveValue, LiveNode, LiveFieldKind, LivePropType},
12 live_node_vec::{LiveNodeSliceApi, LiveNodeVecApi},
13 live_registry::{LiveRegistry, LiveScopeTarget},
14 }
15};
16
17pub struct LiveExpander<'a> {
18 pub live_registry: &'a LiveRegistry,
19 pub in_crate: LiveId,
20 pub in_file_id: LiveFileId,
21 pub errors: &'a mut Vec<LiveError>,
22}
23
24impl<'a> LiveExpander<'a> {
25 pub fn is_baseclass(id: LiveId) -> bool {
26 id == live_id!(struct)
27 }
28
29 pub fn shift_parent_stack(&self, parents: &mut Vec<(LiveId, usize)>, nodes: &[LiveNode], after_point: usize, old_size: usize, new_size: usize) {
30 for (live_id, item) in parents {
31 if *item > after_point {
32 match old_size.cmp(&new_size) {
33 Ordering::Less => *item += new_size - old_size,
34 Ordering::Greater => *item -= old_size - new_size,
35 _ => (),
36 }
37 if nodes[*item].id != *live_id {
38 panic!()
39 }
40 if !nodes[*item].is_open() {
41 panic!()
42 }
43 }
44 }
45 }
46
47 pub fn expand(&mut self, in_doc: &LiveOriginal, out_doc: &mut LiveExpanded, generation: LiveFileGeneration) {
48
49 out_doc.nodes.push(LiveNode {
51 origin: in_doc.nodes[0].origin,
52 id: LiveId(0),
53 value: LiveValue::Root {id_resolve: Box::default()}
54 });
55 let mut current_parent = vec![(LiveId(0), 0usize)];
56 let mut in_index = 1;
57 let mut lazy_define_value = None;
58 loop {
59 if let Some((node_id, ptr)) = lazy_define_value.take() {
60 if let LiveValue::Root {id_resolve} = &mut out_doc.nodes[0].value {
61 id_resolve.insert(node_id, ptr);
62 }
63 }
64
65 if in_index >= in_doc.nodes.len() - 1 {
66 break;
67 }
68
69 let in_node = &in_doc.nodes[in_index];
70 let in_value = &in_node.value;
71
72 match in_value {
73
74 LiveValue::Close => {
75 current_parent.pop();
76 in_index += 1;
77 continue;
78 }
79 LiveValue::Import(live_import) => {
80 let mut found = false;
82 let is_glob = in_node.id == LiveId::empty();
83 if let Some(nodes) = self.live_registry.module_id_to_expanded_nodes(live_import.module_id) {
84 let file_id = self.live_registry.module_id_to_file_id(live_import.module_id).unwrap();
85 let mut node_iter = Some(1);
86 while let Some(index) = node_iter {
87 if is_glob{
88 if let LiveValue::Root {id_resolve} = &mut out_doc.nodes[0].value {
89 id_resolve.insert(nodes[index].id, LiveScopeTarget::LivePtr(
90 self.live_registry.file_id_index_to_live_ptr(file_id, index)
91 ));
92 }
93 found = true;
94 }
95 else if nodes[index].id == live_import.import_id { if let LiveValue::Root {id_resolve} = &mut out_doc.nodes[0].value {
98 id_resolve.insert(in_node.id , LiveScopeTarget::LivePtr(
99 self.live_registry.file_id_index_to_live_ptr(file_id, index)
100 ));
101 }
102 found = true;
103 }
104 node_iter = nodes.next_child(index);
105 }
106 }
107 if !found {
108 self.errors.push(LiveError {
109 origin: live_error_origin!(),
110 span: in_node.origin.token_id().unwrap().into(),
111 message: format!("Import statement nothing found {}::{} as {}", live_import.module_id, live_import.import_id, in_node.id)
112 });
113 }
114 in_index += 1;
115 continue;
116 }
117 _ => ()
118 }
119
120 let out_index = match out_doc.nodes.child_or_append_index_by_name(current_parent.last().unwrap().1, in_node.prop()) {
122 Ok(overwrite) => {
123 if current_parent.len() == 1 {
124 lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(overwrite)));
125 }
126 let out_value = &out_doc.nodes[overwrite].value;
127 let out_origin = out_doc.nodes[overwrite].origin;
128
129 if in_node.origin.edit_info().is_some() {
130 self.errors.push(LiveError {
131 origin: live_error_origin!(),
132 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
133 message: format!("Cannot define edit info after first prop def of {}", in_node.id)
134 });
135 }
136 if in_value.is_object() && (out_value.is_clone() || out_value.is_class() || out_value.is_object()) { }
140 else if out_value.is_expr() || in_value.is_expr() && out_value.is_single_node() {
142 let next_index = out_doc.nodes.skip_node(overwrite);
144
145 let old_len = out_doc.nodes.len();
147 out_doc.nodes.splice(overwrite..next_index, in_doc.nodes.node_slice(in_index).iter().cloned());
148 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
149
150 in_index = in_doc.nodes.skip_node(in_index);
151 out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
152 continue;
153 }
154 else if out_value.is_open() && in_value.is_open() { let next_index = out_doc.nodes.skip_node(overwrite);
156 let old_len = out_doc.nodes.len();
157 out_doc.nodes.drain(overwrite + 1..next_index - 1);
158 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
159 out_doc.nodes[overwrite] = in_node.clone();
160 }
161 else if out_value.is_open() {
163 let next_index = out_doc.nodes.skip_node(overwrite);
164 let old_len = out_doc.nodes.len();
165 out_doc.nodes.drain(overwrite + 1..next_index);
166 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
167 out_doc.nodes[overwrite] = in_node.clone();
168 }
169 else if in_value.is_open() {
171 let old_len = out_doc.nodes.len();
172 out_doc.nodes[overwrite] = in_node.clone();
173 out_doc.nodes.insert(overwrite + 1, in_node.clone());
174 out_doc.nodes[overwrite + 1].value = LiveValue::Close;
175 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
176 }
177 else {
178 out_doc.nodes[overwrite] = in_node.clone();
179 };
180 out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
181 overwrite
182 }
183 Err(insert_point) => {
184 if current_parent.len() == 1 {
185 lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(insert_point)));
186 }
187
188 if in_node.is_expr() {
190 let old_len = out_doc.nodes.len();
192 out_doc.nodes.splice(insert_point..insert_point, in_doc.nodes.node_slice(in_index).iter().cloned());
193 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
194
195 in_index = in_doc.nodes.skip_node(in_index);
196 continue;
197 }
198
199 let old_len = out_doc.nodes.len();
200 out_doc.nodes.insert(insert_point, in_node.clone());
201 if in_node.is_open() {
202 out_doc.nodes.insert(insert_point + 1, in_node.clone());
203 out_doc.nodes[insert_point + 1].value = LiveValue::Close;
204 }
205 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
206
207 insert_point
208 }
209 };
210
211
212 match in_value {
214 LiveValue::Dependency(path) => {
215 if let Some(path) = path.strip_prefix("crate://self/") {
216 let file_id = in_node.origin.token_id().unwrap().file_id().unwrap();
217 let mut final_path = self.live_registry.file_id_to_cargo_manifest_path(file_id);
218 final_path.push('/');
219 final_path.push_str(path);
220 out_doc.nodes[out_index].value = LiveValue::Dependency(Rc::new(final_path));
221 } else if let Some(path) = path.strip_prefix("crate://") {
222 let mut split = path.split('/');
223 if let Some(crate_name) = split.next() {
224 if let Some(mut final_path) = self.live_registry.crate_name_to_cargo_manifest_path(crate_name) {
225 for next in split {
226 final_path.push('/');
227 final_path.push_str(next);
228 }
229 out_doc.nodes[out_index].value = LiveValue::Dependency(Rc::new(final_path));
230 }
231 }
232 }
233 },
234 LiveValue::Clone(clone) => {
235 if let Some(target) = self.live_registry.find_scope_target(*clone, &out_doc.nodes) {
236 match target {
237 LiveScopeTarget::LocalPtr(local_ptr) => {
238
239 let old_len = out_doc.nodes.len();
240
241 out_doc.nodes.insert_children_from_self(local_ptr, out_index + 1);
242 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
243
244 if let LiveValue::Class {live_type: old_live_type, ..} = &out_doc.nodes[out_index].value {
246 if let LiveValue::Class {live_type, ..} = &out_doc.nodes[local_ptr].value {
247 if live_type != old_live_type {
248 self.errors.push(LiveError {
249 origin: live_error_origin!(),
250 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
251 message: format!("Class override with wrong type {}", in_node.id)
252 });
253 }
254 }
255 }
256
257 out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
258 if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
259 *class_parent = Some(LivePtr {file_id: self.in_file_id, index: local_ptr as u32, generation});
261 }
262 }
263 LiveScopeTarget::LivePtr(live_ptr) => {
264 let doc = &self.live_registry.live_files[live_ptr.file_id.to_index()].expanded;
265
266 let old_len = out_doc.nodes.len();
267 out_doc.nodes.insert_children_from_other(live_ptr.node_index(), out_index + 1, &doc.nodes);
268 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
269
270 out_doc.nodes[out_index].value = doc.nodes[live_ptr.node_index()].value.clone();
271 if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
272 *class_parent = Some(live_ptr);
273 }
275 }
276 };
277 }
279 else if !Self::is_baseclass(*clone) { self.errors.push(LiveError {
281 origin: live_error_origin!(),
282 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
283 message: format!("Can't find live definition of {} did you forget to call live_design for it?", clone)
284 });
285 }
286 current_parent.push((out_doc.nodes[out_index].id, out_index));
287 },
288 LiveValue::Class {live_type, ..} => {
289 if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
291 *class_parent = Some(LivePtr {file_id: self.in_file_id, index: out_index as u32, generation});
292 }
293
294 let mut insert_point = out_index + 1;
295 let live_type_info = self.live_registry.live_type_infos.get(live_type).unwrap();
296
297 if let Some(field) = live_type_info.fields.iter().find( | f | f.live_field_kind == LiveFieldKind::Deref) {
298 if !field.live_type_info.live_ignore {
299 let live_type_info = &field.live_type_info;
300 if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&live_type_info.module_id) {
301 let doc = &self.live_registry.live_files[file_id.to_index()].expanded;
302
303 let mut index = 1;
304 let mut found = None;
305 while index < doc.nodes.len() - 1 {
306 if let LiveValue::Class {live_type, ..} = &doc.nodes[index].value {
307 if *live_type == live_type_info.live_type {
308 found = Some(index);
309 break
310 }
311 }
312 index = out_doc.nodes.skip_node(index);
313 }
314 if let Some(index) = found {
315 let old_len = out_doc.nodes.len();
316 out_doc.nodes.insert_children_from_other(index, out_index + 1, &doc.nodes);
317 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
318 }
319 }
320 }
321 }
322 for field in &live_type_info.fields {
324 if field.live_field_kind == LiveFieldKind::Deref {
325 continue;
326 }
327 let lti = &field.live_type_info;
328 if let Some(file_id) = self.live_registry.module_id_to_file_id.get(<i.module_id) {
329
330 if *file_id == self.in_file_id { let mut index = 1;
332 let mut found = None;
333 while index < out_doc.nodes.len() - 1 {
334 if let LiveValue::Class {live_type, ..} = &out_doc.nodes[index].value {
335 if *live_type == lti.live_type {
336 found = Some(index);
337 break
338 }
339 }
340 index = out_doc.nodes.skip_node(index);
341 }
342 if let Some(index) = found {
343 let node_insert_point = insert_point;
344
345 let old_len = out_doc.nodes.len();
346 insert_point = out_doc.nodes.insert_node_from_self(index, insert_point);
347 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
348
349 out_doc.nodes[node_insert_point].id = field.id;
350 out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
351
352 }
353 else if !lti.live_ignore {
354 self.errors.push(LiveError {
355 origin: live_error_origin!(),
356 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
357 message: format!("Can't find live definition of {} did you forget to call live_design for it?", lti.type_name)
358 });
359 }
360 }
361 else {
362 let other_nodes = &self.live_registry.live_files[file_id.to_index()].expanded.nodes;
363 if other_nodes.is_empty() {
364 panic!(
365 "Dependency order bug finding {}, file {} not registered before {}",
366 lti.type_name,
367 self.live_registry.file_id_to_file_name(*file_id),
368 self.live_registry.file_id_to_file_name(self.in_file_id),
369 );
370 }
371 let mut index = 1;
372 let mut found = None;
373 while index < other_nodes.len() - 1 {
374 if let LiveValue::Class {live_type, ..} = &other_nodes[index].value {
375 if *live_type == lti.live_type {
376 found = Some(index);
377 break
378 }
379 }
380 index = other_nodes.skip_node(index);
381 }
382 if let Some(index) = found {
383 let node_insert_point = insert_point;
384
385 let old_len = out_doc.nodes.len();
386 insert_point = out_doc.nodes.insert_node_from_other(index, insert_point, other_nodes);
387 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
388
389 out_doc.nodes[node_insert_point].id = field.id;
390 out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
391 }
392 else if !lti.live_ignore && lti.type_name != LiveId(0) {
393 self.errors.push(LiveError {
394 origin: live_error_origin!(),
395 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
396 message: format!("Typename {}, not defined in file where it was expected", lti.type_name)
397 });
398 }
399 }
400 }
401 else if !lti.live_ignore {
402 self.errors.push(LiveError {
403 origin: live_error_origin!(),
404 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
405 message: format!("Can't find live definition of {} did you forget to call live_design for it?", lti.type_name)
406 });
407 }
408 }
409 current_parent.push((out_doc.nodes[out_index].id, out_index));
411 }
412 LiveValue::Expr {..} => {panic!()},
413 LiveValue::Array |
414 LiveValue::TupleEnum {..} |
415 LiveValue::NamedEnum {..} |
416 LiveValue::Object => { current_parent.push((out_doc.nodes[out_index].id, out_index));
418 },
419 LiveValue::DSL {..} => {
420 },
422 _ => {}
423 }
424
425 in_index += 1;
426 }
427 out_doc.nodes.push(in_doc.nodes.last().unwrap().clone());
428
429 for i in 1..out_doc.nodes.len() {
431 if out_doc.nodes[i].value.is_dsl() {
432 out_doc.nodes[i].value.set_dsl_expand_index_if_none(i);
433 }
434 if out_doc.nodes[i].value.is_expr() {
435 out_doc.nodes[i].value.set_expr_expand_index_if_none(i);
436 }
437 }
438 }
439
440}
441