Replace row/column based Location with byte-offsets. (#3931)

This commit is contained in:
Micha Reiser 2023-04-26 20:11:02 +02:00 committed by GitHub
parent ee91598835
commit cab65b25da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
418 changed files with 6203 additions and 7040 deletions

View file

@ -26,6 +26,7 @@ ruff = { path = "../ruff", features = ["clap"] }
ruff_cache = { path = "../ruff_cache" }
ruff_diagnostics = { path = "../ruff_diagnostics" }
ruff_python_ast = { path = "../ruff_python_ast" }
ruff_text_size = { workspace = true }
annotate-snippets = { version = "0.9.1", features = ["color"] }
anyhow = { workspace = true }

View file

@ -8,12 +8,13 @@ use anyhow::Result;
use filetime::FileTime;
use log::error;
use path_absolutize::Absolutize;
use ruff::message::{Location, Message};
use ruff::message::Message;
use ruff::settings::{flags, AllSettings, Settings};
use ruff_cache::{CacheKey, CacheKeyHasher};
use ruff_diagnostics::{DiagnosticKind, Fix};
use ruff_python_ast::imports::ImportMap;
use ruff_python_ast::source_code::SourceFileBuilder;
use ruff_text_size::{TextRange, TextSize};
use serde::ser::{SerializeSeq, SerializeStruct};
use serde::{Deserialize, Serialize, Serializer};
#[cfg(unix)]
@ -22,8 +23,8 @@ use std::os::unix::fs::PermissionsExt;
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
/// Vec storing all source files. The tuple is (filename, source code).
type Files<'a> = Vec<(&'a str, Option<&'a str>)>;
type FilesBuf = Vec<(String, Option<String>)>;
type Files<'a> = Vec<(&'a str, &'a str)>;
type FilesBuf = Vec<(String, String)>;
struct CheckResultRef<'a> {
imports: &'a ImportMap,
@ -100,19 +101,17 @@ impl Serialize for SerializeMessage<'_> {
{
let Message {
kind,
location,
end_location,
range,
fix,
// Serialized manually for all files
file: _,
noqa_row,
noqa_offset: noqa_row,
} = self.message;
let mut s = serializer.serialize_struct("Message", 6)?;
let mut s = serializer.serialize_struct("Message", 5)?;
s.serialize_field("kind", &kind)?;
s.serialize_field("location", &location)?;
s.serialize_field("end_location", &end_location)?;
s.serialize_field("range", &range)?;
s.serialize_field("fix", &fix)?;
s.serialize_field("file_id", &self.file_id)?;
s.serialize_field("noqa_row", &noqa_row)?;
@ -124,11 +123,10 @@ impl Serialize for SerializeMessage<'_> {
#[derive(Deserialize)]
struct MessageHeader {
kind: DiagnosticKind,
location: Location,
end_location: Location,
range: TextRange,
fix: Fix,
file_id: usize,
noqa_row: usize,
noqa_row: TextSize,
}
#[derive(Deserialize)]
@ -223,15 +221,7 @@ pub fn get(
let source_files: Vec<_> = sources
.into_iter()
.map(|(filename, text)| {
let mut builder = SourceFileBuilder::from_string(filename);
if let Some(text) = text {
builder.set_source_text_string(text);
}
builder.finish()
})
.map(|(filename, text)| SourceFileBuilder::new(filename, text).finish())
.collect();
for header in headers {
@ -242,11 +232,10 @@ pub fn get(
messages.push(Message {
kind: header.kind,
location: header.location,
end_location: header.end_location,
range: header.range,
fix: header.fix,
file: source_file.clone(),
noqa_row: header.noqa_row,
noqa_offset: header.noqa_row,
});
}

View file

@ -8,12 +8,13 @@ use ignore::Error;
use log::{debug, error, warn};
#[cfg(not(target_family = "wasm"))]
use rayon::prelude::*;
use ruff_text_size::{TextRange, TextSize};
use ruff::message::{Location, Message};
use ruff::message::Message;
use ruff::registry::Rule;
use ruff::resolver::PyprojectDiscovery;
use ruff::settings::{flags, AllSettings};
use ruff::{fs, packaging, resolver, warn_user_once, IOError, Range};
use ruff::{fs, packaging, resolver, warn_user_once, IOError};
use ruff_diagnostics::Diagnostic;
use ruff_python_ast::imports::ImportMap;
use ruff_python_ast::source_code::SourceFileBuilder;
@ -117,16 +118,14 @@ pub fn run(
);
let settings = resolver.resolve(path, pyproject_strategy);
if settings.rules.enabled(Rule::IOError) {
let file = SourceFileBuilder::new(&path.to_string_lossy()).finish();
let file =
SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish();
Diagnostics::new(
vec![Message::from_diagnostic(
Diagnostic::new(
IOError { message },
Range::new(Location::default(), Location::default()),
),
Diagnostic::new(IOError { message }, TextRange::default()),
file,
1,
TextSize::default(),
)],
ImportMap::default(),
)

View file

@ -9,16 +9,18 @@ use std::path::Path;
use anyhow::{anyhow, Result};
use colored::Colorize;
use log::{debug, error};
use ruff_text_size::TextSize;
use rustc_hash::FxHashMap;
use similar::TextDiff;
use ruff::fs;
use ruff::jupyter::{is_jupyter_notebook, JupyterIndex, JupyterNotebook};
use ruff::linter::{lint_fix, lint_only, FixTable, FixerResult, LinterResult};
use ruff::logging::DisplayParseError;
use ruff::message::Message;
use ruff::settings::{flags, AllSettings, Settings};
use ruff_python_ast::imports::ImportMap;
use ruff_python_ast::source_code::SourceFileBuilder;
use ruff_python_ast::source_code::{LineIndex, SourceCode, SourceFileBuilder};
use crate::cache;
@ -86,8 +88,8 @@ fn load_jupyter_notebook(path: &Path) -> Result<(String, JupyterIndex), Box<Diag
return Err(Box::new(Diagnostics {
messages: vec![Message::from_diagnostic(
*diagnostic,
SourceFileBuilder::new(&path.to_string_lossy()).finish(),
1,
SourceFileBuilder::new(path.to_string_lossy().as_ref(), "").finish(),
TextSize::default(),
)],
..Diagnostics::default()
}));
@ -197,12 +199,12 @@ pub fn lint_path(
let imports = imports.unwrap_or_default();
if let Some(err) = parse_error {
// Notify the user of any parse errors.
error!(
"{}{}{} {err}",
"Failed to parse ".bold(),
fs::relativize_path(path).bold(),
":".bold()
"{}",
DisplayParseError::new(
err,
SourceCode::new(&contents, &LineIndex::from_source_text(&contents))
)
);
// Purge the cache.

View file

@ -113,6 +113,8 @@ fn check(args: CheckArgs, log_level: LogLevel) -> Result<ExitStatus> {
return Ok(ExitStatus::Success);
}
let top_level_settings = pyproject_strategy.top_level_settings();
// Extract options that are included in `Settings`, but only apply at the top
// level.
let CliSettings {
@ -122,7 +124,7 @@ fn check(args: CheckArgs, log_level: LogLevel) -> Result<ExitStatus> {
show_fixes,
update_check,
..
} = pyproject_strategy.top_level_settings().cli.clone();
} = top_level_settings.cli.clone();
// Autofix rules are as follows:
// - If `--fix` or `--fix-only` is set, always apply fixes to the filesystem (or
@ -153,6 +155,10 @@ fn check(args: CheckArgs, log_level: LogLevel) -> Result<ExitStatus> {
printer_flags |= PrinterFlags::SHOW_FIXES;
}
if top_level_settings.lib.show_source {
printer_flags |= PrinterFlags::SHOW_SOURCE;
}
#[cfg(debug_assertions)]
if cache {
// `--no-cache` doesn't respect code changes, and so is often confusing during

View file

@ -30,6 +30,7 @@ bitflags! {
pub(crate) struct Flags: u8 {
const SHOW_VIOLATIONS = 0b0000_0001;
const SHOW_FIXES = 0b0000_0010;
const SHOW_SOURCE = 0b000_0100;
}
}
@ -180,6 +181,7 @@ impl Printer {
SerializationFormat::Text => {
TextEmitter::default()
.with_show_fix_status(show_fix_status(self.autofix_level))
.with_show_source(self.flags.contains(Flags::SHOW_SOURCE))
.emit(writer, &diagnostics.messages, &context)?;
if self.flags.contains(Flags::SHOW_FIXES) {
@ -194,6 +196,7 @@ impl Printer {
}
SerializationFormat::Grouped => {
GroupedEmitter::default()
.with_show_source(self.flags.contains(Flags::SHOW_SOURCE))
.with_show_fix_status(show_fix_status(self.autofix_level))
.emit(writer, &diagnostics.messages, &context)?;
@ -346,6 +349,7 @@ impl Printer {
let context = EmitterContext::new(&diagnostics.jupyter_index);
TextEmitter::default()
.with_show_fix_status(show_fix_status(self.autofix_level))
.with_show_source(self.flags.contains(Flags::SHOW_SOURCE))
.emit(&mut stdout, &diagnostics.messages, &context)?;
}
stdout.flush()?;