diff --git a/cli/tools/lint/linter.rs b/cli/tools/lint/linter.rs index 165d717d9c..b0981b0d57 100644 --- a/cli/tools/lint/linter.rs +++ b/cli/tools/lint/linter.rs @@ -25,6 +25,18 @@ use super::rules::FileOrPackageLintRule; use super::rules::PackageLintRule; use super::ConfiguredRules; +pub enum LintResult { + /// File was linted and optionally produced diagnostics + Linted { + parsed_source: ParsedSource, + diagnostics: Vec, + }, + /// File was not parsed and linted because, eg. it might have + /// been a minified file. + #[allow(unused)] + Skipped, +} + pub struct CliLinterOptions { pub configured_rules: ConfiguredRules, pub fix: bool, @@ -97,15 +109,12 @@ impl CliLinter { file_path: &Path, source_code: String, ext: Option<&str>, - ) -> Result<(ParsedSource, Vec), AnyError> { + ) -> Result { let specifier = specifier_from_file_path(file_path)?; let metrics = minified_file::analyze_content(&source_code); if metrics.is_likely_minified() { - bail!( - "{} appears to be a minified file, skipping linting", - specifier.as_str() - ); + Ok(LintResult::Skipped); } let media_type = if let Some(ext) = ext { @@ -119,7 +128,7 @@ impl CliLinter { if self.fix { self.lint_file_and_fix(&specifier, media_type, source_code, file_path) } else { - self + let (parsed_source, diagnostics) = self .linter .lint_file(LintFileOptions { specifier, @@ -127,7 +136,11 @@ impl CliLinter { source_code, config: self.deno_lint_config.clone(), }) - .map_err(AnyError::from) + .map_err(AnyError::from)?; + Ok(LintResult::Linted { + parsed_source, + diagnostics, + }) } } @@ -137,7 +150,7 @@ impl CliLinter { media_type: MediaType, source_code: String, file_path: &Path, - ) -> Result<(ParsedSource, Vec), deno_core::anyhow::Error> { + ) -> Result { // initial lint let (source, diagnostics) = self.linter.lint_file(LintFileOptions { specifier: specifier.clone(), @@ -194,7 +207,10 @@ impl CliLinter { .context("Failed writing fix to file.")?; } - Ok((source, diagnostics)) + Ok(LintResult::Linted { + parsed_source: source, + diagnostics, + }) } } diff --git a/cli/tools/lint/mod.rs b/cli/tools/lint/mod.rs index b1d589ac34..048567834d 100644 --- a/cli/tools/lint/mod.rs +++ b/cli/tools/lint/mod.rs @@ -4,7 +4,6 @@ //! [`deno_lint`](https://github.com/denoland/deno_lint). use deno_ast::ModuleSpecifier; -use deno_ast::ParsedSource; use deno_config::deno_json::LintRulesConfig; use deno_config::glob::FileCollector; use deno_config::glob::FilePatterns; @@ -19,8 +18,8 @@ use deno_core::serde_json; use deno_core::unsync::future::LocalFutureExt; use deno_core::unsync::future::SharedLocal; use deno_graph::ModuleGraph; -use deno_lint::diagnostic::LintDiagnostic; use deno_lint::linter::LintConfig; +use linter::LintResult; use log::debug; use reporters::create_reporter; use reporters::LintReporter; @@ -371,14 +370,18 @@ impl WorkspaceLinter { file_text, cli_options.ext_flag().as_deref(), ); - if let Ok((file_source, file_diagnostics)) = &r { + if let Ok(LintResult::Linted { + parsed_source, + diagnostics, + }) = &r + { if let Some(incremental_cache) = &maybe_incremental_cache { - if file_diagnostics.is_empty() { + if diagnostics.is_empty() { // update the incremental cache if there were no diagnostics incremental_cache.update_file( &file_path, // ensure the returned text is used here as it may have been modified via --fix - file_source.text(), + parsed_source.text(), ) } } @@ -496,7 +499,7 @@ fn lint_stdin( file_path: &Path, configured_rules: ConfiguredRules, deno_lint_config: LintConfig, -) -> Result<(ParsedSource, Vec), AnyError> { +) -> Result { let mut source_code = String::new(); if stdin().read_to_string(&mut source_code).is_err() { return Err(generic_error("Failed to read from stdin")); @@ -515,33 +518,41 @@ fn lint_stdin( fn handle_lint_result( file_path: &str, - result: Result<(ParsedSource, Vec), AnyError>, + result: Result, reporter_lock: Arc>>, ) -> bool { let mut reporter = reporter_lock.lock(); match result { - Ok((source, mut file_diagnostics)) => { - if !source.diagnostics().is_empty() { - for parse_diagnostic in source.diagnostics() { - log::warn!("{}: {}", colors::yellow("warn"), parse_diagnostic); - } - } - file_diagnostics.sort_by(|a, b| match a.specifier.cmp(&b.specifier) { - std::cmp::Ordering::Equal => { - let a_start = a.range.as_ref().map(|r| r.range.start); - let b_start = b.range.as_ref().map(|r| r.range.start); - match a_start.cmp(&b_start) { - std::cmp::Ordering::Equal => a.details.code.cmp(&b.details.code), - other => other, + Ok(lint_result) => { + if let LintResult::Linted { + parsed_source, + mut diagnostics, + } = lint_result + { + if !parsed_source.diagnostics().is_empty() { + for parse_diagnostic in parsed_source.diagnostics() { + log::warn!("{}: {}", colors::yellow("warn"), parse_diagnostic); } } - file_order => file_order, - }); - for d in &file_diagnostics { - reporter.visit_diagnostic(d); + diagnostics.sort_by(|a, b| match a.specifier.cmp(&b.specifier) { + std::cmp::Ordering::Equal => { + let a_start = a.range.as_ref().map(|r| r.range.start); + let b_start = b.range.as_ref().map(|r| r.range.start); + match a_start.cmp(&b_start) { + std::cmp::Ordering::Equal => a.details.code.cmp(&b.details.code), + other => other, + } + } + file_order => file_order, + }); + for d in &diagnostics { + reporter.visit_diagnostic(d); + } + diagnostics.is_empty() + } else { + true } - file_diagnostics.is_empty() } Err(err) => { reporter.visit_error(file_path, &err);