Skip to content

Commit db1c556

Browse files
Implement Ranged on more structs (#6639)
## Summary I noticed some inconsistencies around uses of `.range.start()`, structs that have a `TextRange` field but don't implement `Ranged`, etc. ## Test Plan `cargo test`
1 parent a70807e commit db1c556

File tree

66 files changed

+219
-174
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+219
-174
lines changed

crates/ruff/src/checkers/ast/analyze/bindings.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ruff_diagnostics::{Diagnostic, Fix};
2+
use ruff_python_ast::Ranged;
23

34
use crate::checkers::ast::Checker;
45
use crate::codes::Rule;
@@ -29,7 +30,7 @@ pub(crate) fn bindings(checker: &mut Checker) {
2930
pyflakes::rules::UnusedVariable {
3031
name: binding.name(checker.locator).to_string(),
3132
},
32-
binding.range,
33+
binding.range(),
3334
);
3435
if checker.patch(Rule::UnusedVariable) {
3536
diagnostic.try_set_fix(|| {

crates/ruff/src/checkers/ast/analyze/deferred_scopes.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ruff_diagnostics::Diagnostic;
2+
use ruff_python_ast::Ranged;
23
use ruff_python_semantic::analyze::{branch_detection, visibility};
34
use ruff_python_semantic::{Binding, BindingKind, ScopeKind};
45

@@ -81,7 +82,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
8182
pylint::rules::GlobalVariableNotAssigned {
8283
name: (*name).to_string(),
8384
},
84-
binding.range,
85+
binding.range(),
8586
));
8687
}
8788
}
@@ -122,14 +123,14 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
122123
}
123124

124125
#[allow(deprecated)]
125-
let line = checker.locator.compute_line_index(shadowed.range.start());
126+
let line = checker.locator.compute_line_index(shadowed.start());
126127

127128
checker.diagnostics.push(Diagnostic::new(
128129
pyflakes::rules::ImportShadowedByLoopVar {
129130
name: name.to_string(),
130131
line,
131132
},
132-
binding.range,
133+
binding.range(),
133134
));
134135
}
135136
}
@@ -218,13 +219,13 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
218219
}
219220

220221
#[allow(deprecated)]
221-
let line = checker.locator.compute_line_index(shadowed.range.start());
222+
let line = checker.locator.compute_line_index(shadowed.start());
222223
let mut diagnostic = Diagnostic::new(
223224
pyflakes::rules::RedefinedWhileUnused {
224225
name: (*name).to_string(),
225226
line,
226227
},
227-
binding.range,
228+
binding.range(),
228229
);
229230
if let Some(range) = binding.parent_range(&checker.semantic) {
230231
diagnostic.set_parent(range.start());

crates/ruff/src/checkers/ast/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1855,7 +1855,7 @@ impl<'a> Checker<'a> {
18551855
.map(|binding_id| &self.semantic.bindings[binding_id])
18561856
.filter_map(|binding| match &binding.kind {
18571857
BindingKind::Export(Export { names }) => {
1858-
Some(names.iter().map(|name| (*name, binding.range)))
1858+
Some(names.iter().map(|name| (*name, binding.range())))
18591859
}
18601860
_ => None,
18611861
})

crates/ruff/src/checkers/logical_lines.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
use ruff_python_parser::lexer::LexResult;
2-
use ruff_text_size::TextRange;
3-
41
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
2+
use ruff_python_ast::Ranged;
53
use ruff_python_codegen::Stylist;
4+
use ruff_python_parser::lexer::LexResult;
65
use ruff_python_parser::TokenKind;
76
use ruff_source_file::Locator;
7+
use ruff_text_size::TextRange;
88

99
use crate::registry::{AsRule, Rule};
1010
use crate::rules::pycodestyle::rules::logical_lines::{

crates/ruff/src/docstrings/mod.rs

+11-21
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ use std::fmt::{Debug, Formatter};
22
use std::ops::Deref;
33

44
use ruff_python_ast::{Expr, Ranged};
5-
use ruff_text_size::{TextRange, TextSize};
6-
75
use ruff_python_semantic::Definition;
6+
use ruff_text_size::TextRange;
87

98
pub(crate) mod extraction;
109
pub(crate) mod google;
@@ -28,21 +27,15 @@ impl<'a> Docstring<'a> {
2827
DocstringBody { docstring: self }
2928
}
3029

31-
pub(crate) fn start(&self) -> TextSize {
32-
self.expr.start()
33-
}
34-
35-
pub(crate) fn end(&self) -> TextSize {
36-
self.expr.end()
30+
pub(crate) fn leading_quote(&self) -> &'a str {
31+
&self.contents[TextRange::up_to(self.body_range.start())]
3732
}
33+
}
3834

39-
pub(crate) fn range(&self) -> TextRange {
35+
impl Ranged for Docstring<'_> {
36+
fn range(&self) -> TextRange {
4037
self.expr.range()
4138
}
42-
43-
pub(crate) fn leading_quote(&self) -> &'a str {
44-
&self.contents[TextRange::up_to(self.body_range.start())]
45-
}
4639
}
4740

4841
#[derive(Copy, Clone)]
@@ -51,18 +44,15 @@ pub(crate) struct DocstringBody<'a> {
5144
}
5245

