Detect and report duplicate module names during parsing
Funny enough, we thought about that but only across packages. Now, the situation gets a little tricky because of folder structure, it's easy to define a module "foo" in `env`, `lib` and/or `validators`. From the compiler's perspective, they all have the same name.
This commit is contained in:
parent
f8be81baa5
commit
038f6ecbfd
|
@ -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<Box<dyn Display + 'a>> {
|
||||
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(),
|
||||
|
|
|
@ -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<ParsedModules, Vec<Error>> {
|
||||
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::<HashSet<_>>();
|
||||
let keys_right = parsed.keys().collect::<HashSet<_>>();
|
||||
|
||||
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<Error> = errors
|
||||
.into_iter()
|
||||
.map(|(path, src, named, error)| Error::Parse {
|
||||
path,
|
||||
src,
|
||||
named: named.into(),
|
||||
error,
|
||||
})
|
||||
.collect();
|
||||
let mut errors: Vec<Error> = Vec::new();
|
||||
|
||||
errors.extend(
|
||||
duplicates
|
||||
.into_iter()
|
||||
.map(|(module, first, second)| Error::DuplicateModule {
|
||||
module,
|
||||
first,
|
||||
second,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
errors.extend(
|
||||
parse_errors
|
||||
.into_iter()
|
||||
.map(|(path, src, named, error)| Error::Parse {
|
||||
path,
|
||||
src,
|
||||
named: named.into(),
|
||||
error,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
for parsed_module in parsed_modules.values() {
|
||||
if let Some(first) = self
|
||||
|
|
Loading…
Reference in New Issue