diff --git a/cli/tools/lint/linter.rs b/cli/tools/lint/linter.rs index b3e57399bf..f913d930b7 100644 --- a/cli/tools/lint/linter.rs +++ b/cli/tools/lint/linter.rs @@ -11,7 +11,6 @@ use deno_core::anyhow::Context; use deno_core::error::AnyError; use deno_graph::ModuleGraph; use deno_lint::diagnostic::LintDiagnostic; -use deno_lint::diagnostic::LintDiagnosticDetails; use deno_lint::linter::LintConfig as DenoLintConfig; use deno_lint::linter::LintFileOptions; use deno_lint::linter::Linter as DenoLintLinter; @@ -33,7 +32,7 @@ pub enum LintResult { }, /// File was not parsed and linted because, eg. it might have /// been a minified file. - Skipped { diagnostic: Box }, + Skipped { reason: String }, } pub struct CliLinterOptions { @@ -111,22 +110,10 @@ impl CliLinter { ) -> Result { let specifier = specifier_from_file_path(file_path)?; - let metrics = minified_file::analyze_content(&source_code); - if metrics.is_likely_minified() { - let details = LintDiagnosticDetails { - message: "File was not linted, because it's minified".to_string(), - code: "".to_string(), - hint: None, - fixes: vec![], - custom_docs_url: None, - info: vec![], - }; - let diagnostic = Box::new(LintDiagnostic { - specifier, - range: None, - details, + if minified_file::is_likely_minified(&source_code) { + return Ok(LintResult::Skipped { + reason: "The file is minified".to_string(), }); - return Ok(LintResult::Skipped { diagnostic }); } let media_type = if let Some(ext) = ext { diff --git a/cli/tools/lint/minified_file.rs b/cli/tools/lint/minified_file.rs index 5bb3e60c87..44c678bca3 100644 --- a/cli/tools/lint/minified_file.rs +++ b/cli/tools/lint/minified_file.rs @@ -19,7 +19,8 @@ impl FileMetrics { } } -pub fn analyze_content(content: &str) -> FileMetrics { +/// Analyze the content and tell if the file is most likely a minified file or not. +pub fn is_likely_minified(content: &str) -> bool { const LONG_LINE_LEN: usize = 250; let mut total_lines = 0; let mut long_lines_count = 0; @@ -28,6 +29,12 @@ pub fn analyze_content(content: &str) -> FileMetrics { let mut has_license = false; let mut in_multiline_comment = false; + // If total len of a file is shorter than the "long line" length, don't bother analyzing + // and consider non-minified. + if content.len() < LONG_LINE_LEN { + return false; + } + // Preallocate a line buffer to avoid per-line allocations let mut line_buffer = String::with_capacity(1024); @@ -93,12 +100,14 @@ pub fn analyze_content(content: &str) -> FileMetrics { 0.0 }; - FileMetrics { + let metrics = FileMetrics { long_lines_count, total_lines, whitespace_ratio, has_license_comment: has_license, - } + }; + + metrics.is_likely_minified() } #[cfg(test)] @@ -119,31 +128,32 @@ const x = 42; /* Multi-line comment */ "#; - let metrics = analyze_content(content); - assert!(!metrics.is_likely_minified()); + assert!(!is_likely_minified(content)); + } + + #[test] + fn empty_file() { + assert!(!is_likely_minified("")); } #[test] fn test_minified_file_col_length() { let content = "const LOREM_IPSUM = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.`"; - let metrics = analyze_content(content); - assert!(metrics.is_likely_minified()); + assert!(is_likely_minified(content)); } #[test] fn test_minified_js() { let content = "function hello(){console.log(\"Hello, world!\")}const x=42;function veryLongFunction(){return\"This is a very long line that exceeds 250 characters and contains lots of code and stuff and more code and even more stuff until we definitely exceed the limit we set for considering a line to be very long in our minification detection algorithm\"}"; - let metrics = analyze_content(content); - assert!(metrics.is_likely_minified()); + assert!(is_likely_minified(content)); } #[test] fn test_minified_file_whitespace() { let content = "function f(a,b){return a.concat(b)}var x=function(n){return n+1};"; - let metrics = analyze_content(content); - assert!(!metrics.is_likely_minified()); + assert!(!is_likely_minified(content)); } #[test] @@ -153,8 +163,7 @@ const x = 42; * Licensed under MIT License */ "#; - let metrics = analyze_content(content); - assert!(!metrics.is_likely_minified()); + assert!(!is_likely_minified(content)); } #[test] @@ -167,7 +176,6 @@ function concatenateArrays(array1, array2) { const incrementNumber = function(number) { return number + 1; };"#; - let metrics = analyze_content(content); - assert!(!metrics.is_likely_minified()); + assert!(!is_likely_minified(content)); } } diff --git a/cli/tools/lint/mod.rs b/cli/tools/lint/mod.rs index 93c8d797a6..eb60832634 100644 --- a/cli/tools/lint/mod.rs +++ b/cli/tools/lint/mod.rs @@ -552,8 +552,8 @@ fn handle_lint_result( } diagnostics.is_empty() } - LintResult::Skipped { diagnostic } => { - reporter.visit_diagnostic(&diagnostic); + LintResult::Skipped { reason } => { + reporter.visit_skipped(file_path, &reason); true } }, @@ -569,3 +569,9 @@ struct LintError { file_path: String, message: String, } + +#[derive(Serialize)] +struct LintSkipped { + file_path: String, + message: String, +} diff --git a/cli/tools/lint/reporters.rs b/cli/tools/lint/reporters.rs index 18bc1216a6..752f79147b 100644 --- a/cli/tools/lint/reporters.rs +++ b/cli/tools/lint/reporters.rs @@ -11,6 +11,7 @@ use serde::Serialize; use crate::args::LintReporterKind; use super::LintError; +use super::LintSkipped; const JSON_SCHEMA_VERSION: u8 = 1; @@ -24,6 +25,7 @@ pub fn create_reporter(kind: LintReporterKind) -> Box { pub trait LintReporter { fn visit_diagnostic(&mut self, d: &LintDiagnostic); + fn visit_skipped(&mut self, file_path: &str, reason: &str); fn visit_error(&mut self, file_path: &str, err: &AnyError); fn close(&mut self, check_count: usize); } @@ -52,6 +54,11 @@ impl LintReporter for PrettyLintReporter { log::error!("{}\n", d.display()); } + fn visit_skipped(&mut self, file_path: &str, reason: &str) { + log::info!("File was skipped: {file_path}"); + log::info!(" {reason}"); + } + fn visit_error(&mut self, file_path: &str, err: &AnyError) { log::error!("Error linting: {file_path}"); log::error!(" {err}"); @@ -113,6 +120,11 @@ impl LintReporter for CompactLintReporter { } } + fn visit_skipped(&mut self, file_path: &str, reason: &str) { + log::info!("File was skipped: {file_path}"); + log::info!(" {reason}"); + } + fn visit_error(&mut self, file_path: &str, err: &AnyError) { log::error!("Error linting: {file_path}"); log::error!(" {err}"); @@ -174,6 +186,7 @@ struct JsonLintDiagnostic { struct JsonLintReporter { version: u8, diagnostics: Vec, + skipped: Vec, errors: Vec, checked_files: Vec, } @@ -183,6 +196,7 @@ impl JsonLintReporter { JsonLintReporter { version: JSON_SCHEMA_VERSION, diagnostics: Vec::new(), + skipped: Vec::new(), errors: Vec::new(), checked_files: Vec::new(), } @@ -224,6 +238,13 @@ impl LintReporter for JsonLintReporter { } } + fn visit_skipped(&mut self, file_path: &str, reason: &str) { + self.skipped.push(LintSkipped { + file_path: file_path.to_string(), + message: reason.to_string(), + }); + } + fn visit_error(&mut self, file_path: &str, err: &AnyError) { self.errors.push(LintError { file_path: file_path.to_string(), diff --git a/tests/specs/lint/minified/minified.out b/tests/specs/lint/minified/minified.out index 23a3a9d599..b3fb1a6794 100644 --- a/tests/specs/lint/minified/minified.out +++ b/tests/specs/lint/minified/minified.out @@ -1 +1,3 @@ -asdfasdf \ No newline at end of file +File was skipped: [WILDCARD]minified.js + The file is minified +Checked 1 file