1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-08 23:28:18 -05:00

add lint result

This commit is contained in:
Bartek Iwańczuk 2024-11-14 12:56:45 +01:00
parent 4b695e2db0
commit 4d5f9028fd
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
2 changed files with 61 additions and 34 deletions

View file

@ -25,6 +25,18 @@ use super::rules::FileOrPackageLintRule;
use super::rules::PackageLintRule; use super::rules::PackageLintRule;
use super::ConfiguredRules; use super::ConfiguredRules;
pub enum LintResult {
/// File was linted and optionally produced diagnostics
Linted {
parsed_source: ParsedSource,
diagnostics: Vec<LintDiagnostic>,
},
/// File was not parsed and linted because, eg. it might have
/// been a minified file.
#[allow(unused)]
Skipped,
}
pub struct CliLinterOptions { pub struct CliLinterOptions {
pub configured_rules: ConfiguredRules, pub configured_rules: ConfiguredRules,
pub fix: bool, pub fix: bool,
@ -97,15 +109,12 @@ impl CliLinter {
file_path: &Path, file_path: &Path,
source_code: String, source_code: String,
ext: Option<&str>, ext: Option<&str>,
) -> Result<(ParsedSource, Vec<LintDiagnostic>), AnyError> { ) -> Result<LintResult, AnyError> {
let specifier = specifier_from_file_path(file_path)?; let specifier = specifier_from_file_path(file_path)?;
let metrics = minified_file::analyze_content(&source_code); let metrics = minified_file::analyze_content(&source_code);
if metrics.is_likely_minified() { if metrics.is_likely_minified() {
bail!( Ok(LintResult::Skipped);
"{} appears to be a minified file, skipping linting",
specifier.as_str()
);
} }
let media_type = if let Some(ext) = ext { let media_type = if let Some(ext) = ext {
@ -119,7 +128,7 @@ impl CliLinter {
if self.fix { if self.fix {
self.lint_file_and_fix(&specifier, media_type, source_code, file_path) self.lint_file_and_fix(&specifier, media_type, source_code, file_path)
} else { } else {
self let (parsed_source, diagnostics) = self
.linter .linter
.lint_file(LintFileOptions { .lint_file(LintFileOptions {
specifier, specifier,
@ -127,7 +136,11 @@ impl CliLinter {
source_code, source_code,
config: self.deno_lint_config.clone(), 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, media_type: MediaType,
source_code: String, source_code: String,
file_path: &Path, file_path: &Path,
) -> Result<(ParsedSource, Vec<LintDiagnostic>), deno_core::anyhow::Error> { ) -> Result<LintResult, deno_core::anyhow::Error> {
// initial lint // initial lint
let (source, diagnostics) = self.linter.lint_file(LintFileOptions { let (source, diagnostics) = self.linter.lint_file(LintFileOptions {
specifier: specifier.clone(), specifier: specifier.clone(),
@ -194,7 +207,10 @@ impl CliLinter {
.context("Failed writing fix to file.")?; .context("Failed writing fix to file.")?;
} }
Ok((source, diagnostics)) Ok(LintResult::Linted {
parsed_source: source,
diagnostics,
})
} }
} }

View file

@ -4,7 +4,6 @@
//! [`deno_lint`](https://github.com/denoland/deno_lint). //! [`deno_lint`](https://github.com/denoland/deno_lint).
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
use deno_ast::ParsedSource;
use deno_config::deno_json::LintRulesConfig; use deno_config::deno_json::LintRulesConfig;
use deno_config::glob::FileCollector; use deno_config::glob::FileCollector;
use deno_config::glob::FilePatterns; 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::LocalFutureExt;
use deno_core::unsync::future::SharedLocal; use deno_core::unsync::future::SharedLocal;
use deno_graph::ModuleGraph; use deno_graph::ModuleGraph;
use deno_lint::diagnostic::LintDiagnostic;
use deno_lint::linter::LintConfig; use deno_lint::linter::LintConfig;
use linter::LintResult;
use log::debug; use log::debug;
use reporters::create_reporter; use reporters::create_reporter;
use reporters::LintReporter; use reporters::LintReporter;
@ -371,14 +370,18 @@ impl WorkspaceLinter {
file_text, file_text,
cli_options.ext_flag().as_deref(), 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 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 // update the incremental cache if there were no diagnostics
incremental_cache.update_file( incremental_cache.update_file(
&file_path, &file_path,
// ensure the returned text is used here as it may have been modified via --fix // 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, file_path: &Path,
configured_rules: ConfiguredRules, configured_rules: ConfiguredRules,
deno_lint_config: LintConfig, deno_lint_config: LintConfig,
) -> Result<(ParsedSource, Vec<LintDiagnostic>), AnyError> { ) -> Result<LintResult, AnyError> {
let mut source_code = String::new(); let mut source_code = String::new();
if stdin().read_to_string(&mut source_code).is_err() { if stdin().read_to_string(&mut source_code).is_err() {
return Err(generic_error("Failed to read from stdin")); return Err(generic_error("Failed to read from stdin"));
@ -515,33 +518,41 @@ fn lint_stdin(
fn handle_lint_result( fn handle_lint_result(
file_path: &str, file_path: &str,
result: Result<(ParsedSource, Vec<LintDiagnostic>), AnyError>, result: Result<LintResult, AnyError>,
reporter_lock: Arc<Mutex<Box<dyn LintReporter + Send>>>, reporter_lock: Arc<Mutex<Box<dyn LintReporter + Send>>>,
) -> bool { ) -> bool {
let mut reporter = reporter_lock.lock(); let mut reporter = reporter_lock.lock();
match result { match result {
Ok((source, mut file_diagnostics)) => { Ok(lint_result) => {
if !source.diagnostics().is_empty() { if let LintResult::Linted {
for parse_diagnostic in source.diagnostics() { parsed_source,
log::warn!("{}: {}", colors::yellow("warn"), parse_diagnostic); mut diagnostics,
} } = lint_result
} {
file_diagnostics.sort_by(|a, b| match a.specifier.cmp(&b.specifier) { if !parsed_source.diagnostics().is_empty() {
std::cmp::Ordering::Equal => { for parse_diagnostic in parsed_source.diagnostics() {
let a_start = a.range.as_ref().map(|r| r.range.start); log::warn!("{}: {}", colors::yellow("warn"), parse_diagnostic);
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, diagnostics.sort_by(|a, b| match a.specifier.cmp(&b.specifier) {
}); std::cmp::Ordering::Equal => {
for d in &file_diagnostics { let a_start = a.range.as_ref().map(|r| r.range.start);
reporter.visit_diagnostic(d); 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) => { Err(err) => {
reporter.visit_error(file_path, &err); reporter.visit_error(file_path, &err);