diff --git a/crates/aiken-project/src/error.rs b/crates/aiken-project/src/error.rs index 83abec07..c82b0c6a 100644 --- a/crates/aiken-project/src/error.rs +++ b/crates/aiken-project/src/error.rs @@ -24,7 +24,7 @@ use zip::result::ZipError; #[allow(dead_code)] #[derive(thiserror::Error)] pub enum Error { - #[error("I just found two modules with the same name: '{module}'")] + #[error("I just found two modules with the same name: '{}'", module.if_supports_color(Stderr, |s| s.yellow()))] DuplicateModule { module: String, first: PathBuf, @@ -353,9 +353,9 @@ impl Diagnostic for Error { fn help<'a>(&'a self) -> Option> { match self { Error::DuplicateModule { first, second, .. } => Some(Box::new(format!( - "Rename either {} or {}", - first.display(), - second.display() + "Rename either of them:\n- {}\n- {}", + first.display().if_supports_color(Stderr, |s| s.yellow()), + second.display().if_supports_color(Stderr, |s| s.yellow()), ))), Error::FileIo { error, .. } => Some(Box::new(format!("{error}"))), Error::Blueprint(e) => e.help(), diff --git a/crates/aiken-project/src/lib.rs b/crates/aiken-project/src/lib.rs index 2e67c46a..fc97d111 100644 --- a/crates/aiken-project/src/lib.rs +++ b/crates/aiken-project/src/lib.rs @@ -52,7 +52,7 @@ use package_name::PackageName; use pallas_addresses::{Address, Network, ShelleyAddress, ShelleyDelegationPart, StakePayload}; use pallas_primitives::conway::PolicyId; use std::{ - collections::{BTreeSet, HashMap}, + collections::{BTreeSet, HashMap, HashSet}, fs::{self, File}, io::BufReader, path::{Path, PathBuf}, @@ -698,12 +698,12 @@ where fn parse_sources(&mut self, package_name: PackageName) -> Result> { use rayon::prelude::*; - let (parsed_modules, errors) = self + let (parsed_modules, parse_errors, duplicates) = self .sources .par_drain(0..) .fold( - || (ParsedModules::new(), Vec::new()), - |(mut parsed_modules, mut errors), elem| { + || (ParsedModules::new(), Vec::new(), Vec::new()), + |(mut parsed_modules, mut parse_errors, mut duplicates), elem| { let Source { path, name, @@ -720,19 +720,24 @@ where kind, ast, code, - name, + name: name.clone(), path, extra, package: package_name.to_string(), }; - parsed_modules.insert(module.name.clone(), module); + let path = module.path.clone(); - (parsed_modules, errors) + if let Some(first) = parsed_modules.insert(module.name.clone(), module) + { + duplicates.push((name, first.path.clone(), path)) + } + + (parsed_modules, parse_errors, duplicates) } Err(errs) => { for error in errs { - errors.push(( + parse_errors.push(( path.clone(), code.clone(), NamedSource::new(path.display().to_string(), code.clone()), @@ -740,31 +745,62 @@ where )) } - (parsed_modules, errors) + (parsed_modules, parse_errors, duplicates) } } }, ) .reduce( - || (ParsedModules::new(), Vec::new()), - |(mut parsed_modules, mut errors), (mut parsed, mut errs)| { + || (ParsedModules::new(), Vec::new(), Vec::new()), + |(mut parsed_modules, mut parse_errors, mut duplicates), + (mut parsed, mut errs, mut dups)| { + let keys_left = parsed_modules.keys().collect::>(); + let keys_right = parsed.keys().collect::>(); + + for module in keys_left.intersection(&keys_right) { + duplicates.push(( + module.to_string(), + parsed_modules + .get(module.as_str()) + .map(|m| m.path.clone()) + .unwrap(), + parsed.get(module.as_str()).map(|m| m.path.clone()).unwrap(), + )); + } + parsed_modules.extend(parsed.drain()); - errors.append(&mut errs); + parse_errors.append(&mut errs); + duplicates.append(&mut dups); - (parsed_modules, errors) + (parsed_modules, parse_errors, duplicates) }, ); - let mut errors: Vec = errors - .into_iter() - .map(|(path, src, named, error)| Error::Parse { - path, - src, - named: named.into(), - error, - }) - .collect(); + let mut errors: Vec = Vec::new(); + + errors.extend( + duplicates + .into_iter() + .map(|(module, first, second)| Error::DuplicateModule { + module, + first, + second, + }) + .collect::>(), + ); + + errors.extend( + parse_errors + .into_iter() + .map(|(path, src, named, error)| Error::Parse { + path, + src, + named: named.into(), + error, + }) + .collect::>(), + ); for parsed_module in parsed_modules.values() { if let Some(first) = self