use std::path::{Path, PathBuf}; use erg_common::error::ErrorKind; use erg_common::log; use erg_common::style::{remove_style, StyledStr}; // use erg_common::style::{remove_style, StyledString, Color}; use erg_compiler::context::ModuleContext; use erg_compiler::error::{CompileError, CompileErrors}; fn project_root(path: &Path) -> Option { let mut parent = path.to_path_buf(); while parent.pop() { if parent.join("pyproject.toml").exists() || parent.join(".git").exists() { let path = if parent == Path::new("") { PathBuf::from(".") } else { parent }; return path.canonicalize().ok(); } } None } pub(crate) fn filter_errors(ctx: &ModuleContext, errors: CompileErrors) -> CompileErrors { let root = project_root(ctx.get_top_cfg().input.path()); errors .into_iter() .filter_map(|error| filter_error(root.as_deref(), ctx, error)) .collect() } fn handle_name_error(error: CompileError) -> Option { let main = &error.core.main_message; if main.contains("is already declared") || main.contains("cannot be assigned more than once") || { main.contains(" is not defined") && { let name = StyledStr::destyle(main.trim_end_matches(" is not defined")); name == "Any" || error .core .get_hint() .is_some_and(|hint| hint.contains(name)) } } { None } else { Some(error) } } fn filter_error( root: Option<&Path>, ctx: &ModuleContext, mut error: CompileError, ) -> Option { if ctx.get_top_cfg().do_not_show_ext_errors && error.input.path() != Path::new("") && root.is_some_and(|root| { error .input .path() .canonicalize() .is_ok_and(|path| path.starts_with(root.join(".venv")) || !path.starts_with(root)) }) { return None; } match error.core.kind { ErrorKind::FeatureError => { log!(err "this error is ignored:"); log!(err "{error}"); None } ErrorKind::InheritanceError => None, ErrorKind::VisibilityError => None, // exclude doc strings ErrorKind::UnusedWarning => { let code = error.input.reread_lines( error.core.loc.ln_begin().unwrap_or(1) as usize, error.core.loc.ln_end().unwrap_or(1) as usize, ); if code[0].trim().starts_with("\"\"\"") { None } else { for sub in error.core.sub_messages.iter_mut() { if let Some(hint) = &mut sub.hint { *hint = remove_style(hint); *hint = hint.replace("use discard function", "bind to `_` (`_ = ...`)"); } } Some(error) } } ErrorKind::NameError | ErrorKind::AssignError => handle_name_error(error), _ => Some(error), } }