Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ hashbrown = { version = "0.15.0", default-features = false, features = [
"equivalent",
"inline-more",
] }
heck = "0.5.0"
ignore = { version = "0.4.22" }
imara-diff = { version = "0.1.5" }
imperative = { version = "1.0.4" }
Expand Down
18 changes: 14 additions & 4 deletions crates/ruff/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ use itertools::Itertools;
use log::{debug, error};
use rayon::iter::ParallelIterator;
use rayon::iter::{IntoParallelIterator, ParallelBridge};
use ruff_linter::{codes::Rule, registry::AsRule};
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use tempfile::NamedTempFile;

use ruff_cache::{CacheKey, CacheKeyHasher};
use ruff_diagnostics::{DiagnosticKind, Fix};
use ruff_diagnostics::Fix;
use ruff_linter::message::{DiagnosticMessage, Message};
use ruff_linter::package::PackageRoot;
use ruff_linter::{warn_user, VERSION};
Expand Down Expand Up @@ -348,7 +349,9 @@ impl FileCache {
.iter()
.map(|msg| {
Message::Diagnostic(DiagnosticMessage {
kind: msg.kind.clone(),
name: msg.rule.into(),
body: msg.body.clone(),
suggestion: msg.suggestion.clone(),
range: msg.range,
fix: msg.fix.clone(),
file: file.clone(),
Expand Down Expand Up @@ -444,7 +447,9 @@ impl LintCacheData {
"message uses a different source file"
);
CacheMessage {
kind: msg.kind.clone(),
rule: msg.rule(),
body: msg.body.clone(),
suggestion: msg.suggestion.clone(),
range: msg.range,
parent: msg.parent,
fix: msg.fix.clone(),
Expand All @@ -464,7 +469,12 @@ impl LintCacheData {
/// On disk representation of a diagnostic message.
#[derive(Deserialize, Debug, Serialize, PartialEq)]
pub(super) struct CacheMessage {
kind: DiagnosticKind,
/// The rule for the cached diagnostic.
rule: Rule,
/// The message body to display to the user, to explain the diagnostic.
body: String,
/// The message to display to the user, to explain the suggested fix.
suggestion: Option<String>,
/// Range into the message's [`FileCache::source`].
range: TextRange,
parent: Option<TextSize>,
Expand Down
24 changes: 9 additions & 15 deletions crates/ruff_diagnostics/src/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,29 @@
use anyhow::Result;
use log::debug;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

use ruff_text_size::{Ranged, TextRange, TextSize};

use crate::Fix;
use crate::{Fix, Violation};

#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DiagnosticKind {
pub struct Diagnostic {
/// The identifier of the diagnostic, used to align the diagnostic with a rule.
pub name: String,
pub name: &'static str,
/// The message body to display to the user, to explain the diagnostic.
pub body: String,
/// The message to display to the user, to explain the suggested fix.
pub suggestion: Option<String>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Diagnostic {
pub kind: DiagnosticKind,
pub range: TextRange,
pub fix: Option<Fix>,
pub parent: Option<TextSize>,
}

impl Diagnostic {
pub fn new<T: Into<DiagnosticKind>>(kind: T, range: TextRange) -> Self {
pub fn new<T: Violation>(kind: T, range: TextRange) -> Self {
Self {
kind: kind.into(),
name: T::rule_name(),
body: Violation::message(&kind),
suggestion: Violation::fix_title(&kind),
range,
fix: None,
parent: None,
Expand All @@ -56,7 +50,7 @@ impl Diagnostic {
pub fn try_set_fix(&mut self, func: impl FnOnce() -> Result<Fix>) {
match func() {
Ok(fix) => self.fix = Some(fix),
Err(err) => debug!("Failed to create fix for {}: {}", self.kind.name, err),
Err(err) => debug!("Failed to create fix for {}: {}", self.name, err),
}
}

Expand All @@ -67,7 +61,7 @@ impl Diagnostic {
match func() {
Ok(None) => {}
Ok(Some(fix)) => self.fix = Some(fix),
Err(err) => debug!("Failed to create fix for {}: {}", self.kind.name, err),
Err(err) => debug!("Failed to create fix for {}: {}", self.name, err),
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use diagnostic::{Diagnostic, DiagnosticKind};
pub use diagnostic::Diagnostic;
pub use edit::Edit;
pub use fix::{Applicability, Fix, IsolationLevel};
pub use source_map::{SourceMap, SourceMarker};
Expand Down
14 changes: 0 additions & 14 deletions crates/ruff_diagnostics/src/violation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use crate::DiagnosticKind;
use std::fmt::{Debug, Display};

#[derive(Debug, Copy, Clone)]
Expand Down Expand Up @@ -79,16 +78,3 @@ impl<V: AlwaysFixableViolation> Violation for V {
<Self as AlwaysFixableViolation>::message_formats()
}
}

impl<T> From<T> for DiagnosticKind
where
T: Violation,
{
fn from(value: T) -> Self {
Self {
body: Violation::message(&value),
suggestion: Violation::fix_title(&value),
name: T::rule_name().to_string(),
}
}
}
9 changes: 5 additions & 4 deletions crates/ruff_linter/src/checkers/logical_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,17 @@ pub(crate) fn check_logical_lines(
let indent_size = 4;

if enforce_indentation {
for kind in indentation(
for diagnostic in indentation(
&line,
prev_line.as_ref(),
indent_char,
indent_level,
prev_indent_level,
indent_size,
range,
) {
if settings.rules.enabled(kind.rule()) {
context.push_diagnostic(Diagnostic::new(kind, range));
if settings.rules.enabled(diagnostic.rule()) {
context.push_diagnostic(diagnostic);
}
}
}
Expand Down Expand Up @@ -206,7 +207,7 @@ impl<'a> LogicalLinesContext<'a> {
}

pub(crate) fn push_diagnostic(&mut self, diagnostic: Diagnostic) {
if self.settings.rules.enabled(diagnostic.kind.rule()) {
if self.settings.rules.enabled(diagnostic.rule()) {
self.diagnostics.push(diagnostic);
}
}
Expand Down
16 changes: 6 additions & 10 deletions crates/ruff_linter/src/checkers/noqa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub(crate) fn check_noqa(

// Remove any ignored diagnostics.
'outer: for (index, diagnostic) in diagnostics.iter().enumerate() {
if matches!(diagnostic.kind.rule(), Rule::BlanketNOQA) {
if matches!(diagnostic.rule(), Rule::BlanketNOQA) {
continue;
}

Expand All @@ -59,7 +59,7 @@ pub(crate) fn check_noqa(
}
FileExemption::Codes(codes) => {
// If the diagnostic is ignored by a global exemption, ignore it.
if codes.contains(&&diagnostic.kind.rule().noqa_code()) {
if codes.contains(&&diagnostic.rule().noqa_code()) {
ignored_diagnostics.push(index);
continue;
}
Expand All @@ -78,17 +78,13 @@ pub(crate) fn check_noqa(
{
let suppressed = match &directive_line.directive {
Directive::All(_) => {
directive_line
.matches
.push(diagnostic.kind.rule().noqa_code());
directive_line.matches.push(diagnostic.rule().noqa_code());
ignored_diagnostics.push(index);
true
}
Directive::Codes(directive) => {
if directive.includes(diagnostic.kind.rule()) {
directive_line
.matches
.push(diagnostic.kind.rule().noqa_code());
if directive.includes(diagnostic.rule()) {
directive_line.matches.push(diagnostic.rule().noqa_code());
ignored_diagnostics.push(index);
true
} else {
Expand Down Expand Up @@ -161,7 +157,7 @@ pub(crate) fn check_noqa(
let is_code_used = if is_file_level {
diagnostics
.iter()
.any(|diag| diag.kind.rule().noqa_code() == code)
.any(|diag| diag.rule().noqa_code() == code)
} else {
matches.iter().any(|match_| *match_ == code)
} || settings
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_linter/src/checkers/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub(crate) fn check_tokens(
);
}

diagnostics.retain(|diagnostic| settings.rules.enabled(diagnostic.kind.rule()));
diagnostics.retain(|diagnostic| settings.rules.enabled(diagnostic.rule()));

diagnostics
}
4 changes: 3 additions & 1 deletion crates/ruff_linter/src/fix/edits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,9 @@ x = 1 \
iter,
));
DiagnosticMessage {
kind: diag.kind,
name: diag.name,
body: diag.body,
suggestion: diag.suggestion,
range: diag.range,
fix: diag.fix,
parent: diag.parent,
Expand Down
31 changes: 16 additions & 15 deletions crates/ruff_linter/src/fix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,7 @@ fn apply_fixes<'a>(
let mut source_map = SourceMap::default();

for (rule, fix) in diagnostics
.filter_map(|diagnostic| {
diagnostic
.fix
.as_ref()
.map(|fix| (diagnostic.kind.rule(), fix))
})
.filter_map(|diagnostic| diagnostic.fix.as_ref().map(|fix| (diagnostic.rule(), fix)))
.sorted_by(|(rule1, fix1), (rule2, fix2)| cmp_fix(*rule1, *rule2, fix1, fix2))
{
let mut edits = fix
Expand Down Expand Up @@ -163,7 +158,7 @@ fn cmp_fix(rule1: Rule, rule2: Rule, fix1: &Fix, fix2: &Fix) -> std::cmp::Orderi

#[cfg(test)]
mod tests {
use ruff_diagnostics::{Edit, Fix, SourceMarker};
use ruff_diagnostics::{Diagnostic, Edit, Fix, SourceMarker};
use ruff_source_file::SourceFileBuilder;
use ruff_text_size::{Ranged, TextSize};

Expand All @@ -177,15 +172,21 @@ mod tests {
source: &str,
edit: impl IntoIterator<Item = Edit>,
) -> Vec<DiagnosticMessage> {
// The choice of rule here is arbitrary.
edit.into_iter()
.map(|edit| DiagnosticMessage {
// The choice of rule here is arbitrary.
kind: MissingNewlineAtEndOfFile.into(),
range: edit.range(),
fix: Some(Fix::safe_edit(edit)),
parent: None,
file: SourceFileBuilder::new(filename, source).finish(),
noqa_offset: TextSize::default(),
.map(|edit| {
let range = edit.range();
let diagnostic = Diagnostic::new(MissingNewlineAtEndOfFile, range);
DiagnosticMessage {
name: diagnostic.name,
body: diagnostic.body,
suggestion: diagnostic.suggestion,
range,
fix: Some(Fix::safe_edit(edit)),
parent: None,
file: SourceFileBuilder::new(filename, source).finish(),
noqa_offset: TextSize::default(),
}
})
.collect()
}
Expand Down
6 changes: 3 additions & 3 deletions crates/ruff_linter/src/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ pub fn check_path(
RuleSet::empty()
};
if !per_file_ignores.is_empty() {
diagnostics.retain(|diagnostic| !per_file_ignores.contains(diagnostic.kind.rule()));
diagnostics.retain(|diagnostic| !per_file_ignores.contains(diagnostic.rule()));
}

// Enforce `noqa` directives.
Expand Down Expand Up @@ -338,7 +338,7 @@ pub fn check_path(
if parsed.has_valid_syntax() {
// Remove fixes for any rules marked as unfixable.
for diagnostic in &mut diagnostics {
if !settings.rules.should_fix(diagnostic.kind.rule()) {
if !settings.rules.should_fix(diagnostic.rule()) {
diagnostic.fix = None;
}
}
Expand All @@ -349,7 +349,7 @@ pub fn check_path(
if let Some(fix) = diagnostic.fix.take() {
let fixed_applicability = settings
.fix_safety
.resolve_applicability(diagnostic.kind.rule(), fix.applicability());
.resolve_applicability(diagnostic.rule(), fix.applicability());
diagnostic.set_fix(fix.with_applicability(fixed_applicability));
}
}
Expand Down
Loading
Loading