1use {
3 std::collections::{BTreeMap, HashMap},
4 crate::{
5 makepad_live_id::*,
6 makepad_live_tokenizer::{TokenWithLen, Delim, FullToken, State, Cursor, live_error_origin, LiveErrorOrigin},
8 live_error::{LiveError, LiveErrorSpan, LiveFileError},
9 live_parser::LiveParser,
10 live_document::{LiveOriginal, LiveExpanded},
11 live_node::{LiveNodeOrigin, LiveNode, LiveValue, LiveType, LiveTypeInfo, LiveIdAsProp},
12 live_node_vec::{LiveNodeSliceApi, },
14 live_ptr::{LiveFileId, LivePtr, LiveModuleId, LiveFileGeneration},
15 live_token::{LiveToken, LiveTokenId, TokenWithSpan},
16 span::{TextSpan, TextPos},
17 live_expander::{LiveExpander},
18 live_component::{LiveComponentRegistries}
19 }
20};
21
22#[derive(Default)]
23pub struct LiveFile {
24 pub (crate) reexpand: bool,
25 pub module_id: LiveModuleId,
26 pub (crate) start_pos: TextPos,
27 pub file_name: String,
28 pub cargo_manifest_path: String,
29 pub (crate) source: String,
30
31 pub generation: LiveFileGeneration,
32 pub original: LiveOriginal,
33 pub next_original: Option<LiveOriginal>,
34 pub expanded: LiveExpanded,
35
36 pub live_type_infos: Vec<LiveTypeInfo>,
37}
38
39#[derive(Default)]
40pub struct LiveLinkTarget{
41 targets: Vec<LiveFileId>,
42 combined_exports: Option<HashMap<LiveId, LiveFileId>>
43}
44
45pub struct LiveRegistry {
46 pub (crate) file_ids: BTreeMap<String, LiveFileId>,
47 pub (crate) link_targets: BTreeMap<LiveId, LiveLinkTarget>,
48 pub (crate) link_connections: BTreeMap<LiveId, LiveId>,
49
50 pub module_id_to_file_id: BTreeMap<LiveModuleId, LiveFileId>,
51 pub live_files: Vec<LiveFile>,
52 pub live_type_infos: BTreeMap<LiveType, LiveTypeInfo>,
53 pub main_module: Option<LiveTypeInfo>,
55 pub components: LiveComponentRegistries,
56 pub package_root: Option<String>
57}
58
59impl Default for LiveRegistry {
60 fn default() -> Self {
61 Self {
62 main_module: None,
63 file_ids: Default::default(),
64 link_targets: Default::default(),
65 link_connections: Default::default(),
66 module_id_to_file_id: Default::default(),
67 live_files: Vec::new(),
68 live_type_infos: Default::default(),
69 components: LiveComponentRegistries::default(),
70 package_root: None
71 }
72 }
73}
74#[derive(Default)]
82struct ProcessedImports{
83 set: HashMap<LiveId,LiveFileId>
84}
85
86
87#[derive(Copy, Clone, Debug, PartialEq)]
88pub enum LiveScopeTarget {
89 LocalPtr(usize),
90 LivePtr(LivePtr)
91}
92
93
94#[derive(Clone, Debug, PartialEq)]
95pub struct LiveFileChange {
96 pub file_name: String,
97 pub content: String
98}
99
100impl LiveRegistry {
101 pub fn link(&mut self, from:LiveId, to:LiveId){
102 if let Some(from) = self.link_connections.get_mut(&from){
103 *from = to;
104 }
105 else{
106 self.link_connections.insert(from, to);
107 }
108 }
109
110 pub fn file_ids(&self)->&BTreeMap<String, LiveFileId>{
111 &self.file_ids
112 }
113
114 pub fn generation_valid(&self, live_ptr: LivePtr) -> bool {
115 let doc = &self.live_files[live_ptr.file_id.to_index()];
116 doc.generation == live_ptr.generation
117 }
118
119 pub fn ptr_to_node(&self, live_ptr: LivePtr) -> &LiveNode {
120 let doc = &self.live_files[live_ptr.file_id.to_index()];
121 if doc.generation != live_ptr.generation {
122 panic!("ptr_to_node generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
123 }
124 doc.expanded.resolve_ptr(live_ptr.index as usize)
125 }
126
127 pub fn file_name_to_file_id(&self, file_name: &str) -> Option<LiveFileId> {
128 for (index, file) in self.live_files.iter().enumerate() {
129 if file.file_name == file_name {
130 return Some(LiveFileId::new(index))
131 }
132 }
133 None
134 }
135
136 pub fn file_id_to_file_name(&self, file_id: LiveFileId) -> &str {
137 &self.live_files[file_id.to_index()].file_name
138 }
139
140 pub fn file_id_to_cargo_manifest_path(&self, file_id: LiveFileId) -> String {
141 let file = &self.live_files[file_id.to_index()];
142 let manifest_path = &file.cargo_manifest_path;
143 if let Some(package_root) = &self.package_root {
144 if file.module_id.0.0 == 0 {
145 return package_root.to_string();
146 }
147 return format!("{}/{}", package_root, file.module_id.0);
148 }
149 manifest_path.to_string()
150 }
151
152 pub fn crate_name_to_cargo_manifest_path(&self, crate_name: &str) -> Option<String> {
153 let crate_name = crate_name.replace('-', "_");
154 let base_crate = LiveId::from_str_with_lut(&crate_name).unwrap();
155 for file in &self.live_files {
156 if file.module_id.0 == base_crate {
157 if let Some(package_root) = &self.package_root {
158 return Some(format!("{}/{}", package_root, crate_name));
159 }
160 return Some(file.cargo_manifest_path.to_string())
161 }
162 }
163 None
164 }
165
166 pub fn ptr_to_doc_node(&self, live_ptr: LivePtr) -> (&LiveExpanded, &LiveNode) {
167 let doc = &self.live_files[live_ptr.file_id.to_index()];
168 if doc.generation != live_ptr.generation {
169 panic!("ptr_to_doc_node generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
170 }
171 (&doc.expanded, doc.expanded.resolve_ptr(live_ptr.index as usize))
172 }
173
174 pub fn ptr_to_file_name_and_object_span(&self, ptr: LivePtr) -> (String, TextSpan){
175 let doc = self.ptr_to_doc(ptr);
176 let start_node = &doc.nodes[ptr.index as usize];
177 let end_index = doc.nodes.skip_node(ptr.index as usize) - 1;
178 let end_node = &doc.nodes[end_index];
179
180 let start_token = self.token_id_to_token(start_node.origin.token_id().unwrap()).clone();
181 let end_token = self.token_id_to_token(end_node.origin.token_id().unwrap()).clone();
182 let start = start_token.span.start;
183 let end = end_token.span.end;
184 (
185 self.file_id_to_file(ptr.file_id).file_name.clone(),
186 TextSpan{
187 file_id: ptr.file_id,
188 start,
189 end
190 }
191 )
192 }
193
194 pub fn ptr_to_doc(&self, live_ptr: LivePtr) -> &LiveExpanded {
195 let doc = &self.live_files[live_ptr.file_id.to_index()];
196 if doc.generation != live_ptr.generation {
197 panic!("ptr_to_doc generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
198 }
199 &doc.expanded
200 }
201
202 pub fn file_id_to_file(&self, file_id: LiveFileId) -> &LiveFile {
203 &self.live_files[file_id.to_index()]
204 }
205
206 pub fn file_id_to_file_mut(&mut self, file_id: LiveFileId) -> &mut LiveFile {
207 &mut self.live_files[file_id.to_index()]
208 }
209
210 pub fn file_id_index_to_live_ptr(&self, file_id: LiveFileId, index: usize) -> LivePtr {
211 LivePtr {
212 file_id,
213 index: index as u32,
214 generation: self.live_files[file_id.to_index()].generation
215 }
216 }
217
218 pub fn ptr_to_nodes_index(&self, live_ptr: LivePtr) -> (&[LiveNode], usize) {
219 let doc = &self.live_files[live_ptr.file_id.to_index()];
220 if doc.generation != live_ptr.generation {
221 panic!("ptr_to_nodes_index generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
222 }
223 (&doc.expanded.nodes, live_ptr.index as usize)
224 }
225 pub fn path_str_to_file_id(&self, path: &str) -> Option<LiveFileId> {
247 for (index, file) in self.live_files.iter().enumerate() {
248 if file.file_name == path {
249 return Some(LiveFileId(index as u16))
250 }
251 }
252 None
253 }
254
255 pub fn path_end_to_file_id(&self, path: &str) -> Option<LiveFileId> {
256 for (index, file) in self.live_files.iter().enumerate() {
257 if file.file_name.ends_with(path) {
258 return Some(LiveFileId(index as u16))
259 }
260 }
261 None
262 }
263
264
265 pub fn token_id_to_origin_doc(&self, token_id: LiveTokenId) -> &LiveOriginal {
266 &self.live_files[token_id.file_id().unwrap().to_index()].original
267 }
268
269 pub fn token_id_to_token(&self, token_id: LiveTokenId) -> &TokenWithSpan {
270 &self.live_files[token_id.file_id().unwrap().to_index()].original.tokens[token_id.token_index()]
271 }
272
273 pub fn token_id_to_expanded_doc(&self, token_id: LiveTokenId) -> &LiveExpanded {
274 &self.live_files[token_id.file_id().unwrap().to_index()].expanded
275 }
276
277 pub fn module_id_to_file_id(&self, module_id: LiveModuleId) -> Option<LiveFileId> {
278 self.module_id_to_file_id.get(&module_id).cloned()
279 }
280
281 pub fn file_id_to_module_id(&self, file_id: LiveFileId) -> Option<LiveModuleId> {
282 if let Some((k,_v)) = self.module_id_to_file_id.iter().find(|(_k,v)| **v == file_id){
283 return Some(*k)
284 }
285 None
286 }
287
288 pub fn main_file_id(&self) -> Option<LiveFileId> {
289 if let Some(m) = &self.main_module{
290 if let Some(m) = self.module_id_to_file_id.get(&m.module_id){
291 return Some(m.clone())
292 }
293 }
294 None
295 }
296
297
298 pub fn live_node_as_string(&self, node: &LiveNode) -> Option<String> {
299 match &node.value {
300 LiveValue::Str(v) => {
301 Some(v.to_string())
302 }
303 LiveValue::String(v) => {
304 Some(v.as_str().to_string())
305 }
306 LiveValue::InlineString(v) => {
307 Some(v.as_str().to_string())
308 }
309 LiveValue::Dependency (v) => {
310 Some(v.as_str().to_string())
311 }
312 LiveValue::Font (v) => {
313 Some(v.paths[0].as_str().to_string())
314 }
315 _ => None
316 }
317 }
318
319 pub fn get_node_prefix(&self, origin: LiveNodeOrigin) -> Option<LiveId> {
321 if !origin.node_has_prefix() {
322 return None
323 }
324 let first_def = origin.first_def().unwrap();
325 let token_index = first_def.token_index();
326 if token_index == 0 {
327 return None;
328 }
329 let doc = &self.live_files[first_def.file_id().unwrap().to_index()].original;
330 let token = &doc.tokens[token_index - 1];
331 if let LiveToken::Ident(id) = token.token {
332 return Some(id)
333 }
334 None
335 }
336
337 pub fn module_id_to_expanded_nodes(&self, module_id: LiveModuleId) -> Option<&[LiveNode]> {
338 if let Some(file_id) = self.module_id_to_file_id.get(&module_id) {
339 let doc = &self.live_files[file_id.to_index()].expanded;
340 return Some(&doc.nodes)
341 }
342 None
343 }
344
345 pub fn module_id_and_name_to_ptr(&self, module_id: LiveModuleId, name: LiveId) -> Option<LivePtr> {
346 if let Some(file_id) = self.module_id_to_file_id.get(&module_id) {
347 let live = &self.live_files[file_id.to_index()];
348 let doc = &live.expanded;
349 if name != LiveId::empty() {
350 if doc.nodes.is_empty() {
351 eprintln!("module_path_id_to_doc zero nodelen {}", self.file_id_to_file_name(*file_id));
352 return None
353 }
354 if let Some(index) = doc.nodes.child_by_name(0, name.as_instance()) {
355 return Some(LivePtr {file_id: *file_id, index: index as u32, generation: live.generation});
356 }
357 else {
358 return None
359 }
360 }
361 else {
362 return Some(LivePtr {file_id: *file_id, index: 0, generation: live.generation});
363 }
364 }
365 None
366 }
367 pub fn find_module_id_name(&self, item: LiveId, module_id: LiveModuleId) -> Option<LiveScopeTarget> {
401 if let Some(file_id) = self.module_id_to_file_id(module_id) {
403 let file = self.file_id_to_file(file_id);
404 if file.expanded.nodes.is_empty() {
405 println!("Looking for {} but its not expanded yet, dependency order bug", file.file_name);
406 return None
407 }
408 if let Some(index) = file.expanded.nodes.child_by_name(0, item.as_instance()) {
409 return Some(LiveScopeTarget::LivePtr(
410 LivePtr {file_id, index: index as u32, generation: file.generation}
411 ))
412 }
413 }
414 None
415 }
416
417 pub fn find_scope_target(&self, item: LiveId, nodes: &[LiveNode]) -> Option<LiveScopeTarget> {
418 if let LiveValue::Root(root) = &nodes[0].value {
419 root.locals.get(&item).cloned()
420 }
421 else {
422 println!("Can't find scope target on rootnode without id_resolve");
423 None
424 }
425 }
426
427
428 pub fn find_scope_target_one_level_or_global(&self, item: LiveId, index: usize, nodes: &[LiveNode]) -> Option<LiveScopeTarget> {
429 if let Some(index) = nodes.scope_up_down_by_name(index, item.as_instance(), 1) {
430 Some(LiveScopeTarget::LocalPtr(index))
431 } else {
432 self.find_scope_target(item, nodes)
433 }
434 }
435
436 pub fn find_scope_ptr_via_expand_index(&self, file_id: LiveFileId, index: usize, item: LiveId) -> Option<LivePtr> {
437 let file = self.file_id_to_file(file_id);
442 match self.find_scope_target_one_level_or_global(item, index, &file.expanded.nodes) {
443 Some(LiveScopeTarget::LocalPtr(index)) => Some(LivePtr {file_id, index: index as u32, generation: file.generation}),
444 Some(LiveScopeTarget::LivePtr(ptr)) => Some(ptr),
445 None => None
446 }
447 }
448
449 pub fn live_error_to_live_file_error(&self, live_error: LiveError) -> LiveFileError {
450 match live_error.span {
451 LiveErrorSpan::Text(text_span) => {
452 let live_file = &self.live_files[text_span.file_id.to_index()];
453 LiveFileError {
454 origin: live_error.origin,
455 file: live_file.file_name.clone(),
456 span: text_span,
457 message: live_error.message
458 }
459 }
460 LiveErrorSpan::Token(token_span) => {
461 let (file_name, span) = if let Some(file_id) = token_span.token_id.file_id() {
462 let live_file = &self.live_files[file_id.to_index()];
463 (live_file.file_name.as_str(), live_file.original.tokens[token_span.token_id.token_index()].span)
464 }
465 else {
466 ("<file id is not defined>", TextSpan::default())
467 };
468 LiveFileError {
469 origin: live_error.origin,
470 file: file_name.to_string(),
471 span,
472 message: live_error.message
473 }
474 }
475 }
476 }
477
478 pub fn token_id_to_span(&self, token_id: LiveTokenId) -> TextSpan {
479 self.live_files[token_id.file_id().unwrap().to_index()].original.token_id_to_span(token_id)
480 }
481
482 pub fn tokenize_from_str(source: &str, start_pos: TextPos, file_id: LiveFileId) -> Result<Vec<TokenWithSpan>, LiveError> {
483 let mut chars = Vec::new();
484 chars.extend(source.chars());
485 let mut state = State::default();
486 let mut scratch = String::new();
487 let mut tokens = Vec::new();
488 let mut line_start = start_pos.line;
489 let mut cursor = Cursor::new(&chars, &mut scratch);
490 let mut last_index = 0usize;
491 let mut last_new_line = 0usize;
492 loop {
493 let (next_state, full_token) = state.next(&mut cursor);
494 if let Some(full_token) = full_token {
495 let mut line_end = line_start;
497 let mut next_new_line = last_new_line;
498 for i in 0..full_token.len{
499 if chars[last_index + i] == '\n'{
500 line_end += 1;
501 next_new_line = last_index + i + 1;
502 }
503 }
504 let span = TextSpan {
505 file_id,
506 start: TextPos {column: (last_index - last_new_line) as u32, line: line_start},
507 end: TextPos {column: (last_index - last_new_line) as u32 + full_token.len as u32, line: line_end}
508 };
509 match full_token.token {
510 FullToken::Unknown | FullToken::OtherNumber | FullToken::Lifetime => {
511 return Err(LiveError {
512 origin: live_error_origin!(),
513 span: span.into(),
514 message: "Error tokenizing".to_string()
515 })
516 },
517 _ => if let Some(live_token) = LiveToken::from_full_token(&full_token.token) {
518 tokens.push(TokenWithSpan {span, token: live_token})
520 },
521 }
522 line_start = line_end;
523 last_new_line = next_new_line;
524 }
525 else {
526 break;
527 }
528 state = next_state;
529 last_index = cursor.index()
530 }
531 tokens.push(TokenWithSpan {span: TextSpan::default(), token: LiveToken::Eof});
532 Ok(tokens)
533 }
534
535 pub fn tokenize_from_str_live_design(source: &str, start_pos: TextPos, file_id: LiveFileId, mut negative:Option<&mut Vec<TokenWithLen>>) -> Result<Vec<TokenWithSpan>, LiveError> {
536 let mut chars = Vec::new();
537 chars.extend(source.chars());
538 let mut state = State::default();
539 let mut scratch = String::new();
540 let mut tokens = Vec::new();
541 let mut line_start = start_pos.line;
542 #[derive(Debug)]
543 enum Parse{
544 Before,
545 After,
546 Bang,
547 Brace,
548 Body(usize),
549 }
550 let mut parse = Parse::Before;
551 let mut cursor = Cursor::new(&chars, &mut scratch);
552 let mut last_index = 0usize;
553 let mut last_new_line = 0usize;
554 loop {
555 let (next_state, full_token) = state.next(&mut cursor);
556 if let Some(full_token) = full_token {
557 let mut line_end = line_start;
558 let mut next_new_line = last_new_line;
559 for i in 0..full_token.len{
560 if chars[last_index + i] == '\n'{
561 line_end += 1;
562 next_new_line = last_index + i + 1;
563 }
564 }
565 match parse{
567 Parse::Before=>{
568 if let FullToken::Ident(live_id!(live_design)) = &full_token.token{
569 parse = Parse::Bang;
570 }
571 else if let Some(negative) = &mut negative{
572 negative.push(full_token);
573 }
574 }
575 Parse::Bang=> if let FullToken::Punct(live_id!(!)) = &full_token.token{
576 parse = Parse::Brace;
577 }
578 else if let FullToken::Whitespace = &full_token.token{
579 }
580 else{
581 parse = Parse::Before;
582 }
583 Parse::Brace=> if let FullToken::Open(Delim::Brace) = &full_token.token{
584 parse = Parse::Body(0);
585 }
586 else if let FullToken::Whitespace = &full_token.token{
587 }
588 else{
589 parse = Parse::Before;
590 }
591 Parse::Body(depth)=>{
592 if let FullToken::Open(Delim::Brace) = &full_token.token{
593 parse = Parse::Body(depth + 1)
594 }
595 if let FullToken::Close(Delim::Brace) = &full_token.token{
596 if depth == 0{
597 last_index = cursor.index();
598 parse = Parse::After;
599 continue;
600 }
601 parse = Parse::Body(depth - 1);
602 }
603 let span = TextSpan {
604 file_id,
605 start: TextPos {column: (last_index - last_new_line) as u32, line: line_start},
606 end: TextPos {column: (last_index - last_new_line) as u32 + full_token.len as u32, line: line_end}
607 };
608 if let Some(live_token) = LiveToken::from_full_token(&full_token.token) {
609 tokens.push(TokenWithSpan {span, token: live_token})
610 }
611 }
612 Parse::After=>{
613 if let Some(negative) = &mut negative{
614 negative.push(full_token);
615 }
616 else{
617 break;
618 }
619 }
620 }
621 last_new_line = next_new_line;
622 line_start = line_end;
623 }
624 else {
625 break;
626 }
627 state = next_state;
628 last_index = cursor.index();
629 }
630 tokens.push(TokenWithSpan {span: TextSpan::default(), token: LiveToken::Eof});
631 Ok(tokens)
632 }
633
634 pub fn re_expand_all_files(&mut self){
635 for file in &mut self.live_files{
636
637 file.reexpand = true;
638 file.generation.next_gen();
639 }
640 let mut errors = Vec::new();
641 self.expand_all_documents(&mut errors);
642 }
643
644 pub fn process_file_changes(&mut self, changes: Vec<LiveFileChange>, errors:&mut Vec<LiveError >){
645 let mut any_changes = false;
646 for change in changes {
647 if let Some(file_id) = self.file_name_to_file_id(&change.file_name){
648 let module_id = self.file_id_to_module_id(file_id).unwrap();
649 match Self::tokenize_from_str_live_design(&change.content, TextPos::default(), file_id, None) {
650 Err(msg) => errors.push(msg), Ok(new_tokens) => {
652 let live_file = self.file_id_to_file_mut(file_id);
653
654 match LiveParser::parse_live_document(&new_tokens, &live_file.live_type_infos, file_id) {
655 Err(msg) => {
656 errors.push(msg);
657 },
658 Ok(mut ld) => { any_changes = true;
660 ld.tokens = new_tokens;
661 self.build_imports_and_exports(&mut ld, module_id, &change.file_name);
662 let live_file = self.file_id_to_file_mut(file_id);
663 live_file.original = ld;
664 live_file.reexpand = true;
665 live_file.generation.next_gen();
666 }
667 };
668 }
669 }
670 }
671 }
672 if any_changes{
673 self.expand_all_documents(errors);
675 }
676 }
677
678 pub fn register_live_file(
679 &mut self,
680 file_name: &str,
681 cargo_manifest_path: &str,
682 own_module_id: LiveModuleId,
683 source: String,
684 live_type_infos: Vec<LiveTypeInfo>,
685 start_pos: TextPos,
686 ) -> Result<LiveFileId, LiveFileError> {
687 if self.file_ids.get(file_name).is_some() {
689 panic!("cant register same file twice {}", file_name);
690 }
691 let file_id = LiveFileId::new(self.live_files.len());
692
693 let tokens = match Self::tokenize_from_str(&source, start_pos, file_id) {
694 Err(msg) => return Err(msg.into_live_file_error(file_name)), Ok(lex_result) => lex_result
696 };
697
698 let mut original = match LiveParser::parse_live_document(&tokens, &live_type_infos, file_id) {
699 Err(msg) => return Err(msg.into_live_file_error(file_name)), Ok(ld) => ld
701 };
702 original.tokens = tokens;
703 if let Some(link) = original.link{
705 if let Some(lt) = self.link_targets.get_mut(&link){
707 lt.targets.push(file_id);
708 }
709 else{
710 self.link_targets.insert(link, LiveLinkTarget{
711 targets: vec![file_id],
712 combined_exports: None
713 });
714 }
715 }
716
717 for live_type_info in &live_type_infos {
719 if let Some(info) = self.live_type_infos.get(&live_type_info.live_type) {
720 if info.module_id != live_type_info.module_id
721 || info.live_type != live_type_info.live_type {
722 panic!()
723 }
724 };
725 self.live_type_infos.insert(live_type_info.live_type, live_type_info.clone());
726 }
727
728 self.build_imports_and_exports(&mut original, own_module_id, &file_name);
732
733 let live_file = LiveFile {
734 cargo_manifest_path: cargo_manifest_path.to_string(),
735 reexpand: true,
736 module_id: own_module_id,
737 file_name: file_name.to_string(),
738 start_pos,
739 source,
740 generation: LiveFileGeneration::default(),
741 live_type_infos,
742 original,
743 next_original: None,
744 expanded: LiveExpanded::new()
745 };
746 self.module_id_to_file_id.insert(own_module_id, file_id);
747
748 self.file_ids.insert(file_name.to_string(), file_id);
749 self.live_files.push(live_file);
750
751 Ok(file_id)
752 }
753
754 fn doc_original_raw_imports_to_resolved_recur(&mut self, file_id: LiveFileId, errors: &mut Vec<LiveError>, dep_order: &mut Vec<LiveFileId>){
755
756 if dep_order.iter().find(|v| **v == file_id).is_some(){
758
759 fn recur_dep_order(file_id:LiveFileId, dep_order: &mut Vec<LiveFileId>, docs:&[LiveFile], recur_block: &mut Vec<LiveFileId>){
760 if recur_block.contains(&file_id){
761 for recur in recur_block{
762 println!("Dependency recursion in: {:?}", docs[recur.to_index()].file_name);
763 }
764 return
765 }
766 recur_block.push(file_id);
767 let doc = &docs[file_id.to_index()];
768 let imports = &doc.original.resolved_imports.as_ref().unwrap();
769 let pos = if let Some(pos) = dep_order.iter().position(|v| *v == file_id){
770 pos
771 }
772 else{
773 println!("Invalid state in dependency list for {}", docs[file_id.to_index()].file_name);
774 return
775 };
776 dep_order.remove(pos);
777 dep_order.push(file_id);
778 for import in imports.values(){
779 recur_dep_order(*import, dep_order, docs, recur_block)
780 }
781 for type_file_id in &doc.original.type_imports{
782 if file_id != *type_file_id{
783 recur_dep_order(*type_file_id, dep_order, docs, recur_block)
784 }
785 }
786 recur_block.pop();
787 }
788 let mut recur_block = Vec::new();
789 recur_dep_order(file_id, dep_order, &mut self.live_files, &mut recur_block);
790 return;
791 }
792 else{
793 dep_order.push(file_id);
794 }
795
796 let doc = &self.live_files[file_id.to_index()];
797
798 let mut ident_to_file:BTreeMap<LiveId,LiveFileId> = Default::default();
800 for (origin,import) in &doc.original.raw_imports{
801 if import.module_id.0 == live_id!(link){
803 let link_to = if let Some(link_to) = self.link_connections.get(&import.module_id.1){
805 *link_to
806 }
807 else{
808 import.module_id.1
809 };
810
811 if let Some(link_target) = self.link_targets.get(&link_to){
812 let combined_exports = link_target.combined_exports.as_ref().unwrap();
813 if import.import_id == LiveId(0){ for ident in &doc.original.identifiers{
816 if let Some(inner_file_id) = combined_exports.get(&ident){
817 if file_id != *inner_file_id{ ident_to_file.insert(*ident, *inner_file_id);
819 }
820 }
821 }
822 }
823 else{ if let Some(file_id) = combined_exports.get(&import.import_id){
825 ident_to_file.insert(import.import_id, *file_id);
826 }
827 else{
828 errors.push(LiveError {
829 origin: live_error_origin!(),
830 span: doc.original.token_id_to_span(origin.token_id().unwrap()).into(),
831 message: format!("Cannot find use target {}",import.import_id)
832 });
833 }
834 }
835 }
836 else{
837 errors.push(LiveError {
838 origin: live_error_origin!(),
839 span: doc.original.token_id_to_span(origin.token_id().unwrap()).into(),
840 message: format!("No link connection targets {}",link_to)
841 });
842 }
843 }
844 else if let Some(inner_file_id) = self.module_id_to_file_id(import.module_id){
845 let doc2 = &self.live_files[inner_file_id.to_index()];
846 if import.import_id == LiveId(0){ for ident in &doc.original.identifiers{
849 if doc2.original.exports.get(&ident).is_some(){
850 if file_id != inner_file_id{ ident_to_file.insert(*ident, inner_file_id);
852 }
853 }
854 }
855 }
856 else{ if doc2.original.exports.get(&import.import_id).is_some(){
858 ident_to_file.insert(import.import_id, inner_file_id);
859 }
860 else{
861 errors.push(LiveError {
862 origin: live_error_origin!(),
863 span: doc.original.token_id_to_span(origin.token_id().unwrap()).into(),
864 message: format!("Cannot find use target {}",import.import_id)
865 });
866 }
867 }
868 }
869 }
870 let type_imports = doc.original.type_imports.clone();
872 self.live_files[file_id.to_index()].original.resolved_imports = Some(ident_to_file.clone());
873 for file_id in type_imports{
875 self.doc_original_raw_imports_to_resolved_recur(file_id, errors, dep_order);
876 }
877 for file_id in ident_to_file.values(){
878 self.doc_original_raw_imports_to_resolved_recur(*file_id, errors, dep_order);
879 }
880
881 }
882
883 fn build_imports_and_exports(&self, doc:&mut LiveOriginal, own_module_id:LiveModuleId, _name:&str){
884 let mut node_iter = doc.nodes.first_child(0);
885
886 while let Some(node_index) = node_iter {
887
888 let node = &mut doc.nodes[node_index];
889 if node.origin.node_has_prefix(){
890 let prev_token = &doc.tokens[node.origin.first_def().unwrap().token_index()-1];
891 if prev_token.token == LiveToken::Ident(live_id!(pub)){
892 doc.exports.insert(node.id, node.origin);
893 }
894 }
895
896 match &mut node.value {
897 LiveValue::Import(live_import) => {
898 if live_import.module_id.0 == live_id!(crate) { live_import.module_id.0 = own_module_id.0
900 };
901 doc.raw_imports.push((node.origin, *live_import.clone()));
903 },
904 LiveValue::Class {live_type, ..} => {
905 let live_type_info = self.live_type_infos.get(live_type).unwrap();
907 for field in &live_type_info.fields {
908 let lti = &field.live_type_info;
909
910 if let Some(file_id) = self.module_id_to_file_id.get(<i.module_id) {
911 doc.type_imports.insert(*file_id);
912 }
913 }
914 }
915 _ => {
916 }
917 }
918
919 node_iter = doc.nodes.next_child(node_index);
920 }
921 }
922
923 fn collect_combined_exports(&mut self, errors: &mut Vec<LiveError>){
924 for link_target in self.link_targets.values_mut(){
925 let mut combined_exports = HashMap::new();
926 for target in &link_target.targets{
927 let doc = &self.live_files[target.to_index()];
929 for (ident,origin) in &doc.original.exports{
930 if combined_exports.get(ident).is_some(){
931 errors.push(LiveError {
932 origin: live_error_origin!(),
933 span: doc.original.token_id_to_span(origin.token_id().unwrap()).into(),
934 message: format!("Target already present in link set: {}",ident)
935 });
936 }
937 combined_exports.insert(*ident, *target);
938 }
939 }
940 link_target.combined_exports = Some(combined_exports);
941 }
942 }
943
944
945 pub fn expand_all_documents(&mut self, errors: &mut Vec<LiveError>) {
946 self.collect_combined_exports(errors);
949
950 let main_module_id = self.main_module.as_ref().unwrap().module_id;
953 let main_file_id = self.module_id_to_file_id.get(&main_module_id).cloned();
954 if main_file_id.is_none(){
955 println!("Cannot find main file id for file {}", main_module_id);
957 return;
958 }
959 let main_file_id = main_file_id.unwrap();
960
961 let mut dep_order = Vec::new();
962 self.doc_original_raw_imports_to_resolved_recur(main_file_id, errors, &mut dep_order);
963
964 let fixup_file_id = self.path_end_to_file_id("draw_trapezoid.rs").unwrap();
966 self.doc_original_raw_imports_to_resolved_recur(fixup_file_id, errors, &mut dep_order);
967
968 for file_id in dep_order.iter().rev() {
976 let module_id = self.file_id_to_module_id(*file_id).unwrap();
981 let mut out_doc = LiveExpanded::new();
982 std::mem::swap(&mut out_doc, &mut self.live_files[file_id.to_index()].expanded);
983
984 out_doc.nodes.clear();
985
986 let in_doc = &self.live_files[file_id.to_index()].original;
987
988 let mut live_document_expander = LiveExpander {
989 live_registry: self,
990 in_crate: module_id.0,
991 in_file_id: *file_id,
992 errors
993 };
994 live_document_expander.expand(in_doc, &mut out_doc, self.live_files[file_id.to_index()].generation);
995
996 self.live_files[file_id.to_index()].reexpand = false;
997 std::mem::swap(&mut out_doc, &mut self.live_files[file_id.to_index()].expanded);
998 }
999 }
1000}
1001