mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00
Replace row/column based Location
with byte-offsets. (#3931)
This commit is contained in:
parent
ee91598835
commit
cab65b25da
418 changed files with 6203 additions and 7040 deletions
|
@ -8,10 +8,12 @@ mod junit;
|
|||
mod pylint;
|
||||
mod text;
|
||||
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::Write;
|
||||
use std::ops::Deref;
|
||||
|
||||
pub use azure::AzureEmitter;
|
||||
pub use github::GithubEmitter;
|
||||
|
@ -20,49 +22,64 @@ pub use grouped::GroupedEmitter;
|
|||
pub use json::JsonEmitter;
|
||||
pub use junit::JunitEmitter;
|
||||
pub use pylint::PylintEmitter;
|
||||
pub use rustpython_parser::ast::Location;
|
||||
pub use text::TextEmitter;
|
||||
|
||||
use crate::jupyter::JupyterIndex;
|
||||
use crate::registry::AsRule;
|
||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Fix};
|
||||
use ruff_python_ast::source_code::SourceFile;
|
||||
use ruff_python_ast::source_code::{SourceFile, SourceLocation};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Message {
|
||||
pub kind: DiagnosticKind,
|
||||
pub location: Location,
|
||||
pub end_location: Location,
|
||||
pub range: TextRange,
|
||||
pub fix: Fix,
|
||||
pub file: SourceFile,
|
||||
pub noqa_row: usize,
|
||||
pub noqa_offset: TextSize,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn from_diagnostic(diagnostic: Diagnostic, file: SourceFile, noqa_row: usize) -> Self {
|
||||
pub fn from_diagnostic(
|
||||
diagnostic: Diagnostic,
|
||||
file: SourceFile,
|
||||
noqa_offset: TextSize,
|
||||
) -> Self {
|
||||
Self {
|
||||
range: diagnostic.range(),
|
||||
kind: diagnostic.kind,
|
||||
location: Location::new(diagnostic.location.row(), diagnostic.location.column() + 1),
|
||||
end_location: Location::new(
|
||||
diagnostic.end_location.row(),
|
||||
diagnostic.end_location.column() + 1,
|
||||
),
|
||||
fix: diagnostic.fix,
|
||||
file,
|
||||
noqa_row,
|
||||
noqa_offset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filename(&self) -> &str {
|
||||
self.file.name()
|
||||
}
|
||||
|
||||
pub fn compute_start_location(&self) -> SourceLocation {
|
||||
self.file.to_source_code().source_location(self.start())
|
||||
}
|
||||
|
||||
pub fn compute_end_location(&self) -> SourceLocation {
|
||||
self.file.to_source_code().source_location(self.end())
|
||||
}
|
||||
|
||||
pub const fn start(&self) -> TextSize {
|
||||
self.range.start()
|
||||
}
|
||||
|
||||
pub const fn end(&self) -> TextSize {
|
||||
self.range.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Message {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
(self.filename(), self.location.row(), self.location.column()).cmp(&(
|
||||
(self.filename(), self.start(), self.kind.rule()).cmp(&(
|
||||
other.filename(),
|
||||
other.location.row(),
|
||||
other.location.column(),
|
||||
other.start(),
|
||||
other.kind.rule(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -73,13 +90,28 @@ impl PartialOrd for Message {
|
|||
}
|
||||
}
|
||||
|
||||
fn group_messages_by_filename(messages: &[Message]) -> BTreeMap<&str, Vec<&Message>> {
|
||||
struct MessageWithLocation<'a> {
|
||||
message: &'a Message,
|
||||
start_location: SourceLocation,
|
||||
}
|
||||
|
||||
impl Deref for MessageWithLocation<'_> {
|
||||
type Target = Message;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.message
|
||||
}
|
||||
}
|
||||
|
||||
fn group_messages_by_filename(messages: &[Message]) -> BTreeMap<&str, Vec<MessageWithLocation>> {
|
||||
let mut grouped_messages = BTreeMap::default();
|
||||
for message in messages {
|
||||
grouped_messages
|
||||
.entry(message.filename())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(message);
|
||||
.push(MessageWithLocation {
|
||||
message,
|
||||
start_location: message.compute_start_location(),
|
||||
});
|
||||
}
|
||||
grouped_messages
|
||||
}
|
||||
|
@ -120,11 +152,11 @@ impl<'a> EmitterContext<'a> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::message::{Emitter, EmitterContext, Location, Message};
|
||||
use crate::message::{Emitter, EmitterContext, Message};
|
||||
use crate::rules::pyflakes::rules::{UndefinedName, UnusedImport, UnusedVariable};
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||
use ruff_python_ast::source_code::SourceFileBuilder;
|
||||
use ruff_python_ast::types::Range;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
pub(super) fn create_messages() -> Vec<Message> {
|
||||
|
@ -148,20 +180,20 @@ def fibonacci(n):
|
|||
context: None,
|
||||
multiple: false,
|
||||
},
|
||||
Range::new(Location::new(1, 7), Location::new(1, 9)),
|
||||
TextRange::new(TextSize::from(7), TextSize::from(9)),
|
||||
);
|
||||
|
||||
let fib_source = SourceFileBuilder::new("fib.py").source_text(fib).finish();
|
||||
let fib_source = SourceFileBuilder::new("fib.py", fib).finish();
|
||||
|
||||
let unused_variable = Diagnostic::new(
|
||||
UnusedVariable {
|
||||
name: "x".to_string(),
|
||||
},
|
||||
Range::new(Location::new(6, 4), Location::new(6, 5)),
|
||||
TextRange::new(TextSize::from(94), TextSize::from(95)),
|
||||
)
|
||||
.with_fix(Fix::new(vec![Edit::deletion(
|
||||
Location::new(6, 4),
|
||||
Location::new(6, 9),
|
||||
TextSize::from(94),
|
||||
TextSize::from(99),
|
||||
)]));
|
||||
|
||||
let file_2 = r#"if a == 1: pass"#;
|
||||
|
@ -170,17 +202,18 @@ def fibonacci(n):
|
|||
UndefinedName {
|
||||
name: "a".to_string(),
|
||||
},
|
||||
Range::new(Location::new(1, 3), Location::new(1, 4)),
|
||||
TextRange::new(TextSize::from(3), TextSize::from(4)),
|
||||
);
|
||||
|
||||
let file_2_source = SourceFileBuilder::new("undef.py")
|
||||
.source_text(file_2)
|
||||
.finish();
|
||||
let file_2_source = SourceFileBuilder::new("undef.py", file_2).finish();
|
||||
|
||||
let unused_import_start = unused_import.start();
|
||||
let unused_variable_start = unused_variable.start();
|
||||
let undefined_name_start = undefined_name.start();
|
||||
vec![
|
||||
Message::from_diagnostic(unused_import, fib_source.clone(), 1),
|
||||
Message::from_diagnostic(unused_variable, fib_source, 1),
|
||||
Message::from_diagnostic(undefined_name, file_2_source, 1),
|
||||
Message::from_diagnostic(unused_import, fib_source.clone(), unused_import_start),
|
||||
Message::from_diagnostic(unused_variable, fib_source, unused_variable_start),
|
||||
Message::from_diagnostic(undefined_name, file_2_source, undefined_name_start),
|
||||
]
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue