mirror of
https://github.com/astral-sh/ruff.git
synced 2025-12-23 09:19:39 +00:00
Fix grouping
This commit is contained in:
parent
f887e8177a
commit
6484f28f81
4 changed files with 49 additions and 52 deletions
|
|
@ -98,7 +98,7 @@ impl SourceText {
|
|||
match &mut inner.kind {
|
||||
SourceTextKind::Text(text) => *text = new_source,
|
||||
SourceTextKind::Notebook { notebook } => {
|
||||
notebook.update(&source_map, new_source);
|
||||
notebook.update(source_map, new_source);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -416,10 +416,9 @@ impl MainLoop {
|
|||
let exit_status = if diagnostics.is_empty() {
|
||||
ExitStatus::Success
|
||||
} else {
|
||||
let exit_status =
|
||||
exit_status_from_diagnostics(&diagnostics, terminal_settings);
|
||||
|
||||
|
||||
exit_status
|
||||
exit_status_from_diagnostics(&diagnostics, terminal_settings)
|
||||
};
|
||||
|
||||
if exit_status.is_internal_error() {
|
||||
|
|
|
|||
|
|
@ -64,13 +64,13 @@ pub fn suppress_all_diagnostics(db: &dyn Db, diagnostics: Vec<Diagnostic>) -> Su
|
|||
|
||||
let count_current_file = to_suppress.len();
|
||||
|
||||
let fixes = suppress_all(db, file, to_suppress);
|
||||
let fixes = suppress_all(db, file, &to_suppress);
|
||||
let (new_source, source_map) = apply_fixes(db, file, fixes);
|
||||
|
||||
source.updated(new_source, &source_map);
|
||||
|
||||
// Create new source from applying fixes
|
||||
if let Err(err) = system.write_file(path, &*source.to_raw_content()) {
|
||||
if let Err(err) = system.write_file(path, &source.to_raw_content()) {
|
||||
let mut diag = Diagnostic::new(
|
||||
DiagnosticId::Io,
|
||||
Severity::Error,
|
||||
|
|
@ -100,7 +100,7 @@ fn apply_fixes(db: &dyn Db, file: File, mut fixes: Vec<Fix>) -> (String, SourceM
|
|||
|
||||
let mut source_map = SourceMap::default();
|
||||
|
||||
fixes.sort_unstable_by_key(|fix| fix.min_start());
|
||||
fixes.sort_unstable_by_key(ruff_diagnostics::Fix::min_start);
|
||||
|
||||
for fix in fixes {
|
||||
let mut edits = fix.edits().iter().peekable();
|
||||
|
|
|
|||
|
|
@ -1,59 +1,49 @@
|
|||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use crate::Db;
|
||||
use crate::lint::LintId;
|
||||
use crate::suppression::{SuppressionTarget, suppressions};
|
||||
use ruff_db::diagnostic::LintName;
|
||||
use ruff_db::display::FormatterJoinExtension;
|
||||
use ruff_db::files::File;
|
||||
use ruff_db::parsed::parsed_module;
|
||||
use ruff_db::source::source_text;
|
||||
use ruff_diagnostics::{Edit, Fix};
|
||||
use ruff_python_ast::token::TokenKind;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
use smallvec::SmallVec;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fmt::Formatter;
|
||||
|
||||
use crate::Db;
|
||||
use crate::lint::LintId;
|
||||
use crate::suppression::{SuppressionTarget, suppressions};
|
||||
|
||||
pub fn suppress_all<I>(db: &dyn Db, file: File, ids_with_range: I) -> Vec<Fix>
|
||||
where
|
||||
I: IntoIterator<Item = (LintName, TextRange)>,
|
||||
{
|
||||
let grouped = group_by_suppression_range(db, file, ids_with_range);
|
||||
create_all_fixes(db, file, grouped)
|
||||
/// Creates fixes to suppress all violations in `ids_with_range`.
|
||||
///
|
||||
/// This is different from calling `suppress_single` for every item in `ids_with_range`
|
||||
/// in that errors on the same line are grouped together and ty will only insert a single
|
||||
/// suppression with possibly multiple codes instead of adding multiple suppression comments.
|
||||
pub fn suppress_all(db: &dyn Db, file: File, ids_with_range: &[(LintName, TextRange)]) -> Vec<Fix> {
|
||||
group_by_line(db, file, ids_with_range)
|
||||
.into_iter()
|
||||
.map(|(range, lints)| {
|
||||
let codes: SmallVec<[LintName; 2]> = lints.into_iter().collect();
|
||||
create_suppression_fix(db, file, &codes, range)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Creates a fix to suppress a single lint.
|
||||
pub fn suppress_single(db: &dyn Db, file: File, id: LintId, range: TextRange) -> Fix {
|
||||
let suppression_range = suppression_range(db, file, range);
|
||||
create_suppression_fix(db, file, id.name(), suppression_range)
|
||||
create_suppression_fix(db, file, &[id.name()], suppression_range)
|
||||
}
|
||||
|
||||
fn create_all_fixes(
|
||||
/// Computes the suppression range for every provided violation to suppress
|
||||
/// and groups the lints by that range.
|
||||
fn group_by_line(
|
||||
db: &dyn Db,
|
||||
file: File,
|
||||
grouped: BTreeMap<SuppressionRange, BTreeSet<LintName>>,
|
||||
) -> Vec<Fix> {
|
||||
let mut fixes = Vec::new();
|
||||
|
||||
for (range, lints) in grouped {
|
||||
for lint in lints.into_iter().rev() {
|
||||
let fix = create_suppression_fix(db, file, lint, range);
|
||||
fixes.push(fix);
|
||||
}
|
||||
}
|
||||
|
||||
fixes
|
||||
}
|
||||
|
||||
fn group_by_suppression_range<I>(
|
||||
db: &dyn Db,
|
||||
file: File,
|
||||
ids_with_range: I,
|
||||
) -> BTreeMap<SuppressionRange, BTreeSet<LintName>>
|
||||
where
|
||||
I: IntoIterator<Item = (LintName, TextRange)>,
|
||||
{
|
||||
ids_with_range: &[(LintName, TextRange)],
|
||||
) -> BTreeMap<SuppressionRange, BTreeSet<LintName>> {
|
||||
let mut map: BTreeMap<SuppressionRange, BTreeSet<LintName>> = BTreeMap::new();
|
||||
for (id, range) in ids_with_range {
|
||||
for &(id, range) in ids_with_range {
|
||||
let full_range = suppression_range(db, file, range);
|
||||
map.entry(full_range).or_default().insert(id);
|
||||
}
|
||||
|
|
@ -124,11 +114,11 @@ fn suppression_range(db: &dyn Db, file: File, range: TextRange) -> SuppressionRa
|
|||
struct SuppressionRange(TextRange);
|
||||
|
||||
impl SuppressionRange {
|
||||
fn text_range(&self) -> TextRange {
|
||||
fn text_range(self) -> TextRange {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn line_end(&self) -> TextSize {
|
||||
fn line_end(self) -> TextSize {
|
||||
self.0.end()
|
||||
}
|
||||
}
|
||||
|
|
@ -145,14 +135,14 @@ impl Ord for SuppressionRange {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a fix for adding a suppression comment to suppress `lint` for `range`.
|
||||
/// Creates a fix for adding a suppression comment to suppress `codes` for `range`.
|
||||
///
|
||||
/// The fix prefers adding the code to an existing `ty: ignore[]` comment over
|
||||
/// adding a new suppression comment.
|
||||
fn create_suppression_fix(
|
||||
db: &dyn Db,
|
||||
file: File,
|
||||
name: LintName,
|
||||
codes: &[LintName],
|
||||
suppression_range: SuppressionRange,
|
||||
) -> Fix {
|
||||
let suppressions = suppressions(db, file);
|
||||
|
|
@ -175,9 +165,9 @@ fn create_suppression_fix(
|
|||
let up_to_last_code = before_closing_paren.trim_end();
|
||||
|
||||
let insertion = if up_to_last_code.ends_with(',') {
|
||||
format!(" {name}")
|
||||
format!(" {codes}", codes = Codes(codes))
|
||||
} else {
|
||||
format!(", {name}")
|
||||
format!(", {codes}", codes = Codes(codes))
|
||||
};
|
||||
|
||||
let relative_offset_from_end = comment_text.text_len() - up_to_last_code.text_len();
|
||||
|
|
@ -197,7 +187,7 @@ fn create_suppression_fix(
|
|||
let up_to_first_content = up_to_line_end.trim_end();
|
||||
let trailing_whitespace_len = up_to_line_end.text_len() - up_to_first_content.text_len();
|
||||
|
||||
let insertion = format!(" # ty:ignore[{name}]");
|
||||
let insertion = format!(" # ty:ignore[{codes}]", codes = Codes(codes));
|
||||
|
||||
Fix::safe_edit(if trailing_whitespace_len == TextSize::ZERO {
|
||||
Edit::insertion(insertion, line_end)
|
||||
|
|
@ -207,3 +197,11 @@ fn create_suppression_fix(
|
|||
Edit::replacement(insertion, line_end - trailing_whitespace_len, line_end)
|
||||
})
|
||||
}
|
||||
|
||||
struct Codes<'a>(&'a [LintName]);
|
||||
|
||||
impl std::fmt::Display for Codes<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
f.join(", ").entries(self.0).finish()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue