mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
Extract LineIndex
independent methods from Locator
(#13938)
Some checks are pending
CI / Fuzz the parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (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 / python package (push) Waiting to run
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz (push) Blocked by required conditions
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 / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Some checks are pending
CI / Fuzz the parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (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 / python package (push) Waiting to run
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz (push) Blocked by required conditions
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 / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
This commit is contained in:
parent
f8eb547fb4
commit
9f3a38d408
171 changed files with 1348 additions and 1284 deletions
|
@ -26,11 +26,11 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
|||
&& !checker
|
||||
.settings
|
||||
.dummy_variable_rgx
|
||||
.is_match(binding.name(checker.locator))
|
||||
.is_match(binding.name(checker.source()))
|
||||
{
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
pyflakes::rules::UnusedVariable {
|
||||
name: binding.name(checker.locator).to_string(),
|
||||
name: binding.name(checker.source()).to_string(),
|
||||
},
|
||||
binding.range(),
|
||||
);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use ruff_python_ast::str::raw_contents_range;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use ruff_python_semantic::all::DunderAllName;
|
||||
use ruff_python_semantic::{
|
||||
BindingKind, ContextualizedDefinition, Definition, Export, Member, MemberKind,
|
||||
};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::codes::Rule;
|
||||
|
|
|
@ -17,7 +17,7 @@ pub(crate) fn unresolved_references(checker: &mut Checker) {
|
|||
if checker.enabled(Rule::UndefinedLocalWithImportStarUsage) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedLocalWithImportStarUsage {
|
||||
name: reference.name(checker.locator).to_string(),
|
||||
name: reference.name(checker.source()).to_string(),
|
||||
},
|
||||
reference.range(),
|
||||
));
|
||||
|
@ -31,12 +31,12 @@ pub(crate) fn unresolved_references(checker: &mut Checker) {
|
|||
|
||||
// Allow __path__.
|
||||
if checker.path.ends_with("__init__.py") {
|
||||
if reference.name(checker.locator) == "__path__" {
|
||||
if reference.name(checker.source()) == "__path__" {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let symbol_name = reference.name(checker.locator);
|
||||
let symbol_name = reference.name(checker.source());
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedName {
|
||||
|
|
|
@ -59,7 +59,7 @@ use ruff_python_semantic::{
|
|||
};
|
||||
use ruff_python_stdlib::builtins::{python_builtins, MAGIC_GLOBALS};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::{Locator, OneIndexed, SourceRow};
|
||||
use ruff_source_file::{OneIndexed, SourceRow};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::annotation::AnnotationContext;
|
||||
|
@ -69,7 +69,7 @@ use crate::noqa::NoqaMapping;
|
|||
use crate::registry::Rule;
|
||||
use crate::rules::{flake8_pyi, flake8_type_checking, pyflakes, pyupgrade};
|
||||
use crate::settings::{flags, LinterSettings};
|
||||
use crate::{docstrings, noqa};
|
||||
use crate::{docstrings, noqa, Locator};
|
||||
|
||||
mod analyze;
|
||||
mod annotation;
|
||||
|
@ -352,6 +352,10 @@ impl<'a> Checker<'a> {
|
|||
self.locator
|
||||
}
|
||||
|
||||
pub(crate) const fn source(&self) -> &'a str {
|
||||
self.locator.contents()
|
||||
}
|
||||
|
||||
/// The [`Stylist`] for the current file, which detects the current line ending, quote, and
|
||||
/// indentation style.
|
||||
pub(crate) const fn stylist(&self) -> &'a Stylist<'a> {
|
||||
|
|
|
@ -2,13 +2,13 @@ use std::path::Path;
|
|||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::flake8_builtins::rules::builtin_module_shadowing;
|
||||
use crate::rules::flake8_no_pep420::rules::implicit_namespace_package;
|
||||
use crate::rules::pep8_naming::rules::invalid_module_name;
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
pub(crate) fn check_file_path(
|
||||
path: &Path,
|
||||
|
|
|
@ -8,13 +8,13 @@ use ruff_python_ast::{ModModule, PySourceType};
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::Parsed;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::directives::IsortDirectives;
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::isort;
|
||||
use crate::rules::isort::block::{Block, BlockBuilder};
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn check_imports(
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::line_width::IndentWidth;
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::line_width::IndentWidth;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
use crate::rules::pycodestyle::rules::logical_lines::{
|
||||
extraneous_whitespace, indentation, missing_whitespace, missing_whitespace_after_keyword,
|
||||
|
@ -14,6 +14,7 @@ use crate::rules::pycodestyle::rules::logical_lines::{
|
|||
whitespace_before_comment, whitespace_before_parameters, LogicalLines, TokenFlags,
|
||||
};
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
/// Return the amount of indentation, expanding tabs to the next multiple of the settings' tab size.
|
||||
pub(crate) fn expand_indent(line: &str, indent_width: IndentWidth) -> usize {
|
||||
|
|
|
@ -7,7 +7,6 @@ use rustc_hash::FxHashSet;
|
|||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::fix::edits::delete_comment;
|
||||
|
@ -20,6 +19,7 @@ use crate::rules::pygrep_hooks;
|
|||
use crate::rules::ruff;
|
||||
use crate::rules::ruff::rules::{UnusedCodes, UnusedNOQA};
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn check_noqa(
|
||||
|
@ -33,13 +33,8 @@ pub(crate) fn check_noqa(
|
|||
settings: &LinterSettings,
|
||||
) -> Vec<usize> {
|
||||
// Identify any codes that are globally exempted (within the current file).
|
||||
let file_noqa_directives = FileNoqaDirectives::extract(
|
||||
locator.contents(),
|
||||
comment_ranges,
|
||||
&settings.external,
|
||||
path,
|
||||
locator,
|
||||
);
|
||||
let file_noqa_directives =
|
||||
FileNoqaDirectives::extract(locator, comment_ranges, &settings.external, path);
|
||||
let exemption = FileExemption::from(&file_noqa_directives);
|
||||
|
||||
// Extract all `noqa` directives.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::{Locator, UniversalNewlines};
|
||||
use ruff_source_file::UniversalNewlines;
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
use crate::registry::Rule;
|
||||
|
@ -14,6 +14,7 @@ use crate::rules::pycodestyle::rules::{
|
|||
};
|
||||
use crate::rules::pylint;
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
pub(crate) fn check_physical_lines(
|
||||
locator: &Locator,
|
||||
|
@ -92,12 +93,12 @@ mod tests {
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::parse_module;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::line_width::LineLength;
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::pycodestyle;
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
use super::check_physical_lines;
|
||||
|
||||
|
@ -106,8 +107,8 @@ mod tests {
|
|||
let line = "'\u{4e9c}' * 2"; // 7 in UTF-32, 9 in UTF-8.
|
||||
let locator = Locator::new(line);
|
||||
let parsed = parse_module(line).unwrap();
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), locator.contents());
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
let check_with_max_line_length = |line_length: LineLength| {
|
||||
check_physical_lines(
|
||||
|
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
use std::path::Path;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_codegen::Stylist;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::Tokens;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::directives::TodoComment;
|
||||
|
@ -20,6 +18,7 @@ use crate::rules::{
|
|||
flake8_pyi, flake8_todos, pycodestyle, pygrep_hooks, pylint, pyupgrade, ruff,
|
||||
};
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn check_tokens(
|
||||
|
|
|
@ -4,15 +4,16 @@ use std::iter::Peekable;
|
|||
use std::str::FromStr;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::noqa::NoqaMapping;
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -360,24 +361,23 @@ impl TodoDirectiveKind {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::parse_module;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::directives::{
|
||||
extract_isort_directives, extract_noqa_line_for, TodoDirective, TodoDirectiveKind,
|
||||
};
|
||||
use crate::noqa::NoqaMapping;
|
||||
use crate::Locator;
|
||||
|
||||
use super::IsortDirectives;
|
||||
|
||||
fn noqa_mappings(contents: &str) -> NoqaMapping {
|
||||
let parsed = parse_module(contents).unwrap();
|
||||
let locator = Locator::new(contents);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), &locator);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
extract_noqa_line_for(parsed.tokens(), &locator, &indexer)
|
||||
}
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
use std::iter::FusedIterator;
|
||||
use std::slice::Iter;
|
||||
|
||||
use ruff_python_ast::statement_visitor::{walk_stmt, StatementVisitor};
|
||||
use ruff_python_ast::{self as ast, Stmt, Suite};
|
||||
use ruff_python_parser::{Token, TokenKind, Tokens};
|
||||
use ruff_source_file::UniversalNewlineIterator;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_python_ast::statement_visitor::{walk_stmt, StatementVisitor};
|
||||
use ruff_source_file::{Locator, UniversalNewlineIterator};
|
||||
use crate::Locator;
|
||||
|
||||
/// Extract doc lines (standalone comments) from a token sequence.
|
||||
pub(crate) fn doc_lines_from_tokens(tokens: &Tokens) -> DocLines {
|
||||
|
|
|
@ -13,9 +13,9 @@ use unicode_normalization::UnicodeNormalization;
|
|||
use ruff_python_ast::name::UnqualifiedName;
|
||||
use ruff_python_ast::Stmt;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::cst::matchers::match_statement;
|
||||
use crate::Locator;
|
||||
|
||||
/// Glue code to make libcst codegen work with ruff's Stylist
|
||||
pub(crate) trait CodegenStylist<'a>: Codegen<'a> {
|
||||
|
|
|
@ -13,13 +13,14 @@ use ruff_python_trivia::{
|
|||
has_leading_content, is_python_whitespace, CommentRanges, PythonWhitespace, SimpleTokenKind,
|
||||
SimpleTokenizer,
|
||||
};
|
||||
use ruff_source_file::{Locator, NewlineWithTrailingNewline, UniversalNewlines};
|
||||
use ruff_source_file::{LineRanges, NewlineWithTrailingNewline, UniversalNewlines};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::cst::matchers::{match_function_def, match_indented_block, match_statement};
|
||||
use crate::fix::codemods;
|
||||
use crate::fix::codemods::CodegenStylist;
|
||||
use crate::line_width::{IndentWidth, LineLength, LineWidthBuilder};
|
||||
use crate::Locator;
|
||||
|
||||
/// Return the `Fix` to use when deleting a `Stmt`.
|
||||
///
|
||||
|
@ -48,9 +49,11 @@ pub(crate) fn delete_stmt(
|
|||
if let Some(semicolon) = trailing_semicolon(stmt.end(), locator) {
|
||||
let next = next_stmt_break(semicolon, locator);
|
||||
Edit::deletion(stmt.start(), next)
|
||||
} else if has_leading_content(stmt.start(), locator) {
|
||||
} else if has_leading_content(stmt.start(), locator.contents()) {
|
||||
Edit::range_deletion(stmt.range())
|
||||
} else if let Some(start) = indexer.preceded_by_continuations(stmt.start(), locator) {
|
||||
} else if let Some(start) =
|
||||
indexer.preceded_by_continuations(stmt.start(), locator.contents())
|
||||
{
|
||||
Edit::deletion(start, stmt.end())
|
||||
} else {
|
||||
let range = locator.full_lines_range(stmt.range());
|
||||
|
@ -595,13 +598,13 @@ mod tests {
|
|||
use ruff_python_ast::Stmt;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_parser::{parse_expression, parse_module};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::fix::apply_fixes;
|
||||
use crate::fix::edits::{
|
||||
add_to_dunder_all, make_redundant_alias, next_stmt_break, trailing_semicolon,
|
||||
};
|
||||
use crate::Locator;
|
||||
|
||||
/// Parse the given source using [`Mode::Module`] and return the first statement.
|
||||
fn parse_first_stmt(source: &str) -> Result<Stmt> {
|
||||
|
@ -726,7 +729,7 @@ x = 1 \
|
|||
let locator = Locator::new(raw);
|
||||
let edits = {
|
||||
let parsed = parse_expression(raw)?;
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
add_to_dunder_all(names.iter().copied(), parsed.expr(), &stylist)
|
||||
};
|
||||
let diag = {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
use itertools::Itertools;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, IsolationLevel, SourceMap};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::linter::FixTable;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
use crate::settings::types::UnsafeFixes;
|
||||
use crate::Locator;
|
||||
|
||||
pub(crate) mod codemods;
|
||||
pub(crate) mod edits;
|
||||
|
@ -158,13 +158,12 @@ fn cmp_fix(rule1: Rule, rule2: Rule, fix1: &Fix, fix2: &Fix) -> std::cmp::Orderi
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, SourceMarker};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::fix::{apply_fixes, FixResult};
|
||||
use crate::rules::pycodestyle::rules::MissingNewlineAtEndOfFile;
|
||||
use crate::Locator;
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn create_diagnostics(edit: impl IntoIterator<Item = Edit>) -> Vec<Diagnostic> {
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
//! Insert statements into Python code.
|
||||
use std::ops::Add;
|
||||
|
||||
use ruff_python_ast::Stmt;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_diagnostics::Edit;
|
||||
use ruff_python_ast::helpers::is_docstring_stmt;
|
||||
use ruff_python_ast::Stmt;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_python_trivia::{textwrap::indent, PythonWhitespace};
|
||||
use ruff_source_file::{Locator, UniversalNewlineIterator};
|
||||
use ruff_source_file::{LineRanges, UniversalNewlineIterator};
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub(super) enum Placement<'a> {
|
||||
|
@ -64,7 +65,7 @@ impl<'a> Insertion<'a> {
|
|||
// Otherwise, advance to the next row.
|
||||
locator.full_line_end(location)
|
||||
} else {
|
||||
locator.contents_start()
|
||||
locator.bom_start_offset()
|
||||
};
|
||||
|
||||
// Skip over commented lines, with whitespace separation.
|
||||
|
@ -319,9 +320,11 @@ mod tests {
|
|||
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_parser::parse_module;
|
||||
use ruff_source_file::{LineEnding, Locator};
|
||||
use ruff_source_file::LineEnding;
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
use super::Insertion;
|
||||
|
||||
#[test]
|
||||
|
@ -329,7 +332,7 @@ mod tests {
|
|||
fn insert(contents: &str) -> Result<Insertion> {
|
||||
let parsed = parse_module(contents)?;
|
||||
let locator = Locator::new(contents);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
Ok(Insertion::start_of_file(parsed.suite(), &locator, &stylist))
|
||||
}
|
||||
|
||||
|
@ -440,7 +443,7 @@ x = 1
|
|||
fn insert(contents: &str, offset: TextSize) -> Insertion {
|
||||
let parsed = parse_module(contents).unwrap();
|
||||
let locator = Locator::new(contents);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
Insertion::start_of_block(offset, &locator, &stylist, parsed.tokens())
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ use ruff_python_semantic::{
|
|||
ImportedName, MemberNameImport, ModuleNameImport, NameImport, SemanticModel,
|
||||
};
|
||||
use ruff_python_trivia::textwrap::indent;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::cst::matchers::{match_aliases, match_import_from, match_statement};
|
||||
use crate::fix;
|
||||
use crate::fix::codemods::CodegenStylist;
|
||||
use crate::importer::insertion::Insertion;
|
||||
use crate::Locator;
|
||||
|
||||
mod insertion;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
//!
|
||||
//! [Ruff]: https://github.com/astral-sh/ruff
|
||||
|
||||
pub use locator::Locator;
|
||||
pub use noqa::generate_noqa_edits;
|
||||
#[cfg(feature = "clap")]
|
||||
pub use registry::clap_completion::RuleParser;
|
||||
|
@ -27,6 +28,7 @@ pub mod fs;
|
|||
mod importer;
|
||||
pub mod line_width;
|
||||
pub mod linter;
|
||||
mod locator;
|
||||
pub mod logging;
|
||||
pub mod message;
|
||||
mod noqa;
|
||||
|
|
|
@ -14,7 +14,7 @@ use ruff_python_ast::{ModModule, PySourceType};
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::{ParseError, Parsed};
|
||||
use ruff_source_file::{Locator, SourceFileBuilder};
|
||||
use ruff_source_file::SourceFileBuilder;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::check_ast;
|
||||
|
@ -34,7 +34,7 @@ use crate::rules::ruff::rules::test_rules::{self, TestRule, TEST_RULES};
|
|||
use crate::settings::types::UnsafeFixes;
|
||||
use crate::settings::{flags, LinterSettings};
|
||||
use crate::source_kind::SourceKind;
|
||||
use crate::{directives, fs};
|
||||
use crate::{directives, fs, Locator};
|
||||
|
||||
pub struct LinterResult {
|
||||
/// A collection of diagnostic messages generated by the linter.
|
||||
|
@ -335,10 +335,10 @@ pub fn add_noqa_to_path(
|
|||
let locator = Locator::new(source_kind.source_code());
|
||||
|
||||
// Detect the current code style (lazily).
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
// Extra indices from the code.
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), &locator);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||
let directives = directives::extract_directives(
|
||||
|
@ -393,10 +393,10 @@ pub fn lint_only(
|
|||
let locator = Locator::new(source_kind.source_code());
|
||||
|
||||
// Detect the current code style (lazily).
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
// Extra indices from the code.
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), &locator);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||
let directives = directives::extract_directives(
|
||||
|
@ -495,10 +495,10 @@ pub fn lint_fix<'a>(
|
|||
let locator = Locator::new(transformed.source_code());
|
||||
|
||||
// Detect the current code style (lazily).
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
// Extra indices from the code.
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), &locator);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), locator.contents());
|
||||
|
||||
// Extract the `# noqa` and `# isort: skip` directives from the source.
|
||||
let directives = directives::extract_directives(
|
||||
|
|
224
crates/ruff_linter/src/locator.rs
Normal file
224
crates/ruff_linter/src/locator.rs
Normal file
|
@ -0,0 +1,224 @@
|
|||
//! Struct used to efficiently slice source code at (row, column) Locations.
|
||||
|
||||
use std::cell::OnceCell;
|
||||
|
||||
use ruff_source_file::{LineIndex, LineRanges, OneIndexed, SourceCode, SourceLocation};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Locator<'a> {
|
||||
contents: &'a str,
|
||||
index: OnceCell<LineIndex>,
|
||||
}
|
||||
|
||||
impl<'a> Locator<'a> {
|
||||
pub const fn new(contents: &'a str) -> Self {
|
||||
Self {
|
||||
contents,
|
||||
index: OnceCell::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_index(contents: &'a str, index: LineIndex) -> Self {
|
||||
Self {
|
||||
contents,
|
||||
index: OnceCell::from(index),
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(
|
||||
note = "This is expensive, avoid using outside of the diagnostic phase. Prefer the other `Locator` methods instead."
|
||||
)]
|
||||
pub fn compute_line_index(&self, offset: TextSize) -> OneIndexed {
|
||||
self.to_index().line_index(offset)
|
||||
}
|
||||
|
||||
#[deprecated(
|
||||
note = "This is expensive, avoid using outside of the diagnostic phase. Prefer the other `Locator` methods instead."
|
||||
)]
|
||||
pub fn compute_source_location(&self, offset: TextSize) -> SourceLocation {
|
||||
self.to_source_code().source_location(offset)
|
||||
}
|
||||
|
||||
pub fn to_index(&self) -> &LineIndex {
|
||||
self.index
|
||||
.get_or_init(|| LineIndex::from_source_text(self.contents))
|
||||
}
|
||||
|
||||
pub fn line_index(&self) -> Option<&LineIndex> {
|
||||
self.index.get()
|
||||
}
|
||||
|
||||
pub fn to_source_code(&self) -> SourceCode {
|
||||
SourceCode::new(self.contents, self.to_index())
|
||||
}
|
||||
|
||||
/// Take the source code up to the given [`TextSize`].
|
||||
#[inline]
|
||||
pub fn up_to(&self, offset: TextSize) -> &'a str {
|
||||
&self.contents[TextRange::up_to(offset)]
|
||||
}
|
||||
|
||||
/// Take the source code after the given [`TextSize`].
|
||||
#[inline]
|
||||
pub fn after(&self, offset: TextSize) -> &'a str {
|
||||
&self.contents[usize::from(offset)..]
|
||||
}
|
||||
|
||||
/// Finds the closest [`TextSize`] not exceeding the offset for which `is_char_boundary` is
|
||||
/// `true`.
|
||||
///
|
||||
/// Can be replaced with `str::floor_char_boundary` once it's stable.
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
/// # use ruff_linter::Locator;
|
||||
///
|
||||
/// let locator = Locator::new("Hello");
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// locator.floor_char_boundary(TextSize::from(0)),
|
||||
/// TextSize::from(0)
|
||||
/// );
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// locator.floor_char_boundary(TextSize::from(5)),
|
||||
/// TextSize::from(5)
|
||||
/// );
|
||||
///
|
||||
/// let locator = Locator::new("α");
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// locator.floor_char_boundary(TextSize::from(0)),
|
||||
/// TextSize::from(0)
|
||||
/// );
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// locator.floor_char_boundary(TextSize::from(1)),
|
||||
/// TextSize::from(0)
|
||||
/// );
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// locator.floor_char_boundary(TextSize::from(2)),
|
||||
/// TextSize::from(2)
|
||||
/// );
|
||||
/// ```
|
||||
pub fn floor_char_boundary(&self, offset: TextSize) -> TextSize {
|
||||
if offset >= self.text_len() {
|
||||
self.text_len()
|
||||
} else {
|
||||
// We know that the character boundary is within four bytes.
|
||||
(0u32..=3u32)
|
||||
.map(TextSize::from)
|
||||
.filter_map(|index| offset.checked_sub(index))
|
||||
.find(|offset| self.contents.is_char_boundary(offset.to_usize()))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Take the source code between the given [`TextRange`].
|
||||
#[inline]
|
||||
pub fn slice<T: Ranged>(&self, ranged: T) -> &'a str {
|
||||
&self.contents[ranged.range()]
|
||||
}
|
||||
|
||||
/// Return the underlying source code.
|
||||
pub const fn contents(&self) -> &'a str {
|
||||
self.contents
|
||||
}
|
||||
|
||||
/// Return the number of bytes in the source code.
|
||||
pub const fn len(&self) -> usize {
|
||||
self.contents.len()
|
||||
}
|
||||
|
||||
pub fn text_len(&self) -> TextSize {
|
||||
self.contents.text_len()
|
||||
}
|
||||
|
||||
/// Return `true` if the source code is empty.
|
||||
pub const fn is_empty(&self) -> bool {
|
||||
self.contents.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
// Override the `_str` methods from [`LineRanges`] to extend the lifetime to `'a`.
|
||||
impl<'a> Locator<'a> {
|
||||
/// Returns the text of the `offset`'s line.
|
||||
///
|
||||
/// See [`LineRanges::full_lines_str`].
|
||||
pub fn full_line_str(&self, offset: TextSize) -> &'a str {
|
||||
self.contents.full_line_str(offset)
|
||||
}
|
||||
|
||||
/// Returns the text of the `offset`'s line.
|
||||
///
|
||||
/// See [`LineRanges::line_str`].
|
||||
pub fn line_str(&self, offset: TextSize) -> &'a str {
|
||||
self.contents.line_str(offset)
|
||||
}
|
||||
|
||||
/// Returns the text of all lines that include `range`.
|
||||
///
|
||||
/// See [`LineRanges::lines_str`].
|
||||
pub fn lines_str(&self, range: TextRange) -> &'a str {
|
||||
self.contents.lines_str(range)
|
||||
}
|
||||
|
||||
/// Returns the text of all lines that include `range`.
|
||||
///
|
||||
/// See [`LineRanges::full_lines_str`].
|
||||
pub fn full_lines_str(&self, range: TextRange) -> &'a str {
|
||||
self.contents.full_lines_str(range)
|
||||
}
|
||||
}
|
||||
|
||||
// Allow calling [`LineRanges`] methods on [`Locator`] directly.
|
||||
impl LineRanges for Locator<'_> {
|
||||
#[inline]
|
||||
fn line_start(&self, offset: TextSize) -> TextSize {
|
||||
self.contents.line_start(offset)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bom_start_offset(&self) -> TextSize {
|
||||
self.contents.bom_start_offset()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn full_line_end(&self, offset: TextSize) -> TextSize {
|
||||
self.contents.full_line_end(offset)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn line_end(&self, offset: TextSize) -> TextSize {
|
||||
self.contents.line_end(offset)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn full_line_str(&self, offset: TextSize) -> &str {
|
||||
self.contents.full_line_str(offset)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn line_str(&self, offset: TextSize) -> &str {
|
||||
self.contents.line_str(offset)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn contains_line_break(&self, range: TextRange) -> bool {
|
||||
self.contents.contains_line_break(range)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn lines_str(&self, range: TextRange) -> &str {
|
||||
self.contents.lines_str(range)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn full_lines_str(&self, range: TextRange) -> &str {
|
||||
self.contents.full_lines_str(range)
|
||||
}
|
||||
}
|
|
@ -14,17 +14,17 @@ pub use json_lines::JsonLinesEmitter;
|
|||
pub use junit::JunitEmitter;
|
||||
pub use pylint::PylintEmitter;
|
||||
pub use rdjson::RdjsonEmitter;
|
||||
pub use sarif::SarifEmitter;
|
||||
pub use text::TextEmitter;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Fix};
|
||||
use ruff_notebook::NotebookIndex;
|
||||
use ruff_python_parser::ParseError;
|
||||
use ruff_source_file::{Locator, SourceFile, SourceLocation};
|
||||
use ruff_source_file::{SourceFile, SourceLocation};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
pub use sarif::SarifEmitter;
|
||||
pub use text::TextEmitter;
|
||||
|
||||
use crate::logging::DisplayParseErrorType;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
use crate::Locator;
|
||||
|
||||
mod azure;
|
||||
mod diff;
|
||||
|
@ -310,10 +310,11 @@ mod tests {
|
|||
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Edit, Fix};
|
||||
use ruff_notebook::NotebookIndex;
|
||||
use ruff_python_parser::{parse_unchecked, Mode};
|
||||
use ruff_source_file::{Locator, OneIndexed, SourceFileBuilder};
|
||||
use ruff_source_file::{OneIndexed, SourceFileBuilder};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::message::{Emitter, EmitterContext, Message};
|
||||
use crate::Locator;
|
||||
|
||||
pub(super) fn create_syntax_error_messages() -> Vec<Message> {
|
||||
let source = r"from os import
|
||||
|
|
|
@ -8,16 +8,17 @@ use std::path::Path;
|
|||
use anyhow::Result;
|
||||
use itertools::Itertools;
|
||||
use log::warn;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit};
|
||||
use ruff_python_trivia::{indentation_at_offset, CommentRanges};
|
||||
use ruff_source_file::{LineEnding, Locator};
|
||||
use ruff_source_file::{LineEnding, LineRanges};
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::codes::NoqaCode;
|
||||
use crate::fs::relativize_path;
|
||||
use crate::registry::{AsRule, Rule, RuleSet};
|
||||
use crate::rule_redirects::get_redirect_target;
|
||||
use crate::Locator;
|
||||
|
||||
/// Generates an array of edits that matches the length of `diagnostics`.
|
||||
/// Each potential edit in the array is paired, in order, with the associated diagnostic.
|
||||
|
@ -33,8 +34,7 @@ pub fn generate_noqa_edits(
|
|||
noqa_line_for: &NoqaMapping,
|
||||
line_ending: LineEnding,
|
||||
) -> Vec<Option<Edit>> {
|
||||
let file_directives =
|
||||
FileNoqaDirectives::extract(locator.contents(), comment_ranges, external, path, locator);
|
||||
let file_directives = FileNoqaDirectives::extract(locator, comment_ranges, external, path);
|
||||
let exemption = FileExemption::from(&file_directives);
|
||||
let directives = NoqaDirectives::from_commented_ranges(comment_ranges, path, locator);
|
||||
let comments = find_noqa_comments(diagnostics, locator, &exemption, &directives, noqa_line_for);
|
||||
|
@ -352,16 +352,15 @@ impl<'a> FileNoqaDirectives<'a> {
|
|||
/// Extract the [`FileNoqaDirectives`] for a given Python source file, enumerating any rules
|
||||
/// that are globally ignored within the file.
|
||||
pub(crate) fn extract(
|
||||
contents: &'a str,
|
||||
locator: &Locator<'a>,
|
||||
comment_ranges: &CommentRanges,
|
||||
external: &[String],
|
||||
path: &Path,
|
||||
locator: &Locator,
|
||||
) -> Self {
|
||||
let mut lines = vec![];
|
||||
|
||||
for range in comment_ranges {
|
||||
match ParsedFileExemption::try_extract(&contents[range]) {
|
||||
match ParsedFileExemption::try_extract(&locator.contents()[range]) {
|
||||
Err(err) => {
|
||||
#[allow(deprecated)]
|
||||
let line = locator.compute_line_index(range.start());
|
||||
|
@ -369,7 +368,7 @@ impl<'a> FileNoqaDirectives<'a> {
|
|||
warn!("Invalid `# ruff: noqa` directive at {path_display}:{line}: {err}");
|
||||
}
|
||||
Ok(Some(exemption)) => {
|
||||
if indentation_at_offset(range.start(), locator).is_none() {
|
||||
if indentation_at_offset(range.start(), locator.contents()).is_none() {
|
||||
#[allow(deprecated)]
|
||||
let line = locator.compute_line_index(range.start());
|
||||
let path_display = relativize_path(path);
|
||||
|
@ -619,8 +618,7 @@ fn add_noqa_inner(
|
|||
let mut count = 0;
|
||||
|
||||
// Whether the file is exempted from all checks.
|
||||
let directives =
|
||||
FileNoqaDirectives::extract(locator.contents(), comment_ranges, external, path, locator);
|
||||
let directives = FileNoqaDirectives::extract(locator, comment_ranges, external, path);
|
||||
let exemption = FileExemption::from(&directives);
|
||||
|
||||
let directives = NoqaDirectives::from_commented_ranges(comment_ranges, path, locator);
|
||||
|
@ -1055,17 +1053,17 @@ mod tests {
|
|||
use std::path::Path;
|
||||
|
||||
use insta::assert_debug_snapshot;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::{LineEnding, Locator};
|
||||
use ruff_source_file::LineEnding;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::generate_noqa_edits;
|
||||
use crate::noqa::{add_noqa_inner, Directive, NoqaMapping, ParsedFileExemption};
|
||||
use crate::rules::pycodestyle::rules::{AmbiguousVariableName, UselessSemicolon};
|
||||
use crate::rules::pyflakes::rules::UnusedVariable;
|
||||
use crate::rules::pyupgrade::rules::PrintfStringFormatting;
|
||||
use crate::{generate_noqa_edits, Locator};
|
||||
|
||||
#[test]
|
||||
fn noqa_all() {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::settings::LinterSettings;
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::{Locator, UniversalNewlineIterator};
|
||||
use ruff_source_file::{LineRanges, UniversalNewlineIterator};
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
use super::super::detection::comment_contains_code;
|
||||
|
||||
/// ## What it does
|
||||
|
@ -53,7 +55,7 @@ pub(crate) fn commented_out_code(
|
|||
let mut comments = comment_ranges.into_iter().peekable();
|
||||
// Iterate over all comments in the document.
|
||||
while let Some(range) = comments.next() {
|
||||
let line = locator.line(range.start());
|
||||
let line = locator.line_str(range.start());
|
||||
|
||||
if is_script_tag_start(line) {
|
||||
if skip_script_comments(range, &mut comments, locator) {
|
||||
|
@ -176,11 +178,14 @@ fn is_script_tag_start(line: &str) -> bool {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::rules::eradicate::rules::commented_out_code::skip_script_comments;
|
||||
use ruff_python_parser::parse_module;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
use crate::rules::eradicate::rules::commented_out_code::skip_script_comments;
|
||||
use crate::Locator;
|
||||
|
||||
#[test]
|
||||
fn script_comment() {
|
||||
let code = r#"
|
||||
|
|
|
@ -6,10 +6,10 @@ use ruff_diagnostics::{Diagnostic, Violation};
|
|||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::str::raw_contents;
|
||||
use ruff_python_ast::{self as ast, Expr, Operator};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
static SQL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"(?i)\b(select\s+.*\s+from\s|delete\s+from\s|(insert|replace)\s+.*\s+values\s|update\s+.*\s+set\s)")
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// Return `true` if the statement containing the current expression is the last
|
||||
/// top-level expression in the cell. This assumes that the source is a Jupyter
|
||||
/// Notebook.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::fix::edits::pad;
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_stdlib::identifiers::{is_identifier, is_mangled_private};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::pad;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `getattr` that take a constant attribute value as an
|
||||
|
|
|
@ -9,10 +9,11 @@ use ruff_python_semantic::analyze::function_type::is_stub;
|
|||
use ruff_python_semantic::analyze::typing::{is_immutable_annotation, is_mutable_expr};
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_trivia::{indentation_at_offset, textwrap};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of mutable objects as function argument defaults.
|
||||
|
@ -145,7 +146,7 @@ fn move_initialization(
|
|||
|
||||
// Avoid attempting to fix single-line functions.
|
||||
let statement = body.peek()?;
|
||||
if indexer.preceded_by_multi_statement_line(statement, locator) {
|
||||
if indexer.preceded_by_multi_statement_line(statement, locator.contents()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -170,7 +171,7 @@ fn move_initialization(
|
|||
content.push_str(stylist.line_ending().as_str());
|
||||
|
||||
// Determine the indentation depth of the function body.
|
||||
let indentation = indentation_at_offset(statement.start(), locator)?;
|
||||
let indentation = indentation_at_offset(statement.start(), locator.contents())?;
|
||||
|
||||
// Indent the edit to match the body indentation.
|
||||
let mut content = textwrap::indent(&content, indentation).to_string();
|
||||
|
@ -186,7 +187,7 @@ fn move_initialization(
|
|||
if let Some(next) = body.peek() {
|
||||
// If there's a second statement, insert _before_ it, but ensure this isn't a
|
||||
// multi-statement line.
|
||||
if indexer.in_multi_statement_line(statement, locator) {
|
||||
if indexer.in_multi_statement_line(statement, locator.contents()) {
|
||||
continue;
|
||||
}
|
||||
pos = locator.line_start(next.start());
|
||||
|
|
|
@ -3,9 +3,10 @@ use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
|||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// Simplified token type.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
enum TokenType {
|
||||
|
|
|
@ -14,13 +14,13 @@ use ruff_diagnostics::{Edit, Fix};
|
|||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::cst::helpers::{negate, space};
|
||||
use crate::fix::codemods::CodegenStylist;
|
||||
use crate::fix::edits::pad;
|
||||
use crate::rules::flake8_comprehensions::rules::ObjectType;
|
||||
use crate::Locator;
|
||||
use crate::{
|
||||
checkers::ast::Checker,
|
||||
cst::matchers::{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the absence of copyright notices within Python files.
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use ruff_python_ast::{self as ast, Arguments, Expr, Stmt};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::whitespace;
|
||||
use ruff_python_ast::{self as ast, Arguments, Expr, Stmt};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the use of string literals in exception constructors.
|
||||
|
@ -190,7 +190,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
|
|||
let mut diagnostic =
|
||||
Diagnostic::new(RawStringInException, first.range());
|
||||
if let Some(indentation) =
|
||||
whitespace::indentation(checker.locator(), stmt)
|
||||
whitespace::indentation(checker.source(), stmt)
|
||||
{
|
||||
diagnostic.set_fix(generate_fix(
|
||||
stmt,
|
||||
|
@ -208,8 +208,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
|
|||
Expr::FString(_) => {
|
||||
if checker.enabled(Rule::FStringInException) {
|
||||
let mut diagnostic = Diagnostic::new(FStringInException, first.range());
|
||||
if let Some(indentation) = whitespace::indentation(checker.locator(), stmt)
|
||||
{
|
||||
if let Some(indentation) = whitespace::indentation(checker.source(), stmt) {
|
||||
diagnostic.set_fix(generate_fix(
|
||||
stmt,
|
||||
first,
|
||||
|
@ -231,7 +230,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
|
|||
let mut diagnostic =
|
||||
Diagnostic::new(DotFormatInException, first.range());
|
||||
if let Some(indentation) =
|
||||
whitespace::indentation(checker.locator(), stmt)
|
||||
whitespace::indentation(checker.source(), stmt)
|
||||
{
|
||||
diagnostic.set_fix(generate_fix(
|
||||
stmt,
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
use std::path::Path;
|
||||
|
||||
use crate::codes::Rule;
|
||||
use crate::comments::shebang::ShebangDirective;
|
||||
use crate::settings::LinterSettings;
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
pub(crate) use shebang_leading_whitespace::*;
|
||||
pub(crate) use shebang_missing_executable_file::*;
|
||||
pub(crate) use shebang_missing_python::*;
|
||||
pub(crate) use shebang_not_executable::*;
|
||||
pub(crate) use shebang_not_first_line::*;
|
||||
|
||||
use crate::codes::Rule;
|
||||
use crate::comments::shebang::ShebangDirective;
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
mod shebang_leading_whitespace;
|
||||
mod shebang_missing_executable_file;
|
||||
mod shebang_missing_python;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::is_python_whitespace;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for whitespace before a shebang directive.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::is_python_whitespace;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for a shebang directive that is not at the beginning of the file.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use ruff_python_ast::{self as ast, Expr, Operator};
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_python_ast::{self as ast, Expr, Operator};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for string literals that are explicitly concatenated (using the
|
||||
/// `+` operator).
|
||||
|
|
|
@ -7,10 +7,11 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for implicitly concatenated strings on a single line.
|
||||
|
|
|
@ -65,7 +65,7 @@ pub(crate) fn unconventional_import_alias(
|
|||
let qualified_name = import.qualified_name().to_string();
|
||||
let expected_alias = conventions.get(qualified_name.as_str())?;
|
||||
|
||||
let name = binding.name(checker.locator());
|
||||
let name = binding.name(checker.source());
|
||||
if name == expected_alias {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ use ruff_diagnostics::{Diagnostic, Violation};
|
|||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::comments::shebang::ShebangDirective;
|
||||
use crate::fs;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for packages that are missing an `__init__.py` file.
|
||||
|
|
|
@ -105,7 +105,7 @@ pub(crate) fn unnecessary_placeholder(checker: &mut Checker, body: &[Stmt]) {
|
|||
};
|
||||
|
||||
let mut diagnostic = Diagnostic::new(UnnecessaryPlaceholder { kind }, stmt.range());
|
||||
let edit = if let Some(index) = trailing_comment_start_offset(stmt, checker.locator()) {
|
||||
let edit = if let Some(index) = trailing_comment_start_offset(stmt, checker.source()) {
|
||||
Edit::range_deletion(stmt.range().add_end(index))
|
||||
} else {
|
||||
fix::edits::delete_stmt(stmt, None, checker.locator(), checker.indexer())
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use ruff_python_ast::{self as ast, Expr};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for unnecessary dictionary unpacking operators (`**`).
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{self as ast, comparable::ComparableExpr};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::snippet::SourceCodeSnippet;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for redundant `Final[Literal[...]]` annotations.
|
||||
|
|
|
@ -5,13 +5,13 @@ use ruff_python_ast::{
|
|||
self as ast, Expr, Operator, ParameterWithDefault, Parameters, Stmt, UnaryOp,
|
||||
};
|
||||
use ruff_python_semantic::{analyze::class::is_enumeration, ScopeKind, SemanticModel};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::rules::flake8_pyi::rules::TypingModule;
|
||||
use crate::settings::types::PythonVersion;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for typed function arguments in stubs with complex default values.
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use regex::Regex;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use regex::Regex;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for the use of type comments (e.g., `x = 1 # type: int`) in stub
|
||||
|
|
|
@ -73,7 +73,7 @@ pub(crate) fn unaliased_collections_abc_set_import(
|
|||
return None;
|
||||
}
|
||||
|
||||
let name = binding.name(checker.locator());
|
||||
let name = binding.name(checker.source());
|
||||
if name == "AbstractSet" {
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use ruff_python_ast::{
|
|||
};
|
||||
use ruff_python_ast::{visitor, whitespace};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -26,6 +26,7 @@ use crate::cst::matchers::match_indented_block;
|
|||
use crate::cst::matchers::match_module;
|
||||
use crate::fix::codemods::CodegenStylist;
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::Locator;
|
||||
|
||||
use super::unittest_assert::UnittestAssert;
|
||||
|
||||
|
@ -386,7 +387,7 @@ pub(crate) fn unittest_raises_assertion(
|
|||
);
|
||||
if !checker
|
||||
.comment_ranges()
|
||||
.has_comments(call, checker.locator())
|
||||
.has_comments(call, checker.source())
|
||||
{
|
||||
if let Some(args) = to_pytest_raises_args(checker, attr.as_str(), &call.arguments) {
|
||||
diagnostic.try_set_fix(|| {
|
||||
|
@ -622,11 +623,11 @@ fn parenthesize<'a>(expression: &Expression<'a>, parent: &Expression<'a>) -> Exp
|
|||
/// `assert a == "hello"` and `assert b == "world"`.
|
||||
fn fix_composite_condition(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> Result<Edit> {
|
||||
// Infer the indentation of the outer block.
|
||||
let outer_indent =
|
||||
whitespace::indentation(locator, stmt).context("Unable to fix multiline statement")?;
|
||||
let outer_indent = whitespace::indentation(locator.contents(), stmt)
|
||||
.context("Unable to fix multiline statement")?;
|
||||
|
||||
// Extract the module text.
|
||||
let contents = locator.lines(stmt.range());
|
||||
let contents = locator.lines_str(stmt.range());
|
||||
|
||||
// If the block is indented, "embed" it in a function definition, to preserve
|
||||
// indentation while retaining valid source code. (We'll strip the prefix later
|
||||
|
@ -747,7 +748,7 @@ pub(crate) fn composite_condition(
|
|||
&& !checker.comment_ranges().intersects(stmt.range())
|
||||
&& !checker
|
||||
.indexer()
|
||||
.in_multi_statement_line(stmt, checker.locator())
|
||||
.in_multi_statement_line(stmt, checker.source())
|
||||
{
|
||||
diagnostic.try_set_fix(|| {
|
||||
fix_composite_condition(stmt, checker.locator(), checker.stylist())
|
||||
|
|
|
@ -9,6 +9,7 @@ use ruff_python_ast::Decorator;
|
|||
use ruff_python_ast::{self as ast, Expr, Parameters, Stmt};
|
||||
use ruff_python_semantic::analyze::visibility::is_abstract;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_text_size::{TextLen, TextRange};
|
||||
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
use flake8_quotes::helpers::{contains_escaped_quote, raw_contents, unescape_string};
|
||||
use flake8_quotes::settings::Quote;
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::visitor::{walk_f_string, Visitor};
|
||||
use ruff_python_ast::{self as ast, AnyStringFlags, StringFlags, StringLike};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::rules::flake8_quotes;
|
||||
use crate::settings::LinterSettings;
|
||||
|
||||
use flake8_quotes::helpers::{contains_escaped_quote, raw_contents, unescape_string};
|
||||
use flake8_quotes::settings::Quote;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for strings that include escaped quotes, and suggests changing
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::StringLike;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::Rule;
|
||||
use crate::Locator;
|
||||
|
||||
use super::super::settings::Quote;
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{self as ast, AnyStringFlags, StringFlags, StringLike};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
use super::super::helpers::{contains_escaped_quote, raw_contents, unescape_string};
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::Stmt;
|
||||
use ruff_source_file::UniversalNewlines;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_source_file::{Locator, UniversalNewlines};
|
||||
use crate::Locator;
|
||||
|
||||
/// Return `true` if a function's return statement include at least one
|
||||
/// non-`None` value.
|
||||
|
|
|
@ -15,7 +15,7 @@ use ruff_python_index::Indexer;
|
|||
use ruff_python_semantic::analyze::visibility::is_property;
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
use ruff_python_trivia::{is_python_whitespace, SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -23,6 +23,7 @@ use crate::fix::edits;
|
|||
use crate::fix::edits::adjust_indentation;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
use crate::rules::flake8_return::helpers::end_of_last_statement;
|
||||
use crate::Locator;
|
||||
|
||||
use super::super::branch::Branch;
|
||||
use super::super::helpers::result_exists;
|
||||
|
@ -453,7 +454,7 @@ fn is_noreturn_func(func: &Expr, semantic: &SemanticModel) -> bool {
|
|||
|
||||
fn add_return_none(checker: &mut Checker, stmt: &Stmt, range: TextRange) {
|
||||
let mut diagnostic = Diagnostic::new(ImplicitReturn, range);
|
||||
if let Some(indent) = indentation(checker.locator(), stmt) {
|
||||
if let Some(indent) = indentation(checker.source(), stmt) {
|
||||
let mut content = String::new();
|
||||
content.push_str(checker.stylist().line_ending().as_str());
|
||||
content.push_str(indent);
|
||||
|
@ -851,14 +852,14 @@ fn remove_else(
|
|||
};
|
||||
|
||||
// get the indentation of the `else`, since that is the indent level we want to end with
|
||||
let Some(desired_indentation) = indentation(locator, elif_else) else {
|
||||
let Some(desired_indentation) = indentation(locator.contents(), elif_else) else {
|
||||
return Err(anyhow::anyhow!("Compound statement cannot be inlined"));
|
||||
};
|
||||
|
||||
// If the statement is on the same line as the `else`, just remove the `else: `.
|
||||
// Ex) `else: return True` -> `return True`
|
||||
if let Some(first) = elif_else.body.first() {
|
||||
if indexer.preceded_by_multi_statement_line(first, locator) {
|
||||
if indexer.preceded_by_multi_statement_line(first, locator.contents()) {
|
||||
return Ok(Fix::safe_edit(Edit::deletion(
|
||||
elif_else.start(),
|
||||
first.start(),
|
||||
|
|
|
@ -536,7 +536,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) {
|
|||
// Avoid removing comments.
|
||||
if checker
|
||||
.comment_ranges()
|
||||
.has_comments(expr, checker.locator())
|
||||
.has_comments(expr, checker.source())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use ruff_python_ast::{self as ast, whitespace, ElifElseClause, Expr, Stmt};
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_semantic::analyze::typing::{is_sys_version_block, is_type_checking_block};
|
||||
use ruff_python_trivia::{SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -19,6 +19,7 @@ use crate::cst::helpers::space;
|
|||
use crate::cst::matchers::{match_function_def, match_if, match_indented_block, match_statement};
|
||||
use crate::fix::codemods::CodegenStylist;
|
||||
use crate::fix::edits::fits;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for nested `if` statements that can be collapsed into a single `if`
|
||||
|
@ -292,12 +293,12 @@ pub(super) fn collapse_nested_if(
|
|||
nested_if: NestedIf,
|
||||
) -> Result<Edit> {
|
||||
// Infer the indentation of the outer block.
|
||||
let Some(outer_indent) = whitespace::indentation(locator, &nested_if) else {
|
||||
let Some(outer_indent) = whitespace::indentation(locator.contents(), &nested_if) else {
|
||||
bail!("Unable to fix multiline statement");
|
||||
};
|
||||
|
||||
// Extract the module text.
|
||||
let contents = locator.lines(nested_if.range());
|
||||
let contents = locator.lines_str(nested_if.range());
|
||||
|
||||
// If this is an `elif`, we have to remove the `elif` keyword for now. (We'll
|
||||
// restore the `el` later on.)
|
||||
|
|
|
@ -5,11 +5,12 @@ use ruff_diagnostics::Edit;
|
|||
use ruff_python_ast as ast;
|
||||
use ruff_python_ast::whitespace;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::cst::matchers::{match_function_def, match_indented_block, match_statement, match_with};
|
||||
use crate::fix::codemods::CodegenStylist;
|
||||
use crate::Locator;
|
||||
|
||||
/// (SIM117) Convert `with a: with b:` to `with a, b:`.
|
||||
pub(crate) fn fix_multiple_with_statements(
|
||||
|
@ -18,12 +19,12 @@ pub(crate) fn fix_multiple_with_statements(
|
|||
with_stmt: &ast::StmtWith,
|
||||
) -> Result<Edit> {
|
||||
// Infer the indentation of the outer block.
|
||||
let Some(outer_indent) = whitespace::indentation(locator, with_stmt) else {
|
||||
let Some(outer_indent) = whitespace::indentation(locator.contents(), with_stmt) else {
|
||||
bail!("Unable to fix multiline statement");
|
||||
};
|
||||
|
||||
// Extract the module text.
|
||||
let contents = locator.lines(with_stmt.range());
|
||||
let contents = locator.lines_str(with_stmt.range());
|
||||
|
||||
// If the block is indented, "embed" it in a function definition, to preserve
|
||||
// indentation while retaining valid source code. (We'll strip the prefix later
|
||||
|
|
|
@ -211,7 +211,7 @@ pub(crate) fn if_else_block_instead_of_dict_get(checker: &mut Checker, stmt_if:
|
|||
);
|
||||
if !checker
|
||||
.comment_ranges()
|
||||
.has_comments(stmt_if, checker.locator())
|
||||
.has_comments(stmt_if, checker.source())
|
||||
{
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
contents,
|
||||
|
@ -300,7 +300,7 @@ pub(crate) fn if_exp_instead_of_dict_get(
|
|||
);
|
||||
if !checker
|
||||
.comment_ranges()
|
||||
.has_comments(expr, checker.locator())
|
||||
.has_comments(expr, checker.source())
|
||||
{
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
contents,
|
||||
|
|
|
@ -227,7 +227,7 @@ pub(crate) fn if_else_block_instead_of_if_exp(checker: &mut Checker, stmt_if: &a
|
|||
);
|
||||
if !checker
|
||||
.comment_ranges()
|
||||
.has_comments(stmt_if, checker.locator())
|
||||
.has_comments(stmt_if, checker.source())
|
||||
{
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
contents,
|
||||
|
|
|
@ -9,10 +9,11 @@ use ruff_python_ast::parenthesize::parenthesized_range;
|
|||
use ruff_python_ast::stmt_if::{if_elif_branches, IfElifBranch};
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_python_trivia::{CommentRanges, SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `if` branches with identical arm bodies.
|
||||
|
|
|
@ -200,7 +200,7 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) {
|
|||
// Generate the replacement condition.
|
||||
let condition = if checker
|
||||
.comment_ranges()
|
||||
.has_comments(&range, checker.locator())
|
||||
.has_comments(&range, checker.source())
|
||||
{
|
||||
None
|
||||
} else {
|
||||
|
|
|
@ -7,6 +7,7 @@ use ruff_python_ast::{
|
|||
self as ast, Arguments, CmpOp, Comprehension, Expr, ExprContext, Stmt, UnaryOp,
|
||||
};
|
||||
use ruff_python_codegen::Generator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
|
@ -3,6 +3,7 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use ruff_python_ast::helpers;
|
||||
use ruff_python_ast::name::UnqualifiedName;
|
||||
use ruff_python_ast::{self as ast, ExceptHandler, Stmt};
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_text_size::{TextLen, TextRange};
|
||||
|
||||
|
@ -127,7 +128,7 @@ pub(crate) fn suppressible_exception(
|
|||
);
|
||||
if !checker
|
||||
.comment_ranges()
|
||||
.has_comments(stmt, checker.locator())
|
||||
.has_comments(stmt, checker.source())
|
||||
{
|
||||
diagnostic.try_set_fix(|| {
|
||||
// let range = statement_range(stmt, checker.locator(), checker.indexer());
|
||||
|
|
|
@ -8,7 +8,6 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use ruff_python_ast::{self as ast, CmpOp, Expr, UnaryOp};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_stdlib::str::{self};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -16,6 +15,7 @@ use crate::cst::helpers::or_space;
|
|||
use crate::cst::matchers::{match_comparison, transform_expression};
|
||||
use crate::fix::edits::pad;
|
||||
use crate::fix::snippet::SourceCodeSnippet;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for conditions that position a constant on the left-hand side of the
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use regex::RegexSet;
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use regex::RegexSet;
|
||||
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::directives::{TodoComment, TodoDirective, TodoDirectiveKind};
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks that a TODO comment is labelled with "TODO".
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use ruff_python_ast::{self as ast, Stmt};
|
||||
use ruff_python_parser::Tokens;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use ruff_source_file::Locator;
|
||||
use crate::Locator;
|
||||
|
||||
use super::comments::Comment;
|
||||
use super::helpers::trailing_comma;
|
||||
|
|
|
@ -4,11 +4,11 @@ use std::slice;
|
|||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_ast::statement_visitor::StatementVisitor;
|
||||
use ruff_python_ast::{self as ast, ElifElseClause, ExceptHandler, MatchCase, Stmt};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::directives::IsortDirectives;
|
||||
use crate::rules::isort::helpers;
|
||||
use crate::Locator;
|
||||
|
||||
/// A block of imports within a Python module.
|
||||
#[derive(Debug, Default)]
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Comment<'a> {
|
||||
pub(crate) value: Cow<'a, str>,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use ruff_python_ast::Stmt;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_python_trivia::PythonWhitespace;
|
||||
use ruff_source_file::{Locator, UniversalNewlines};
|
||||
use ruff_source_file::UniversalNewlines;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::rules::isort::types::TrailingComma;
|
||||
use crate::Locator;
|
||||
|
||||
/// Return `true` if a `Stmt::ImportFrom` statement ends with a magic
|
||||
/// trailing comma.
|
||||
|
|
|
@ -13,13 +13,13 @@ use order::order_imports;
|
|||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_parser::Tokens;
|
||||
use ruff_source_file::Locator;
|
||||
use settings::Settings;
|
||||
use types::EitherImport::{Import, ImportFrom};
|
||||
use types::{AliasData, ImportBlock, TrailingComma};
|
||||
|
||||
use crate::line_width::{LineLength, LineWidthBuilder};
|
||||
use crate::settings::types::PythonVersion;
|
||||
use crate::Locator;
|
||||
|
||||
mod annotate;
|
||||
pub(crate) mod block;
|
||||
|
@ -282,11 +282,12 @@ mod tests {
|
|||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use ruff_python_semantic::{MemberNameImport, ModuleNameImport, NameImport};
|
||||
use ruff_text_size::Ranged;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use test_case::test_case;
|
||||
|
||||
use ruff_python_semantic::{MemberNameImport, ModuleNameImport, NameImport};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::assert_messages;
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::isort::categorize::{ImportSection, KnownModules};
|
||||
|
|
|
@ -5,12 +5,11 @@ use ruff_python_ast::{self as ast, ModModule, PySourceType, Stmt};
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_parser::Parsed;
|
||||
use ruff_python_semantic::{FutureImport, NameImport};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::importer::Importer;
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Adds any required imports, as specified by the user, to the top of the
|
||||
|
|
|
@ -10,12 +10,12 @@ use ruff_python_codegen::Stylist;
|
|||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::Tokens;
|
||||
use ruff_python_trivia::{leading_indentation, textwrap::indent, PythonWhitespace};
|
||||
use ruff_source_file::{Locator, UniversalNewlines};
|
||||
use ruff_source_file::{LineRanges, UniversalNewlines};
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::line_width::LineWidthBuilder;
|
||||
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
use super::super::block::Block;
|
||||
use super::super::{comments, format_imports};
|
||||
|
@ -98,8 +98,9 @@ pub(crate) fn organize_imports(
|
|||
|
||||
// Special-cases: there's leading or trailing content in the import block. These
|
||||
// are too hard to get right, and relatively rare, so flag but don't fix.
|
||||
if indexer.preceded_by_multi_statement_line(block.imports.first().unwrap(), locator)
|
||||
|| indexer.followed_by_multi_statement_line(block.imports.last().unwrap(), locator)
|
||||
if indexer.preceded_by_multi_statement_line(block.imports.first().unwrap(), locator.contents())
|
||||
|| indexer
|
||||
.followed_by_multi_statement_line(block.imports.last().unwrap(), locator.contents())
|
||||
{
|
||||
return Some(Diagnostic::new(UnsortedImports, range));
|
||||
}
|
||||
|
@ -114,7 +115,7 @@ pub(crate) fn organize_imports(
|
|||
let trailing_line_end = if block.trailer.is_none() {
|
||||
locator.full_line_end(range.end())
|
||||
} else {
|
||||
trailing_lines_end(block.imports.last().unwrap(), locator)
|
||||
trailing_lines_end(block.imports.last().unwrap(), locator.contents())
|
||||
};
|
||||
|
||||
// Generate the sorted import block.
|
||||
|
|
|
@ -4,11 +4,11 @@ use ruff_python_ast::helpers::is_const_true;
|
|||
use ruff_python_ast::parenthesize::parenthesized_range;
|
||||
use ruff_python_ast::{self as ast, Keyword, Stmt};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::{remove_argument, Parentheses};
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `inplace=True` usages in `pandas` function and method
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ruff_python_ast::{self as ast, ExceptHandler, Expr, Stmt};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::identifier::except;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_python_ast::{self as ast, ExceptHandler, Expr, Stmt};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for bare `except` catches in `try`-`except` statements.
|
||||
|
|
|
@ -1,28 +1,30 @@
|
|||
use itertools::Itertools;
|
||||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_parser::TokenIterWithContext;
|
||||
use ruff_python_parser::Tokens;
|
||||
use std::cmp::Ordering;
|
||||
use std::iter::Peekable;
|
||||
use std::num::NonZeroU32;
|
||||
use std::slice::Iter;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use ruff_diagnostics::AlwaysFixableViolation;
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_diagnostics::Edit;
|
||||
use ruff_diagnostics::Fix;
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_parser::TokenIterWithContext;
|
||||
use ruff_python_parser::TokenKind;
|
||||
use ruff_python_parser::Tokens;
|
||||
use ruff_python_trivia::PythonWhitespace;
|
||||
use ruff_source_file::{Locator, UniversalNewlines};
|
||||
use ruff_source_file::{LineRanges, UniversalNewlines};
|
||||
use ruff_text_size::TextRange;
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
use crate::checkers::logical_lines::expand_indent;
|
||||
use crate::line_width::IndentWidth;
|
||||
use crate::rules::pycodestyle::helpers::is_non_logical_token;
|
||||
use crate::Locator;
|
||||
|
||||
/// Number of blank lines around top level classes and functions.
|
||||
const BLANK_LINES_TOP_LEVEL: u32 = 2;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_parser::{TokenIterWithContext, TokenKind, Tokens};
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Violation};
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_notebook::CellOffsets;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_python_parser::{TokenIterWithContext, TokenKind, Tokens};
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for compound statements (multiple statements on the same line).
|
||||
|
@ -170,7 +170,7 @@ pub(crate) fn compound_statements(
|
|||
let mut diagnostic = Diagnostic::new(UselessSemicolon, range);
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::deletion(
|
||||
indexer
|
||||
.preceded_by_continuations(range.start(), locator)
|
||||
.preceded_by_continuations(range.start(), locator.contents())
|
||||
.unwrap_or(range.start()),
|
||||
range.end(),
|
||||
)));
|
||||
|
|
|
@ -3,11 +3,11 @@ use memchr::memchr_iter;
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{AnyStringFlags, FStringElement, StringLike, StringLikePart};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::pad_start;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for invalid escape sequences.
|
||||
|
|
|
@ -79,10 +79,10 @@ pub(crate) fn lambda_assignment(
|
|||
stmt.range(),
|
||||
);
|
||||
|
||||
if !has_leading_content(stmt.start(), checker.locator())
|
||||
&& !has_trailing_content(stmt.end(), checker.locator())
|
||||
if !has_leading_content(stmt.start(), checker.source())
|
||||
&& !has_trailing_content(stmt.end(), checker.source())
|
||||
{
|
||||
let first_line = checker.locator().line(stmt.start());
|
||||
let first_line = checker.locator().line_str(stmt.start());
|
||||
let indentation = leading_indentation(first_line);
|
||||
let mut indented = String::new();
|
||||
for (idx, line) in function(
|
||||
|
|
|
@ -336,7 +336,7 @@ pub(crate) fn literal_comparisons(checker: &mut Checker, compare: &ast::ExprComp
|
|||
&compare.comparators,
|
||||
compare.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator(),
|
||||
checker.source(),
|
||||
);
|
||||
for diagnostic in &mut diagnostics {
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
pub(crate) use extraneous_whitespace::*;
|
||||
pub(crate) use indentation::*;
|
||||
pub(crate) use missing_whitespace::*;
|
||||
pub(crate) use missing_whitespace_after_keyword::*;
|
||||
pub(crate) use missing_whitespace_around_operator::*;
|
||||
pub(crate) use redundant_backslash::*;
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_python_trivia::is_python_whitespace;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
pub(crate) use space_around_operator::*;
|
||||
pub(crate) use whitespace_around_keywords::*;
|
||||
pub(crate) use whitespace_around_named_parameter_equals::*;
|
||||
pub(crate) use whitespace_before_comment::*;
|
||||
pub(crate) use whitespace_before_parameters::*;
|
||||
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
use bitflags::bitflags;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use ruff_python_parser::{TokenKind, Tokens};
|
||||
use ruff_python_trivia::is_python_whitespace;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::rules::pycodestyle::helpers::is_non_logical_token;
|
||||
use crate::Locator;
|
||||
|
||||
mod extraneous_whitespace;
|
||||
mod indentation;
|
||||
|
@ -579,7 +578,8 @@ impl TypeParamsState {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruff_python_parser::parse_module;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
use super::LogicalLines;
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
|||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::TokenKind;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::logical_lines::LogicalLinesContext;
|
||||
use crate::Locator;
|
||||
|
||||
use super::LogicalLine;
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
|||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_parser::TokenKind;
|
||||
use ruff_python_trivia::PythonWhitespace;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::logical_lines::LogicalLinesContext;
|
||||
use crate::rules::pycodestyle::rules::logical_lines::LogicalLine;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks if inline comments are separated by at least two spaces.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ruff_text_size::{TextLen, TextRange};
|
||||
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextLen, TextRange};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for files missing a new line at the end of the file.
|
||||
|
|
|
@ -6,10 +6,11 @@ use ruff_python_ast::{Alias, Stmt};
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_trivia::indentation_at_offset;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Check for multiple imports on one line.
|
||||
|
@ -68,7 +69,7 @@ fn split_imports(
|
|||
indexer: &Indexer,
|
||||
stylist: &Stylist,
|
||||
) -> Fix {
|
||||
if indexer.in_multi_statement_line(stmt, locator) {
|
||||
if indexer.in_multi_statement_line(stmt, locator.contents()) {
|
||||
// Ex) `x = 1; import os, sys` (convert to `x = 1; import os; import sys`)
|
||||
let replacement = names
|
||||
.iter()
|
||||
|
@ -90,7 +91,8 @@ fn split_imports(
|
|||
Fix::safe_edit(Edit::range_replacement(replacement, stmt.range()))
|
||||
} else {
|
||||
// Ex) `import os, sys` (convert to `import os\nimport sys`)
|
||||
let indentation = indentation_at_offset(stmt.start(), locator).unwrap_or_default();
|
||||
let indentation =
|
||||
indentation_at_offset(stmt.start(), locator.contents()).unwrap_or_default();
|
||||
|
||||
// Generate newline-delimited imports.
|
||||
let replacement = names
|
||||
|
|
|
@ -105,7 +105,7 @@ pub(crate) fn not_tests(checker: &mut Checker, unary_op: &ast::ExprUnaryOp) {
|
|||
comparators,
|
||||
unary_op.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator(),
|
||||
checker.source(),
|
||||
),
|
||||
unary_op.range(),
|
||||
checker.locator(),
|
||||
|
@ -126,7 +126,7 @@ pub(crate) fn not_tests(checker: &mut Checker, unary_op: &ast::ExprUnaryOp) {
|
|||
comparators,
|
||||
unary_op.into(),
|
||||
checker.comment_ranges(),
|
||||
checker.locator(),
|
||||
checker.source(),
|
||||
),
|
||||
unary_op.range(),
|
||||
checker.locator(),
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for indentation that uses tabs.
|
||||
///
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::{Line, Locator};
|
||||
use ruff_source_file::Line;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::registry::Rule;
|
||||
use crate::settings::LinterSettings;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for superfluous trailing whitespace.
|
||||
|
@ -100,7 +101,7 @@ pub(crate) fn trailing_whitespace(
|
|||
diagnostic.set_fix(Fix::applicable_edit(
|
||||
Edit::range_deletion(TextRange::new(
|
||||
indexer
|
||||
.preceded_by_continuations(line.start(), locator)
|
||||
.preceded_by_continuations(line.start(), locator.contents())
|
||||
.unwrap_or(range.start()),
|
||||
range.end(),
|
||||
)),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::{indentation_at_offset, PythonWhitespace};
|
||||
use ruff_source_file::{Line, UniversalNewlineIterator};
|
||||
use ruff_source_file::{Line, LineRanges, UniversalNewlineIterator};
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_text_size::{TextLen, TextRange};
|
||||
|
||||
|
@ -240,7 +240,7 @@ pub(crate) fn blank_before_after_class(checker: &mut Checker, docstring: &Docstr
|
|||
if let Some(first_line) = &first_line {
|
||||
let trailing = first_line.as_str().trim_whitespace_start();
|
||||
if let Some(next_statement) = trailing.strip_prefix(';') {
|
||||
let indentation = indentation_at_offset(docstring.start(), checker.locator())
|
||||
let indentation = indentation_at_offset(docstring.start(), checker.source())
|
||||
.expect("Own line docstring must have indentation");
|
||||
let mut diagnostic = Diagnostic::new(OneBlankLineAfterClass, docstring.range());
|
||||
let line_ending = checker.stylist().line_ending().as_str();
|
||||
|
|
|
@ -2,7 +2,7 @@ use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
|||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::str::{is_triple_quote, leading_quote};
|
||||
use ruff_python_semantic::Definition;
|
||||
use ruff_source_file::{NewlineWithTrailingNewline, UniversalNewlineIterator};
|
||||
use ruff_source_file::{LineRanges, NewlineWithTrailingNewline, UniversalNewlineIterator};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
|
|
@ -1464,7 +1464,7 @@ fn blanks_and_section_underline(
|
|||
// Otherwise, documentation generators will not recognize the directive.
|
||||
let is_sphinx = checker
|
||||
.locator()
|
||||
.line(blank_lines_after_dashes_end)
|
||||
.line_str(blank_lines_after_dashes_end)
|
||||
.trim_start()
|
||||
.starts_with(".. ");
|
||||
|
||||
|
@ -1569,7 +1569,7 @@ fn blanks_and_section_underline(
|
|||
// Otherwise, documentation generators will not recognize the directive.
|
||||
let is_sphinx = checker
|
||||
.locator()
|
||||
.line(blank_lines_end)
|
||||
.line_str(blank_lines_end)
|
||||
.trim_start()
|
||||
.starts_with(".. ");
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ use ruff_python_ast as ast;
|
|||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_semantic::Binding;
|
||||
use ruff_python_trivia::{BackwardsTokenizer, SimpleTokenKind, SimpleTokenizer};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::cst::matchers::{match_call_mut, match_dict, transform_expression};
|
||||
use crate::Locator;
|
||||
|
||||
/// Generate a [`Edit`] to remove unused keys from format dict.
|
||||
pub(super) fn remove_unused_format_arguments_from_dict(
|
||||
|
|
|
@ -12,15 +12,12 @@ mod tests {
|
|||
use anyhow::Result;
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use test_case::test_case;
|
||||
|
||||
use ruff_python_ast::PySourceType;
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
|
||||
use ruff_python_trivia::textwrap::dedent;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::linter::check_path;
|
||||
|
@ -31,6 +28,7 @@ mod tests {
|
|||
use crate::settings::{flags, LinterSettings};
|
||||
use crate::source_kind::SourceKind;
|
||||
use crate::test::{test_contents, test_path, test_snippet};
|
||||
use crate::Locator;
|
||||
use crate::{assert_messages, directives};
|
||||
|
||||
#[test_case(Rule::UnusedImport, Path::new("F401_0.py"))]
|
||||
|
@ -712,8 +710,8 @@ mod tests {
|
|||
let parsed =
|
||||
ruff_python_parser::parse_unchecked_source(source_kind.source_code(), source_type);
|
||||
let locator = Locator::new(&contents);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), &locator);
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), &locator);
|
||||
let stylist = Stylist::from_tokens(parsed.tokens(), locator.contents());
|
||||
let indexer = Indexer::from_tokens(parsed.tokens(), locator.contents());
|
||||
let directives = directives::extract_directives(
|
||||
parsed.tokens(),
|
||||
directives::Flags::from_settings(&settings),
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use ruff_python_ast::{self as ast, ExceptHandler};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::identifier::except;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_python_ast::{self as ast, ExceptHandler};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `except` blocks that handle all exceptions, but are not the last
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast as ast;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for f-strings that do not contain any placeholder expressions.
|
||||
|
|
|
@ -295,7 +295,7 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut
|
|||
continue;
|
||||
};
|
||||
|
||||
let name = binding.name(checker.locator());
|
||||
let name = binding.name(checker.source());
|
||||
|
||||
// If an import is marked as required, avoid treating it as unused, regardless of whether
|
||||
// it was _actually_ used.
|
||||
|
|
|
@ -183,7 +183,7 @@ fn remove_unused_variable(binding: &Binding, checker: &Checker) -> Option<Fix> {
|
|||
};
|
||||
}
|
||||
} else {
|
||||
let name = binding.name(checker.locator());
|
||||
let name = binding.name(checker.source());
|
||||
let renamed = format!("_{name}");
|
||||
if checker.settings.dummy_variable_rgx.is_match(&renamed) {
|
||||
let edit = Edit::range_replacement(renamed, binding.range());
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::Cursor;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::noqa::{Directive, FileNoqaDirectives, NoqaDirectives, ParsedFileExemption};
|
||||
use crate::settings::types::PreviewMode;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Check for `noqa` annotations that suppress all diagnostics, as opposed to
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use memchr::memchr_iter;
|
||||
use regex::Regex;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Check for `type: ignore` annotations that suppress all type warnings, as
|
||||
/// opposed to targeting specific type warnings.
|
||||
|
|
|
@ -6,11 +6,12 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use ruff_python_ast::{self as ast, ElifElseClause, Stmt};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::fix::edits::adjust_indentation;
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for `else` blocks that consist of a single `if` statement.
|
||||
|
@ -113,7 +114,7 @@ fn convert_to_elif(
|
|||
let trivia_range = TextRange::new(else_line_end, inner_if_line_start);
|
||||
|
||||
// Identify the indentation of the outer clause
|
||||
let Some(indentation) = indentation(locator, else_clause) else {
|
||||
let Some(indentation) = indentation(locator.contents(), else_clause) else {
|
||||
return Err(anyhow::anyhow!("`else` is expected to be on its own line"));
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_trivia::{is_python_whitespace, CommentRanges};
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_source_file::LineRanges;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for a # symbol appearing on a line not followed by an actual comment.
|
||||
///
|
||||
|
@ -47,7 +49,7 @@ pub(crate) fn empty_comments(
|
|||
comment_ranges: &CommentRanges,
|
||||
locator: &Locator,
|
||||
) {
|
||||
let block_comments = comment_ranges.block_comments(locator);
|
||||
let block_comments = comment_ranges.block_comments(locator.contents());
|
||||
|
||||
for range in comment_ranges {
|
||||
// Ignore comments that are part of multi-line "comment blocks".
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use ruff_diagnostics::AlwaysFixableViolation;
|
||||
use ruff_diagnostics::Edit;
|
||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_parser::TokenKind;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::Locator;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for strings that contain the control character `BS`.
|
||||
|
|
|
@ -157,7 +157,7 @@ pub(crate) fn nested_min_max(
|
|||
let mut diagnostic = Diagnostic::new(NestedMinMax { func: min_max }, expr.range());
|
||||
if !checker
|
||||
.comment_ranges()
|
||||
.has_comments(expr, checker.locator())
|
||||
.has_comments(expr, checker.source())
|
||||
{
|
||||
let flattened_expr = Expr::Call(ast::ExprCall {
|
||||
func: Box::new(func.clone()),
|
||||
|
|
|
@ -175,7 +175,7 @@ fn get_undecorated_methods(checker: &mut Checker, class_stmt: &Stmt, method_type
|
|||
TextRange::new(stmt.range().start(), stmt.range().start()),
|
||||
);
|
||||
|
||||
let indentation = indentation_at_offset(stmt.range().start(), checker.locator());
|
||||
let indentation = indentation_at_offset(stmt.range().start(), checker.source());
|
||||
|
||||
match indentation {
|
||||
Some(indentation) => {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue