diff options
-rw-r--r-- | src/resolver.rs | 39 | ||||
-rw-r--r-- | src/source_unit.rs | 67 |
2 files changed, 65 insertions, 41 deletions
diff --git a/src/resolver.rs b/src/resolver.rs index 2b49055..8d3a16d 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -43,12 +43,20 @@ impl Resolver { let source_id = self.source_units.len(); use std::mem::take; - info!("Including source file at {:?}", source_unit.main.path); - self.include_symbols(take(&mut source_unit.main.symbols), source_id, SourceRole::Main); + info!("Including source unit at {:?}", source_unit.main.path); + if let Some(symbols) = &mut source_unit.main.symbols { + self.include_symbols(take(symbols), source_id, SourceRole::Main); + } if let Some(head) = &mut source_unit.head { - self.include_symbols(take(&mut head.symbols), source_id, SourceRole::Head); } + if let Some(symbols) = &mut head.symbols { + self.include_symbols(take(symbols), source_id, SourceRole::Head); + } + } if let Some(tail) = &mut source_unit.tail { - self.include_symbols(take(&mut tail.symbols), source_id, SourceRole::Tail); } + if let Some(symbols) = &mut tail.symbols { + self.include_symbols(take(symbols), source_id, SourceRole::Tail); + } + } match parent_id { Some(parent_id) => match self.source_units.get_mut(parent_id) { @@ -153,19 +161,18 @@ impl Resolver { /// Return the ID of a source unit that contains an unresolved reference /// to a symbol defined by this unit. fn unit_resolved_by_unit(&self, source_unit: &SourceUnit) -> Option<usize> { - if let Some(id) = self.unit_resolved_by_symbol(&source_unit.main.symbols) { - return Some(id); - } - if let Some(head) = &source_unit.head { - if let Some(id) = self.unit_resolved_by_symbol(&head.symbols) { - return Some(id); - } - } - if let Some(tail) = &source_unit.tail { - if let Some(id) = self.unit_resolved_by_symbol(&tail.symbols) { - return Some(id); - } + macro_rules! return_resolved_unit { + ($file:expr) => { + if let Some(symbols) = &$file.symbols { + if let Some(id) = self.unit_resolved_by_symbol(&symbols) { + return Some(id); + } + } + }; } + return_resolved_unit!(&source_unit.main); + if let Some(head) = &source_unit.head { return_resolved_unit!(&head) } + if let Some(tail) = &source_unit.tail { return_resolved_unit!(&tail) } return None; } diff --git a/src/source_unit.rs b/src/source_unit.rs index 3e30284..9c51ccb 100644 --- a/src/source_unit.rs +++ b/src/source_unit.rs @@ -1,10 +1,10 @@ use crate::*; -use log::info; +use log::{info, warn}; use vagabond::*; -type ParseFn = fn(&str, Option<&Path>) -> Vec<Symbol>; +type ParseFn = fn(&str, Option<&Path>) -> Option<Vec<Symbol>>; /// Gather all source units with a given extension using a PATH-style environment variable. @@ -22,20 +22,39 @@ pub fn gather_from_path_variable(variable: &str, extension: Option<&str>, parse: /// Gather source units with a given extension at or descending from a path. pub fn gather_from_path(path: &Path, extension: Option<&str>, parse: ParseFn) -> Vec<SourceUnit> { let mut source_units = Vec::new(); + let check_optional_file = |file: &Option<SourceFile>| -> bool { + match file { + Some(file) => match file.symbols { + Some(_) => { info!("Found source file at {:?}", file.path); true } + None => { warn!("Could not parse source file at {:?}", file.path); false } + } + None => true, + } + }; + let mut gather_source_unit = |path: &Path| { + if let Ok(unit) = SourceUnit::from_path(&path, extension, parse) { + if unit.main.symbols.is_some() { + info!("Found source file at {:?}", unit.main.path); + let head_good = check_optional_file(&unit.head); + let tail_good = check_optional_file(&unit.tail); + if head_good && tail_good { + source_units.push(unit); + } + } else { + warn!("Could not parse source file at {path:?}"); + check_optional_file(&unit.head); + check_optional_file(&unit.tail); + } + } + }; if let Ok(entry) = Entry::from_path(path) { if EntryType::File == entry.entry_type { - if let Ok(unit) = SourceUnit::from_path(&entry.path, extension, parse) { - info!("Found source file at {path:?}"); - source_units.push(unit); - } + gather_source_unit(&entry.path) } else if EntryType::Directory == entry.entry_type { info!("Traversing directory {path:?} for source files"); if let Ok(entries) = traverse_directory(entry.path) { for entry in entries { - if let Ok(unit) = SourceUnit::from_path(&entry.path, extension, parse) { - info!("Found source file at {:?}", entry.path); - source_units.push(unit); - } + gather_source_unit(&entry.path) } } } @@ -66,29 +85,27 @@ impl SourceUnit { // Head and tail files will be picked up later along with the main file. if !is_main || is_head || is_tail { return Err(FileError::InvalidExtension); } + let parse_file = |path: PathBuf| { + if let Ok(source_code) = read_file(&path) { + let symbols = parse(&source_code, Some(&path)); + return Some(SourceFile { symbols, source_code, path: path }); + } + return None; + }; + let head = head_extension.map_or(None, |ext| parse_file(main_path.with_extension(&ext))); + let tail = tail_extension.map_or(None, |ext| parse_file(main_path.with_extension(&ext))); let source_code = read_file(path.as_ref())?; let symbols = parse(&source_code, Some(path.as_ref())); - macro_rules! parse_file { - ($path:expr) => { - read_file(&$path).ok().map(|source_code| { - let symbols = parse(&source_code, Some(&$path)); - let path = $path; - SourceFile { symbols, source_code, path } - }) - }; - } - - let head = head_extension.map_or(None, |ext| parse_file!(main_path.with_extension(&ext))); - let tail = tail_extension.map_or(None, |ext| parse_file!(main_path.with_extension(&ext))); let main = SourceFile { path: main_path, source_code, symbols }; - Ok( SourceUnit { main, head, tail } ) + Ok(SourceUnit { main, head, tail }) } /// Load from a string of source code. pub fn from_string<P: AsRef<Path>>(source_code: String, path: P, parse: ParseFn) -> Self { let path = { path.as_ref().canonicalize().unwrap_or_else(|_| path.as_ref().to_path_buf()) }; let symbols = parse(&source_code, Some(&path)); - Self { main: SourceFile { path, source_code, symbols }, head: None, tail: None } + let main = SourceFile { path, source_code, symbols }; + Self { main, head: None, tail: None } } pub fn name(&self) -> Option<String> { @@ -105,7 +122,7 @@ impl SourceUnit { pub struct SourceFile { pub path: PathBuf, pub source_code: String, - pub symbols: Vec<Symbol>, + pub symbols: Option<Vec<Symbol>>, } pub struct Symbol { |