1use std::cmp::Ordering;
2
3use {
4 std::sync::Arc,
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_eval::live_eval_value,
11 live_document::{LiveOriginal, LiveExpanded},
12 live_node::{LiveFont, LiveValue, LiveNode, LiveFieldKind, LivePropType, LiveNodeRoot},
13 live_node_vec::{LiveNodeSliceApi, LiveNodeVecApi},
14 live_registry::{LiveRegistry, LiveScopeTarget},
15 }
16};
17
18pub struct LiveExpander<'a> {
19 pub live_registry: &'a LiveRegistry,
20 pub in_crate: LiveId,
21 pub in_file_id: LiveFileId,
22 pub errors: &'a mut Vec<LiveError>,
23}
24
25impl<'a> LiveExpander<'a> {
26 pub fn is_baseclass(id: LiveId) -> bool {
27 id == live_id!(struct)
28 }
29
30 pub fn shift_parent_stack(&self, parents: &mut Vec<(LiveId, usize)>, nodes: &[LiveNode], after_point: usize, old_size: usize, new_size: usize) {
31 for (live_id, item) in parents {
32 if *item > after_point {
33 match old_size.cmp(&new_size) {
34 Ordering::Less => *item += new_size - old_size,
35 Ordering::Greater => *item -= old_size - new_size,
36 _ => (),
37 }
38 if nodes[*item].id != *live_id {
39 panic!()
40 }
41 if !nodes[*item].is_open() {
42 panic!()
43 }
44 }
45 }
46 }
47
48 fn resolve_path(&self, file_id:LiveFileId, path:&str)->Option<Arc<String>>{
49 if let Some(path) = path.strip_prefix("crate://self/") {
50 let mut final_path = self.live_registry.file_id_to_cargo_manifest_path(file_id);
51 final_path.push('/');
52 final_path.push_str(path);
53 return Some(Arc::new(final_path))
54 } else if let Some(path) = path.strip_prefix("crate://") {
55 let mut split = path.split('/');
56 if let Some(crate_name) = split.next() {
57 if let Some(mut final_path) = self.live_registry.crate_name_to_cargo_manifest_path(crate_name) {
58 for next in split {
59 final_path.push('/');
60 final_path.push_str(next);
61 }
62 return Some(Arc::new(final_path))
63 }
64 }
65 }
66 None
67 }
68
69 pub fn expand(&mut self, in_doc: &LiveOriginal, out_doc: &mut LiveExpanded, generation: LiveFileGeneration) {
70
71 let mut root = LiveNodeRoot::default();
72
73 let resolved_imports = in_doc.resolved_imports.as_ref().unwrap();
75 for (ident, file_id) in resolved_imports{
76 let other = &self.live_registry.live_files[file_id.to_index()].expanded;
77 if let LiveValue::Root(root2) = &other.nodes[0].value {
78 let index = root2.exports.get(&ident).unwrap();
79 root.locals.insert(
80 *ident,
81 LiveScopeTarget::LivePtr(
82 self.live_registry.file_id_index_to_live_ptr(*file_id, *index)
83 )
84 );
85 }
86 }
87
88 out_doc.nodes.push(LiveNode {
90 origin: in_doc.nodes[0].origin,
91 id: LiveId(0),
92 value: LiveValue::Root(Box::new(root))
93 });
94 let mut current_parent = vec![(LiveId(0), 0usize)];
97 let mut in_index = 1;
98 let mut lazy_define_value = None;
99 loop {
100
101 if let Some((node_id, ptr)) = lazy_define_value.take() {
102 if let LiveValue::Root(root) = &mut out_doc.nodes[0].value {
103 root.locals.insert(node_id, ptr);
104 }
105 }
106
107 if in_index >= in_doc.nodes.len() - 1 {
108 break;
109 }
110
111 let in_node = &in_doc.nodes[in_index];
112 let in_value = &in_node.value;
113
114 match in_value {
115
116 LiveValue::Close => {
117 let close_index = out_doc.nodes.skip_node(current_parent.last().unwrap().1) - 1;
119 let out_close = &mut out_doc.nodes[close_index];
120 let mut origin = in_node.origin;
121 origin.inherit_origin(out_close.origin);
122 out_close.origin = origin;
123
124 current_parent.pop();
125 in_index += 1;
126 continue;
127 }
128 LiveValue::Import(_live_import) => {
129 in_index += 1;
166 continue;
167 }
168 _ => ()
169 }
170
171 let out_index = match out_doc.nodes.child_or_append_index_by_name(current_parent.last().unwrap().1, in_node.prop()) {
173 Ok(overwrite) => {
174 if current_parent.len() == 1 {
175 lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(overwrite)));
176 }
177 let out_value = &out_doc.nodes[overwrite].value;
178 let out_origin = out_doc.nodes[overwrite].origin;
179
180 if in_node.origin.edit_info().is_some() {
181 self.errors.push(LiveError {
182 origin: live_error_origin!(),
183 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
184 message: format!("Cannot define edit info after first prop def of {}", in_node.id)
185 });
186 }
187
188 if out_value.is_expr(){
189 panic!("No expressions expected in out_value")
190 }
191 if in_value.is_object() && (out_value.is_clone() || out_value.is_class() || out_value.is_object()) { }
195 else if in_value.is_expr(){
196
197 if !out_value.is_single_node(){
198 panic!("overriding is_expr on not is_single_node in file {:?}", self.live_registry.file_id_to_file_name(self.in_file_id));
199 }
200 let mut index = in_index;
202 match live_eval_value(&self.live_registry, &mut index, &in_doc.nodes, &out_doc.nodes){
203 Ok(v)=>{
204 out_doc.nodes[overwrite] = in_node.clone();
205 out_doc.nodes[overwrite].value = v;
206 }
207 Err(e)=>{ out_doc.nodes[overwrite] = in_node.clone();
209 out_doc.nodes[overwrite].value = LiveValue::None;
210 self.errors.push(e);
211 }
212 }
213 out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
215 in_index = in_doc.nodes.skip_node(in_index);
216 continue;
217 }
218 else if out_value.is_open() && in_value.is_open() { let next_index = out_doc.nodes.skip_node(overwrite);
220 let old_len = out_doc.nodes.len();
221 out_doc.nodes.drain(overwrite + 1..next_index - 1);
222 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
223 out_doc.nodes[overwrite] = in_node.clone();
224 }
225 else if out_value.is_open() {
227 let next_index = out_doc.nodes.skip_node(overwrite);
228 let old_len = out_doc.nodes.len();
229 out_doc.nodes.drain(overwrite + 1..next_index);
230 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
231 out_doc.nodes[overwrite] = in_node.clone();
232 }
233 else if in_value.is_open() {
235 let old_len = out_doc.nodes.len();
236 out_doc.nodes[overwrite] = in_node.clone();
237 out_doc.nodes.insert(overwrite + 1, in_node.clone());
238 out_doc.nodes[overwrite + 1].value = LiveValue::Close;
239 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, overwrite, old_len, out_doc.nodes.len());
240 }
241 else {
242 out_doc.nodes[overwrite] = in_node.clone();
243 };
244 out_doc.nodes[overwrite].origin.inherit_origin(out_origin);
245 overwrite
246 }
247 Err(insert_point) => {
248 if current_parent.len() == 1 {
249 lazy_define_value = Some((in_node.id, LiveScopeTarget::LocalPtr(insert_point)));
250 }
251
252 if in_node.is_expr() {
254
255 let mut index = in_index;
257 let old_len = out_doc.nodes.len();
258
259 match live_eval_value(&self.live_registry, &mut index, &in_doc.nodes, &out_doc.nodes){
260 Ok(v)=>{
261 out_doc.nodes.insert(insert_point, in_node.clone());
262 out_doc.nodes[insert_point].value = v;
263 }
264 Err(e)=>{
265 out_doc.nodes.insert(insert_point, in_node.clone());
266 out_doc.nodes[insert_point].value = LiveValue::None;
267 self.errors.push(e);
268 }
269 }
270 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
271 in_index = in_doc.nodes.skip_node(in_index);
273 continue;
274 }
275
276 let old_len = out_doc.nodes.len();
277 out_doc.nodes.insert(insert_point, in_node.clone());
278 if in_node.is_open() {
279 out_doc.nodes.insert(insert_point + 1, in_node.clone());
280 out_doc.nodes[insert_point + 1].value = LiveValue::Close;
281 }
282 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, insert_point - 1, old_len, out_doc.nodes.len());
283
284 insert_point
285 }
286 };
287
288
289 match in_value {
291 LiveValue::Dependency(path) => {
292 let file_id = in_node.origin.token_id().unwrap().file_id().unwrap();
293 if let Some(final_path) = self.resolve_path(file_id, &path){
294 out_doc.nodes[out_index].value = LiveValue::Dependency(final_path);
295 }
296 },
297 LiveValue::Font(font) => {
298 let file_id = in_node.origin.token_id().unwrap().file_id().unwrap();
299 if let Some(final_path) = self.resolve_path(file_id, &font.path){
300 out_doc.nodes[out_index].value = LiveValue::Font(LiveFont{
301 path:final_path,
302 ..*font
303 });
304 }
305 },
306 LiveValue::Clone{clone,..} | LiveValue::Deref{clone,..}=> {
307 if let Some(target) = self.live_registry.find_scope_target(*clone, &out_doc.nodes) {
308 match target {
309 LiveScopeTarget::LocalPtr(local_ptr) => {
310
311 let old_len = out_doc.nodes.len();
312
313 out_doc.nodes.insert_children_from_self(local_ptr, out_index + 1);
314 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
315
316 if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
318 out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
319 if let LiveValue::Class {live_type, ..} = &mut out_doc.nodes[out_index].value {
320 *live_type = *new_live_type
321 }
322 }
323 else{
324 if let LiveValue::Class {live_type: old_live_type, ..} = &out_doc.nodes[out_index].value {
325 if let LiveValue::Class {live_type, ..} = &out_doc.nodes[local_ptr].value {
326 if live_type != old_live_type {
327 self.errors.push(LiveError {
328 origin: live_error_origin!(),
329 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
330 message: format!("Class override with wrong type {}", in_node.id)
331 });
332 }
333 }
334 }
335 out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
336 }
337
338 if let LiveValue::Class {class_parent,..} = &mut out_doc.nodes[out_index].value {
339 *class_parent = LivePtr {file_id: self.in_file_id, index: local_ptr as u32, generation};
341 }
342 }
343 LiveScopeTarget::LivePtr(live_ptr) => {
344 let doc = &self.live_registry.live_files[live_ptr.file_id.to_index()].expanded;
345
346 let old_len = out_doc.nodes.len();
347 out_doc.nodes.insert_children_from_other(live_ptr.node_index(), out_index + 1, &doc.nodes);
348 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
349
350 out_doc.nodes[out_index].value = doc.nodes[live_ptr.node_index()].value.clone();
351
352 if let LiveValue::Class {class_parent,live_type, ..} = &mut out_doc.nodes[out_index].value {
353 if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
354 *live_type = *new_live_type;
355 }
356 else{
357 *class_parent = live_ptr;
358 }
359 }
361 }
362 };
363 }
365 else if !Self::is_baseclass(*clone) { self.errors.push(LiveError {
367 origin: live_error_origin!(),
368 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
369 message: format!("Can't find live definition of {} did you forget to call live_design for it, put the definition above the place where you use it or if imported put pub before the definition?", clone)
370 });
371 }
372 current_parent.push((out_doc.nodes[out_index].id, out_index));
373 },
374 LiveValue::Class {live_type, ..} => {
375
376 if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
378 *class_parent = LivePtr {file_id: self.in_file_id, index: out_index as u32, generation};
379 }
380
381 let mut insert_point = out_index + 1;
382 let live_type_info = self.live_registry.live_type_infos.get(live_type).unwrap();
383
384 if let Some(field) = live_type_info.fields.iter().find( | f | f.live_field_kind == LiveFieldKind::Deref) {
385 if !field.live_type_info.live_ignore {
386 let live_type_info = &field.live_type_info;
387 if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&live_type_info.module_id) {
388 let doc = &self.live_registry.live_files[file_id.to_index()].expanded;
389
390 let mut index = 1;
391 let mut found = None;
392 while index < doc.nodes.len() {
393 if let LiveValue::Class {live_type, ..} = &doc.nodes[index].value {
394 if *live_type == live_type_info.live_type {
395 found = Some(index);
396 break
397 }
398 }
399 index = doc.nodes.skip_node(index);
400 }
401 if let Some(index) = found {
402 let old_len = out_doc.nodes.len();
403 out_doc.nodes.insert_children_from_other(index, out_index + 1, &doc.nodes);
404 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
405 }
406 }
407 }
408 }
409 for field in &live_type_info.fields {
411 if field.live_field_kind == LiveFieldKind::Deref {
412 continue;
413 }
414 let lti = &field.live_type_info;
415 if let Some(file_id) = self.live_registry.module_id_to_file_id.get(<i.module_id) {
416
417 if *file_id == self.in_file_id { let mut index = 1;
419 let mut found = None;
420 while index < out_doc.nodes.len() - 1 {
421 if let LiveValue::Class {live_type, ..} = &out_doc.nodes[index].value {
422 if *live_type == lti.live_type {
423 found = Some(index);
424 break
425 }
426 }
427 index = out_doc.nodes.skip_node(index);
428 }
429 if let Some(index) = found {
430 let node_insert_point = insert_point;
431
432 let old_len = out_doc.nodes.len();
433 insert_point = out_doc.nodes.insert_node_from_self(index, insert_point);
434 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
435
436 out_doc.nodes[node_insert_point].id = field.id;
437 out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
438
439 }
440 else if !lti.live_ignore {
441 self.errors.push(LiveError {
442 origin: live_error_origin!(),
443 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
444 message: format!("Can't find live definition of {} did you forget to call live_design for it, put the definition above the place where you use it or if imported put pub before the definition?", lti.type_name)
445 });
446 }
447 }
448 else {
449 let other_nodes = &self.live_registry.live_files[file_id.to_index()].expanded.nodes;
450 if other_nodes.is_empty() {
451 panic!(
452 "Dependency order bug finding {}, file {} not registered before {}",
453 lti.type_name,
454 self.live_registry.file_id_to_file_name(*file_id),
455 self.live_registry.file_id_to_file_name(self.in_file_id),
456 );
457 }
458 let mut index = 1;
459 let mut found = None;
460 while index < other_nodes.len() - 1 {
461 if let LiveValue::Class {live_type, ..} = &other_nodes[index].value {
462 if *live_type == lti.live_type {
463 found = Some(index);
464 break
465 }
466 }
467 index = other_nodes.skip_node(index);
468 }
469 if let Some(index) = found {
470 let node_insert_point = insert_point;
471
472 let old_len = out_doc.nodes.len();
473 insert_point = out_doc.nodes.insert_node_from_other(index, insert_point, other_nodes);
474 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
475
476 out_doc.nodes[node_insert_point].id = field.id;
477 out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
478 }
479 else if !lti.live_ignore && lti.type_name != LiveId(0) {
480 self.errors.push(LiveError {
481 origin: live_error_origin!(),
482 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
483 message: format!("Typename {}, not defined in file where it was expected", lti.type_name)
484 });
485 }
486 }
487 }
488 else if !lti.live_ignore {
489 self.errors.push(LiveError {
490 origin: live_error_origin!(),
491 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
492 message: format!("Can't find live definition of {} did you forget to call live_design for it, put the definition above the place where you use it or if imported put pub before the definition?", lti.type_name)
493 });
494 }
495 }
496 current_parent.push((out_doc.nodes[out_index].id, out_index));
499 }
500 LiveValue::Expr {..} => {panic!()},
501 LiveValue::Array |
502 LiveValue::TupleEnum {..} |
503 LiveValue::NamedEnum {..} |
504 LiveValue::Object => { current_parent.push((out_doc.nodes[out_index].id, out_index));
506 },
507 LiveValue::DSL {..} => {
508 },
510 _ => {}
511 }
512
513 in_index += 1;
514 }
515 out_doc.nodes.push(in_doc.nodes.last().unwrap().clone());
516 let mut level = 0;
518
519 for i in 1..out_doc.nodes.len() {
520 let node = &mut out_doc.nodes[i];
524 if node.value.is_dsl() {
525 node.value.set_dsl_expand_index_if_none(i);
526 }
527 if level == 0 && in_doc.exports.get(&node.id).is_some(){
528 let id = node.id;
529 if let LiveValue::Root(root) = &mut out_doc.nodes[0].value{
530 root.exports.insert(id, i);
531 }
532 }
533 let node = &mut out_doc.nodes[i];
534 if node.value.is_open(){
535 level += 1
536 }
537 else if node.value.is_close() && level > 0{
538 level -= 1
539 }
540
541 }
542 }
543
544}
545