Skip to content

Commit dda5536

Browse files
MichaReiseryouknowone
authored andcommitted
Replace row/column based Location with byte-offsets.
1 parent a73bac9 commit dda5536

File tree

129 files changed

+2740
-13810
lines changed

Some content is hidden

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

129 files changed

+2740
-13810
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ include = ["LICENSE", "Cargo.toml", "src/**/*.rs"]
1212
resolver = "2"
1313
members = [
1414
"ast", "core", "literal", "parser",
15+
"ruff_text_size",
1516
]
1617

1718
[workspace.dependencies]

ast/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ unparse = ["rustpython-literal"]
1616
[dependencies]
1717
rustpython-compiler-core = { path = "../core", version = "0.2.0" }
1818
rustpython-literal = { path = "../literal", version = "0.2.0", optional = true }
19+
ruff_text_size = { path = "../ruff_text_size" }
1920

2021
num-bigint = { workspace = true }

ast/asdl_rs.py

+49-16
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,18 @@ def visitField(self, field, parent, vis, depth, constructor=None):
238238
if fieldtype and fieldtype.has_userdata:
239239
typ = f"{typ}<U>"
240240
# don't box if we're doing Vec<T>, but do box if we're doing Vec<Option<Box<T>>>
241-
if fieldtype and fieldtype.boxed and (not (parent.product or field.seq) or field.opt):
241+
if (
242+
fieldtype
243+
and fieldtype.boxed
244+
and (not (parent.product or field.seq) or field.opt)
245+
):
242246
typ = f"Box<{typ}>"
243247
if field.opt or (
244248
# When a dictionary literal contains dictionary unpacking (e.g., `{**d}`),
245249
# the expression to be unpacked goes in `values` with a `None` at the corresponding
246250
# position in `keys`. To handle this, the type of `keys` needs to be `Option<Vec<T>>`.
247-
constructor == "Dict" and field.name == "keys"
251+
constructor == "Dict"
252+
and field.name == "keys"
248253
):
249254
typ = f"Option<{typ}>"
250255
if field.seq:
@@ -311,7 +316,7 @@ def visitModule(self, mod, depth):
311316
depth,
312317
)
313318
self.emit(
314-
"Ok(Located { custom: folder.map_user(node.custom)?, location: node.location, end_location: node.end_location, node: f(folder, node.node)? })",
319+
"Ok(Located { custom: folder.map_user(node.custom)?, range: node.range, node: f(folder, node.node)? })",
315320
depth + 1,
316321
)
317322
self.emit("}", depth)
@@ -649,7 +654,7 @@ def write_ast_def(mod, typeinfo, f):
649654
#![allow(clippy::derive_partial_eq_without_eq)]
650655
651656
pub use crate::constant::*;
652-
pub use crate::Location;
657+
pub use ruff_text_size::{TextSize, TextRange};
653658
654659
type Ident = String;
655660
\n
@@ -661,26 +666,54 @@ def write_ast_def(mod, typeinfo, f):
661666
textwrap.dedent(
662667
"""
663668
pub struct Located<T, U = ()> {
664-
pub location: Location,
665-
pub end_location: Option<Location>,
669+
pub range: TextRange,
666670
pub custom: U,
667671
pub node: T,
668672
}
669673
670674
impl<T> Located<T> {
671-
pub fn new(location: Location, end_location: Location, node: T) -> Self {
672-
Self { location, end_location: Some(end_location), custom: (), node }
675+
pub fn new(start: TextSize, end: TextSize, node: T) -> Self {
676+
Self { range: TextRange::new(start, end), custom: (), node }
673677
}
674678
675-
pub const fn start(&self) -> Location {
676-
self.location
679+
/// Creates a new node that spans the position specified by `range`.
680+
pub fn with_range(node: T, range: TextRange) -> Self {
681+
Self {
682+
range,
683+
custom: (),
684+
node,
685+
}
686+
}
687+
688+
/// Returns the absolute start position of the node from the beginning of the document.
689+
#[inline]
690+
pub const fn start(&self) -> TextSize {
691+
self.range.start()
692+
}
693+
694+
/// Returns the node
695+
#[inline]
696+
pub fn node(&self) -> &T {
697+
&self.node
698+
}
699+
700+
/// Consumes self and returns the node.
701+
#[inline]
702+
pub fn into_node(self) -> T {
703+
self.node
704+
}
705+
706+
/// Returns the `range` of the node. The range offsets are absolute to the start of the document.
707+
#[inline]
708+
pub const fn range(&self) -> TextRange {
709+
self.range
710+
}
711+
712+
/// Returns the absolute position at which the node ends in the source document.
713+
#[inline]
714+
pub const fn end(&self) -> TextSize {
715+
self.range.end()
677716
}
678-
679-
/// Returns the node's [`end_location`](Located::end_location) or [`location`](Located::start) if
680-
/// [`end_location`](Located::end_location) is `None`.
681-
pub fn end(&self) -> Location {
682-
self.end_location.unwrap_or(self.location)
683-
}
684717
}
685718
686719
impl<T, U> std::ops::Deref for Located<T, U> {

ast/src/ast_gen.rs

+40-14
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,63 @@
33
#![allow(clippy::derive_partial_eq_without_eq)]
44

55
pub use crate::constant::*;
6-
pub use crate::Location;
6+
pub use ruff_text_size::{TextRange, TextSize};
77

88
type Ident = String;
99

1010
#[derive(Clone, Debug, PartialEq)]
1111
pub struct Located<T, U = ()> {
12-
pub location: Location,
13-
pub end_location: Option<Location>,
12+
pub range: TextRange,
1413
pub custom: U,
1514
pub node: T,
1615
}
1716

1817
impl<T> Located<T> {
19-
pub fn new(location: Location, end_location: Location, node: T) -> Self {
18+
pub fn new(start: TextSize, end: TextSize, node: T) -> Self {
2019
Self {
21-
location,
22-
end_location: Some(end_location),
20+
range: TextRange::new(start, end),
2321
custom: (),
2422
node,
2523
}
2624
}
2725

28-
pub const fn start(&self) -> Location {
29-
self.location
26+
/// Creates a new node that spans the position specified by `range`.
27+
pub fn with_range(node: T, range: TextRange) -> Self {
28+
Self {
29+
range,
30+
custom: (),
31+
node,
32+
}
33+
}
34+
35+
/// Returns the absolute start position of the node from the beginning of the document.
36+
#[inline]
37+
pub const fn start(&self) -> TextSize {
38+
self.range.start()
39+
}
40+
41+
/// Returns the node
42+
#[inline]
43+
pub fn node(&self) -> &T {
44+
&self.node
45+
}
46+
47+
/// Consumes self and returns the node.
48+
#[inline]
49+
pub fn into_node(self) -> T {
50+
self.node
51+
}
52+
53+
/// Returns the `range` of the node. The range offsets are absolute to the start of the document.
54+
#[inline]
55+
pub const fn range(&self) -> TextRange {
56+
self.range
3057
}
3158

32-
/// Returns the node's [`end_location`](Located::end_location) or [`location`](Located::start) if
33-
/// [`end_location`](Located::end_location) is `None`.
34-
pub fn end(&self) -> Location {
35-
self.end_location.unwrap_or(self.location)
59+
/// Returns the absolute position at which the node ends in the source document.
60+
#[inline]
61+
pub const fn end(&self) -> TextSize {
62+
self.range.end()
3663
}
3764
}
3865

@@ -554,8 +581,7 @@ pub mod fold {
554581
) -> Result<Located<MT, F::TargetU>, F::Error> {
555582
Ok(Located {
556583
custom: folder.map_user(node.custom)?,
557-
location: node.location,
558-
end_location: node.end_location,
584+
range: node.range,
559585
node: f(folder, node.node)?,
560586
})
561587
}

ast/src/constant.rs

+11-20
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ impl<U> crate::fold::Fold<U> for ConstantOptimizer {
126126
Ok(crate::Expr {
127127
node: expr,
128128
custom: node.custom,
129-
location: node.location,
130-
end_location: node.end_location,
129+
range: node.range,
131130
})
132131
}
133132
_ => crate::fold::fold_expr(self, node),
@@ -144,62 +143,55 @@ mod tests {
144143
fn test_constant_opt() {
145144
use crate::{fold::Fold, *};
146145

147-
let start = Default::default();
148-
let end = None;
146+
let range = TextRange::default();
147+
#[allow(clippy::let_unit_value)]
149148
let custom = ();
150149
let ast = Located {
151-
location: start,
152-
end_location: end,
150+
range,
153151
custom,
154152
node: ExprKind::Tuple {
155153
ctx: ExprContext::Load,
156154
elts: vec![
157155
Located {
158-
location: start,
159-
end_location: end,
156+
range,
160157
custom,
161158
node: ExprKind::Constant {
162159
value: BigInt::from(1).into(),
163160
kind: None,
164161
},
165162
},
166163
Located {
167-
location: start,
168-
end_location: end,
164+
range,
169165
custom,
170166
node: ExprKind::Constant {
171167
value: BigInt::from(2).into(),
172168
kind: None,
173169
},
174170
},
175171
Located {
176-
location: start,
177-
end_location: end,
172+
range,
178173
custom,
179174
node: ExprKind::Tuple {
180175
ctx: ExprContext::Load,
181176
elts: vec![
182177
Located {
183-
location: start,
184-
end_location: end,
178+
range,
185179
custom,
186180
node: ExprKind::Constant {
187181
value: BigInt::from(3).into(),
188182
kind: None,
189183
},
190184
},
191185
Located {
192-
location: start,
193-
end_location: end,
186+
range,
194187
custom,
195188
node: ExprKind::Constant {
196189
value: BigInt::from(4).into(),
197190
kind: None,
198191
},
199192
},
200193
Located {
201-
location: start,
202-
end_location: end,
194+
range,
203195
custom,
204196
node: ExprKind::Constant {
205197
value: BigInt::from(5).into(),
@@ -218,8 +210,7 @@ mod tests {
218210
assert_eq!(
219211
new_ast,
220212
Located {
221-
location: start,
222-
end_location: end,
213+
range,
223214
custom,
224215
node: ExprKind::Constant {
225216
value: Constant::Tuple(vec![

ast/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,5 @@ mod impls;
77
mod unparse;
88

99
pub use ast_gen::*;
10-
pub use rustpython_compiler_core::Location;
1110

1211
pub type Suite<U = ()> = Vec<Stmt<U>>;

core/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ license = "MIT"
99

1010
[dependencies]
1111
bitflags = { workspace = true }
12-
bstr = { workspace = true }
1312
itertools = { workspace = true }
1413
num-bigint = { workspace = true }
1514
num-complex = { workspace = true }
1615
serde = { version = "1.0.133", optional = true, default-features = false, features = ["derive"] }
16+
ruff_text_size = { path = "../ruff_text_size" }
1717

1818
lz4_flex = "0.9.2"
19+

core/src/error.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::Location;
1+
use ruff_text_size::TextSize;
22
use std::error::Error as StdError;
33
use std::fmt::Display;
44

55
#[derive(Debug, PartialEq, Eq)]
66
pub struct BaseError<T> {
77
pub error: T,
8-
pub location: Location,
8+
pub location: TextSize,
99
pub source_path: String,
1010
}
1111

@@ -31,7 +31,12 @@ where
3131
T: std::fmt::Display,
3232
{
3333
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
34-
self.location.fmt_with(f, &self.error)
34+
write!(
35+
f,
36+
"{} at byte offset {}",
37+
&self.error,
38+
u32::from(self.location)
39+
)
3540
}
3641
}
3742

parser/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ tiny-keccak = { version = "2", features = ["sha3"] }
2121
[dependencies]
2222
rustpython-ast = { path = "../ast", version = "0.2.0" }
2323
rustpython-compiler-core = { path = "../core", version = "0.2.0" }
24+
ruff_text_size = { path = "../ruff_text_size" }
2425

2526
ahash = { workspace = true }
2627
itertools = { workspace = true }

parser/src/function.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
ast,
55
lexer::{LexicalError, LexicalErrorType},
66
};
7+
use ruff_text_size::TextSize;
78
use rustc_hash::FxHashSet;
89

910
pub(crate) struct ArgumentList {
@@ -83,10 +84,7 @@ pub(crate) fn parse_params(
8384
Ok((pos_only, names, defaults))
8485
}
8586

86-
type FunctionArgument = (
87-
Option<(ast::Location, ast::Location, Option<String>)>,
88-
ast::Expr,
89-
);
87+
type FunctionArgument = (Option<(TextSize, TextSize, Option<String>)>, ast::Expr);
9088

9189
// Parse arguments as supplied during a function/lambda *call*.
9290
pub(crate) fn parse_args(func_args: Vec<FunctionArgument>) -> Result<ArgumentList, LexicalError> {

0 commit comments

Comments
 (0)