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 let mut paths = Vec::new();
300 for path in &*font.paths{
301 if let Some(final_path) = self.resolve_path(file_id, &path){
302 paths.push(final_path);
303 }
304 }
305 if paths.len()>0{
306 out_doc.nodes[out_index].value = LiveValue::Font(LiveFont{
307 paths: Arc::new(paths),
308 ..*font
309 });
310 }
311 },
312 LiveValue::Clone{clone,..} | LiveValue::Deref{clone,..}=> {
313 if let Some(target) = self.live_registry.find_scope_target(*clone, &out_doc.nodes) {
314 match target {
315 LiveScopeTarget::LocalPtr(local_ptr) => {
316
317 let old_len = out_doc.nodes.len();
318
319 out_doc.nodes.insert_children_from_self(local_ptr, out_index + 1);
320 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
321
322 if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
324 out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
325 if let LiveValue::Class {live_type, ..} = &mut out_doc.nodes[out_index].value {
326 *live_type = *new_live_type
327 }
328 }
329 else{
330 if let LiveValue::Class {live_type: old_live_type, ..} = &out_doc.nodes[out_index].value {
331 if let LiveValue::Class {live_type, ..} = &out_doc.nodes[local_ptr].value {
332 if live_type != old_live_type {
333 self.errors.push(LiveError {
334 origin: live_error_origin!(),
335 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
336 message: format!("Class override with wrong type {}", in_node.id)
337 });
338 }
339 }
340 }
341 out_doc.nodes[out_index].value = out_doc.nodes[local_ptr].value.clone();
342 }
343
344 if let LiveValue::Class {class_parent,..} = &mut out_doc.nodes[out_index].value {
345 *class_parent = LivePtr {file_id: self.in_file_id, index: local_ptr as u32, generation};
347 }
348 }
349 LiveScopeTarget::LivePtr(live_ptr) => {
350 let doc = &self.live_registry.live_files[live_ptr.file_id.to_index()].expanded;
351
352 let old_len = out_doc.nodes.len();
353 out_doc.nodes.insert_children_from_other(live_ptr.node_index(), out_index + 1, &doc.nodes);
354 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
355
356 out_doc.nodes[out_index].value = doc.nodes[live_ptr.node_index()].value.clone();
357
358 if let LiveValue::Class {class_parent,live_type, ..} = &mut out_doc.nodes[out_index].value {
359 if let LiveValue::Deref{live_type:new_live_type,..} = in_value{
360 *live_type = *new_live_type;
361 }
362 else{
363 *class_parent = live_ptr;
364 }
365 }
367 }
368 };
369 }
371 else if !Self::is_baseclass(*clone) { self.errors.push(LiveError {
373 origin: live_error_origin!(),
374 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
375 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)
376 });
377 }
378 current_parent.push((out_doc.nodes[out_index].id, out_index));
379 },
380 LiveValue::Class {live_type, ..} => {
381
382 if let LiveValue::Class {class_parent, ..} = &mut out_doc.nodes[out_index].value {
384 *class_parent = LivePtr {file_id: self.in_file_id, index: out_index as u32, generation};
385 }
386
387 let mut insert_point = out_index + 1;
388 let live_type_info = self.live_registry.live_type_infos.get(live_type).unwrap();
389
390 if let Some(field) = live_type_info.fields.iter().find( | f | f.live_field_kind == LiveFieldKind::Deref) {
391 if !field.live_type_info.live_ignore {
392 let live_type_info = &field.live_type_info;
393 if let Some(file_id) = self.live_registry.module_id_to_file_id.get(&live_type_info.module_id) {
394 let doc = &self.live_registry.live_files[file_id.to_index()].expanded;
395
396 let mut index = 1;
397 let mut found = None;
398 while index < doc.nodes.len() {
399 if let LiveValue::Class {live_type, ..} = &doc.nodes[index].value {
400 if *live_type == live_type_info.live_type {
401 found = Some(index);
402 break
403 }
404 }
405 index = doc.nodes.skip_node(index);
406 }
407 if let Some(index) = found {
408 let old_len = out_doc.nodes.len();
409 out_doc.nodes.insert_children_from_other(index, out_index + 1, &doc.nodes);
410 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, out_index, old_len, out_doc.nodes.len());
411 }
412 }
413 }
414 }
415 for field in &live_type_info.fields {
417 if field.live_field_kind == LiveFieldKind::Deref {
418 continue;
419 }
420 let lti = &field.live_type_info;
421 if let Some(file_id) = self.live_registry.module_id_to_file_id.get(<i.module_id) {
422
423 if *file_id == self.in_file_id { let mut index = 1;
425 let mut found = None;
426 while index < out_doc.nodes.len() - 1 {
427 if let LiveValue::Class {live_type, ..} = &out_doc.nodes[index].value {
428 if *live_type == lti.live_type {
429 found = Some(index);
430 break
431 }
432 }
433 index = out_doc.nodes.skip_node(index);
434 }
435 if let Some(index) = found {
436 let node_insert_point = insert_point;
437
438 let old_len = out_doc.nodes.len();
439 insert_point = out_doc.nodes.insert_node_from_self(index, insert_point);
440 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
441
442 out_doc.nodes[node_insert_point].id = field.id;
443 out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
444
445 }
446 else if !lti.live_ignore {
447 self.errors.push(LiveError {
448 origin: live_error_origin!(),
449 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
450 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)
451 });
452 }
453 }
454 else {
455 let other_nodes = &self.live_registry.live_files[file_id.to_index()].expanded.nodes;
456 if other_nodes.is_empty() {
457 panic!(
458 "Dependency order bug finding {}, file {} not registered before {}",
459 lti.type_name,
460 self.live_registry.file_id_to_file_name(*file_id),
461 self.live_registry.file_id_to_file_name(self.in_file_id),
462 );
463 }
464 let mut index = 1;
465 let mut found = None;
466 while index < other_nodes.len() - 1 {
467 if let LiveValue::Class {live_type, ..} = &other_nodes[index].value {
468 if *live_type == lti.live_type {
469 found = Some(index);
470 break
471 }
472 }
473 index = other_nodes.skip_node(index);
474 }
475 if let Some(index) = found {
476 let node_insert_point = insert_point;
477
478 let old_len = out_doc.nodes.len();
479 insert_point = out_doc.nodes.insert_node_from_other(index, insert_point, other_nodes);
480 self.shift_parent_stack(&mut current_parent, &out_doc.nodes, node_insert_point - 1, old_len, out_doc.nodes.len());
481
482 out_doc.nodes[node_insert_point].id = field.id;
483 out_doc.nodes[node_insert_point].origin.set_prop_type(LivePropType::Field);
484 }
485 else if !lti.live_ignore && lti.type_name != LiveId(0) {
486 self.errors.push(LiveError {
487 origin: live_error_origin!(),
488 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
489 message: format!("Typename {}, not defined in file where it was expected", lti.type_name)
490 });
491 }
492 }
493 }
494 else if !lti.live_ignore {
495 self.errors.push(LiveError {
496 origin: live_error_origin!(),
497 span: in_doc.token_id_to_span(in_node.origin.token_id().unwrap()).into(),
498 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)
499 });
500 }
501 }
502 current_parent.push((out_doc.nodes[out_index].id, out_index));
505 }
506 LiveValue::Expr {..} => {panic!()},
507 LiveValue::Array |
508 LiveValue::TupleEnum {..} |
509 LiveValue::NamedEnum {..} |
510 LiveValue::Object => { current_parent.push((out_doc.nodes[out_index].id, out_index));
512 },
513 LiveValue::DSL {..} => {
514 },
516 _ => {}
517 }
518
519 in_index += 1;
520 }
521 out_doc.nodes.push(in_doc.nodes.last().unwrap().clone());
522 let mut level = 0;
524
525 for i in 1..out_doc.nodes.len() {
526 let node = &mut out_doc.nodes[i];
530 if node.value.is_dsl() {
531 node.value.set_dsl_expand_index_if_none(i);
532 }
533 if level == 0 && in_doc.exports.get(&node.id).is_some(){
534 let id = node.id;
535 if let LiveValue::Root(root) = &mut out_doc.nodes[0].value{
536 root.exports.insert(id, i);
537 }
538 }
539 let node = &mut out_doc.nodes[i];
540 if node.value.is_open(){
541 level += 1
542 }
543 else if node.value.is_close() && level > 0{
544 level -= 1
545 }
546
547 }
548 }
549
550}
551