5346
impl<'a> DocstringBody<'a> {
54-
#[inline]
55-
pub(crate) fn start(self) -> TextSize {
56-
self.range().start()
47+
pub(crate) fn as_str(self) -> &'a str {
48+
&self.docstring.contents[self.docstring.body_range]
5749
}
50+
}
5851

59-
pub(crate) fn range(self) -> TextRange {
52+
impl Ranged for DocstringBody<'_> {
53+
fn range(&self) -> TextRange {
6054
self.docstring.body_range + self.docstring.start()
6155
}
62-
63-
pub(crate) fn as_str(self) -> &'a str {
64-
&self.docstring.contents[self.docstring.body_range]
65-
}
6656
}
6757

6858
impl Deref for DocstringBody<'_> {

crates/ruff/src/docstrings/sections.rs

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::fmt::{Debug, Formatter};
22
use std::iter::FusedIterator;
33

44
use ruff_python_ast::docstrings::{leading_space, leading_words};
5+
use ruff_python_ast::Ranged;
56
use ruff_text_size::{TextLen, TextRange, TextSize};
67
use strum_macros::EnumIter;
78

@@ -366,6 +367,12 @@ impl<'a> SectionContext<'a> {
366367
}
367368
}
368369

370+
impl Ranged for SectionContext<'_> {
371+
fn range(&self) -> TextRange {
372+
self.range()
373+
}
374+
}
375+
369376
impl Debug for SectionContext<'_> {
370377
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
371378
f.debug_struct("SectionContext")

crates/ruff/src/importer/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl<'a> Importer<'a> {
194194
// import and the current location, and thus the symbol would not be available). It's also
195195
// unclear whether should add an import statement at the start of the file, since it could
196196
// be shadowed between the import and the current location.
197-
if imported_name.range().start() > at {
197+
if imported_name.start() > at {
198198
return Some(Err(ResolutionError::ImportAfterUsage));
199199
}
200200

crates/ruff/src/renamer.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use anyhow::{anyhow, Result};
44
use itertools::Itertools;
55

66
use ruff_diagnostics::Edit;
7+
use ruff_python_ast::Ranged;
78
use ruff_python_semantic::{Binding, BindingKind, Scope, ScopeId, SemanticModel};
89

910
pub(crate) struct Renamer;
@@ -220,12 +221,12 @@ impl Renamer {
220221
BindingKind::Import(_) | BindingKind::FromImport(_) => {
221222
if binding.is_alias() {
222223
// Ex) Rename `import pandas as alias` to `import pandas as pd`.
223-
Some(Edit::range_replacement(target.to_string(), binding.range))
224+
Some(Edit::range_replacement(target.to_string(), binding.range()))
224225
} else {
225226
// Ex) Rename `import pandas` to `import pandas as pd`.
226227
Some(Edit::range_replacement(
227228
format!("{name} as {target}"),
228-
binding.range,
229+
binding.range(),
229230
))
230231
}
231232
}
@@ -234,7 +235,7 @@ impl Renamer {
234235
let module_name = import.call_path.first().unwrap();
235236
Some(Edit::range_replacement(
236237
format!("{module_name} as {target}"),
237-
binding.range,
238+
binding.range(),
238239
))
239240
}
240241
// Avoid renaming builtins and other "special" bindings.
@@ -254,7 +255,7 @@ impl Renamer {
254255
| BindingKind::FunctionDefinition(_)
255256
| BindingKind::Deletion
256257
| BindingKind::UnboundException(_) => {
257-
Some(Edit::range_replacement(target.to_string(), binding.range))
258+
Some(Edit::range_replacement(target.to_string(), binding.range()))
258259
}
259260
}
260261
}

crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr,
163163
if scope
164164
.get_all(name)
165165
.map(|binding_id| checker.semantic().binding(binding_id))
166-
.filter(|binding| binding.range.start() >= expr.range().start())
166+
.filter(|binding| binding.start() >= expr.start())
167167
.all(|binding| !binding.is_used())
168168
{
169169
diagnostic.set_fix(Fix::suggested(Edit::range_replacement(

crates/ruff/src/rules/flake8_import_conventions/rules/unconventional_import_alias.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use rustc_hash::FxHashMap;
22

33
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
44
use ruff_macros::{derive_message_formats, violation};
5+
use ruff_python_ast::Ranged;
56
use ruff_python_semantic::{Binding, Imported};
67

78
use crate::checkers::ast::Checker;
@@ -76,7 +77,7 @@ pub(crate) fn unconventional_import_alias(
7677
name: qualified_name,
7778
asname: expected_alias.to_string(),
7879
},
79-
binding.range,
80+
binding.range(),
8081
);
8182
if checker.patch(diagnostic.kind.rule()) {
8283
if checker.semantic().is_available(expected_alias) {

crates/ruff/src/rules/flake8_pyi/rules/unaliased_collections_abc_set_import.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
22
use ruff_macros::{derive_message_formats, violation};
3+
use ruff_python_ast::Ranged;
34
use ruff_python_semantic::Imported;
45
use ruff_python_semantic::{Binding, BindingKind};
56

@@ -63,7 +64,7 @@ pub(crate) fn unaliased_collections_abc_set_import(
6364
return None;
6465
}
6566

66-
let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range);
67+
let mut diagnostic = Diagnostic::new(UnaliasedCollectionsAbcSetImport, binding.range());
6768
if checker.patch(diagnostic.kind.rule()) {
6869
if checker.semantic().is_available("AbstractSet") {
6970
diagnostic.try_set_fix(|| {

crates/ruff/src/rules/flake8_pyi/rules/unused_private_type_definition.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use ruff_diagnostics::{Diagnostic, Violation};
22
use ruff_macros::{derive_message_formats, violation};
3-
use ruff_python_ast::{self as ast, Expr, Stmt};
3+
use ruff_python_ast::{self as ast, Expr, Ranged, Stmt};
44
use ruff_python_semantic::Scope;
55

66
use crate::checkers::ast::Checker;
@@ -192,7 +192,7 @@ pub(crate) fn unused_private_type_var(
192192
UnusedPrivateTypeVar {
193193
name: id.to_string(),
194194
},
195-
binding.range,
195+
binding.range(),
196196
));
197197
}
198198
}
@@ -234,7 +234,7 @@ pub(crate) fn unused_private_protocol(
234234
UnusedPrivateProtocol {
235235
name: class_def.name.to_string(),
236236
},
237-
binding.range,
237+
binding.range(),
238238
));
239239
}
240240
}
@@ -280,7 +280,7 @@ pub(crate) fn unused_private_type_alias(
280280
UnusedPrivateTypeAlias {
281281
name: id.to_string(),
282282
},
283-
binding.range,
283+
binding.range(),
284284
));
285285
}
286286
}
@@ -321,7 +321,7 @@ pub(crate) fn unused_private_typed_dict(
321321
UnusedPrivateTypedDict {
322322
name: class_def.name.to_string(),
323323
},
324-
binding.range,
324+
binding.range(),
325325
));
326326
}
327327
}

