@@ -238,13 +238,18 @@ def visitField(self, field, parent, vis, depth, constructor=None):
238
238
if fieldtype and fieldtype .has_userdata :
239
239
typ = f"{ typ } <U>"
240
240
# 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
+ ):
242
246
typ = f"Box<{ typ } >"
243
247
if field .opt or (
244
248
# When a dictionary literal contains dictionary unpacking (e.g., `{**d}`),
245
249
# the expression to be unpacked goes in `values` with a `None` at the corresponding
246
250
# 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"
248
253
):
249
254
typ = f"Option<{ typ } >"
250
255
if field .seq :
@@ -311,7 +316,7 @@ def visitModule(self, mod, depth):
311
316
depth ,
312
317
)
313
318
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)? })" ,
315
320
depth + 1 ,
316
321
)
317
322
self .emit ("}" , depth )
@@ -649,7 +654,7 @@ def write_ast_def(mod, typeinfo, f):
649
654
#![allow(clippy::derive_partial_eq_without_eq)]
650
655
651
656
pub use crate::constant::*;
652
- pub use crate::Location ;
657
+ pub use ruff_text_size::{TextSize, TextRange} ;
653
658
654
659
type Ident = String;
655
660
\n
@@ -661,26 +666,54 @@ def write_ast_def(mod, typeinfo, f):
661
666
textwrap .dedent (
662
667
"""
663
668
pub struct Located<T, U = ()> {
664
- pub location: Location,
665
- pub end_location: Option<Location>,
669
+ pub range: TextRange,
666
670
pub custom: U,
667
671
pub node: T,
668
672
}
669
673
670
674
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 }
673
677
}
674
678
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()
677
716
}
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
- }
684
717
}
685
718
686
719
impl<T, U> std::ops::Deref for Located<T, U> {
0 commit comments