makepad_live_compiler/
live_registry.rs

1//use crate::id::Id;
2use {
3    std::collections::{BTreeMap, HashMap},
4    crate::{
5        makepad_live_id::*,
6       // makepad_error_log::*,
7        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_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    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 ignore_no_dsl: HashSet<LiveId>,
54    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/*
75pub struct LiveDocNodes<'a> {
76    pub nodes: &'a [LiveNode],
77    pub file_id: LiveFileId,
78    pub index: usize
79}*/
80
81#[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    /*
226    pub fn ptr_to_design_info(&self, live_ptr: LivePtr) -> Option<&LiveDesignInfo> {
227        let doc = &self.live_files[live_ptr.file_id.to_index()];
228        if doc.generation != live_ptr.generation {
229            panic!("ptr_to_nodes_index generation invalid for file {} gen:{} ptr:{}", doc.file_name, doc.generation, live_ptr.generation);
230        }
231        match &doc.expanded.nodes[live_ptr.index as usize].value{
232            LiveValue::Clone{design_info,..}|
233            LiveValue::Deref{design_info,..}|
234            LiveValue::Class {design_info,..}=>{
235                // alright lets fetch the original doc
236                if !design_info.is_invalid(){
237                    // alright we parse the nodes
238                    return Some(&doc.original.design_info[design_info.index()])
239                }
240            }
241            _=>()
242        }
243        None
244    }*/
245    
246    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    // this looks at the 'id' before the live token id
320    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    /*
368    pub fn find_scope_item_via_class_parent(&self, start_ptr: LivePtr, item: LiveId) -> Option<(&[LiveNode], usize)> {
369        let (nodes, index) = self.ptr_to_nodes_index(start_ptr);
370        if let LiveValue::Class {class_parent, ..} = &nodes[index].value {
371            // ok its a class so now first scan up from here.
372            
373            if let Some(index) = nodes.scope_up_down_by_name(index, item) {
374                // item can be a 'use' as well.
375                // if its a use we need to resolve it, otherwise w found it
376                if let LiveValue::Use(module_id) = &nodes[index].value {
377                    if let Some(ldn) = self.module_id_and_name_to_doc(*module_id, nodes[index].id) {
378                        return Some((ldn.nodes, ldn.index))
379                    }
380                }
381                else {
382                    return Some((nodes, index))
383                }
384            }
385            else {
386                if let Some(class_parent) = class_parent {
387                    if class_parent.file_id != start_ptr.file_id {
388                        return self.find_scope_item_via_class_parent(*class_parent, item)
389                    }
390                }
391                
392            }
393        }
394        else {
395            println!("WRONG TYPE  {:?}", nodes[index].value);
396        }
397        None
398    }*/
399    
400    pub fn find_module_id_name(&self, item: LiveId, module_id: LiveModuleId) -> Option<LiveScopeTarget> {
401        // ok lets find it in that other doc
402        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        // ok lets start
438        // let token_id = origin.token_id().unwrap();
439        //let index = origin.node_index().unwrap();
440        //let file_id = token_id.file_id();
441        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                // lets count the newlines 
496                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                        // lets build up the span info
519                        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                //log!("PARSE STATE {:?} {:?}", parse, full_token);
566                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), //panic!("Lex error {}", msg),
651                    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) => { // only swap it out when it parses
659                                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            // try to re-expand
674            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        // lets register our live_type_infos
688        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)), //panic!("Lex error {}", msg),
695            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)), //panic!("Parse error {}", msg.to_live_file_error(file, &source)),
700            Ok(ld) => ld
701        };
702        original.tokens = tokens;
703        // if we set a link, store it and point to our file_id
704        if let Some(link) = original.link{
705            // lets append our module_id
706            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        // update our live type info
718        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        //let mut deps = BTreeSet::new();
729        // lets populate all our exports on an exports table
730        // lets only walk the root level
731        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        // lets see if we are already in the dep order, and ifso put us at the end
757        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        // per link targets we should collect all exports in one hashtable
799        let mut ident_to_file:BTreeMap<LiveId,LiveFileId> = Default::default();
800        for (origin,import) in &doc.original.raw_imports{
801            // alright so if module id is link, we have to get a list of files
802            if import.module_id.0 == live_id!(link){
803                // module_id.1 is the link name
804                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){ // its a wildcard
814                        // compare our entire symbolset with the combined_exports
815                        for ident in &doc.original.identifiers{
816                            if let Some(inner_file_id) = combined_exports.get(&ident){
817                                if file_id != *inner_file_id{ // block refs to self
818                                    ident_to_file.insert(*ident, *inner_file_id);
819                                }
820                            }
821                        }
822                    }
823                    else{ // specific thing
824                        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){ // its a wildcard
847                    // compare our entire symbolset with the combined_exports
848                    for ident in &doc.original.identifiers{
849                        if doc2.original.exports.get(&ident).is_some(){
850                            if file_id != inner_file_id{ // block refs to self
851                                ident_to_file.insert(*ident, inner_file_id);
852                            }
853                        }
854                    }
855                }
856                else{ // specific thing
857                    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        // store an empty one to block recursion
871        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        // recur over all imported files
874        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) { // patch up crate refs
899                        live_import.module_id.0 = own_module_id.0
900                    };
901                    // ok lets emit the imports to the original
902                    doc.raw_imports.push((node.origin, *live_import.clone()));
903                },
904                LiveValue::Class {live_type, ..} => {
905                    // get our direct typed dependencies
906                    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(&lti.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                // lets grab the file
928                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        // ok so first off
947        // we need to run over our link_connections to gather our combined_exports
948        self.collect_combined_exports(errors);
949        
950        // alright lets start at the main module
951        // and then we have to hop from dependency to dependency
952        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            // there was likely an error in the main file
956            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        // FIX dont hardcode this, will fix it up with the icon refactor
965        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        /*
969        for dep in &dep_order{
970            let mi = self.file_id_to_module_id(*dep);
971        
972            println!("{:?}", mi);
973        }*/
974                
975        for file_id in dep_order.iter().rev() {
976            /*
977            if !self.live_files[file_id.to_index()].reexpand {
978                continue;
979            }*/
980            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/*
1002#[derive(Debug)]
1003pub struct DesignInfoRange{
1004    pub line: u32,
1005    pub start_column: u32,
1006    pub end_column: u32
1007}
1008
1009struct FileDepIter {
1010    files_todo: Vec<LiveFileId>,
1011    files_done: Vec<LiveFileId>
1012}
1013
1014impl FileDepIter {
1015    pub fn new(start: LiveFileId) -> Self {
1016        Self {
1017            files_todo: vec![start],
1018            files_done: Vec::new()
1019        }
1020    }
1021    
1022    pub fn pop_todo(&mut self) -> Option<LiveFileId> {
1023        if let Some(file_id) = self.files_todo.pop() {
1024            self.files_done.push(file_id);
1025            Some(file_id)
1026        }
1027        else {
1028            None
1029        }
1030    }
1031    
1032    pub fn scan_next(&mut self, live_files: &[LiveFile]) {
1033        let last_file_id = self.files_done.last().unwrap();
1034        let module_id = live_files[last_file_id.to_index()].module_id;
1035        
1036        for (file_index, live_file) in live_files.iter().enumerate() {
1037            if live_file.deps.contains(&module_id) {
1038                let dep_id = LiveFileId::new(file_index);
1039                if !self.files_done.iter().any( | v | *v == dep_id) {
1040                    self.files_todo.push(dep_id);
1041                }
1042            }
1043        }
1044    }
1045}*/