makepad_live_compiler/
live_registry.rs

1//use crate::id::Id;
2use {
3    std::collections::{HashMap, BTreeSet},
4    crate::{
5        makepad_live_id::*,
6        makepad_error_log::*,
7        makepad_live_tokenizer::{TokenWithLen, Delim, FullToken, LiveId, 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_reader::{LiveNodeMutReader},*/
13        live_node_vec::{LiveNodeSliceApi, /*LiveNodeVecApi*/},
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    
26    pub module_id: LiveModuleId,
27    pub (crate) start_pos: TextPos,
28    pub file_name: String,
29    pub cargo_manifest_path: String,
30    pub (crate) source: String,
31    pub (crate) deps: BTreeSet<LiveModuleId>,
32    
33    pub generation: LiveFileGeneration,
34    pub original: LiveOriginal,
35    pub next_original: Option<LiveOriginal>,
36    pub expanded: LiveExpanded,
37    
38    pub live_type_infos: Vec<LiveTypeInfo>,
39}
40
41pub struct LiveRegistry {
42    pub (crate) file_ids: HashMap<String, LiveFileId>,
43    pub module_id_to_file_id: HashMap<LiveModuleId, LiveFileId>,
44    pub live_files: Vec<LiveFile>,
45    pub live_type_infos: HashMap<LiveType, LiveTypeInfo>,
46    //pub ignore_no_dsl: HashSet<LiveId>,
47    pub main_module: Option<(LiveModuleId, LiveId)>,
48    pub components: LiveComponentRegistries,
49    pub package_root: Option<String>
50}
51
52impl Default for LiveRegistry {
53    fn default() -> Self {
54        Self {
55            main_module: None,
56            file_ids: HashMap::new(),
57            module_id_to_file_id: HashMap::new(),
58            live_files: Vec::new(),
59            live_type_infos: HashMap::new(),
60            components: LiveComponentRegistries::default(),
61            package_root: None
62        }
63    }
64}
65/*
66pub struct LiveDocNodes<'a> {
67    pub nodes: &'a [LiveNode],
68    pub file_id: LiveFileId,
69    pub index: usize
70}*/
71
72#[derive(Copy, Clone, Debug, PartialEq)]
73pub enum LiveScopeTarget {
74    LocalPtr(usize),
75    LivePtr(LivePtr)
76}
77
78
79#[derive(Clone, Debug, PartialEq)]
80pub struct LiveFileChange {
81    pub file_name: String,
82    pub content: String
83}
84
85impl LiveRegistry {
86    
87    pub fn generation_valid(&self, live_ptr: LivePtr) -> bool {
88        let doc = &self.live_files[live_ptr.file_id.to_index()];
89        doc.generation == live_ptr.generation
90    }
91    
92    pub fn ptr_to_node(&self, live_ptr: LivePtr) -> &LiveNode {
93        let doc = &self.live_files[live_ptr.file_id.to_index()];
94        if doc.generation != live_ptr.generation {
95            panic!("ptr_to_node generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
96        }
97        doc.expanded.resolve_ptr(live_ptr.index as usize)
98    }
99    
100    pub fn file_name_to_file_id(&self, file_name: &str) -> Option<LiveFileId> {
101        for (index, file) in self.live_files.iter().enumerate() {
102            if file.file_name == file_name {
103                return Some(LiveFileId::new(index))
104            }
105        }
106        None
107    }
108    
109    pub fn file_id_to_file_name(&self, file_id: LiveFileId) -> &str {
110        &self.live_files[file_id.to_index()].file_name
111    }
112    
113    pub fn file_id_to_cargo_manifest_path(&self, file_id: LiveFileId) -> String {
114        let file = &self.live_files[file_id.to_index()];
115        let manifest_path = &file.cargo_manifest_path;
116        if let Some(package_root) = &self.package_root {
117            if file.module_id.0.0 == 0 {
118                return package_root.to_string();
119            }
120            return format!("{}/{}", package_root, file.module_id.0);
121        }
122        manifest_path.to_string()
123    }
124    
125    pub fn crate_name_to_cargo_manifest_path(&self, crate_name: &str) -> Option<String> {
126        let crate_name = crate_name.replace('-', "_");
127        let base_crate = LiveId::from_str_with_lut(&crate_name).unwrap();
128        for file in &self.live_files {
129            if file.module_id.0 == base_crate {
130                if let Some(package_root) = &self.package_root {
131                    return Some(format!("{}/{}", package_root, crate_name));
132                }
133                return Some(file.cargo_manifest_path.to_string())
134            }
135        }
136        None
137    }
138    
139    pub fn ptr_to_doc_node(&self, live_ptr: LivePtr) -> (&LiveExpanded, &LiveNode) {
140        let doc = &self.live_files[live_ptr.file_id.to_index()];
141        if doc.generation != live_ptr.generation {
142            panic!("ptr_to_doc_node generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
143        }
144        (&doc.expanded, doc.expanded.resolve_ptr(live_ptr.index as usize))
145    }
146    
147    pub fn ptr_to_doc(&self, live_ptr: LivePtr) -> &LiveExpanded {
148        let doc = &self.live_files[live_ptr.file_id.to_index()];
149        if doc.generation != live_ptr.generation {
150            panic!("ptr_to_doc generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
151        }
152        &doc.expanded
153    }
154    
155    pub fn file_id_to_file(&self, file_id: LiveFileId) -> &LiveFile {
156        &self.live_files[file_id.to_index()]
157    }
158    
159    pub fn file_id_to_file_mut(&mut self, file_id: LiveFileId) -> &mut LiveFile {
160        &mut self.live_files[file_id.to_index()]
161    }
162    
163    pub fn file_id_index_to_live_ptr(&self, file_id: LiveFileId, index: usize) -> LivePtr {
164        LivePtr {
165            file_id,
166            index: index as u32,
167            generation: self.live_files[file_id.to_index()].generation
168        }
169    }
170    
171    pub fn ptr_to_nodes_index(&self, live_ptr: LivePtr) -> (&[LiveNode], usize) {
172        let doc = &self.live_files[live_ptr.file_id.to_index()];
173        if doc.generation != live_ptr.generation {
174            panic!("ptr_to_nodes_index generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
175        }
176        (&doc.expanded.nodes, live_ptr.index as usize)
177    }
178    
179    pub fn path_str_to_file_id(&self, path: &str) -> Option<LiveFileId> {
180        for (index, file) in self.live_files.iter().enumerate() {
181            if file.file_name == path {
182                return Some(LiveFileId(index as u16))
183            }
184        }
185        None
186    }
187    
188    
189    pub fn token_id_to_origin_doc(&self, token_id: LiveTokenId) -> &LiveOriginal {
190        &self.live_files[token_id.file_id().unwrap().to_index()].original
191    }
192    
193    pub fn token_id_to_token(&self, token_id: LiveTokenId) -> &TokenWithSpan {
194        &self.live_files[token_id.file_id().unwrap().to_index()].original.tokens[token_id.token_index()]
195    }
196    
197    pub fn token_id_to_expanded_doc(&self, token_id: LiveTokenId) -> &LiveExpanded {
198        &self.live_files[token_id.file_id().unwrap().to_index()].expanded
199    }
200    
201    pub fn module_id_to_file_id(&self, module_id: LiveModuleId) -> Option<LiveFileId> {
202        self.module_id_to_file_id.get(&module_id).cloned()
203    }
204    
205    pub fn file_id_to_module_id(&self, file_id: LiveFileId) -> Option<LiveModuleId> {
206        if let Some((k,_v)) = self.module_id_to_file_id.iter().find(|(_k,v)| **v == file_id){
207            return Some(*k)
208        }
209        None
210    }
211    
212    pub fn live_node_as_string(&self, node: &LiveNode) -> Option<String> {
213        match &node.value {
214            LiveValue::Str(v) => {
215                Some(v.to_string())
216            }
217            LiveValue::String(v) => {
218                Some(v.as_str().to_string())
219            }
220            LiveValue::InlineString(v) => {
221                Some(v.as_str().to_string())
222            }
223            LiveValue::Dependency (v) => {
224                Some(v.as_str().to_string())
225            }
226            _ => None
227        }
228    }
229    
230    // this looks at the 'id' before the live token id
231    pub fn get_node_prefix(&self, origin: LiveNodeOrigin) -> Option<LiveId> {
232        if !origin.node_has_prefix() {
233            return None
234        }
235        let first_def = origin.first_def().unwrap();
236        let token_index = first_def.token_index();
237        if token_index == 0 {
238            return None;
239        }
240        let doc = &self.live_files[first_def.file_id().unwrap().to_index()].original;
241        let token = &doc.tokens[token_index - 1];
242        if let LiveToken::Ident(id) = token.token {
243            return Some(id)
244        }
245        None
246    }
247    
248    pub fn module_id_to_expanded_nodes(&self, module_id: LiveModuleId) -> Option<&[LiveNode]> {
249        if let Some(file_id) = self.module_id_to_file_id.get(&module_id) {
250            let doc = &self.live_files[file_id.to_index()].expanded;
251            return Some(&doc.nodes)
252        }
253        None
254    }
255    
256    pub fn module_id_and_name_to_ptr(&self, module_id: LiveModuleId, name: LiveId) -> Option<LivePtr> {
257        if let Some(file_id) = self.module_id_to_file_id.get(&module_id) {
258            let live = &self.live_files[file_id.to_index()];
259            let doc = &live.expanded;
260            if name != LiveId::empty() {
261                if doc.nodes.is_empty() {
262                    error!("module_path_id_to_doc zero nodelen {}", self.file_id_to_file_name(*file_id));
263                    return None
264                }
265                if let Some(index) = doc.nodes.child_by_name(0, name.as_instance()) {
266                    return Some(LivePtr {file_id: *file_id, index: index as u32, generation: live.generation});
267                }
268                else {
269                    return None
270                }
271            }
272            else {
273                return Some(LivePtr {file_id: *file_id, index: 0, generation: live.generation});
274            }
275        }
276        None
277    }
278    /*
279    pub fn find_scope_item_via_class_parent(&self, start_ptr: LivePtr, item: LiveId) -> Option<(&[LiveNode], usize)> {
280        let (nodes, index) = self.ptr_to_nodes_index(start_ptr);
281        if let LiveValue::Class {class_parent, ..} = &nodes[index].value {
282            // ok its a class so now first scan up from here.
283            
284            if let Some(index) = nodes.scope_up_down_by_name(index, item) {
285                // item can be a 'use' as well.
286                // if its a use we need to resolve it, otherwise w found it
287                if let LiveValue::Use(module_id) = &nodes[index].value {
288                    if let Some(ldn) = self.module_id_and_name_to_doc(*module_id, nodes[index].id) {
289                        return Some((ldn.nodes, ldn.index))
290                    }
291                }
292                else {
293                    return Some((nodes, index))
294                }
295            }
296            else {
297                if let Some(class_parent) = class_parent {
298                    if class_parent.file_id != start_ptr.file_id {
299                        return self.find_scope_item_via_class_parent(*class_parent, item)
300                    }
301                }
302                
303            }
304        }
305        else {
306            println!("WRONG TYPE  {:?}", nodes[index].value);
307        }
308        None
309    }*/
310    
311    pub fn find_module_id_name(&self, item: LiveId, module_id: LiveModuleId) -> Option<LiveScopeTarget> {
312        // ok lets find it in that other doc
313        if let Some(file_id) = self.module_id_to_file_id(module_id) {
314            let file = self.file_id_to_file(file_id);
315            if file.expanded.nodes.is_empty() {
316                log!("Looking for {} but its not expanded yet, dependency order bug", file.file_name);
317                return None
318            }
319            if let Some(index) = file.expanded.nodes.child_by_name(0, item.as_instance()) {
320                return Some(LiveScopeTarget::LivePtr(
321                    LivePtr {file_id, index: index as u32, generation: file.generation}
322                ))
323            }
324        }
325        None
326    }
327    
328    pub fn find_scope_target(&self, item: LiveId, nodes: &[LiveNode]) -> Option<LiveScopeTarget> {
329        if let LiveValue::Root {id_resolve} = &nodes[0].value {
330            id_resolve.get(&item).cloned()
331        }
332        else {
333            log!("Can't find scope target on rootnode without id_resolve");
334            None
335        }
336    }
337    
338    
339    pub fn find_scope_target_one_level_or_global(&self, item: LiveId, index: usize, nodes: &[LiveNode]) -> Option<LiveScopeTarget> {
340        if let Some(index) = nodes.scope_up_down_by_name(index, item.as_instance(), 1) {
341            Some(LiveScopeTarget::LocalPtr(index))
342        } else {
343            self.find_scope_target(item, nodes)
344        }
345    }
346    
347    pub fn find_scope_ptr_via_expand_index(&self, file_id: LiveFileId, index: usize, item: LiveId) -> Option<LivePtr> {
348        // ok lets start
349        // let token_id = origin.token_id().unwrap();
350        //let index = origin.node_index().unwrap();
351        //let file_id = token_id.file_id();
352        let file = self.file_id_to_file(file_id);
353        match self.find_scope_target_one_level_or_global(item, index, &file.expanded.nodes) {
354            Some(LiveScopeTarget::LocalPtr(index)) => Some(LivePtr {file_id, index: index as u32, generation: file.generation}),
355            Some(LiveScopeTarget::LivePtr(ptr)) => Some(ptr),
356            None => None
357        }
358    }
359    
360    pub fn live_error_to_live_file_error(&self, live_error: LiveError) -> LiveFileError {
361        match live_error.span {
362            LiveErrorSpan::Text(text_span) => {
363                let live_file = &self.live_files[text_span.file_id.to_index()];
364                LiveFileError {
365                    origin: live_error.origin,
366                    file: live_file.file_name.clone(),
367                    span: text_span,
368                    message: live_error.message
369                }
370            }
371            LiveErrorSpan::Token(token_span) => {
372                let (file_name, span) = if let Some(file_id) = token_span.token_id.file_id() {
373                    let live_file = &self.live_files[file_id.to_index()];
374                    (live_file.file_name.as_str(), live_file.original.tokens[token_span.token_id.token_index()].span)
375                }
376                else {
377                    ("<file id is not defined>", TextSpan::default())
378                };
379                LiveFileError {
380                    origin: live_error.origin,
381                    file: file_name.to_string(),
382                    span,
383                    message: live_error.message
384                }
385            }
386        }
387    }
388    
389    pub fn token_id_to_span(&self, token_id: LiveTokenId) -> TextSpan {
390        self.live_files[token_id.file_id().unwrap().to_index()].original.token_id_to_span(token_id)
391    }
392    
393    pub fn tokenize_from_str(source: &str, start_pos: TextPos, file_id: LiveFileId) -> Result<Vec<TokenWithSpan>, LiveError> {
394        let mut line_chars = Vec::new();
395        let mut state = State::default();
396        let mut scratch = String::new();
397        let mut tokens = Vec::new();
398        let mut line_count = start_pos.line;
399        for line_str in source.lines() {
400            line_chars.clear();
401            line_chars.extend(line_str.chars());
402            let mut cursor = Cursor::new(&line_chars, &mut scratch);
403            let mut last_index = 0usize;
404            loop {
405                let (next_state, full_token) = state.next(&mut cursor);
406                if let Some(full_token) = full_token {
407                    let span = TextSpan {
408                        file_id,
409                        start: TextPos {column: last_index  as u32, line: line_count},
410                        end: TextPos {column: last_index as u32 + full_token.len  as u32, line: line_count}
411                    };
412                    match full_token.token {
413                        FullToken::Unknown | FullToken::OtherNumber | FullToken::Lifetime => {
414                            return Err(LiveError {
415                                origin: live_error_origin!(),
416                                span: span.into(),
417                                message: "Error tokenizing".to_string()
418                            })
419                        },
420                        _ => if let Some(live_token) = LiveToken::from_full_token(&full_token.token) {
421                            // lets build up the span info
422                            tokens.push(TokenWithSpan {span, token: live_token})
423                        },
424                    }
425                }
426                else {
427                    break;
428                }
429                state = next_state;
430                last_index = cursor.index();
431            }
432            line_count += 1;
433        }
434        tokens.push(TokenWithSpan {span: TextSpan::default(), token: LiveToken::Eof});
435        Ok(tokens)
436    }
437    
438    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> {
439        let mut line_chars = Vec::new();
440        let mut state = State::default();
441        let mut scratch = String::new();
442        let mut tokens = Vec::new();
443        let mut line_count = start_pos.line;
444        #[derive(Debug)]
445        enum Parse{
446            Before,
447            After,
448            Bang,
449            Brace,
450            Body(usize),
451        }
452        let mut parse = Parse::Before;
453        
454        'outer: for line_str in source.lines() {
455            line_chars.clear();
456            line_chars.extend(line_str.chars());
457            let mut cursor = Cursor::new(&line_chars, &mut scratch);
458            let mut last_index = 0usize;
459            loop {
460                let (next_state, full_token) = state.next(&mut cursor);
461                if let Some(full_token) = full_token {
462                    //log!("PARSE STATE {:?} {:?}", parse, full_token);
463                    match parse{
464                        Parse::Before=>{
465                            if let FullToken::Ident(live_id!(live_design)) = &full_token.token{
466                                parse = Parse::Bang;
467                            }
468                            else if let Some(negative) = &mut negative{
469                                negative.push(full_token);
470                            }
471                        }
472                        Parse::Bang=> if let FullToken::Punct(live_id!(!)) = &full_token.token{
473                            parse = Parse::Brace;
474                        }
475                        else if let FullToken::Whitespace = &full_token.token{
476                        }
477                        else{
478                            parse = Parse::Before;
479                        }
480                        Parse::Brace=> if let FullToken::Open(Delim::Brace) = &full_token.token{
481                            parse = Parse::Body(0);
482                        }
483                        else if let FullToken::Whitespace = &full_token.token{
484                        }
485                        else{
486                            parse = Parse::Before;
487                        }
488                        Parse::Body(depth)=>{
489                             if let FullToken::Open(Delim::Brace) = &full_token.token{
490                                 parse = Parse::Body(depth + 1)
491                            }
492                            if let FullToken::Close(Delim::Brace) = &full_token.token{
493                                if depth == 0{
494                                    last_index = cursor.index();
495                                    parse = Parse::After;
496                                    continue;
497                                }
498                                parse = Parse::Body(depth - 1);
499                            }
500                            let span = TextSpan {
501                                file_id,
502                                start: TextPos {column: last_index  as u32, line: line_count},
503                                end: TextPos {column: last_index as u32 + full_token.len  as u32, line: line_count}
504                            };
505                            if let Some(live_token) = LiveToken::from_full_token(&full_token.token) {
506                                tokens.push(TokenWithSpan {span, token: live_token})
507                            }
508                        }
509                        Parse::After=>{
510                            if let Some(negative) = &mut negative{
511                                negative.push(full_token);
512                            }
513                            else{
514                                break 'outer;
515                            }
516                        }
517                    }
518                }
519                else {
520                    break;
521                }
522                state = next_state;
523                last_index = cursor.index();
524            }
525            line_count += 1;
526        }
527        tokens.push(TokenWithSpan {span: TextSpan::default(), token: LiveToken::Eof});
528        Ok(tokens)
529    }
530    
531    pub fn process_file_changes(&mut self, changes: Vec<LiveFileChange>, errors:&mut Vec<LiveError >){
532        let mut any_changes = false;
533        for change in changes {
534            if let Some(file_id) = self.file_name_to_file_id(&change.file_name){
535                let module_id = self.file_id_to_module_id(file_id).unwrap();
536                let live_file = self.file_id_to_file_mut(file_id);
537                match Self::tokenize_from_str_live_design(&change.content, TextPos::default(), file_id, None) {
538                    Err(msg) => errors.push(msg), //panic!("Lex error {}", msg),
539                    Ok(new_tokens) => {
540                        let mut parser = LiveParser::new(&new_tokens, &live_file.live_type_infos, file_id);
541                        match parser.parse_live_document() {
542                            Err(msg) => {
543                                errors.push(msg);
544                            },
545                            Ok(mut ld) => { // only swap it out when it parses
546                                for node in &mut ld.nodes {
547                                    match &mut node.value {
548                                        LiveValue::Import(live_import) => {
549                                            if live_import.module_id.0 == live_id!(crate) { // patch up crate refs
550                                               live_import.module_id.0 = module_id.0
551                                            };
552                                        }
553                                        _=>()
554                                    }
555                                }
556                                any_changes = true;
557                                ld.tokens = new_tokens;
558                                live_file.original = ld;
559                                live_file.reexpand = true;
560                                live_file.generation.next_gen();
561                            }
562                        };
563                    }
564                }
565            }
566        }
567        if any_changes{
568            // try to re-expand
569            self.expand_all_documents(errors);
570        }
571    }
572
573    pub fn register_live_file(
574        &mut self,
575        file_name: &str,
576        cargo_manifest_path: &str,
577        own_module_id: LiveModuleId,
578        source: String,
579        live_type_infos: Vec<LiveTypeInfo>,
580        start_pos: TextPos,
581    ) -> Result<LiveFileId, LiveFileError> {
582        
583        // lets register our live_type_infos
584        if self.file_ids.get(file_name).is_some() {
585            panic!("cant register same file twice {}", file_name);
586        }
587        let file_id = LiveFileId::new(self.live_files.len());
588        
589        let tokens = match Self::tokenize_from_str(&source, start_pos, file_id) {
590            Err(msg) => return Err(msg.into_live_file_error(file_name)), //panic!("Lex error {}", msg),
591            Ok(lex_result) => lex_result
592        };
593        
594        let mut parser = LiveParser::new(&tokens, &live_type_infos, file_id);
595        
596        let mut original = match parser.parse_live_document() {
597            Err(msg) => return Err(msg.into_live_file_error(file_name)), //panic!("Parse error {}", msg.to_live_file_error(file, &source)),
598            Ok(ld) => ld
599        };
600        
601        original.tokens = tokens;
602        
603        // update our live type info
604        for live_type_info in &live_type_infos {
605            if let Some(info) = self.live_type_infos.get(&live_type_info.live_type) {
606                if info.module_id != live_type_info.module_id
607                    || info.live_type != live_type_info.live_type {
608                    panic!()
609                }
610            };
611            self.live_type_infos.insert(live_type_info.live_type, live_type_info.clone());
612        }
613        
614        let mut deps = BTreeSet::new();
615        
616        for node in &mut original.nodes {
617            match &mut node.value {
618                LiveValue::Import(live_import) => {
619                    if live_import.module_id.0 == live_id!(crate) { // patch up crate refs
620                       live_import.module_id.0 = own_module_id.0
621                    };
622                    deps.insert(live_import.module_id);
623                }, // import
624                /*LiveValue::Registry(component_id) => {
625                    let reg = self.components.0.borrow();
626                    if let Some(entry) = reg.values().find(|entry| entry.component_type() == *component_id){
627                        entry.get_module_set(&mut deps);
628                    }
629                }, */
630                LiveValue::Class {live_type, ..} => { // hold up. this is always own_module_path
631                    let infos = self.live_type_infos.get(live_type).unwrap();
632                    for sub_type in infos.fields.clone() {
633                        let sub_module_id = sub_type.live_type_info.module_id;
634                        if sub_module_id != own_module_id {
635                            deps.insert(sub_module_id);
636                        }
637                    }
638                }
639                _ => {
640                }
641            }
642        }
643        
644        let live_file = LiveFile {
645            cargo_manifest_path: cargo_manifest_path.to_string(),
646            reexpand: true,
647            module_id: own_module_id,
648            file_name: file_name.to_string(),
649            start_pos,
650            deps,
651            source,
652            generation: LiveFileGeneration::default(),
653            live_type_infos,
654            original,
655            next_original: None,
656            expanded: LiveExpanded::new()
657        };
658        self.module_id_to_file_id.insert(own_module_id, file_id);
659        
660        self.file_ids.insert(file_name.to_string(), file_id);
661        self.live_files.push(live_file);
662        
663        Ok(file_id)
664    }
665    
666    pub fn expand_all_documents(&mut self, errors: &mut Vec<LiveError>) {
667        // lets build up all dependencies here
668        
669        // alright so. we iterate
670        let mut dep_order = Vec::new();
671        
672        fn recur_insert_dep(parent_index: usize, dep_order: &mut Vec<LiveModuleId>, current: LiveModuleId, files: &Vec<LiveFile>) {
673            let file = if let Some(file) = files.iter().find( | v | v.module_id == current) {
674                file
675            }
676            else {
677                return
678            };
679            let final_index = if let Some(index) = dep_order.iter().position( | v | *v == current) {
680                if index > parent_index { // insert before
681                    dep_order.remove(index);
682                    dep_order.insert(parent_index, current);
683                    parent_index
684                }
685                else {
686                    index
687                }
688            }
689            else {
690                dep_order.insert(parent_index, current);
691                parent_index
692            };
693            
694            for dep in &file.deps {
695                recur_insert_dep(final_index, dep_order, *dep, files);
696            }
697        }
698        
699        for file in &self.live_files {
700            recur_insert_dep(dep_order.len(), &mut dep_order, file.module_id, &self.live_files);
701        }
702        
703        // now lets do the recursive recompile parsing.
704        fn recur_check_reexpand(current: LiveModuleId, files: &Vec<LiveFile>) -> bool {
705            let file = if let Some(file) = files.iter().find( | v | v.module_id == current) {
706                file
707            }
708            else {
709                return false
710            };
711            
712            if file.reexpand {
713                return true;
714            }
715            
716            for dep in &file.deps {
717                if recur_check_reexpand(*dep, files) {
718                    return true
719                }
720            }
721            false
722        }
723        
724        for i in 0..self.live_files.len() {
725            if recur_check_reexpand(self.live_files[i].module_id, &self.live_files) {
726                self.live_files[i].reexpand = true;
727            }
728        }
729        
730        for module_id in dep_order {
731            let file_id = if let Some(file_id) = self.module_id_to_file_id.get(&module_id) {
732                file_id
733            }
734            else {
735                continue
736            };
737            
738            if !self.live_files[file_id.to_index()].reexpand {
739                continue;
740            }
741            
742            let mut out_doc = LiveExpanded::new();
743            std::mem::swap(&mut out_doc, &mut self.live_files[file_id.to_index()].expanded);
744            
745            out_doc.nodes.clear();
746            
747            let in_doc = &self.live_files[file_id.to_index()].original;
748            
749            let mut live_document_expander = LiveExpander {
750                live_registry: self,
751                in_crate: module_id.0,
752                in_file_id: *file_id,
753                errors
754            };
755            live_document_expander.expand(in_doc, &mut out_doc, self.live_files[file_id.to_index()].generation);
756            
757            self.live_files[file_id.to_index()].reexpand = false;
758            std::mem::swap(&mut out_doc, &mut self.live_files[file_id.to_index()].expanded);
759        }
760    }
761}
762
763struct FileDepIter {
764    files_todo: Vec<LiveFileId>,
765    files_done: Vec<LiveFileId>
766}
767
768impl FileDepIter {
769    pub fn new(start: LiveFileId) -> Self {
770        Self {
771            files_todo: vec![start],
772            files_done: Vec::new()
773        }
774    }
775    
776    pub fn pop_todo(&mut self) -> Option<LiveFileId> {
777        if let Some(file_id) = self.files_todo.pop() {
778            self.files_done.push(file_id);
779            Some(file_id)
780        }
781        else {
782            None
783        }
784    }
785    
786    pub fn scan_next(&mut self, live_files: &[LiveFile]) {
787        let last_file_id = self.files_done.last().unwrap();
788        let module_id = live_files[last_file_id.to_index()].module_id;
789        
790        for (file_index, live_file) in live_files.iter().enumerate() {
791            if live_file.deps.contains(&module_id) {
792                let dep_id = LiveFileId::new(file_index);
793                if !self.files_done.iter().any( | v | *v == dep_id) {
794                    self.files_todo.push(dep_id);
795                }
796            }
797        }
798    }
799}