crates/ruff/src/rules/flake8_return/rules/function.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack) {
558558
// Replace from the start of the assignment statement to the end of the equals
559559
// sign.
560560
TextRange::new(
561-
assign.range().start(),
561+
assign.start(),
562562
assign
563563
.range()
564564
.start()

crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt) {
693693
fn body_range(branch: &IfElifBranch, locator: &Locator) -> TextRange {
694694
TextRange::new(
695695
locator.line_end(branch.test.end()),
696-
locator.line_end(branch.range.end()),
696+
locator.line_end(branch.end()),
697697
)
698698
}
699699

@@ -731,7 +731,7 @@ pub(crate) fn if_with_same_arms(checker: &mut Checker, locator: &Locator, stmt_i
731731

732732
checker.diagnostics.push(Diagnostic::new(
733733
IfWithSameArms,
734-
TextRange::new(current_branch.range.start(), following_branch.range.end()),
734+
TextRange::new(current_branch.start(), following_branch.end()),
735735
));
736736
}
737737
}

crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_hash::FxHashMap;
55

66
use ruff_diagnostics::{AutofixKind, Diagnostic, Fix, Violation};
77
use ruff_macros::{derive_message_formats, violation};
8+
use ruff_python_ast::Ranged;
89
use ruff_python_semantic::{AnyImport, Imported, ResolvedReferenceId, Scope, StatementId};
910
use ruff_text_size::TextRange;
1011

@@ -101,11 +102,11 @@ pub(crate) fn runtime_import_in_type_checking_block(
101102
let import = ImportBinding {
102103
import,
103104
reference_id,
104-
range: binding.range,
105+
range: binding.range(),
105106
parent_range: binding.parent_range(checker.semantic()),
106107
};
107108

108-
if checker.rule_is_ignored(Rule::RuntimeImportInTypeCheckingBlock, import.range.start())
109+
if checker.rule_is_ignored(Rule::RuntimeImportInTypeCheckingBlock, import.start())
109110
|| import.parent_range.is_some_and(|parent_range| {
110111
checker.rule_is_ignored(
111112
Rule::RuntimeImportInTypeCheckingBlock,
@@ -192,6 +193,12 @@ struct ImportBinding<'a> {
192193
parent_range: Option<TextRange>,
193194
}
194195

196+
impl Ranged for ImportBinding<'_> {
197+
fn range(&self) -> TextRange {
198+
self.range
199+
}
200+
}
201+
195202
/// Generate a [`Fix`] to remove runtime imports from a type-checking block.
196203
fn fix_imports(
197204
checker: &Checker,
@@ -211,7 +218,7 @@ fn fix_imports(
211218
let at = imports
212219
.iter()
213220
.map(|ImportBinding { reference_id, .. }| {
214-
checker.semantic().reference(*reference_id).range().start()
221+
checker.semantic().reference(*reference_id).start()
215222
})
216223
.min()
217224
.expect("Expected at least one import");

0 commit comments

Comments
 (0)