Unify OldDiagnostic and Message (#18391)
Some checks are pending
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks-instrumented (push) Blocked by required conditions
CI / benchmarks-walltime (push) Blocked by required conditions

Summary
--

This PR unifies the remaining differences between `OldDiagnostic` and
`Message` (`OldDiagnostic` was only missing an optional `noqa_offset`
field) and
replaces `Message` with `OldDiagnostic`.

The biggest functional difference is that the combined `OldDiagnostic`
kind no
longer implements `AsRule` for an infallible conversion to `Rule`. This
was
pretty easy to work around with `is_some_and` and `is_none_or` in the
few places
it was needed. In `LintContext::report_diagnostic_if_enabled` we can
just use
the new `Violation::rule` method, which takes care of most cases.

Most of the interesting changes are in [this
range](8156992540)
before I started renaming.

Test Plan
--

Existing tests

Future Work
--

I think it's time to start shifting some of these fields to the new
`Diagnostic`
kind. I believe we want `Fix` for sure, but I'm less sure about the
others. We
may want to keep a thin wrapper type here anyway to implement a `rule`
method,
so we could leave some of these fields on that too.
This commit is contained in:
Brent Westbrook 2025-06-19 09:37:58 -04:00 committed by GitHub
parent 4e83db4d40
commit 10a1d9f01e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
96 changed files with 902 additions and 914 deletions

View file

@ -19,7 +19,7 @@ use tempfile::NamedTempFile;
use ruff_cache::{CacheKey, CacheKeyHasher};
use ruff_diagnostics::Fix;
use ruff_linter::message::Message;
use ruff_linter::message::OldDiagnostic;
use ruff_linter::package::PackageRoot;
use ruff_linter::{VERSION, warn_user};
use ruff_macros::CacheKey;
@ -341,16 +341,16 @@ impl FileCache {
/// Convert the file cache into `Diagnostics`, using `path` as file name.
pub(crate) fn to_diagnostics(&self, path: &Path) -> Option<Diagnostics> {
self.data.lint.as_ref().map(|lint| {
let messages = if lint.messages.is_empty() {
let diagnostics = if lint.messages.is_empty() {
Vec::new()
} else {
let file = SourceFileBuilder::new(path.to_string_lossy(), &*lint.source).finish();
lint.messages
.iter()
.map(|msg| {
Message::diagnostic(
msg.body.clone(),
msg.suggestion.clone(),
OldDiagnostic::lint(
&msg.body,
msg.suggestion.as_ref(),
msg.range,
msg.fix.clone(),
msg.parent,
@ -366,7 +366,7 @@ impl FileCache {
} else {
FxHashMap::default()
};
Diagnostics::new(messages, notebook_indexes)
Diagnostics::new(diagnostics, notebook_indexes)
})
}
}
@ -427,27 +427,27 @@ pub(crate) struct LintCacheData {
}
impl LintCacheData {
pub(crate) fn from_messages(
messages: &[Message],
pub(crate) fn from_diagnostics(
diagnostics: &[OldDiagnostic],
notebook_index: Option<NotebookIndex>,
) -> Self {
let source = if let Some(msg) = messages.first() {
let source = if let Some(msg) = diagnostics.first() {
msg.source_file().source_text().to_owned()
} else {
String::new() // No messages, no need to keep the source!
};
let messages = messages
let messages = diagnostics
.iter()
// Parse the kebab-case rule name into a `Rule`. This will fail for syntax errors, so
// this also serves to filter them out, but we shouldn't be caching files with syntax
// errors anyway.
.filter_map(|msg| Some((msg.name().parse().ok()?, msg)))
.filter_map(|msg| Some((msg.noqa_code().and_then(|code| code.rule())?, msg)))
.map(|(rule, msg)| {
// Make sure that all message use the same source file.
assert_eq!(
msg.source_file(),
messages.first().unwrap().source_file(),
diagnostics.first().unwrap().source_file(),
"message uses a different source file"
);
CacheMessage {
@ -612,7 +612,7 @@ mod tests {
use test_case::test_case;
use ruff_cache::CACHE_DIR_NAME;
use ruff_linter::message::Message;
use ruff_linter::message::OldDiagnostic;
use ruff_linter::package::PackageRoot;
use ruff_linter::settings::flags;
use ruff_linter::settings::types::UnsafeFixes;
@ -680,7 +680,7 @@ mod tests {
UnsafeFixes::Enabled,
)
.unwrap();
if diagnostics.messages.iter().any(Message::is_syntax_error) {
if diagnostics.inner.iter().any(OldDiagnostic::is_syntax_error) {
parse_errors.push(path.clone());
}
paths.push(path);

View file

@ -13,7 +13,6 @@ use rustc_hash::FxHashMap;
use ruff_db::panic::catch_unwind;
use ruff_linter::OldDiagnostic;
use ruff_linter::message::Message;
use ruff_linter::package::PackageRoot;
use ruff_linter::registry::Rule;
use ruff_linter::settings::types::UnsafeFixes;
@ -130,9 +129,10 @@ pub(crate) fn check(
SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish();
Diagnostics::new(
vec![Message::from_diagnostic(
OldDiagnostic::new(IOError { message }, TextRange::default(), &dummy),
None,
vec![OldDiagnostic::new(
IOError { message },
TextRange::default(),
&dummy,
)],
FxHashMap::default(),
)
@ -166,7 +166,7 @@ pub(crate) fn check(
|a, b| (a.0 + b.0, a.1 + b.1),
);
all_diagnostics.messages.sort();
all_diagnostics.inner.sort();
// Store the caches.
caches.persist()?;
@ -283,7 +283,7 @@ mod test {
.with_show_fix_status(true)
.emit(
&mut output,
&diagnostics.messages,
&diagnostics.inner,
&EmitterContext::new(&FxHashMap::default()),
)
.unwrap();

View file

@ -52,6 +52,6 @@ pub(crate) fn check_stdin(
noqa,
fix_mode,
)?;
diagnostics.messages.sort_unstable();
diagnostics.inner.sort_unstable();
Ok(diagnostics)
}

View file

@ -15,7 +15,6 @@ use rustc_hash::FxHashMap;
use ruff_linter::OldDiagnostic;
use ruff_linter::codes::Rule;
use ruff_linter::linter::{FixTable, FixerResult, LinterResult, ParseSource, lint_fix, lint_only};
use ruff_linter::message::Message;
use ruff_linter::package::PackageRoot;
use ruff_linter::pyproject_toml::lint_pyproject_toml;
use ruff_linter::settings::types::UnsafeFixes;
@ -32,18 +31,18 @@ use crate::cache::{Cache, FileCacheKey, LintCacheData};
#[derive(Debug, Default, PartialEq)]
pub(crate) struct Diagnostics {
pub(crate) messages: Vec<Message>,
pub(crate) inner: Vec<OldDiagnostic>,
pub(crate) fixed: FixMap,
pub(crate) notebook_indexes: FxHashMap<String, NotebookIndex>,
}
impl Diagnostics {
pub(crate) fn new(
messages: Vec<Message>,
diagnostics: Vec<OldDiagnostic>,
notebook_indexes: FxHashMap<String, NotebookIndex>,
) -> Self {
Self {
messages,
inner: diagnostics,
fixed: FixMap::default(),
notebook_indexes,
}
@ -63,15 +62,12 @@ impl Diagnostics {
let name = path.map_or_else(|| "-".into(), Path::to_string_lossy);
let source_file = SourceFileBuilder::new(name, "").finish();
Self::new(
vec![Message::from_diagnostic(
OldDiagnostic::new(
IOError {
message: err.to_string(),
},
TextRange::default(),
&source_file,
),
None,
vec![OldDiagnostic::new(
IOError {
message: err.to_string(),
},
TextRange::default(),
&source_file,
)],
FxHashMap::default(),
)
@ -102,7 +98,11 @@ impl Diagnostics {
let name = path.map_or_else(|| "-".into(), Path::to_string_lossy);
let dummy = SourceFileBuilder::new(name, "").finish();
Self::new(
vec![Message::syntax_error(err, TextRange::default(), dummy)],
vec![OldDiagnostic::syntax_error(
err,
TextRange::default(),
dummy,
)],
FxHashMap::default(),
)
}
@ -121,7 +121,7 @@ impl Add for Diagnostics {
impl AddAssign for Diagnostics {
fn add_assign(&mut self, other: Self) {
self.messages.extend(other.messages);
self.inner.extend(other.inner);
self.fixed += other.fixed;
self.notebook_indexes.extend(other.notebook_indexes);
}
@ -202,7 +202,7 @@ pub(crate) fn lint_path(
if match fix_mode {
flags::FixMode::Generate => true,
flags::FixMode::Apply | flags::FixMode::Diff => {
diagnostics.messages.is_empty() && diagnostics.fixed.is_empty()
diagnostics.inner.is_empty() && diagnostics.fixed.is_empty()
}
} {
return Ok(diagnostics);
@ -222,7 +222,7 @@ pub(crate) fn lint_path(
Some(source_type) => source_type,
None => match SourceType::from(path) {
SourceType::Toml(TomlSourceType::Pyproject) => {
let messages = if settings
let diagnostics = if settings
.rules
.iter_enabled()
.any(|rule_code| rule_code.lint_source().is_pyproject_toml())
@ -240,7 +240,7 @@ pub(crate) fn lint_path(
vec![]
};
return Ok(Diagnostics {
messages,
inner: diagnostics,
..Diagnostics::default()
});
}
@ -324,7 +324,7 @@ pub(crate) fn lint_path(
};
let has_error = result.has_syntax_errors();
let messages = result.messages;
let diagnostics = result.diagnostics;
if let Some((cache, relative_path, key)) = caching {
// We don't cache parsing errors.
@ -335,14 +335,14 @@ pub(crate) fn lint_path(
if match fix_mode {
flags::FixMode::Generate => true,
flags::FixMode::Apply | flags::FixMode::Diff => {
messages.is_empty() && fixed.is_empty()
diagnostics.is_empty() && fixed.is_empty()
}
} {
cache.update_lint(
relative_path.to_owned(),
&key,
LintCacheData::from_messages(
&messages,
LintCacheData::from_diagnostics(
&diagnostics,
transformed.as_ipy_notebook().map(Notebook::index).cloned(),
),
);
@ -357,7 +357,7 @@ pub(crate) fn lint_path(
};
Ok(Diagnostics {
messages,
inner: diagnostics,
fixed: FixMap::from_iter([(fs::relativize_path(path), fixed)]),
notebook_indexes,
})
@ -396,7 +396,7 @@ pub(crate) fn lint_stdin(
}
return Ok(Diagnostics {
messages: lint_pyproject_toml(&source_file, &settings.linter),
inner: lint_pyproject_toml(&source_file, &settings.linter),
fixed: FixMap::from_iter([(fs::relativize_path(path), FixTable::default())]),
notebook_indexes: FxHashMap::default(),
});
@ -417,7 +417,7 @@ pub(crate) fn lint_stdin(
};
// Lint the inputs.
let (LinterResult { messages, .. }, transformed, fixed) =
let (LinterResult { diagnostics, .. }, transformed, fixed) =
if matches!(fix_mode, flags::FixMode::Apply | flags::FixMode::Diff) {
if let Ok(FixerResult {
result,
@ -501,7 +501,7 @@ pub(crate) fn lint_stdin(
};
Ok(Diagnostics {
messages,
inner: diagnostics,
fixed: FixMap::from_iter([(
fs::relativize_path(path.unwrap_or_else(|| Path::new("-"))),
fixed,

View file

@ -363,7 +363,7 @@ pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result<Exi
Printer::clear_screen()?;
printer.write_to_user("Starting linter in watch mode...\n");
let messages = commands::check::check(
let diagnostics = commands::check::check(
&files,
&pyproject_config,
&config_arguments,
@ -372,7 +372,7 @@ pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result<Exi
fix_mode,
unsafe_fixes,
)?;
printer.write_continuously(&mut writer, &messages, preview)?;
printer.write_continuously(&mut writer, &diagnostics, preview)?;
// In watch mode, we may need to re-resolve the configuration.
// TODO(charlie): Re-compute other derivative values, like the `printer`.
@ -392,7 +392,7 @@ pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result<Exi
Printer::clear_screen()?;
printer.write_to_user("File change detected...\n");
let messages = commands::check::check(
let diagnostics = commands::check::check(
&files,
&pyproject_config,
&config_arguments,
@ -401,7 +401,7 @@ pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result<Exi
fix_mode,
unsafe_fixes,
)?;
printer.write_continuously(&mut writer, &messages, preview)?;
printer.write_continuously(&mut writer, &diagnostics, preview)?;
}
Err(err) => return Err(err.into()),
}
@ -463,11 +463,11 @@ pub fn check(args: CheckCommand, global_options: GlobalConfigArgs) -> Result<Exi
// there are any violations, unless we're explicitly asked to exit zero on
// fix.
if cli.exit_non_zero_on_fix {
if !diagnostics.fixed.is_empty() || !diagnostics.messages.is_empty() {
if !diagnostics.fixed.is_empty() || !diagnostics.inner.is_empty() {
return Ok(ExitStatus::Failure);
}
} else {
if !diagnostics.messages.is_empty() {
if !diagnostics.inner.is_empty() {
return Ok(ExitStatus::Failure);
}
}

View file

@ -14,7 +14,7 @@ use ruff_linter::fs::relativize_path;
use ruff_linter::logging::LogLevel;
use ruff_linter::message::{
AzureEmitter, Emitter, EmitterContext, GithubEmitter, GitlabEmitter, GroupedEmitter,
JsonEmitter, JsonLinesEmitter, JunitEmitter, Message, PylintEmitter, RdjsonEmitter,
JsonEmitter, JsonLinesEmitter, JunitEmitter, OldDiagnostic, PylintEmitter, RdjsonEmitter,
SarifEmitter, TextEmitter,
};
use ruff_linter::notify_user;
@ -85,7 +85,7 @@ impl Printer {
.sum::<usize>();
if self.flags.intersects(Flags::SHOW_VIOLATIONS) {
let remaining = diagnostics.messages.len();
let remaining = diagnostics.inner.len();
let total = fixed + remaining;
if fixed > 0 {
let s = if total == 1 { "" } else { "s" };
@ -229,16 +229,16 @@ impl Printer {
match self.format {
OutputFormat::Json => {
JsonEmitter.emit(writer, &diagnostics.messages, &context)?;
JsonEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Rdjson => {
RdjsonEmitter.emit(writer, &diagnostics.messages, &context)?;
RdjsonEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::JsonLines => {
JsonLinesEmitter.emit(writer, &diagnostics.messages, &context)?;
JsonLinesEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Junit => {
JunitEmitter.emit(writer, &diagnostics.messages, &context)?;
JunitEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Concise | OutputFormat::Full => {
TextEmitter::default()
@ -246,7 +246,7 @@ impl Printer {
.with_show_fix_diff(self.flags.intersects(Flags::SHOW_FIX_DIFF))
.with_show_source(self.format == OutputFormat::Full)
.with_unsafe_fixes(self.unsafe_fixes)
.emit(writer, &diagnostics.messages, &context)?;
.emit(writer, &diagnostics.inner, &context)?;
if self.flags.intersects(Flags::SHOW_FIX_SUMMARY) {
if !diagnostics.fixed.is_empty() {
@ -262,7 +262,7 @@ impl Printer {
GroupedEmitter::default()
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
.with_unsafe_fixes(self.unsafe_fixes)
.emit(writer, &diagnostics.messages, &context)?;
.emit(writer, &diagnostics.inner, &context)?;
if self.flags.intersects(Flags::SHOW_FIX_SUMMARY) {
if !diagnostics.fixed.is_empty() {
@ -274,19 +274,19 @@ impl Printer {
self.write_summary_text(writer, diagnostics)?;
}
OutputFormat::Github => {
GithubEmitter.emit(writer, &diagnostics.messages, &context)?;
GithubEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Gitlab => {
GitlabEmitter::default().emit(writer, &diagnostics.messages, &context)?;
GitlabEmitter::default().emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Pylint => {
PylintEmitter.emit(writer, &diagnostics.messages, &context)?;
PylintEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Azure => {
AzureEmitter.emit(writer, &diagnostics.messages, &context)?;
AzureEmitter.emit(writer, &diagnostics.inner, &context)?;
}
OutputFormat::Sarif => {
SarifEmitter.emit(writer, &diagnostics.messages, &context)?;
SarifEmitter.emit(writer, &diagnostics.inner, &context)?;
}
}
@ -301,13 +301,13 @@ impl Printer {
writer: &mut dyn Write,
) -> Result<()> {
let statistics: Vec<ExpandedStatistics> = diagnostics
.messages
.inner
.iter()
.map(|message| (message.noqa_code(), message))
.sorted_by_key(|(code, message)| (*code, message.fixable()))
.fold(
vec![],
|mut acc: Vec<((Option<NoqaCode>, &Message), usize)>, (code, message)| {
|mut acc: Vec<((Option<NoqaCode>, &OldDiagnostic), usize)>, (code, message)| {
if let Some(((prev_code, _prev_message), count)) = acc.last_mut() {
if *prev_code == code {
*count += 1;
@ -416,20 +416,20 @@ impl Printer {
}
if self.log_level >= LogLevel::Default {
let s = if diagnostics.messages.len() == 1 {
let s = if diagnostics.inner.len() == 1 {
""
} else {
"s"
};
notify_user!(
"Found {} error{s}. Watching for file changes.",
diagnostics.messages.len()
diagnostics.inner.len()
);
}
let fixables = FixableStatistics::try_from(diagnostics, self.unsafe_fixes);
if !diagnostics.messages.is_empty() {
if !diagnostics.inner.is_empty() {
if self.log_level >= LogLevel::Default {
writeln!(writer)?;
}
@ -439,7 +439,7 @@ impl Printer {
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
.with_show_source(preview)
.with_unsafe_fixes(self.unsafe_fixes)
.emit(writer, &diagnostics.messages, &context)?;
.emit(writer, &diagnostics.inner, &context)?;
}
writer.flush()?;
@ -522,7 +522,7 @@ impl FixableStatistics {
let mut applicable = 0;
let mut inapplicable_unsafe = 0;
for message in &diagnostics.messages {
for message in &diagnostics.inner {
if let Some(fix) = message.fix() {
if fix.applies(unsafe_fixes.required_applicability()) {
applicable += 1;

View file

@ -66,7 +66,7 @@ use crate::importer::{ImportRequest, Importer, ResolutionError};
use crate::noqa::NoqaMapping;
use crate::package::PackageRoot;
use crate::preview::is_undefined_export_in_dunder_init_enabled;
use crate::registry::{AsRule, Rule};
use crate::registry::Rule;
use crate::rules::pyflakes::rules::{
LateFutureImport, ReturnOutsideFunction, YieldOutsideFunction,
};
@ -3147,11 +3147,10 @@ impl<'a> LintContext<'a> {
kind: T,
range: TextRange,
) -> Option<DiagnosticGuard<'chk, 'a>> {
let diagnostic = OldDiagnostic::new(kind, range, self.source_file);
if self.settings.rules.enabled(diagnostic.rule()) {
if self.settings.rules.enabled(T::rule()) {
Some(DiagnosticGuard {
context: self,
diagnostic: Some(diagnostic),
diagnostic: Some(OldDiagnostic::new(kind, range, self.source_file)),
})
} else {
None

View file

@ -12,7 +12,7 @@ use crate::fix::edits::delete_comment;
use crate::noqa::{
Code, Directive, FileExemption, FileNoqaDirectives, NoqaDirectives, NoqaMapping,
};
use crate::registry::{AsRule, Rule, RuleSet};
use crate::registry::{Rule, RuleSet};
use crate::rule_redirects::get_redirect_target;
use crate::rules::pygrep_hooks;
use crate::rules::ruff;
@ -47,14 +47,15 @@ pub(crate) fn check_noqa(
// Remove any ignored diagnostics.
'outer: for (index, diagnostic) in context.iter().enumerate() {
let rule = diagnostic.rule();
// Can't ignore syntax errors.
let Some(code) = diagnostic.noqa_code() else {
continue;
};
if matches!(rule, Rule::BlanketNOQA) {
if code == Rule::BlanketNOQA.noqa_code() {
continue;
}
let code = rule.noqa_code();
match &exemption {
FileExemption::All(_) => {
// If the file is exempted, ignore all diagnostics.
@ -148,7 +149,9 @@ pub(crate) fn check_noqa(
if seen_codes.insert(original_code) {
let is_code_used = if is_file_level {
context.iter().any(|diag| diag.rule().noqa_code() == code)
context
.iter()
.any(|diag| diag.noqa_code().is_some_and(|noqa| noqa == code))
} else {
matches.iter().any(|match_| *match_ == code)
} || settings

View file

@ -1,104 +0,0 @@
use anyhow::Result;
use log::debug;
use ruff_source_file::SourceFile;
use ruff_text_size::{Ranged, TextRange, TextSize};
use crate::registry::AsRule;
use crate::violation::Violation;
use crate::{Fix, codes::Rule};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct OldDiagnostic {
/// 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>,
pub range: TextRange,
pub fix: Option<Fix>,
pub parent: Option<TextSize>,
pub(crate) rule: Rule,
pub(crate) file: SourceFile,
}
impl OldDiagnostic {
// TODO(brent) We temporarily allow this to avoid updating all of the call sites to add
// references. I expect this method to go away or change significantly with the rest of the
// diagnostic refactor, but if it still exists in this form at the end of the refactor, we
// should just update the call sites.
#[expect(clippy::needless_pass_by_value)]
pub fn new<T: Violation>(kind: T, range: TextRange, file: &SourceFile) -> Self {
Self {
body: Violation::message(&kind),
suggestion: Violation::fix_title(&kind),
range,
fix: None,
parent: None,
rule: T::rule(),
file: file.clone(),
}
}
/// Consumes `self` and returns a new `Diagnostic` with the given `fix`.
#[inline]
#[must_use]
pub fn with_fix(mut self, fix: Fix) -> Self {
self.set_fix(fix);
self
}
/// Set the [`Fix`] used to fix the diagnostic.
#[inline]
pub fn set_fix(&mut self, fix: Fix) {
self.fix = Some(fix);
}
/// Set the [`Fix`] used to fix the diagnostic, if the provided function returns `Ok`.
/// Otherwise, log the error.
#[inline]
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.rule, err),
}
}
/// Set the [`Fix`] used to fix the diagnostic, if the provided function returns `Ok`.
/// Otherwise, log the error.
#[inline]
pub fn try_set_optional_fix(&mut self, func: impl FnOnce() -> Result<Option<Fix>>) {
match func() {
Ok(None) => {}
Ok(Some(fix)) => self.fix = Some(fix),
Err(err) => debug!("Failed to create fix for {}: {}", self.rule, err),
}
}
/// Consumes `self` and returns a new `Diagnostic` with the given parent node.
#[inline]
#[must_use]
pub fn with_parent(mut self, parent: TextSize) -> Self {
self.set_parent(parent);
self
}
/// Set the location of the diagnostic's parent node.
#[inline]
pub fn set_parent(&mut self, parent: TextSize) {
self.parent = Some(parent);
}
}
impl AsRule for OldDiagnostic {
fn rule(&self) -> Rule {
self.rule
}
}
impl Ranged for OldDiagnostic {
fn range(&self) -> TextRange {
self.range
}
}

View file

@ -608,7 +608,6 @@ mod tests {
use crate::fix::edits::{
add_to_dunder_all, make_redundant_alias, next_stmt_break, trailing_semicolon,
};
use crate::message::Message;
use crate::{Edit, Fix, Locator, OldDiagnostic};
/// Parse the given source using [`Mode::Module`] and return the first statement.
@ -740,7 +739,7 @@ x = 1 \
let diag = {
use crate::rules::pycodestyle::rules::MissingNewlineAtEndOfFile;
let mut iter = edits.into_iter();
let diag = OldDiagnostic::new(
OldDiagnostic::new(
MissingNewlineAtEndOfFile, // The choice of rule here is arbitrary.
TextRange::default(),
&SourceFileBuilder::new("<filename>", "<code>").finish(),
@ -748,8 +747,7 @@ x = 1 \
.with_fix(Fix::safe_edits(
iter.next().ok_or(anyhow!("expected edits nonempty"))?,
iter,
));
Message::from_diagnostic(diag, None)
))
};
assert_eq!(apply_fixes([diag].iter(), &locator).code, expect);
Ok(())

View file

@ -8,7 +8,7 @@ use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use crate::Locator;
use crate::linter::FixTable;
use crate::message::Message;
use crate::message::OldDiagnostic;
use crate::registry::Rule;
use crate::settings::types::UnsafeFixes;
use crate::{Edit, Fix};
@ -28,13 +28,13 @@ pub(crate) struct FixResult {
/// Fix errors in a file, and write the fixed source code to disk.
pub(crate) fn fix_file(
messages: &[Message],
diagnostics: &[OldDiagnostic],
locator: &Locator,
unsafe_fixes: UnsafeFixes,
) -> Option<FixResult> {
let required_applicability = unsafe_fixes.required_applicability();
let mut with_fixes = messages
let mut with_fixes = diagnostics
.iter()
.filter(|message| {
message
@ -52,7 +52,7 @@ pub(crate) fn fix_file(
/// Apply a series of fixes.
fn apply_fixes<'a>(
diagnostics: impl Iterator<Item = &'a Message>,
diagnostics: impl Iterator<Item = &'a OldDiagnostic>,
locator: &'a Locator<'a>,
) -> FixResult {
let mut output = String::with_capacity(locator.len());
@ -173,9 +173,8 @@ mod tests {
use ruff_text_size::{Ranged, TextSize};
use crate::Locator;
use crate::diagnostic::OldDiagnostic;
use crate::OldDiagnostic;
use crate::fix::{FixResult, apply_fixes};
use crate::message::Message;
use crate::rules::pycodestyle::rules::MissingNewlineAtEndOfFile;
use crate::{Edit, Fix};
@ -183,7 +182,7 @@ mod tests {
filename: &str,
source: &str,
edit: impl IntoIterator<Item = Edit>,
) -> Vec<Message> {
) -> Vec<OldDiagnostic> {
edit.into_iter()
.map(|edit| {
// The choice of rule here is arbitrary.
@ -192,7 +191,7 @@ mod tests {
edit.range(),
&SourceFileBuilder::new(filename, source).finish(),
);
Message::from_diagnostic(diagnostic.with_fix(Fix::safe_edit(edit)), None)
diagnostic.with_fix(Fix::safe_edit(edit))
})
.collect()
}

View file

@ -14,7 +14,7 @@ pub use rule_selector::RuleSelector;
pub use rule_selector::clap_completion::RuleSelectorParser;
pub use rules::pycodestyle::rules::IOError;
pub use diagnostic::OldDiagnostic;
pub use message::OldDiagnostic;
pub(crate) use ruff_diagnostics::{Applicability, Edit, Fix};
pub use violation::{AlwaysFixableViolation, FixAvailability, Violation, ViolationMetadata};
@ -24,7 +24,6 @@ mod checkers;
pub mod codes;
mod comments;
mod cst;
mod diagnostic;
pub mod directives;
mod doc_lines;
mod docstrings;

View file

@ -27,11 +27,10 @@ use crate::codes::NoqaCode;
use crate::directives::Directives;
use crate::doc_lines::{doc_lines_from_ast, doc_lines_from_tokens};
use crate::fix::{FixResult, fix_file};
use crate::message::Message;
use crate::noqa::add_noqa;
use crate::package::PackageRoot;
use crate::preview::is_py314_support_enabled;
use crate::registry::{AsRule, Rule, RuleSet};
use crate::registry::{Rule, RuleSet};
#[cfg(any(feature = "test-rules", test))]
use crate::rules::ruff::rules::test_rules::{self, TEST_RULES, TestRule};
use crate::settings::types::UnsafeFixes;
@ -43,7 +42,7 @@ pub(crate) mod float;
pub struct LinterResult {
/// A collection of diagnostic messages generated by the linter.
pub messages: Vec<Message>,
pub diagnostics: Vec<OldDiagnostic>,
/// Flag indicating that the parsed source code does not contain any
/// [`ParseError`]s
has_valid_syntax: bool,
@ -145,7 +144,7 @@ pub struct FixerResult<'a> {
pub fixed: FixTable,
}
/// Generate [`Message`]s from the source code contents at the given `Path`.
/// Generate [`OldDiagnostic`]s from the source code contents at the given `Path`.
#[expect(clippy::too_many_arguments)]
pub fn check_path(
path: &Path,
@ -160,7 +159,7 @@ pub fn check_path(
source_type: PySourceType,
parsed: &Parsed<ModModule>,
target_version: TargetVersion,
) -> Vec<Message> {
) -> Vec<OldDiagnostic> {
let source_file =
SourceFileBuilder::new(path.to_string_lossy().as_ref(), locator.contents()).finish();
@ -392,9 +391,12 @@ pub fn check_path(
RuleSet::empty()
};
if !per_file_ignores.is_empty() {
diagnostics
.as_mut_vec()
.retain(|diagnostic| !per_file_ignores.contains(diagnostic.rule()));
diagnostics.as_mut_vec().retain(|diagnostic| {
diagnostic
.noqa_code()
.and_then(|code| code.rule())
.is_none_or(|rule| !per_file_ignores.contains(rule))
});
}
// Enforce `noqa` directives.
@ -426,7 +428,11 @@ 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.rule()) {
if diagnostic
.noqa_code()
.and_then(|code| code.rule())
.is_none_or(|rule| !settings.rules.should_fix(rule))
{
diagnostic.fix = None;
}
}
@ -435,10 +441,12 @@ pub fn check_path(
if !settings.fix_safety.is_empty() {
for diagnostic in &mut diagnostics {
if let Some(fix) = diagnostic.fix.take() {
let fixed_applicability = settings
.fix_safety
.resolve_applicability(diagnostic.rule(), fix.applicability());
diagnostic.set_fix(fix.with_applicability(fixed_applicability));
if let Some(rule) = diagnostic.noqa_code().and_then(|code| code.rule()) {
let fixed_applicability = settings
.fix_safety
.resolve_applicability(rule, fix.applicability());
diagnostic.set_fix(fix.with_applicability(fixed_applicability));
}
}
}
}
@ -494,7 +502,7 @@ pub fn add_noqa_to_path(
);
// Generate diagnostics, ignoring any existing `noqa` directives.
let messages = check_path(
let diagnostics = check_path(
path,
package,
&locator,
@ -513,7 +521,7 @@ pub fn add_noqa_to_path(
// TODO(dhruvmanila): Add support for Jupyter Notebooks
add_noqa(
path,
&messages,
&diagnostics,
&locator,
indexer.comment_ranges(),
&settings.external,
@ -522,8 +530,7 @@ pub fn add_noqa_to_path(
)
}
/// Generate a [`Message`] for each [`OldDiagnostic`] triggered by the given source
/// code.
/// Generate an [`OldDiagnostic`] for each diagnostic triggered by the given source code.
pub fn lint_only(
path: &Path,
package: Option<PackageRoot<'_>>,
@ -563,7 +570,7 @@ pub fn lint_only(
);
// Generate diagnostics.
let messages = check_path(
let diagnostics = check_path(
path,
package,
&locator,
@ -580,12 +587,14 @@ pub fn lint_only(
LinterResult {
has_valid_syntax: parsed.has_valid_syntax(),
has_no_syntax_errors: !messages.iter().any(Message::is_syntax_error),
messages,
has_no_syntax_errors: !diagnostics.iter().any(OldDiagnostic::is_syntax_error),
diagnostics,
}
}
/// Convert from diagnostics to messages.
/// Convert various error types into a single collection of diagnostics.
///
/// Also use `directives` to attach noqa offsets to lint diagnostics.
fn diagnostics_to_messages(
diagnostics: Vec<OldDiagnostic>,
parse_errors: &[ParseError],
@ -594,21 +603,23 @@ fn diagnostics_to_messages(
locator: &Locator,
directives: &Directives,
source_file: &SourceFile,
) -> Vec<Message> {
) -> Vec<OldDiagnostic> {
parse_errors
.iter()
.map(|parse_error| Message::from_parse_error(parse_error, locator, source_file.clone()))
.map(|parse_error| {
OldDiagnostic::from_parse_error(parse_error, locator, source_file.clone())
})
.chain(unsupported_syntax_errors.iter().map(|syntax_error| {
Message::from_unsupported_syntax_error(syntax_error, source_file.clone())
OldDiagnostic::from_unsupported_syntax_error(syntax_error, source_file.clone())
}))
.chain(
semantic_syntax_errors
.iter()
.map(|error| Message::from_semantic_syntax_error(error, source_file.clone())),
.map(|error| OldDiagnostic::from_semantic_syntax_error(error, source_file.clone())),
)
.chain(diagnostics.into_iter().map(|diagnostic| {
let noqa_offset = directives.noqa_line_for.resolve(diagnostic.start());
Message::from_diagnostic(diagnostic, Some(noqa_offset))
diagnostic.with_noqa_offset(noqa_offset)
}))
.collect()
}
@ -672,7 +683,7 @@ pub fn lint_fix<'a>(
);
// Generate diagnostics.
let messages = check_path(
let diagnostics = check_path(
path,
package,
&locator,
@ -689,7 +700,7 @@ pub fn lint_fix<'a>(
if iterations == 0 {
has_valid_syntax = parsed.has_valid_syntax();
has_no_syntax_errors = !messages.iter().any(Message::is_syntax_error);
has_no_syntax_errors = !diagnostics.iter().any(OldDiagnostic::is_syntax_error);
} else {
// If the source code had no syntax errors on the first pass, but
// does on a subsequent pass, then we've introduced a
@ -707,7 +718,7 @@ pub fn lint_fix<'a>(
code: fixed_contents,
fixes: applied,
source_map,
}) = fix_file(&messages, &locator, unsafe_fixes)
}) = fix_file(&diagnostics, &locator, unsafe_fixes)
{
if iterations < MAX_ITERATIONS {
// Count the number of fixed errors.
@ -724,12 +735,12 @@ pub fn lint_fix<'a>(
continue;
}
report_failed_to_converge_error(path, transformed.source_code(), &messages);
report_failed_to_converge_error(path, transformed.source_code(), &diagnostics);
}
return Ok(FixerResult {
result: LinterResult {
messages,
diagnostics,
has_valid_syntax,
has_no_syntax_errors,
},
@ -749,8 +760,8 @@ fn collect_rule_codes(rules: impl IntoIterator<Item = NoqaCode>) -> String {
}
#[expect(clippy::print_stderr)]
fn report_failed_to_converge_error(path: &Path, transformed: &str, messages: &[Message]) {
let codes = collect_rule_codes(messages.iter().filter_map(Message::noqa_code));
fn report_failed_to_converge_error(path: &Path, transformed: &str, diagnostics: &[OldDiagnostic]) {
let codes = collect_rule_codes(diagnostics.iter().filter_map(OldDiagnostic::noqa_code));
if cfg!(debug_assertions) {
eprintln!(
"{}{} Failed to converge after {} iterations in `{}` with rule codes {}:---\n{}\n---",
@ -874,12 +885,12 @@ mod tests {
use ruff_notebook::{Notebook, NotebookError};
use crate::linter::check_path;
use crate::message::Message;
use crate::message::OldDiagnostic;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::source_kind::SourceKind;
use crate::test::{TestedNotebook, assert_notebook_path, test_contents, test_snippet};
use crate::{Locator, assert_messages, directives, settings};
use crate::{Locator, assert_diagnostics, directives, settings};
/// Construct a path to a Jupyter notebook in the `resources/test/fixtures/jupyter` directory.
fn notebook_path(path: impl AsRef<Path>) -> std::path::PathBuf {
@ -891,7 +902,7 @@ mod tests {
let actual = notebook_path("isort.ipynb");
let expected = notebook_path("isort_expected.ipynb");
let TestedNotebook {
messages,
diagnostics,
source_notebook,
..
} = assert_notebook_path(
@ -899,7 +910,7 @@ mod tests {
expected,
&LinterSettings::for_rule(Rule::UnsortedImports),
)?;
assert_messages!(messages, actual, source_notebook);
assert_diagnostics!(diagnostics, actual, source_notebook);
Ok(())
}
@ -908,7 +919,7 @@ mod tests {
let actual = notebook_path("ipy_escape_command.ipynb");
let expected = notebook_path("ipy_escape_command_expected.ipynb");
let TestedNotebook {
messages,
diagnostics,
source_notebook,
..
} = assert_notebook_path(
@ -916,7 +927,7 @@ mod tests {
expected,
&LinterSettings::for_rule(Rule::UnusedImport),
)?;
assert_messages!(messages, actual, source_notebook);
assert_diagnostics!(diagnostics, actual, source_notebook);
Ok(())
}
@ -925,7 +936,7 @@ mod tests {
let actual = notebook_path("unused_variable.ipynb");
let expected = notebook_path("unused_variable_expected.ipynb");
let TestedNotebook {
messages,
diagnostics,
source_notebook,
..
} = assert_notebook_path(
@ -933,7 +944,7 @@ mod tests {
expected,
&LinterSettings::for_rule(Rule::UnusedVariable),
)?;
assert_messages!(messages, actual, source_notebook);
assert_diagnostics!(diagnostics, actual, source_notebook);
Ok(())
}
@ -942,7 +953,7 @@ mod tests {
let actual = notebook_path("undefined_name.ipynb");
let expected = notebook_path("undefined_name.ipynb");
let TestedNotebook {
messages,
diagnostics,
source_notebook,
..
} = assert_notebook_path(
@ -950,7 +961,7 @@ mod tests {
expected,
&LinterSettings::for_rule(Rule::UndefinedName),
)?;
assert_messages!(messages, actual, source_notebook);
assert_diagnostics!(diagnostics, actual, source_notebook);
Ok(())
}
@ -980,7 +991,7 @@ mod tests {
let actual = notebook_path("vscode_language_id.ipynb");
let expected = notebook_path("vscode_language_id_expected.ipynb");
let TestedNotebook {
messages,
diagnostics,
source_notebook,
..
} = assert_notebook_path(
@ -988,7 +999,7 @@ mod tests {
expected,
&LinterSettings::for_rule(Rule::UnusedImport),
)?;
assert_messages!(messages, actual, source_notebook);
assert_diagnostics!(diagnostics, actual, source_notebook);
Ok(())
}
@ -1032,7 +1043,7 @@ mod tests {
/// Wrapper around `test_contents_syntax_errors` for testing a snippet of code instead of a
/// file.
fn test_snippet_syntax_errors(contents: &str, settings: &LinterSettings) -> Vec<Message> {
fn test_snippet_syntax_errors(contents: &str, settings: &LinterSettings) -> Vec<OldDiagnostic> {
let contents = dedent(contents);
test_contents_syntax_errors(
&SourceKind::Python(contents.to_string()),
@ -1047,7 +1058,7 @@ mod tests {
source_kind: &SourceKind,
path: &Path,
settings: &LinterSettings,
) -> Vec<Message> {
) -> Vec<OldDiagnostic> {
let source_type = PySourceType::from(path);
let target_version = settings.resolve_target_version(path);
let options =
@ -1064,7 +1075,7 @@ mod tests {
&locator,
&indexer,
);
let mut messages = check_path(
let mut diagnostics = check_path(
path,
None,
&locator,
@ -1078,8 +1089,8 @@ mod tests {
&parsed,
target_version,
);
messages.sort_by_key(Ranged::start);
messages
diagnostics.sort_by_key(Ranged::start);
diagnostics
}
#[test_case(
@ -1284,7 +1295,7 @@ mod tests {
error_type: &str,
) {
let snapshot = format!("semantic_syntax_error_{error_type}_{name}_{python_version}");
let messages = test_snippet_syntax_errors(
let diagnostics = test_snippet_syntax_errors(
contents,
&LinterSettings {
rules: settings::rule_table::RuleTable::empty(),
@ -1293,7 +1304,7 @@ mod tests {
..Default::default()
},
);
assert_messages!(snapshot, messages);
assert_diagnostics!(snapshot, diagnostics);
}
#[test_case(PythonVersion::PY310)]
@ -1302,7 +1313,7 @@ mod tests {
let snapshot =
format!("async_comprehension_in_sync_comprehension_notebook_{python_version}");
let path = Path::new("resources/test/fixtures/syntax_errors/async_comprehension.ipynb");
let messages = test_contents_syntax_errors(
let diagnostics = test_contents_syntax_errors(
&SourceKind::ipy_notebook(Notebook::from_path(path)?),
path,
&LinterSettings {
@ -1312,7 +1323,7 @@ mod tests {
..Default::default()
},
);
assert_messages!(snapshot, messages);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1329,13 +1340,13 @@ mod tests {
fn test_syntax_errors(rule: Rule, path: &Path) -> Result<()> {
let snapshot = path.to_string_lossy().to_string();
let path = Path::new("resources/test/fixtures/syntax_errors").join(path);
let messages = test_contents_syntax_errors(
let diagnostics = test_contents_syntax_errors(
&SourceKind::Python(std::fs::read_to_string(&path)?),
&path,
&LinterSettings::for_rule(rule),
);
insta::with_settings!({filters => vec![(r"\\", "/")]}, {
assert_messages!(snapshot, messages);
assert_diagnostics!(snapshot, diagnostics);
});
Ok(())
@ -1345,7 +1356,7 @@ mod tests {
fn test_await_scope_notebook() -> Result<()> {
let path = Path::new("resources/test/fixtures/syntax_errors/await_scope.ipynb");
let TestedNotebook {
messages,
diagnostics,
source_notebook,
..
} = assert_notebook_path(
@ -1353,7 +1364,7 @@ mod tests {
path,
&LinterSettings::for_rule(Rule::YieldOutsideFunction),
)?;
assert_messages!(messages, path, source_notebook);
assert_diagnostics!(diagnostics, path, source_notebook);
Ok(())
}
@ -1435,8 +1446,8 @@ mod tests {
)]
fn test_disabled_typing_extensions(name: &str, contents: &str, settings: &LinterSettings) {
let snapshot = format!("disabled_typing_extensions_{name}");
let messages = test_snippet(contents, settings);
assert_messages!(snapshot, messages);
let diagnostics = test_snippet(contents, settings);
assert_diagnostics!(snapshot, diagnostics);
}
#[test_case(
@ -1452,7 +1463,8 @@ mod tests {
let snapshot = format!("disabled_typing_extensions_pyi_{name}");
let path = Path::new("<filename>.pyi");
let contents = dedent(contents);
let messages = test_contents(&SourceKind::Python(contents.into_owned()), path, settings).0;
assert_messages!(snapshot, messages);
let diagnostics =
test_contents(&SourceKind::Python(contents.into_owned()), path, settings).0;
assert_diagnostics!(snapshot, diagnostics);
}
}

View file

@ -2,7 +2,7 @@ use std::io::Write;
use ruff_source_file::LineColumn;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
/// Generate error logging commands for Azure Pipelines format.
/// See [documentation](https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash#logissue-log-an-error-or-warning)
@ -13,29 +13,29 @@ impl Emitter for AzureEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
for message in messages {
let location = if context.is_notebook(&message.filename()) {
for diagnostic in diagnostics {
let location = if context.is_notebook(&diagnostic.filename()) {
// We can't give a reasonable location for the structured formats,
// so we show one that's clearly a fallback
LineColumn::default()
} else {
message.compute_start_location()
diagnostic.compute_start_location()
};
writeln!(
writer,
"##vso[task.logissue type=error\
;sourcepath={filename};linenumber={line};columnnumber={col};{code}]{body}",
filename = message.filename(),
filename = diagnostic.filename(),
line = location.line,
col = location.column,
code = message
code = diagnostic
.noqa_code()
.map_or_else(String::new, |code| format!("code={code};")),
body = message.body(),
body = diagnostic.body(),
)?;
}
@ -49,13 +49,13 @@ mod tests {
use crate::message::AzureEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = AzureEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -63,7 +63,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = AzureEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}

View file

@ -8,7 +8,7 @@ use similar::{ChangeTag, TextDiff};
use ruff_source_file::{OneIndexed, SourceFile};
use crate::message::Message;
use crate::message::OldDiagnostic;
use crate::text_helpers::ShowNonprinting;
use crate::{Applicability, Fix};
@ -26,7 +26,7 @@ pub(super) struct Diff<'a> {
}
impl<'a> Diff<'a> {
pub(crate) fn from_message(message: &'a Message) -> Option<Diff<'a>> {
pub(crate) fn from_message(message: &'a OldDiagnostic) -> Option<Diff<'a>> {
message.fix().map(|fix| Diff {
source_code: message.source_file(),
fix,

View file

@ -3,7 +3,7 @@ use std::io::Write;
use ruff_source_file::LineColumn;
use crate::fs::relativize_path;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
/// Generate error workflow command in GitHub Actions format.
/// See: [GitHub documentation](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message)
@ -14,12 +14,12 @@ impl Emitter for GithubEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
for message in messages {
let source_location = message.compute_start_location();
let location = if context.is_notebook(&message.filename()) {
for diagnostic in diagnostics {
let source_location = diagnostic.compute_start_location();
let location = if context.is_notebook(&diagnostic.filename()) {
// We can't give a reasonable location for the structured formats,
// so we show one that's clearly a fallback
LineColumn::default()
@ -27,15 +27,15 @@ impl Emitter for GithubEmitter {
source_location
};
let end_location = message.compute_end_location();
let end_location = diagnostic.compute_end_location();
write!(
writer,
"::error title=Ruff{code},file={file},line={row},col={column},endLine={end_row},endColumn={end_column}::",
code = message
code = diagnostic
.noqa_code()
.map_or_else(String::new, |code| format!(" ({code})")),
file = message.filename(),
file = diagnostic.filename(),
row = source_location.line,
column = source_location.column,
end_row = end_location.line,
@ -45,16 +45,16 @@ impl Emitter for GithubEmitter {
write!(
writer,
"{path}:{row}:{column}:",
path = relativize_path(&*message.filename()),
path = relativize_path(&*diagnostic.filename()),
row = location.line,
column = location.column,
)?;
if let Some(code) = message.noqa_code() {
if let Some(code) = diagnostic.noqa_code() {
write!(writer, " {code}")?;
}
writeln!(writer, " {}", message.body())?;
writeln!(writer, " {}", diagnostic.body())?;
}
Ok(())
@ -67,13 +67,13 @@ mod tests {
use crate::message::GithubEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = GithubEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -81,7 +81,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = GithubEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}

View file

@ -8,7 +8,7 @@ use serde::{Serialize, Serializer};
use serde_json::json;
use crate::fs::{relativize_path, relativize_path_to};
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
/// Generate JSON with violations in GitLab CI format
// https://docs.gitlab.com/ee/ci/testing/code_quality.html#implement-a-custom-tool
@ -28,13 +28,13 @@ impl Emitter for GitlabEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
serde_json::to_writer_pretty(
writer,
&SerializedMessages {
messages,
diagnostics,
context,
project_dir: self.project_dir.as_deref(),
},
@ -45,7 +45,7 @@ impl Emitter for GitlabEmitter {
}
struct SerializedMessages<'a> {
messages: &'a [Message],
diagnostics: &'a [OldDiagnostic],
context: &'a EmitterContext<'a>,
project_dir: Option<&'a str>,
}
@ -55,14 +55,14 @@ impl Serialize for SerializedMessages<'_> {
where
S: Serializer,
{
let mut s = serializer.serialize_seq(Some(self.messages.len()))?;
let mut fingerprints = HashSet::<u64>::with_capacity(self.messages.len());
let mut s = serializer.serialize_seq(Some(self.diagnostics.len()))?;
let mut fingerprints = HashSet::<u64>::with_capacity(self.diagnostics.len());
for message in self.messages {
let start_location = message.compute_start_location();
let end_location = message.compute_end_location();
for diagnostic in self.diagnostics {
let start_location = diagnostic.compute_start_location();
let end_location = diagnostic.compute_end_location();
let lines = if self.context.is_notebook(&message.filename()) {
let lines = if self.context.is_notebook(&diagnostic.filename()) {
// We can't give a reasonable location for the structured formats,
// so we show one that's clearly a fallback
json!({
@ -77,23 +77,23 @@ impl Serialize for SerializedMessages<'_> {
};
let path = self.project_dir.as_ref().map_or_else(
|| relativize_path(&*message.filename()),
|project_dir| relativize_path_to(&*message.filename(), project_dir),
|| relativize_path(&*diagnostic.filename()),
|project_dir| relativize_path_to(&*diagnostic.filename(), project_dir),
);
let mut message_fingerprint = fingerprint(message, &path, 0);
let mut message_fingerprint = fingerprint(diagnostic, &path, 0);
// Make sure that we do not get a fingerprint that is already in use
// by adding in the previously generated one.
while fingerprints.contains(&message_fingerprint) {
message_fingerprint = fingerprint(message, &path, message_fingerprint);
message_fingerprint = fingerprint(diagnostic, &path, message_fingerprint);
}
fingerprints.insert(message_fingerprint);
let (description, check_name) = if let Some(code) = message.noqa_code() {
(message.body().to_string(), code.to_string())
let (description, check_name) = if let Some(code) = diagnostic.noqa_code() {
(diagnostic.body().to_string(), code.to_string())
} else {
let description = message.body();
let description = diagnostic.body();
let description_without_prefix = description
.strip_prefix("SyntaxError: ")
.unwrap_or(description);
@ -123,7 +123,7 @@ impl Serialize for SerializedMessages<'_> {
}
/// Generate a unique fingerprint to identify a violation.
fn fingerprint(message: &Message, project_path: &str, salt: u64) -> u64 {
fn fingerprint(message: &OldDiagnostic, project_path: &str, salt: u64) -> u64 {
let mut hasher = DefaultHasher::new();
salt.hash(&mut hasher);
@ -139,13 +139,13 @@ mod tests {
use crate::message::GitlabEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = GitlabEmitter::default();
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(redact_fingerprint(&content));
}
@ -153,7 +153,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = GitlabEmitter::default();
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(redact_fingerprint(&content));
}

View file

@ -11,7 +11,7 @@ use crate::fs::relativize_path;
use crate::message::diff::calculate_print_width;
use crate::message::text::{MessageCodeFrame, RuleCodeAndBody};
use crate::message::{
Emitter, EmitterContext, Message, MessageWithLocation, group_messages_by_filename,
Emitter, EmitterContext, MessageWithLocation, OldDiagnostic, group_diagnostics_by_filename,
};
use crate::settings::types::UnsafeFixes;
@ -46,10 +46,10 @@ impl Emitter for GroupedEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
for (filename, messages) in group_messages_by_filename(messages) {
for (filename, messages) in group_diagnostics_by_filename(diagnostics) {
// Compute the maximum number of digits in the row and column, for messages in
// this file.
@ -207,14 +207,14 @@ mod tests {
use crate::message::GroupedEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
use crate::settings::types::UnsafeFixes;
#[test]
fn default() {
let mut emitter = GroupedEmitter::default();
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -222,7 +222,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = GroupedEmitter::default();
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}
@ -230,7 +230,7 @@ mod tests {
#[test]
fn show_source() {
let mut emitter = GroupedEmitter::default().with_show_source(true);
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -240,7 +240,7 @@ mod tests {
let mut emitter = GroupedEmitter::default()
.with_show_fix_status(true)
.with_show_source(true);
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -251,7 +251,7 @@ mod tests {
.with_show_fix_status(true)
.with_show_source(true)
.with_unsafe_fixes(UnsafeFixes::Enabled);
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}

View file

@ -9,7 +9,7 @@ use ruff_source_file::{LineColumn, OneIndexed, SourceCode};
use ruff_text_size::Ranged;
use crate::Edit;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
#[derive(Default)]
pub struct JsonEmitter;
@ -18,17 +18,23 @@ impl Emitter for JsonEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
serde_json::to_writer_pretty(writer, &ExpandedMessages { messages, context })?;
serde_json::to_writer_pretty(
writer,
&ExpandedMessages {
diagnostics,
context,
},
)?;
Ok(())
}
}
struct ExpandedMessages<'a> {
messages: &'a [Message],
diagnostics: &'a [OldDiagnostic],
context: &'a EmitterContext<'a>,
}
@ -37,9 +43,9 @@ impl Serialize for ExpandedMessages<'_> {
where
S: Serializer,
{
let mut s = serializer.serialize_seq(Some(self.messages.len()))?;
let mut s = serializer.serialize_seq(Some(self.diagnostics.len()))?;
for message in self.messages {
for message in self.diagnostics {
let value = message_to_json_value(message, self.context);
s.serialize_element(&value)?;
}
@ -48,7 +54,7 @@ impl Serialize for ExpandedMessages<'_> {
}
}
pub(crate) fn message_to_json_value(message: &Message, context: &EmitterContext) -> Value {
pub(crate) fn message_to_json_value(message: &OldDiagnostic, context: &EmitterContext) -> Value {
let source_file = message.source_file();
let source_code = source_file.to_source_code();
let notebook_index = context.notebook_index(&message.filename());
@ -180,14 +186,14 @@ mod tests {
use crate::message::JsonEmitter;
use crate::message::tests::{
capture_emitter_notebook_output, capture_emitter_output, create_messages,
create_notebook_messages, create_syntax_error_messages,
capture_emitter_notebook_output, capture_emitter_output, create_diagnostics,
create_notebook_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = JsonEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -195,7 +201,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = JsonEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}
@ -203,8 +209,9 @@ mod tests {
#[test]
fn notebook_output() {
let mut emitter = JsonEmitter;
let (messages, notebook_indexes) = create_notebook_messages();
let content = capture_emitter_notebook_output(&mut emitter, &messages, &notebook_indexes);
let (diagnostics, notebook_indexes) = create_notebook_diagnostics();
let content =
capture_emitter_notebook_output(&mut emitter, &diagnostics, &notebook_indexes);
assert_snapshot!(content);
}

View file

@ -1,7 +1,7 @@
use std::io::Write;
use crate::message::json::message_to_json_value;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
#[derive(Default)]
pub struct JsonLinesEmitter;
@ -10,11 +10,11 @@ impl Emitter for JsonLinesEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
for message in messages {
serde_json::to_writer(&mut *writer, &message_to_json_value(message, context))?;
for diagnostic in diagnostics {
serde_json::to_writer(&mut *writer, &message_to_json_value(diagnostic, context))?;
writer.write_all(b"\n")?;
}
Ok(())
@ -27,14 +27,14 @@ mod tests {
use crate::message::json_lines::JsonLinesEmitter;
use crate::message::tests::{
capture_emitter_notebook_output, capture_emitter_output, create_messages,
create_notebook_messages, create_syntax_error_messages,
capture_emitter_notebook_output, capture_emitter_output, create_diagnostics,
create_notebook_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = JsonLinesEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -42,7 +42,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = JsonLinesEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}
@ -50,7 +50,7 @@ mod tests {
#[test]
fn notebook_output() {
let mut emitter = JsonLinesEmitter;
let (messages, notebook_indexes) = create_notebook_messages();
let (messages, notebook_indexes) = create_notebook_diagnostics();
let content = capture_emitter_notebook_output(&mut emitter, &messages, &notebook_indexes);
assert_snapshot!(content);

View file

@ -6,7 +6,7 @@ use quick_junit::{NonSuccessKind, Report, TestCase, TestCaseStatus, TestSuite, X
use ruff_source_file::LineColumn;
use crate::message::{
Emitter, EmitterContext, Message, MessageWithLocation, group_messages_by_filename,
Emitter, EmitterContext, MessageWithLocation, OldDiagnostic, group_diagnostics_by_filename,
};
#[derive(Default)]
@ -16,12 +16,12 @@ impl Emitter for JunitEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
let mut report = Report::new("ruff");
if messages.is_empty() {
if diagnostics.is_empty() {
let mut test_suite = TestSuite::new("ruff");
test_suite
.extra
@ -31,7 +31,7 @@ impl Emitter for JunitEmitter {
test_suite.add_test_case(case);
report.add_test_suite(test_suite);
} else {
for (filename, messages) in group_messages_by_filename(messages) {
for (filename, messages) in group_diagnostics_by_filename(diagnostics) {
let mut test_suite = TestSuite::new(&filename);
test_suite
.extra
@ -97,13 +97,13 @@ mod tests {
use crate::message::JunitEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = JunitEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -111,7 +111,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = JunitEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}

View file

@ -1,5 +1,6 @@
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::io::Write;
use std::ops::Deref;
@ -23,11 +24,11 @@ use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
pub use sarif::SarifEmitter;
pub use text::TextEmitter;
use crate::Locator;
use crate::Fix;
use crate::codes::NoqaCode;
use crate::logging::DisplayParseErrorType;
use crate::registry::Rule;
use crate::{Fix, OldDiagnostic};
use crate::{Locator, Violation};
mod azure;
mod diff;
@ -42,33 +43,34 @@ mod rdjson;
mod sarif;
mod text;
/// Message represents either a diagnostic message corresponding to a rule violation or a syntax
/// error message.
/// `OldDiagnostic` represents either a diagnostic message corresponding to a rule violation or a
/// syntax error message.
///
/// All of the information for syntax errors is captured in the underlying [`db::Diagnostic`], while
/// rule violations can have the additional optional fields like fixes, suggestions, and (parent)
/// `noqa` offsets.
///
/// For diagnostic messages, the [`db::Diagnostic`]'s primary message contains the
/// [`OldDiagnostic::body`], and the primary annotation optionally contains the suggestion accompanying
/// a fix. The `db::Diagnostic::id` field contains the kebab-case lint name derived from the `Rule`.
/// [`OldDiagnostic::body`], and the primary annotation optionally contains the suggestion
/// accompanying a fix. The `db::Diagnostic::id` field contains the kebab-case lint name derived
/// from the `Rule`.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Message {
pub struct OldDiagnostic {
pub diagnostic: db::Diagnostic,
// these fields are specific to rule violations
pub fix: Option<Fix>,
pub parent: Option<TextSize>,
pub(crate) noqa_offset: Option<TextSize>,
noqa_code: Option<NoqaCode>,
pub(crate) noqa_code: Option<NoqaCode>,
}
impl Message {
impl OldDiagnostic {
pub fn syntax_error(
message: impl std::fmt::Display,
message: impl Display,
range: TextRange,
file: SourceFile,
) -> Message {
) -> OldDiagnostic {
let mut diag = db::Diagnostic::new(DiagnosticId::InvalidSyntax, Severity::Error, message);
let span = Span::from(file).with_range(range);
diag.annotate(Annotation::primary(span));
@ -82,16 +84,20 @@ impl Message {
}
#[expect(clippy::too_many_arguments)]
pub fn diagnostic(
body: String,
suggestion: Option<String>,
pub fn lint<B, S>(
body: B,
suggestion: Option<S>,
range: TextRange,
fix: Option<Fix>,
parent: Option<TextSize>,
file: SourceFile,
noqa_offset: Option<TextSize>,
rule: Rule,
) -> Message {
) -> OldDiagnostic
where
B: Display,
S: Display,
{
let mut diagnostic = db::Diagnostic::new(
DiagnosticId::Lint(LintName::of(rule.into())),
Severity::Error,
@ -104,7 +110,7 @@ impl Message {
}
diagnostic.annotate(annotation);
Message {
OldDiagnostic {
diagnostic,
fix,
parent,
@ -113,35 +119,12 @@ impl Message {
}
}
/// Create a [`Message`] from the given [`OldDiagnostic`] corresponding to a rule violation.
pub fn from_diagnostic(diagnostic: OldDiagnostic, noqa_offset: Option<TextSize>) -> Message {
let OldDiagnostic {
body,
suggestion,
range,
fix,
parent,
rule,
file,
} = diagnostic;
Self::diagnostic(
body,
suggestion,
range,
fix,
parent,
file,
noqa_offset,
rule,
)
}
/// Create a [`Message`] from the given [`ParseError`].
/// Create an [`OldDiagnostic`] from the given [`ParseError`].
pub fn from_parse_error(
parse_error: &ParseError,
locator: &Locator,
file: SourceFile,
) -> Message {
) -> OldDiagnostic {
// Try to create a non-empty range so that the diagnostic can print a caret at the right
// position. This requires that we retrieve the next character, if any, and take its length
// to maintain char-boundaries.
@ -151,7 +134,7 @@ impl Message {
.next()
.map_or(TextSize::new(0), TextLen::text_len);
Message::syntax_error(
OldDiagnostic::syntax_error(
format_args!(
"SyntaxError: {}",
DisplayParseErrorType::new(&parse_error.error)
@ -161,30 +144,105 @@ impl Message {
)
}
/// Create a [`Message`] from the given [`UnsupportedSyntaxError`].
/// Create an [`OldDiagnostic`] from the given [`UnsupportedSyntaxError`].
pub fn from_unsupported_syntax_error(
unsupported_syntax_error: &UnsupportedSyntaxError,
file: SourceFile,
) -> Message {
Message::syntax_error(
) -> OldDiagnostic {
OldDiagnostic::syntax_error(
format_args!("SyntaxError: {unsupported_syntax_error}"),
unsupported_syntax_error.range,
file,
)
}
/// Create a [`Message`] from the given [`SemanticSyntaxError`].
/// Create an [`OldDiagnostic`] from the given [`SemanticSyntaxError`].
pub fn from_semantic_syntax_error(
semantic_syntax_error: &SemanticSyntaxError,
file: SourceFile,
) -> Message {
Message::syntax_error(
) -> OldDiagnostic {
OldDiagnostic::syntax_error(
format_args!("SyntaxError: {semantic_syntax_error}"),
semantic_syntax_error.range,
file,
)
}
// TODO(brent) We temporarily allow this to avoid updating all of the call sites to add
// references. I expect this method to go away or change significantly with the rest of the
// diagnostic refactor, but if it still exists in this form at the end of the refactor, we
// should just update the call sites.
#[expect(clippy::needless_pass_by_value)]
pub fn new<T: Violation>(kind: T, range: TextRange, file: &SourceFile) -> Self {
Self::lint(
Violation::message(&kind),
Violation::fix_title(&kind),
range,
None,
None,
file.clone(),
None,
T::rule(),
)
}
/// Consumes `self` and returns a new `Diagnostic` with the given `fix`.
#[inline]
#[must_use]
pub fn with_fix(mut self, fix: Fix) -> Self {
self.set_fix(fix);
self
}
/// Set the [`Fix`] used to fix the diagnostic.
#[inline]
pub fn set_fix(&mut self, fix: Fix) {
self.fix = Some(fix);
}
/// Set the [`Fix`] used to fix the diagnostic, if the provided function returns `Ok`.
/// Otherwise, log the error.
#[inline]
pub fn try_set_fix(&mut self, func: impl FnOnce() -> anyhow::Result<Fix>) {
match func() {
Ok(fix) => self.fix = Some(fix),
Err(err) => log::debug!("Failed to create fix for {}: {}", self.name(), err),
}
}
/// Set the [`Fix`] used to fix the diagnostic, if the provided function returns `Ok`.
/// Otherwise, log the error.
#[inline]
pub fn try_set_optional_fix(&mut self, func: impl FnOnce() -> anyhow::Result<Option<Fix>>) {
match func() {
Ok(None) => {}
Ok(Some(fix)) => self.fix = Some(fix),
Err(err) => log::debug!("Failed to create fix for {}: {}", self.name(), err),
}
}
/// Consumes `self` and returns a new `Diagnostic` with the given parent node.
#[inline]
#[must_use]
pub fn with_parent(mut self, parent: TextSize) -> Self {
self.set_parent(parent);
self
}
/// Set the location of the diagnostic's parent node.
#[inline]
pub fn set_parent(&mut self, parent: TextSize) {
self.parent = Some(parent);
}
/// Consumes `self` and returns a new `Diagnostic` with the given noqa offset.
#[inline]
#[must_use]
pub fn with_noqa_offset(mut self, noqa_offset: TextSize) -> Self {
self.noqa_offset = Some(noqa_offset);
self
}
/// Returns `true` if `self` is a syntax error message.
pub fn is_syntax_error(&self) -> bool {
self.diagnostic.id().is_invalid_syntax()
@ -214,12 +272,12 @@ impl Message {
self.noqa_offset
}
/// Returns the [`Fix`] for the message, if there is any.
/// Returns the [`Fix`] for the diagnostic, if there is any.
pub fn fix(&self) -> Option<&Fix> {
self.fix.as_ref()
}
/// Returns `true` if the message contains a [`Fix`].
/// Returns `true` if the diagnostic contains a [`Fix`].
pub fn fixable(&self) -> bool {
self.fix().is_some()
}
@ -278,19 +336,19 @@ impl Message {
}
}
impl Ord for Message {
impl Ord for OldDiagnostic {
fn cmp(&self, other: &Self) -> Ordering {
(self.source_file(), self.start()).cmp(&(other.source_file(), other.start()))
}
}
impl PartialOrd for Message {
impl PartialOrd for OldDiagnostic {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ranged for Message {
impl Ranged for OldDiagnostic {
fn range(&self) -> TextRange {
self.diagnostic
.expect_primary_span()
@ -300,41 +358,43 @@ impl Ranged for Message {
}
struct MessageWithLocation<'a> {
message: &'a Message,
message: &'a OldDiagnostic,
start_location: LineColumn,
}
impl Deref for MessageWithLocation<'_> {
type Target = Message;
type Target = OldDiagnostic;
fn deref(&self) -> &Self::Target {
self.message
}
}
fn group_messages_by_filename(messages: &[Message]) -> BTreeMap<String, Vec<MessageWithLocation>> {
fn group_diagnostics_by_filename(
diagnostics: &[OldDiagnostic],
) -> BTreeMap<String, Vec<MessageWithLocation>> {
let mut grouped_messages = BTreeMap::default();
for message in messages {
for diagnostic in diagnostics {
grouped_messages
.entry(message.filename().to_string())
.entry(diagnostic.filename().to_string())
.or_insert_with(Vec::new)
.push(MessageWithLocation {
message,
start_location: message.compute_start_location(),
message: diagnostic,
start_location: diagnostic.compute_start_location(),
});
}
grouped_messages
}
/// Display format for a [`Message`]s.
/// Display format for [`OldDiagnostic`]s.
///
/// The emitter serializes a slice of [`Message`]'s and writes them to a [`Write`].
/// The emitter serializes a slice of [`OldDiagnostic`]s and writes them to a [`Write`].
pub trait Emitter {
/// Serializes the `messages` and writes the output to `writer`.
/// Serializes the `diagnostics` and writes the output to `writer`.
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()>;
}
@ -371,9 +431,9 @@ mod tests {
use ruff_text_size::{TextRange, TextSize};
use crate::Locator;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
pub(super) fn create_syntax_error_messages() -> Vec<Message> {
pub(super) fn create_syntax_error_diagnostics() -> Vec<OldDiagnostic> {
let source = r"from os import
if call(foo
@ -386,12 +446,12 @@ if call(foo
.errors()
.iter()
.map(|parse_error| {
Message::from_parse_error(parse_error, &locator, source_file.clone())
OldDiagnostic::from_parse_error(parse_error, &locator, source_file.clone())
})
.collect()
}
pub(super) fn create_messages() -> Vec<Message> {
pub(super) fn create_diagnostics() -> Vec<OldDiagnostic> {
let fib = r#"import os
@ -409,9 +469,9 @@ def fibonacci(n):
let fib_source = SourceFileBuilder::new("fib.py", fib).finish();
let unused_import_start = TextSize::from(7);
let unused_import = Message::diagnostic(
"`os` imported but unused".to_string(),
Some("Remove unused import: `os`".to_string()),
let unused_import = OldDiagnostic::lint(
"`os` imported but unused",
Some("Remove unused import: `os`"),
TextRange::new(unused_import_start, TextSize::from(9)),
Some(Fix::unsafe_edit(Edit::range_deletion(TextRange::new(
TextSize::from(0),
@ -424,9 +484,9 @@ def fibonacci(n):
);
let unused_variable_start = TextSize::from(94);
let unused_variable = Message::diagnostic(
"Local variable `x` is assigned to but never used".to_string(),
Some("Remove assignment to unused variable `x`".to_string()),
let unused_variable = OldDiagnostic::lint(
"Local variable `x` is assigned to but never used",
Some("Remove assignment to unused variable `x`"),
TextRange::new(unused_variable_start, TextSize::from(95)),
Some(Fix::unsafe_edit(Edit::deletion(
TextSize::from(94),
@ -441,9 +501,9 @@ def fibonacci(n):
let file_2 = r"if a == 1: pass";
let undefined_name_start = TextSize::from(3);
let undefined_name = Message::diagnostic(
"Undefined name `a`".to_string(),
None,
let undefined_name = OldDiagnostic::lint(
"Undefined name `a`",
Option::<&'static str>::None,
TextRange::new(undefined_name_start, TextSize::from(4)),
None,
None,
@ -455,7 +515,8 @@ def fibonacci(n):
vec![unused_import, unused_variable, undefined_name]
}
pub(super) fn create_notebook_messages() -> (Vec<Message>, FxHashMap<String, NotebookIndex>) {
pub(super) fn create_notebook_diagnostics()
-> (Vec<OldDiagnostic>, FxHashMap<String, NotebookIndex>) {
let notebook = r"# cell 1
import os
# cell 2
@ -471,9 +532,9 @@ def foo():
let notebook_source = SourceFileBuilder::new("notebook.ipynb", notebook).finish();
let unused_import_os_start = TextSize::from(16);
let unused_import_os = Message::diagnostic(
"`os` imported but unused".to_string(),
Some("Remove unused import: `os`".to_string()),
let unused_import_os = OldDiagnostic::lint(
"`os` imported but unused",
Some("Remove unused import: `os`"),
TextRange::new(unused_import_os_start, TextSize::from(18)),
Some(Fix::safe_edit(Edit::range_deletion(TextRange::new(
TextSize::from(9),
@ -486,9 +547,9 @@ def foo():
);
let unused_import_math_start = TextSize::from(35);
let unused_import_math = Message::diagnostic(
"`math` imported but unused".to_string(),
Some("Remove unused import: `math`".to_string()),
let unused_import_math = OldDiagnostic::lint(
"`math` imported but unused",
Some("Remove unused import: `math`"),
TextRange::new(unused_import_math_start, TextSize::from(39)),
Some(Fix::safe_edit(Edit::range_deletion(TextRange::new(
TextSize::from(28),
@ -501,9 +562,9 @@ def foo():
);
let unused_variable_start = TextSize::from(98);
let unused_variable = Message::diagnostic(
"Local variable `x` is assigned to but never used".to_string(),
Some("Remove assignment to unused variable `x`".to_string()),
let unused_variable = OldDiagnostic::lint(
"Local variable `x` is assigned to but never used",
Some("Remove assignment to unused variable `x`"),
TextRange::new(unused_variable_start, TextSize::from(99)),
Some(Fix::unsafe_edit(Edit::deletion(
TextSize::from(94),
@ -554,24 +615,24 @@ def foo():
pub(super) fn capture_emitter_output(
emitter: &mut dyn Emitter,
messages: &[Message],
diagnostics: &[OldDiagnostic],
) -> String {
let notebook_indexes = FxHashMap::default();
let context = EmitterContext::new(&notebook_indexes);
let mut output: Vec<u8> = Vec::new();
emitter.emit(&mut output, messages, &context).unwrap();
emitter.emit(&mut output, diagnostics, &context).unwrap();
String::from_utf8(output).expect("Output to be valid UTF-8")
}
pub(super) fn capture_emitter_notebook_output(
emitter: &mut dyn Emitter,
messages: &[Message],
diagnostics: &[OldDiagnostic],
notebook_indexes: &FxHashMap<String, NotebookIndex>,
) -> String {
let context = EmitterContext::new(notebook_indexes);
let mut output: Vec<u8> = Vec::new();
emitter.emit(&mut output, messages, &context).unwrap();
emitter.emit(&mut output, diagnostics, &context).unwrap();
String::from_utf8(output).expect("Output to be valid UTF-8")
}

View file

@ -3,7 +3,7 @@ use std::io::Write;
use ruff_source_file::OneIndexed;
use crate::fs::relativize_path;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
/// Generate violations in Pylint format.
/// See: [Flake8 documentation](https://flake8.pycqa.org/en/latest/internal/formatters.html#pylint-formatter)
@ -14,28 +14,28 @@ impl Emitter for PylintEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
for message in messages {
let row = if context.is_notebook(&message.filename()) {
for diagnostic in diagnostics {
let row = if context.is_notebook(&diagnostic.filename()) {
// We can't give a reasonable location for the structured formats,
// so we show one that's clearly a fallback
OneIndexed::from_zero_indexed(0)
} else {
message.compute_start_location().line
diagnostic.compute_start_location().line
};
let body = if let Some(code) = message.noqa_code() {
format!("[{code}] {body}", body = message.body())
let body = if let Some(code) = diagnostic.noqa_code() {
format!("[{code}] {body}", body = diagnostic.body())
} else {
message.body().to_string()
diagnostic.body().to_string()
};
writeln!(
writer,
"{path}:{row}: {body}",
path = relativize_path(&*message.filename()),
path = relativize_path(&*diagnostic.filename()),
)?;
}
@ -49,13 +49,13 @@ mod tests {
use crate::message::PylintEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = PylintEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -63,7 +63,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = PylintEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}

View file

@ -8,7 +8,7 @@ use ruff_source_file::SourceCode;
use ruff_text_size::Ranged;
use crate::Edit;
use crate::message::{Emitter, EmitterContext, LineColumn, Message};
use crate::message::{Emitter, EmitterContext, LineColumn, OldDiagnostic};
#[derive(Default)]
pub struct RdjsonEmitter;
@ -17,7 +17,7 @@ impl Emitter for RdjsonEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
_context: &EmitterContext,
) -> anyhow::Result<()> {
serde_json::to_writer_pretty(
@ -28,7 +28,7 @@ impl Emitter for RdjsonEmitter {
"url": "https://docs.astral.sh/ruff",
},
"severity": "warning",
"diagnostics": &ExpandedMessages{ messages }
"diagnostics": &ExpandedMessages{ diagnostics }
}),
)?;
@ -37,7 +37,7 @@ impl Emitter for RdjsonEmitter {
}
struct ExpandedMessages<'a> {
messages: &'a [Message],
diagnostics: &'a [OldDiagnostic],
}
impl Serialize for ExpandedMessages<'_> {
@ -45,9 +45,9 @@ impl Serialize for ExpandedMessages<'_> {
where
S: Serializer,
{
let mut s = serializer.serialize_seq(Some(self.messages.len()))?;
let mut s = serializer.serialize_seq(Some(self.diagnostics.len()))?;
for message in self.messages {
for message in self.diagnostics {
let value = message_to_rdjson_value(message);
s.serialize_element(&value)?;
}
@ -56,7 +56,7 @@ impl Serialize for ExpandedMessages<'_> {
}
}
fn message_to_rdjson_value(message: &Message) -> Value {
fn message_to_rdjson_value(message: &OldDiagnostic) -> Value {
let source_file = message.source_file();
let source_code = source_file.to_source_code();
@ -121,13 +121,13 @@ mod tests {
use crate::message::RdjsonEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
#[test]
fn output() {
let mut emitter = RdjsonEmitter;
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -135,7 +135,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = RdjsonEmitter;
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}

View file

@ -10,7 +10,7 @@ use ruff_source_file::OneIndexed;
use crate::VERSION;
use crate::codes::NoqaCode;
use crate::fs::normalize_path;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
use crate::registry::{Linter, RuleNamespace};
pub struct SarifEmitter;
@ -19,10 +19,10 @@ impl Emitter for SarifEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
_context: &EmitterContext,
) -> Result<()> {
let results = messages
let results = diagnostics
.iter()
.map(SarifResult::from_message)
.collect::<Result<Vec<_>>>()?;
@ -124,7 +124,7 @@ struct SarifResult {
impl SarifResult {
#[cfg(not(target_arch = "wasm32"))]
fn from_message(message: &Message) -> Result<Self> {
fn from_message(message: &OldDiagnostic) -> Result<Self> {
let start_location = message.compute_start_location();
let end_location = message.compute_end_location();
let path = normalize_path(&*message.filename());
@ -144,7 +144,7 @@ impl SarifResult {
#[cfg(target_arch = "wasm32")]
#[expect(clippy::unnecessary_wraps)]
fn from_message(message: &Message) -> Result<Self> {
fn from_message(message: &OldDiagnostic) -> Result<Self> {
let start_location = message.compute_start_location();
let end_location = message.compute_end_location();
let path = normalize_path(&*message.filename());
@ -194,12 +194,12 @@ impl Serialize for SarifResult {
mod tests {
use crate::message::SarifEmitter;
use crate::message::tests::{
capture_emitter_output, create_messages, create_syntax_error_messages,
capture_emitter_output, create_diagnostics, create_syntax_error_diagnostics,
};
fn get_output() -> String {
let mut emitter = SarifEmitter {};
capture_emitter_output(&mut emitter, &create_messages())
capture_emitter_output(&mut emitter, &create_diagnostics())
}
#[test]
@ -211,7 +211,7 @@ mod tests {
#[test]
fn valid_syntax_error_json() {
let mut emitter = SarifEmitter {};
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
serde_json::from_str::<serde_json::Value>(&content).unwrap();
}

View file

@ -14,7 +14,7 @@ use crate::Locator;
use crate::fs::relativize_path;
use crate::line_width::{IndentWidth, LineWidthBuilder};
use crate::message::diff::Diff;
use crate::message::{Emitter, EmitterContext, Message};
use crate::message::{Emitter, EmitterContext, OldDiagnostic};
use crate::settings::types::UnsafeFixes;
bitflags! {
@ -66,10 +66,10 @@ impl Emitter for TextEmitter {
fn emit(
&mut self,
writer: &mut dyn Write,
messages: &[Message],
diagnostics: &[OldDiagnostic],
context: &EmitterContext,
) -> anyhow::Result<()> {
for message in messages {
for message in diagnostics {
write!(
writer,
"{path}{sep}",
@ -140,7 +140,7 @@ impl Emitter for TextEmitter {
}
pub(super) struct RuleCodeAndBody<'a> {
pub(crate) message: &'a Message,
pub(crate) message: &'a OldDiagnostic,
pub(crate) show_fix_status: bool,
pub(crate) unsafe_fixes: UnsafeFixes,
}
@ -178,7 +178,7 @@ impl Display for RuleCodeAndBody<'_> {
}
pub(super) struct MessageCodeFrame<'a> {
pub(crate) message: &'a Message,
pub(crate) message: &'a OldDiagnostic,
pub(crate) notebook_index: Option<&'a NotebookIndex>,
}
@ -409,15 +409,15 @@ mod tests {
use crate::message::TextEmitter;
use crate::message::tests::{
capture_emitter_notebook_output, capture_emitter_output, create_messages,
create_notebook_messages, create_syntax_error_messages,
capture_emitter_notebook_output, capture_emitter_output, create_diagnostics,
create_notebook_diagnostics, create_syntax_error_diagnostics,
};
use crate::settings::types::UnsafeFixes;
#[test]
fn default() {
let mut emitter = TextEmitter::default().with_show_source(true);
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -427,7 +427,7 @@ mod tests {
let mut emitter = TextEmitter::default()
.with_show_fix_status(true)
.with_show_source(true);
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -438,7 +438,7 @@ mod tests {
.with_show_fix_status(true)
.with_show_source(true)
.with_unsafe_fixes(UnsafeFixes::Enabled);
let content = capture_emitter_output(&mut emitter, &create_messages());
let content = capture_emitter_output(&mut emitter, &create_diagnostics());
assert_snapshot!(content);
}
@ -449,7 +449,7 @@ mod tests {
.with_show_fix_status(true)
.with_show_source(true)
.with_unsafe_fixes(UnsafeFixes::Enabled);
let (messages, notebook_indexes) = create_notebook_messages();
let (messages, notebook_indexes) = create_notebook_diagnostics();
let content = capture_emitter_notebook_output(&mut emitter, &messages, &notebook_indexes);
assert_snapshot!(content);
@ -458,7 +458,7 @@ mod tests {
#[test]
fn syntax_errors() {
let mut emitter = TextEmitter::default().with_show_source(true);
let content = capture_emitter_output(&mut emitter, &create_syntax_error_messages());
let content = capture_emitter_output(&mut emitter, &create_syntax_error_diagnostics());
assert_snapshot!(content);
}

View file

@ -18,7 +18,7 @@ use crate::Edit;
use crate::Locator;
use crate::codes::NoqaCode;
use crate::fs::relativize_path;
use crate::message::Message;
use crate::message::OldDiagnostic;
use crate::registry::Rule;
use crate::rule_redirects::get_redirect_target;
@ -29,7 +29,7 @@ use crate::rule_redirects::get_redirect_target;
/// simultaneously.
pub fn generate_noqa_edits(
path: &Path,
messages: &[Message],
diagnostics: &[OldDiagnostic],
locator: &Locator,
comment_ranges: &CommentRanges,
external: &[String],
@ -39,7 +39,7 @@ pub fn generate_noqa_edits(
let file_directives = FileNoqaDirectives::extract(locator, comment_ranges, external, path);
let exemption = FileExemption::from(&file_directives);
let directives = NoqaDirectives::from_commented_ranges(comment_ranges, external, path, locator);
let comments = find_noqa_comments(messages, locator, &exemption, &directives, noqa_line_for);
let comments = find_noqa_comments(diagnostics, locator, &exemption, &directives, noqa_line_for);
build_noqa_edits_by_diagnostic(comments, locator, line_ending)
}
@ -707,7 +707,7 @@ impl Error for LexicalError {}
/// Adds noqa comments to suppress all messages of a file.
pub(crate) fn add_noqa(
path: &Path,
messages: &[Message],
diagnostics: &[OldDiagnostic],
locator: &Locator,
comment_ranges: &CommentRanges,
external: &[String],
@ -716,7 +716,7 @@ pub(crate) fn add_noqa(
) -> Result<usize> {
let (count, output) = add_noqa_inner(
path,
messages,
diagnostics,
locator,
comment_ranges,
external,
@ -730,7 +730,7 @@ pub(crate) fn add_noqa(
fn add_noqa_inner(
path: &Path,
messages: &[Message],
diagnostics: &[OldDiagnostic],
locator: &Locator,
comment_ranges: &CommentRanges,
external: &[String],
@ -745,7 +745,7 @@ fn add_noqa_inner(
let directives = NoqaDirectives::from_commented_ranges(comment_ranges, external, path, locator);
let comments = find_noqa_comments(messages, locator, &exemption, &directives, noqa_line_for);
let comments = find_noqa_comments(diagnostics, locator, &exemption, &directives, noqa_line_for);
let edits = build_noqa_edits_by_line(comments, locator, line_ending);
@ -835,7 +835,7 @@ struct NoqaComment<'a> {
}
fn find_noqa_comments<'a>(
messages: &'a [Message],
diagnostics: &'a [OldDiagnostic],
locator: &'a Locator,
exemption: &'a FileExemption,
directives: &'a NoqaDirectives,
@ -845,7 +845,7 @@ fn find_noqa_comments<'a>(
let mut comments_by_line: Vec<Option<NoqaComment<'a>>> = vec![];
// Mark any non-ignored diagnostics.
for message in messages {
for message in diagnostics {
let Some(code) = message.noqa_code() else {
comments_by_line.push(None);
continue;
@ -1219,9 +1219,8 @@ mod tests {
use ruff_python_trivia::CommentRanges;
use ruff_source_file::{LineEnding, SourceFileBuilder};
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
use ruff_text_size::{TextLen, TextRange, TextSize};
use crate::message::Message;
use crate::noqa::{
Directive, LexicalError, NoqaLexerOutput, NoqaMapping, add_noqa_inner, lex_codes,
lex_file_exemption, lex_inline_noqa,
@ -1247,12 +1246,6 @@ mod tests {
}
}
/// Create a [`Message`] with a placeholder filename and rule code from `diagnostic`.
fn message_from_diagnostic(diagnostic: OldDiagnostic) -> Message {
let noqa_offset = diagnostic.start();
Message::from_diagnostic(diagnostic, Some(noqa_offset))
}
#[test]
fn noqa_lex_codes() {
let source = " F401,,F402F403 # and so on";
@ -2840,8 +2833,7 @@ mod tests {
},
TextRange::new(TextSize::from(0), TextSize::from(0)),
&source_file,
)]
.map(message_from_diagnostic);
)];
let contents = "x = 1";
let noqa_line_for = NoqaMapping::default();
@ -2871,8 +2863,7 @@ mod tests {
TextRange::new(TextSize::from(0), TextSize::from(0)),
&source_file,
),
]
.map(message_from_diagnostic);
];
let contents = "x = 1 # noqa: E741\n";
let noqa_line_for = NoqaMapping::default();
let comment_ranges =
@ -2903,8 +2894,7 @@ mod tests {
TextRange::new(TextSize::from(0), TextSize::from(0)),
&source_file,
),
]
.map(message_from_diagnostic);
];
let contents = "x = 1 # noqa";
let noqa_line_for = NoqaMapping::default();
let comment_ranges =
@ -2940,8 +2930,7 @@ print(
PrintfStringFormatting,
TextRange::new(12.into(), 79.into()),
&source_file,
)]
.map(message_from_diagnostic);
)];
let comment_ranges = CommentRanges::default();
let edits = generate_noqa_edits(
path,
@ -2974,8 +2963,7 @@ bar =
UselessSemicolon,
TextRange::new(4.into(), 5.into()),
&source_file,
)]
.map(message_from_diagnostic);
)];
let noqa_line_for = NoqaMapping::default();
let comment_ranges = CommentRanges::default();
let edits = generate_noqa_edits(

View file

@ -7,12 +7,14 @@ use ruff_source_file::SourceFile;
use crate::IOError;
use crate::OldDiagnostic;
use crate::message::Message;
use crate::registry::Rule;
use crate::rules::ruff::rules::InvalidPyprojectToml;
use crate::settings::LinterSettings;
pub fn lint_pyproject_toml(source_file: &SourceFile, settings: &LinterSettings) -> Vec<Message> {
pub fn lint_pyproject_toml(
source_file: &SourceFile,
settings: &LinterSettings,
) -> Vec<OldDiagnostic> {
let Some(err) = toml::from_str::<PyProjectToml>(source_file.source_text()).err() else {
return Vec::default();
};
@ -31,7 +33,7 @@ pub fn lint_pyproject_toml(source_file: &SourceFile, settings: &LinterSettings)
if settings.rules.enabled(Rule::IOError) {
let diagnostic =
OldDiagnostic::new(IOError { message }, TextRange::default(), source_file);
messages.push(Message::from_diagnostic(diagnostic, None));
messages.push(diagnostic);
} else {
warn!(
"{}{}{} {message}",
@ -57,7 +59,7 @@ pub fn lint_pyproject_toml(source_file: &SourceFile, settings: &LinterSettings)
range,
source_file,
);
messages.push(Message::from_diagnostic(diagnostic, None));
messages.push(diagnostic);
}
messages

View file

@ -215,12 +215,6 @@ pub enum Linter {
}
pub trait RuleNamespace: Sized {
/// Returns the prefix that every single code that ruff uses to identify
/// rules from this linter starts with. In the case that multiple
/// `#[prefix]`es are configured for the variant in the `Linter` enum
/// definition this is the empty string.
fn common_prefix(&self) -> &'static str;
/// Attempts to parse the given rule code. If the prefix is recognized
/// returns the respective variant along with the code with the common
/// prefix stripped.

View file

@ -265,7 +265,6 @@ mod schema {
use strum::IntoEnumIterator;
use crate::RuleSelector;
use crate::registry::RuleNamespace;
use crate::rule_selector::{Linter, RuleCodePrefix};
impl JsonSchema for RuleSelector {

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::AirflowVariableNameTaskIdMismatch, Path::new("AIR001.py"))]
#[test_case(Rule::AirflowDagNoScheduleArgument, Path::new("AIR002.py"))]
@ -58,7 +58,7 @@ mod tests {
Path::new("airflow").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::CommentedOutCode, Path::new("ERA001.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
@ -20,7 +20,7 @@ mod tests {
Path::new("eradicate").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::FastApiRedundantResponseModel, Path::new("FAST001.py"))]
#[test_case(Rule::FastApiNonAnnotatedDependency, Path::new("FAST002_0.py"))]
@ -22,7 +22,7 @@ mod tests {
Path::new("fastapi").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -39,7 +39,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::SysVersionSlice3, Path::new("YTT101.py"))]
#[test_case(Rule::SysVersion2, Path::new("YTT102.py"))]
@ -29,7 +29,7 @@ mod tests {
Path::new("flake8_2020").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use anyhow::Result;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
@ -33,7 +33,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -59,7 +59,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -79,7 +79,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -101,7 +101,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -119,7 +119,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -138,7 +138,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -164,7 +164,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -180,7 +180,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::AnyType])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -198,7 +198,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -216,7 +216,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -226,7 +226,7 @@ mod tests {
Path::new("flake8_annotations/simple_magic_methods.py"),
&LinterSettings::for_rule(Rule::MissingReturnTypeSpecialMethod),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
@ -34,7 +34,7 @@ mod tests {
Path::new("flake8_async").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -48,7 +48,7 @@ mod tests {
..LinterSettings::for_rule(Rule::AsyncFunctionWithTimeout)
},
)?;
assert_messages!(path.file_name().unwrap().to_str().unwrap(), diagnostics);
assert_diagnostics!(path.file_name().unwrap().to_str().unwrap(), diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::settings::types::PreviewMode;
@ -94,7 +94,7 @@ mod tests {
Path::new("flake8_bandit").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -117,7 +117,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -139,7 +139,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -160,7 +160,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -181,7 +181,7 @@ mod tests {
..LinterSettings::for_rule(Rule::HardcodedTempFile)
},
)?;
assert_messages!("S108_extend", diagnostics);
assert_diagnostics!("S108_extend", diagnostics);
Ok(())
}
@ -197,7 +197,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TryExceptPass)
},
)?;
assert_messages!("S110_typed", diagnostics);
assert_diagnostics!("S110_typed", diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::BlindExcept, Path::new("BLE.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
@ -19,7 +19,7 @@ mod tests {
Path::new("flake8_blind_except").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -13,7 +13,7 @@ mod tests {
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::BooleanTypeHintPositionalArgument, Path::new("FBT.py"))]
#[test_case(Rule::BooleanDefaultValuePositionalArgument, Path::new("FBT.py"))]
@ -24,7 +24,7 @@ mod tests {
Path::new("flake8_boolean_trap").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -42,7 +42,7 @@ mod tests {
..LinterSettings::for_rule(Rule::BooleanPositionalValueInCall)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
@ -76,7 +76,7 @@ mod tests {
Path::new("flake8_bugbear").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -104,7 +104,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -115,7 +115,7 @@ mod tests {
Path::new("flake8_bugbear").join(snapshot).as_path(),
&LinterSettings::for_rule(Rule::ZipWithoutExplicitStrict),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -134,7 +134,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MutableArgumentDefault)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -155,7 +155,7 @@ mod tests {
..LinterSettings::for_rule(Rule::FunctionCallInDefaultArgument)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -171,7 +171,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MutableContextvarDefault)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::rules::flake8_builtins;
use crate::settings::LinterSettings;
@ -59,7 +59,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -89,7 +89,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -112,7 +112,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -136,7 +136,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -163,7 +163,7 @@ mod tests {
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -207,7 +207,7 @@ mod tests {
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -221,7 +221,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Path::new("COM81.py"))]
#[test_case(Path::new("COM81_syntax_error.py"))]
@ -24,7 +24,7 @@ mod tests {
Rule::ProhibitedTrailingComma,
]),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::settings::types::PreviewMode;
@ -44,7 +44,7 @@ mod tests {
Path::new("flake8_comprehensions").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -63,7 +63,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -83,7 +83,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -7,7 +7,7 @@ pub mod settings;
mod tests {
use crate::registry::Rule;
use crate::test::test_snippet;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test]
fn notice() {
@ -20,7 +20,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -34,7 +34,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -48,7 +48,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -62,7 +62,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -76,7 +76,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -90,7 +90,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -110,7 +110,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -130,7 +130,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -150,7 +150,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -170,7 +170,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -190,7 +190,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -210,7 +210,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -230,7 +230,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -250,7 +250,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -268,7 +268,7 @@ import os
..settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice])
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -331,7 +331,7 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test]
@ -342,6 +342,6 @@ import os
.trim(),
&settings::LinterSettings::for_rules(vec![Rule::MissingCopyrightNotice]),
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::CallDatetimeWithoutTzinfo, Path::new("DTZ001.py"))]
#[test_case(Rule::CallDatetimeToday, Path::new("DTZ002.py"))]
@ -28,7 +28,7 @@ mod tests {
Path::new("flake8_datetimez").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::Debugger, Path::new("T100.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
@ -20,7 +20,7 @@ mod tests {
Path::new("flake8_debugger").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::DjangoNullableModelStringField, Path::new("DJ001.py"))]
#[test_case(Rule::DjangoLocalsInRenderFunction, Path::new("DJ003.py"))]
@ -25,7 +25,7 @@ mod tests {
Path::new("flake8_django").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test]
fn defaults() -> Result<()> {
@ -22,7 +22,7 @@ mod tests {
Rule::DotFormatInException,
]),
)?;
assert_messages!("defaults", diagnostics);
assert_diagnostics!("defaults", diagnostics);
Ok(())
}
@ -41,7 +41,7 @@ mod tests {
])
},
)?;
assert_messages!("custom", diagnostics);
assert_diagnostics!("custom", diagnostics);
Ok(())
}
}

View file

@ -12,7 +12,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Path::new("EXE001_1.py"))]
#[test_case(Path::new("EXE001_2.py"))]
@ -41,7 +41,7 @@ mod tests {
Rule::ShebangMissingPython,
]),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::LineContainsFixme; "T001")]
#[test_case(Rule::LineContainsHack; "T002")]
@ -21,7 +21,7 @@ mod tests {
Path::new("flake8_fixme/T00.py"),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
use ruff_python_ast::PythonVersion;
#[test_case(Path::new("edge_case.py"))]
@ -34,7 +34,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::FutureRewritableTypeAnnotation)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -53,7 +53,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::FutureRequiredTypeAnnotation)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -23,7 +23,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::FStringInGetTextFuncCall, Path::new("INT001.py"))]
#[test_case(Rule::FormatInGetTextFuncCall, Path::new("INT002.py"))]
@ -34,7 +34,7 @@ mod tests {
Path::new("flake8_gettext").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::SingleLineImplicitStringConcatenation, Path::new("ISC.py"))]
#[test_case(Rule::MultiLineImplicitStringConcatenation, Path::new("ISC.py"))]
@ -30,7 +30,7 @@ mod tests {
Path::new("flake8_implicit_str_concat").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -52,7 +52,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use anyhow::Result;
use rustc_hash::{FxHashMap, FxHashSet};
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::rules::flake8_import_conventions::settings::{BannedAliases, default_aliases};
use crate::settings::LinterSettings;
@ -21,7 +21,7 @@ mod tests {
Path::new("flake8_import_conventions/defaults.py"),
&LinterSettings::for_rule(Rule::UnconventionalImportAlias),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -43,7 +43,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnconventionalImportAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -77,7 +77,7 @@ mod tests {
..LinterSettings::for_rule(Rule::BannedImportAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -98,7 +98,7 @@ mod tests {
..LinterSettings::for_rule(Rule::BannedImportFrom)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -120,7 +120,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnconventionalImportAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -143,7 +143,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnconventionalImportAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -169,7 +169,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnconventionalImportAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -179,7 +179,7 @@ mod tests {
Path::new("flake8_import_conventions/tricky.py"),
&LinterSettings::for_rule(Rule::UnconventionalImportAlias),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -201,7 +201,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnconventionalImportAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -8,7 +8,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
@ -28,7 +28,7 @@ mod tests {
Path::new("flake8_logging").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Path::new("G_argparse_parser_error_ok.py"))]
#[test_case(Path::new("G_extra_ok.py"))]
@ -45,7 +45,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::settings::LinterSettings;
use crate::test::{test_path, test_resource_path};
@ -40,7 +40,7 @@ mod tests {
},
)?;
insta::with_settings!({filters => vec![(r"\\", "/")]}, {
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
});
Ok(())
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::DuplicateClassFieldDefinition, Path::new("PIE794.py"))]
#[test_case(Rule::UnnecessaryDictKwargs, Path::new("PIE804.py"))]
@ -27,7 +27,7 @@ mod tests {
Path::new("flake8_pie").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::Print, Path::new("T201.py"))]
#[test_case(Rule::PPrint, Path::new("T203.py"))]
@ -20,7 +20,7 @@ mod tests {
Path::new("flake8_print").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -12,7 +12,7 @@ mod tests {
use crate::registry::Rule;
use crate::rules::pep8_naming;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::AnyEqNeAnnotation, Path::new("PYI032.py"))]
#[test_case(Rule::AnyEqNeAnnotation, Path::new("PYI032.pyi"))]
@ -132,7 +132,7 @@ mod tests {
Path::new("flake8_pyi").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -151,7 +151,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -168,7 +168,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -13,7 +13,7 @@ mod tests {
use crate::registry::Rule;
use crate::settings::types::IdentifierPattern;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
use super::settings::Settings;
use super::types;
@ -354,7 +354,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(name, diagnostics);
assert_diagnostics!(name, diagnostics);
Ok(())
}
@ -373,7 +373,7 @@ mod tests {
])
},
)?;
assert_messages!("PT006_and_PT007", diagnostics);
assert_diagnostics!("PT006_and_PT007", diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
@ -46,7 +46,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -65,7 +65,7 @@ mod tests {
.with_target_version(PythonVersion::PY311)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -84,7 +84,7 @@ mod tests {
.with_target_version(PythonVersion::PY311)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -116,7 +116,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -154,7 +154,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -192,7 +192,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -211,7 +211,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::BadQuotesInlineString])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -230,7 +230,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::BadQuotesMultilineString])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -249,7 +249,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::BadQuotesDocstring])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::UnnecessaryParenOnRaiseException, Path::new("RSE102.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
@ -19,7 +19,7 @@ mod tests {
Path::new("flake8_raise").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
@ -30,7 +30,7 @@ mod tests {
Path::new("flake8_return").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use crate::registry::Rule;
use crate::rules::flake8_self;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
use anyhow::Result;
use ruff_python_ast::name::Name;
use test_case::test_case;
@ -22,7 +22,7 @@ mod tests {
Path::new("flake8_self").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -37,7 +37,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::PrivateMemberAccess)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -12,7 +12,7 @@ mod tests {
use crate::settings::LinterSettings;
use crate::settings::types::PreviewMode;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::DuplicateIsinstanceCall, Path::new("SIM101.py"))]
#[test_case(Rule::CollapsibleIf, Path::new("SIM102.py"))]
@ -54,7 +54,7 @@ mod tests {
Path::new("flake8_simplify").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -72,7 +72,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::NoSlotsInStrSubclass, Path::new("SLOT000.py"))]
#[test_case(Rule::NoSlotsInTupleSubclass, Path::new("SLOT001.py"))]
@ -21,7 +21,7 @@ mod tests {
Path::new("flake8_slots").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -10,7 +10,7 @@ mod tests {
use anyhow::Result;
use rustc_hash::FxHashMap;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::rules::flake8_tidy_imports;
use crate::rules::flake8_tidy_imports::settings::{ApiBan, Strictness};
@ -42,7 +42,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::BannedApi])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -72,7 +72,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::BannedApi])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -88,7 +88,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::RelativeImports])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -104,7 +104,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::RelativeImports])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -121,7 +121,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::RelativeImports])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -140,7 +140,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::BannedModuleLevelImports])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::InvalidTodoTag, Path::new("TD001.py"))]
#[test_case(Rule::MissingTodoAuthor, Path::new("TD002.py"))]
@ -24,7 +24,7 @@ mod tests {
Path::new("flake8_todos").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -14,7 +14,7 @@ mod tests {
use crate::registry::{Linter, Rule};
use crate::test::{test_path, test_snippet};
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::EmptyTypeCheckingBlock, Path::new("TC005.py"))]
#[test_case(Rule::RuntimeCastValue, Path::new("TC006.py"))]
@ -59,7 +59,7 @@ mod tests {
Path::new("flake8_type_checking").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -77,7 +77,7 @@ mod tests {
Rule::QuotedTypeAlias,
]),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -91,7 +91,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -113,7 +113,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -132,7 +132,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -148,7 +148,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -177,7 +177,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -216,7 +216,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -248,7 +248,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -270,7 +270,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -297,7 +297,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -518,7 +518,7 @@ mod tests {
contents,
&settings::LinterSettings::for_rules(Linter::Flake8TypeChecking.rules()),
);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
}
#[test_case(
@ -570,6 +570,6 @@ mod tests {
..settings::LinterSettings::for_rules(Linter::Flake8TypeChecking.rules())
},
);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::UnusedFunctionArgument, Path::new("ARG.py"))]
#[test_case(Rule::UnusedMethodArgument, Path::new("ARG.py"))]
@ -24,7 +24,7 @@ mod tests {
Path::new("flake8_unused_arguments").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -45,7 +45,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -66,7 +66,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings;
use crate::test::test_path;
@ -50,7 +50,7 @@ mod tests {
Rule::BuiltinOpen,
]),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -73,7 +73,7 @@ mod tests {
Path::new("flake8_use_pathlib").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::StaticJoinToFString, Path::new("FLY002.py"))]
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
@ -20,7 +20,7 @@ mod tests {
Path::new("flynt").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -292,7 +292,7 @@ mod tests {
use ruff_python_semantic::{MemberNameImport, ModuleNameImport, NameImport};
use ruff_text_size::Ranged;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::rules::isort::categorize::{ImportSection, KnownModules};
use crate::settings::LinterSettings;
@ -363,7 +363,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -391,7 +391,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -415,7 +415,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -439,7 +439,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -454,7 +454,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
crate::assert_messages!(snapshot, diagnostics);
crate::assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -478,7 +478,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -503,7 +503,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -521,7 +521,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -545,7 +545,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -563,7 +563,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -582,7 +582,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -600,7 +600,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -622,7 +622,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -640,7 +640,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -659,7 +659,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -687,7 +687,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -717,7 +717,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -745,7 +745,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -767,7 +767,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -787,7 +787,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -820,7 +820,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MissingRequiredImport)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -854,7 +854,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MissingRequiredImport)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -882,7 +882,7 @@ mod tests {
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -905,7 +905,7 @@ mod tests {
..LinterSettings::for_rules([Rule::MissingRequiredImport, Rule::UselessImportAlias])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -935,7 +935,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MissingRequiredImport)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -958,7 +958,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MissingRequiredImport)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -992,7 +992,7 @@ mod tests {
..LinterSettings::for_rules([Rule::MissingRequiredImport, Rule::UnusedImport])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1011,7 +1011,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1029,7 +1029,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1047,7 +1047,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1082,7 +1082,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1106,7 +1106,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1131,7 +1131,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1156,7 +1156,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1178,7 +1178,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1199,7 +1199,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(&*snapshot, diagnostics);
assert_diagnostics!(&*snapshot, diagnostics);
Ok(())
}
@ -1218,7 +1218,7 @@ mod tests {
},
)?;
diagnostics.sort_by_key(Ranged::start);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1241,7 +1241,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1274,7 +1274,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1306,7 +1306,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1330,7 +1330,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1347,7 +1347,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -1364,7 +1364,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -1387,7 +1387,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -1407,7 +1407,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnsortedImports)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
@ -26,7 +26,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::ComplexStructure])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::NumpyDeprecatedTypeAlias, Path::new("NPY001.py"))]
#[test_case(Rule::NumpyLegacyRandom, Path::new("NPY002.py"))]
@ -26,7 +26,7 @@ mod tests {
Path::new("numpy").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::{Linter, Rule};
use crate::test::{test_path, test_snippet};
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(
r#"
@ -355,7 +355,7 @@ mod tests {
contents,
&settings::LinterSettings::for_rules(Linter::PandasVet.rules()),
);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
}
#[test_case(
@ -370,7 +370,7 @@ mod tests {
Path::new("pandas_vet").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -15,7 +15,7 @@ mod tests {
use crate::rules::pep8_naming::settings::IgnoreNames;
use crate::rules::{flake8_import_conventions, pep8_naming};
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::InvalidClassName, Path::new("N801.py"))]
#[test_case(Rule::InvalidFunctionName, Path::new("N802.py"))]
@ -85,7 +85,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -104,7 +104,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::CamelcaseImportedAsAcronym)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -124,7 +124,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::InvalidFirstArgumentNameForMethod)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -143,7 +143,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::InvalidFirstArgumentNameForMethod)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -181,7 +181,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -9,7 +9,7 @@ mod tests {
use ruff_python_ast::PythonVersion;
use test_case::test_case;
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::settings::types::PreviewMode;
@ -27,7 +27,7 @@ mod tests {
Path::new("perflint").join(path).as_path(),
&LinterSettings::for_rule(rule_code).with_target_version(PythonVersion::PY310),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -48,7 +48,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -19,7 +19,7 @@ mod tests {
use crate::rules::{isort, pycodestyle};
use crate::settings::types::PreviewMode;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
use super::settings::Settings;
@ -71,7 +71,7 @@ mod tests {
Path::new("pycodestyle").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -95,7 +95,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -106,7 +106,7 @@ mod tests {
&settings::LinterSettings::for_rule(Rule::MissingNewlineAtEndOfFile),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -155,7 +155,7 @@ mod tests {
Path::new("pycodestyle").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -172,7 +172,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -190,7 +190,7 @@ mod tests {
Path::new("pycodestyle").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -214,7 +214,7 @@ mod tests {
Path::new("pycodestyle").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -244,7 +244,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -274,7 +274,7 @@ mod tests {
])
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -290,7 +290,7 @@ mod tests {
Path::new("pycodestyle").join("E30.pyi"),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -306,7 +306,7 @@ mod tests {
Path::new("pycodestyle").join("E30.ipynb"),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -322,7 +322,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -336,7 +336,7 @@ mod tests {
Rule::IsLiteral,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -351,7 +351,7 @@ mod tests {
Rule::MultipleLeadingHashesForBlockComment,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -369,7 +369,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::LineTooLong)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -385,7 +385,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::DocLineTooLong)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -401,7 +401,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::DocLineTooLong)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -422,7 +422,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::LineTooLong)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -13,7 +13,7 @@ mod tests {
use crate::rules::pydocstyle;
use crate::rules::pydocstyle::settings::Convention;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
use super::settings::Settings;
@ -24,7 +24,7 @@ mod tests {
Path::new("pydoclint").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -46,7 +46,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -68,7 +68,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -94,7 +94,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -14,7 +14,7 @@ mod tests {
use super::settings::{Convention, Settings};
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::MissingBlankLineAfterLastSection, Path::new("sections.py"))]
#[test_case(Rule::NoBlankLineAfterSection, Path::new("sections.py"))]
@ -109,7 +109,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -119,7 +119,7 @@ mod tests {
Path::new("pydocstyle/bom.py"),
&settings::LinterSettings::for_rule(Rule::TripleSingleQuotes),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -134,7 +134,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -147,7 +147,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -164,7 +164,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -181,7 +181,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -198,7 +198,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::UndocumentedParam)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -211,7 +211,7 @@ mod tests {
Rule::MissingTrailingPeriod,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -230,7 +230,7 @@ mod tests {
Rule::UndocumentedPublicInit,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -21,9 +21,7 @@ mod tests {
use ruff_python_trivia::textwrap::dedent;
use ruff_text_size::Ranged;
use crate::Locator;
use crate::linter::check_path;
use crate::message::Message;
use crate::registry::{Linter, Rule};
use crate::rules::isort;
use crate::rules::pyflakes;
@ -31,7 +29,7 @@ mod tests {
use crate::settings::{LinterSettings, flags};
use crate::source_kind::SourceKind;
use crate::test::{test_contents, test_path, test_snippet};
use crate::{assert_messages, directives};
use crate::{Locator, OldDiagnostic, assert_diagnostics, directives};
#[test_case(Rule::UnusedImport, Path::new("F401_0.py"))]
#[test_case(Rule::UnusedImport, Path::new("F401_1.py"))]
@ -187,7 +185,7 @@ mod tests {
Path::new("pyflakes").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -210,7 +208,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -223,7 +221,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UndefinedName)
},
);
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
}
#[test_case(Rule::UnusedImport, Path::new("__init__.py"))]
@ -247,7 +245,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -286,7 +284,7 @@ mod tests {
},
)
.0;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
}
// Regression test for https://github.com/astral-sh/ruff/issues/12897
@ -314,7 +312,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
};
let diagnostics = test_path(Path::new("pyflakes").join(path).as_path(), &settings)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -334,7 +332,7 @@ mod tests {
Path::new("pyflakes").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -358,7 +356,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -374,7 +372,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -387,7 +385,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnusedVariable)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -401,7 +399,7 @@ mod tests {
Rule::UnusedImport,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -411,7 +409,7 @@ mod tests {
Path::new("pyflakes/builtins.py"),
&LinterSettings::for_rules(vec![Rule::UndefinedName]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -424,7 +422,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::UndefinedName])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -434,7 +432,7 @@ mod tests {
Path::new("pyflakes/typing_modules.py"),
&LinterSettings::for_rules(vec![Rule::UndefinedName]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -447,7 +445,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::UndefinedName])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -457,7 +455,7 @@ mod tests {
Path::new("pyflakes/future_annotations.py"),
&LinterSettings::for_rules(vec![Rule::UnusedImport, Rule::UndefinedName]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -467,7 +465,7 @@ mod tests {
Path::new("pyflakes/multi_statement_lines.py"),
&LinterSettings::for_rule(Rule::UnusedImport),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -480,7 +478,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UndefinedName)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -493,7 +491,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UndefinedName)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -510,7 +508,7 @@ mod tests {
..LinterSettings::for_rule(Rule::UnusedImport)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -734,7 +732,7 @@ mod tests {
contents,
&LinterSettings::for_rules(Linter::Pyflakes.rules()),
);
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
}
/// A re-implementation of the Pyflakes test runner.
@ -776,10 +774,9 @@ mod tests {
messages.sort_by_key(Ranged::start);
let actual = messages
.iter()
.filter(|msg| !msg.is_syntax_error())
.map(Message::name)
.filter_map(OldDiagnostic::noqa_code)
.collect::<Vec<_>>();
let expected: Vec<_> = expected.iter().map(|rule| rule.name().as_str()).collect();
let expected: Vec<_> = expected.iter().map(Rule::noqa_code).collect();
assert_eq!(actual, expected);
}

View file

@ -11,7 +11,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::BlanketTypeIgnore, Path::new("PGH003_0.py"))]
#[test_case(Rule::BlanketTypeIgnore, Path::new("PGH003_1.py"))]
@ -26,7 +26,7 @@ mod tests {
Path::new("pygrep_hooks").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -16,7 +16,7 @@ mod tests {
use crate::registry::Rule;
use crate::rules::{flake8_tidy_imports, pylint};
use crate::assert_messages;
use crate::assert_diagnostics;
use crate::settings::LinterSettings;
use crate::settings::types::PreviewMode;
use crate::test::test_path;
@ -246,7 +246,7 @@ mod tests {
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -257,7 +257,7 @@ mod tests {
&LinterSettings::for_rule(Rule::ContinueInFinally)
.with_target_version(PythonVersion::PY37),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -273,7 +273,7 @@ mod tests {
..LinterSettings::for_rule(Rule::MagicValueComparison)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -289,7 +289,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyArguments)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -302,7 +302,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyArguments)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -318,7 +318,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyPositionalArguments)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -334,7 +334,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyBranches)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -350,7 +350,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyBooleanExpressions)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -366,7 +366,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyStatements)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -382,7 +382,7 @@ mod tests {
..LinterSettings::for_rule(Rule::TooManyReturnStatements)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -398,7 +398,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::TooManyPublicMethods])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -414,7 +414,7 @@ mod tests {
..LinterSettings::for_rules(vec![Rule::TooManyLocals])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -438,7 +438,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -17,7 +17,7 @@ mod tests {
use crate::rules::pyupgrade;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::ConvertNamedTupleFunctionalToClass, Path::new("UP014.py"))]
#[test_case(Rule::ConvertTypedDictFunctionalToClass, Path::new("UP013.py"))]
@ -118,7 +118,7 @@ mod tests {
Path::new("pyupgrade").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -131,7 +131,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::TimeoutErrorAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -144,7 +144,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::NonPEP695TypeAlias)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -160,7 +160,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::NonPEP585Annotation)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -176,7 +176,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::NonPEP585Annotation)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -189,7 +189,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::NonPEP585Annotation)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -202,7 +202,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::NonPEP585Annotation)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -218,7 +218,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -234,7 +234,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -247,7 +247,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::DatetimeTimezoneUTC)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -260,7 +260,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::NonPEP646Unpack)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -13,7 +13,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::ReadWholeFile, Path::new("FURB101.py"))]
#[test_case(Rule::RepeatedAppend, Path::new("FURB113.py"))]
@ -58,7 +58,7 @@ mod tests {
Path::new("refurb").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -69,7 +69,7 @@ mod tests {
&settings::LinterSettings::for_rule(Rule::WriteWholeFile)
.with_target_version(PythonVersion::PY39),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -80,7 +80,7 @@ mod tests {
&settings::LinterSettings::for_rule(Rule::FStringNumberFormat)
.with_target_version(PythonVersion::PY311),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
}

View file

@ -21,7 +21,7 @@ mod tests {
use crate::settings::LinterSettings;
use crate::settings::types::{CompiledPerFileIgnoreList, PerFileIgnore, PreviewMode};
use crate::test::{test_path, test_resource_path};
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::CollectionLiteralConcatenation, Path::new("RUF005.py"))]
#[test_case(Rule::CollectionLiteralConcatenation, Path::new("RUF005_slices.py"))]
@ -119,7 +119,7 @@ mod tests {
Path::new("ruff").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -134,7 +134,7 @@ mod tests {
..LinterSettings::for_rule(Rule::IncorrectlyParenthesizedTupleInSubscript)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -150,7 +150,7 @@ mod tests {
..LinterSettings::for_rule(Rule::IncorrectlyParenthesizedTupleInSubscript)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -167,7 +167,7 @@ mod tests {
&settings::LinterSettings::for_rule(Rule::ImplicitOptional)
.with_target_version(PythonVersion::PY39),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -184,7 +184,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -202,7 +202,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -215,7 +215,7 @@ mod tests {
Rule::AmbiguousVariableName,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -236,7 +236,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -257,7 +257,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -267,7 +267,7 @@ mod tests {
Path::new("ruff/RUF100_1.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedNOQA, Rule::UnusedImport]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -284,7 +284,7 @@ mod tests {
.unwrap();
let diagnostics = test_path(Path::new("ruff/RUF100_2.py"), &settings)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -298,7 +298,7 @@ mod tests {
Rule::UndefinedName,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -308,7 +308,7 @@ mod tests {
Path::new("ruff/RUF100_4.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedNOQA, Rule::UnusedImport]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -324,7 +324,7 @@ mod tests {
])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -334,7 +334,7 @@ mod tests {
Path::new("ruff/RUF100_6.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedNOQA]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -349,7 +349,7 @@ mod tests {
Rule::UnusedVariable,
]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -362,7 +362,7 @@ mod tests {
..settings::LinterSettings::for_rule(Rule::InvalidRuleCode)
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -380,7 +380,7 @@ mod tests {
..settings::LinterSettings::for_rules(vec![Rule::UnusedImport, Rule::UnusedNOQA])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -398,7 +398,7 @@ mod tests {
..settings::LinterSettings::for_rules(vec![Rule::UnusedNOQA])
},
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -408,7 +408,7 @@ mod tests {
Path::new("ruff/flake8_noqa.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedImport, Rule::UnusedVariable]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -418,7 +418,7 @@ mod tests {
Path::new("ruff/ruff_noqa_all.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedImport, Rule::UnusedVariable]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -428,7 +428,7 @@ mod tests {
Path::new("ruff/ruff_noqa_codes.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedImport, Rule::UnusedVariable]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -438,7 +438,7 @@ mod tests {
Path::new("ruff/ruff_noqa_invalid.py"),
&settings::LinterSettings::for_rules(vec![Rule::UnusedImport, Rule::UnusedVariable]),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -448,7 +448,7 @@ mod tests {
Path::new("ruff/redirects.py"),
&settings::LinterSettings::for_rule(Rule::NonPEP604AnnotationUnion),
)?;
assert_messages!(diagnostics);
assert_diagnostics!(diagnostics);
Ok(())
}
@ -470,7 +470,7 @@ mod tests {
&source_file,
&settings::LinterSettings::for_rule(Rule::InvalidPyprojectToml),
);
assert_messages!(snapshot, messages);
assert_diagnostics!(snapshot, messages);
Ok(())
}
@ -495,7 +495,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
@ -523,7 +523,7 @@ mod tests {
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -12,7 +12,7 @@ mod tests {
use crate::registry::Rule;
use crate::test::test_path;
use crate::{assert_messages, settings};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::RaiseVanillaClass, Path::new("TRY002.py"))]
#[test_case(Rule::RaiseVanillaArgs, Path::new("TRY003.py"))]
@ -29,7 +29,7 @@ mod tests {
Path::new("tryceratops").join(path).as_path(),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_messages!(snapshot, diagnostics);
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
}

View file

@ -23,7 +23,7 @@ use ruff_source_file::SourceFileBuilder;
use crate::codes::Rule;
use crate::fix::{FixResult, fix_file};
use crate::linter::check_path;
use crate::message::{Emitter, EmitterContext, Message, TextEmitter};
use crate::message::{Emitter, EmitterContext, OldDiagnostic, TextEmitter};
use crate::package::PackageRoot;
use crate::packaging::detect_package_root;
use crate::settings::types::UnsafeFixes;
@ -39,7 +39,10 @@ pub(crate) fn test_resource_path(path: impl AsRef<Path>) -> std::path::PathBuf {
/// Run [`check_path`] on a Python file in the `resources/test/fixtures` directory.
#[cfg(not(fuzzing))]
pub(crate) fn test_path(path: impl AsRef<Path>, settings: &LinterSettings) -> Result<Vec<Message>> {
pub(crate) fn test_path(
path: impl AsRef<Path>,
settings: &LinterSettings,
) -> Result<Vec<OldDiagnostic>> {
let path = test_resource_path("fixtures").join(path);
let source_type = PySourceType::from(&path);
let source_kind = SourceKind::from_path(path.as_ref(), source_type)?.expect("valid source");
@ -48,7 +51,7 @@ pub(crate) fn test_path(path: impl AsRef<Path>, settings: &LinterSettings) -> Re
#[cfg(not(fuzzing))]
pub(crate) struct TestedNotebook {
pub(crate) messages: Vec<Message>,
pub(crate) diagnostics: Vec<OldDiagnostic>,
pub(crate) source_notebook: Notebook,
pub(crate) linted_notebook: Notebook,
}
@ -77,14 +80,14 @@ pub(crate) fn assert_notebook_path(
);
Ok(TestedNotebook {
messages,
diagnostics: messages,
source_notebook: source_kind.expect_ipy_notebook(),
linted_notebook,
})
}
/// Run [`check_path`] on a snippet of Python code.
pub fn test_snippet(contents: &str, settings: &LinterSettings) -> Vec<Message> {
pub fn test_snippet(contents: &str, settings: &LinterSettings) -> Vec<OldDiagnostic> {
let path = Path::new("<filename>");
let contents = dedent(contents);
test_contents(&SourceKind::Python(contents.into_owned()), path, settings).0
@ -108,7 +111,7 @@ pub(crate) fn test_contents<'a>(
source_kind: &'a SourceKind,
path: &Path,
settings: &LinterSettings,
) -> (Vec<Message>, Cow<'a, SourceKind>) {
) -> (Vec<OldDiagnostic>, Cow<'a, SourceKind>) {
let source_type = PySourceType::from(path);
let target_version = settings.resolve_target_version(path);
let options =
@ -288,7 +291,7 @@ Either ensure you always emit a fix or change `Violation::FIX_AVAILABILITY` to e
diagnostic
})
.chain(parsed.errors().iter().map(|parse_error| {
Message::from_parse_error(parse_error, &locator, source_code.clone())
OldDiagnostic::from_parse_error(parse_error, &locator, source_code.clone())
}))
.sorted()
.collect();
@ -306,7 +309,9 @@ fn print_syntax_errors(
let messages: Vec<_> = errors
.iter()
.map(|parse_error| Message::from_parse_error(parse_error, locator, source_file.clone()))
.map(|parse_error| {
OldDiagnostic::from_parse_error(parse_error, locator, source_file.clone())
})
.collect();
if let Some(notebook) = source.as_ipy_notebook() {
@ -317,18 +322,22 @@ fn print_syntax_errors(
}
/// Print the [`Message::Diagnostic`]s in `messages`.
fn print_diagnostics(mut messages: Vec<Message>, path: &Path, source: &SourceKind) -> String {
messages.retain(|msg| !msg.is_syntax_error());
fn print_diagnostics(
mut diagnostics: Vec<OldDiagnostic>,
path: &Path,
source: &SourceKind,
) -> String {
diagnostics.retain(|msg| !msg.is_syntax_error());
if let Some(notebook) = source.as_ipy_notebook() {
print_jupyter_messages(&messages, path, notebook)
print_jupyter_messages(&diagnostics, path, notebook)
} else {
print_messages(&messages)
print_messages(&diagnostics)
}
}
pub(crate) fn print_jupyter_messages(
messages: &[Message],
diagnostics: &[OldDiagnostic],
path: &Path,
notebook: &Notebook,
) -> String {
@ -341,7 +350,7 @@ pub(crate) fn print_jupyter_messages(
.with_unsafe_fixes(UnsafeFixes::Enabled)
.emit(
&mut output,
messages,
diagnostics,
&EmitterContext::new(&FxHashMap::from_iter([(
path.file_name().unwrap().to_string_lossy().to_string(),
notebook.index().clone(),
@ -352,7 +361,7 @@ pub(crate) fn print_jupyter_messages(
String::from_utf8(output).unwrap()
}
pub(crate) fn print_messages(messages: &[Message]) -> String {
pub(crate) fn print_messages(diagnostics: &[OldDiagnostic]) -> String {
let mut output = Vec::new();
TextEmitter::default()
@ -362,7 +371,7 @@ pub(crate) fn print_messages(messages: &[Message]) -> String {
.with_unsafe_fixes(UnsafeFixes::Enabled)
.emit(
&mut output,
messages,
diagnostics,
&EmitterContext::new(&FxHashMap::default()),
)
.unwrap();
@ -371,7 +380,7 @@ pub(crate) fn print_messages(messages: &[Message]) -> String {
}
#[macro_export]
macro_rules! assert_messages {
macro_rules! assert_diagnostics {
($value:expr, $path:expr, $notebook:expr) => {{
insta::with_settings!({ omit_expression => true }, {
insta::assert_snapshot!(

View file

@ -254,9 +254,11 @@ fn generate_rule_to_code(linter_to_rules: &BTreeMap<Ident, BTreeMap<String, Rule
}
let mut rule_noqa_code_match_arms = quote!();
let mut noqa_code_rule_match_arms = quote!();
let mut rule_group_match_arms = quote!();
let mut noqa_code_consts = quote!();
for (rule, codes) in rule_to_codes {
for (i, (rule, codes)) in rule_to_codes.into_iter().enumerate() {
let rule_name = rule.segments.last().unwrap();
assert_eq!(
codes.len(),
@ -292,6 +294,14 @@ See also https://github.com/astral-sh/ruff/issues/2186.
#(#attrs)* Rule::#rule_name => NoqaCode(crate::registry::Linter::#linter.common_prefix(), #code),
});
let const_ident = quote::format_ident!("NOQA_PREFIX_{}", i);
noqa_code_consts.extend(quote! {
const #const_ident: &str = crate::registry::Linter::#linter.common_prefix();
});
noqa_code_rule_match_arms.extend(quote! {
#(#attrs)* NoqaCode(#const_ident, #code) => Some(Rule::#rule_name),
});
rule_group_match_arms.extend(quote! {
#(#attrs)* Rule::#rule_name => #group,
});
@ -340,6 +350,16 @@ See also https://github.com/astral-sh/ruff/issues/2186.
}
}
}
impl NoqaCode {
pub fn rule(&self) -> Option<Rule> {
#noqa_code_consts
match self {
#noqa_code_rule_match_arms
_ => None
}
}
}
};
rule_to_code
}

View file

@ -118,10 +118,6 @@ pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenS
None
}
fn common_prefix(&self) -> &'static str {
match self { #common_prefix_match_arms }
}
fn name(&self) -> &'static str {
match self { #name_match_arms }
}
@ -130,6 +126,16 @@ pub(crate) fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenS
match self { #url_match_arms }
}
}
impl #ident {
/// Returns the prefix that every single code that ruff uses to identify
/// rules from this linter starts with. In the case that multiple
/// `#[prefix]`es are configured for the variant in the `Linter` enum
/// definition this is the empty string.
pub const fn common_prefix(&self) -> &'static str {
match self { #common_prefix_match_arms }
}
}
})
}

View file

@ -15,7 +15,7 @@ use ruff_linter::{
directives::{Flags, extract_directives},
generate_noqa_edits,
linter::check_path,
message::Message,
message::OldDiagnostic,
package::PackageRoot,
packaging::detect_package_root,
settings::flags,
@ -122,7 +122,7 @@ pub(crate) fn check(
let directives = extract_directives(parsed.tokens(), Flags::all(), &locator, &indexer);
// Generate checks.
let messages = check_path(
let diagnostics = check_path(
&query.virtual_file_path(),
package,
&locator,
@ -139,7 +139,7 @@ pub(crate) fn check(
let noqa_edits = generate_noqa_edits(
&query.virtual_file_path(),
&messages,
&diagnostics,
&locator,
indexer.comment_ranges(),
&settings.linter.external,
@ -162,7 +162,7 @@ pub(crate) fn check(
}
let lsp_diagnostics =
messages
diagnostics
.into_iter()
.zip(noqa_edits)
.filter_map(|(message, noqa_edit)| {
@ -231,7 +231,7 @@ pub(crate) fn fixes_for_diagnostics(
/// Generates an LSP diagnostic with an associated cell index for the diagnostic to go in.
/// If the source kind is a text document, the cell index will always be `0`.
fn to_lsp_diagnostic(
diagnostic: &Message,
diagnostic: &OldDiagnostic,
noqa_edit: Option<Edit>,
source_kind: &SourceKind,
index: &LineIndex,

View file

@ -188,7 +188,7 @@ impl Workspace {
);
// Generate checks.
let messages = check_path(
let diagnostics = check_path(
Path::new("<filename>"),
None,
&locator,
@ -205,7 +205,7 @@ impl Workspace {
let source_code = locator.to_source_code();
let messages: Vec<ExpandedMessage> = messages
let messages: Vec<ExpandedMessage> = diagnostics
.into_iter()
.map(|msg| ExpandedMessage {
code: msg.noqa_code().map(|code| code.to_string()),

View file

@ -22,7 +22,6 @@ use ruff_cache::cache_dir;
use ruff_formatter::IndentStyle;
use ruff_graph::{AnalyzeSettings, Direction};
use ruff_linter::line_width::{IndentWidth, LineLength};
use ruff_linter::registry::RuleNamespace;
use ruff_linter::registry::{INCOMPATIBLE_CODES, Rule, RuleSet};
use ruff_linter::rule_selector::{PreviewOptions, Specificity};
use ruff_linter::rules::{flake8_import_conventions, isort, pycodestyle};

View file

@ -43,7 +43,7 @@ fn do_fuzz(case: &[u8]) -> Corpus {
let mut warnings = HashMap::new();
for msg in &linter_result.messages {
for msg in &linter_result.diagnostics {
let count: &mut usize = warnings.entry(msg.name()).or_default();
*count += 1;
}
@ -67,7 +67,7 @@ fn do_fuzz(case: &[u8]) -> Corpus {
"formatter introduced a parse error"
);
for msg in &linter_result.messages {
for msg in &linter_result.diagnostics {
if let Some(count) = warnings.get_mut(msg.name()) {
if let Some(decremented) = count.checked_sub(1) {
*count = decremented;