mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-17 09:17:14 +00:00
Update comments / docs for Spanned
(#1549)
Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com>
This commit is contained in:
parent
f4f112d7d6
commit
4ab3ab9147
8 changed files with 306 additions and 91 deletions
132
src/tokenizer.rs
132
src/tokenizer.rs
|
@ -422,13 +422,35 @@ impl fmt::Display for Whitespace {
|
|||
}
|
||||
|
||||
/// Location in input string
|
||||
///
|
||||
/// # Create an "empty" (unknown) `Location`
|
||||
/// ```
|
||||
/// # use sqlparser::tokenizer::Location;
|
||||
/// let location = Location::empty();
|
||||
/// ```
|
||||
///
|
||||
/// # Create a `Location` from a line and column
|
||||
/// ```
|
||||
/// # use sqlparser::tokenizer::Location;
|
||||
/// let location = Location::new(1, 1);
|
||||
/// ```
|
||||
///
|
||||
/// # Create a `Location` from a pair
|
||||
/// ```
|
||||
/// # use sqlparser::tokenizer::Location;
|
||||
/// let location = Location::from((1, 1));
|
||||
/// ```
|
||||
#[derive(Eq, PartialEq, Hash, Clone, Copy, Ord, PartialOrd)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
pub struct Location {
|
||||
/// Line number, starting from 1
|
||||
/// Line number, starting from 1.
|
||||
///
|
||||
/// Note: Line 0 is used for empty spans
|
||||
pub line: u64,
|
||||
/// Line column, starting from 1
|
||||
/// Line column, starting from 1.
|
||||
///
|
||||
/// Note: Column 0 is used for empty spans
|
||||
pub column: u64,
|
||||
}
|
||||
|
||||
|
@ -448,10 +470,25 @@ impl fmt::Debug for Location {
|
|||
}
|
||||
|
||||
impl Location {
|
||||
pub fn of(line: u64, column: u64) -> Self {
|
||||
/// Return an "empty" / unknown location
|
||||
pub fn empty() -> Self {
|
||||
Self { line: 0, column: 0 }
|
||||
}
|
||||
|
||||
/// Create a new `Location` for a given line and column
|
||||
pub fn new(line: u64, column: u64) -> Self {
|
||||
Self { line, column }
|
||||
}
|
||||
|
||||
/// Create a new location for a given line and column
|
||||
///
|
||||
/// Alias for [`Self::new`]
|
||||
// TODO: remove / deprecate in favor of` `new` for consistency?
|
||||
pub fn of(line: u64, column: u64) -> Self {
|
||||
Self::new(line, column)
|
||||
}
|
||||
|
||||
/// Combine self and `end` into a new `Span`
|
||||
pub fn span_to(self, end: Self) -> Span {
|
||||
Span { start: self, end }
|
||||
}
|
||||
|
@ -463,7 +500,9 @@ impl From<(u64, u64)> for Location {
|
|||
}
|
||||
}
|
||||
|
||||
/// A span of source code locations (start, end)
|
||||
/// A span represents a linear portion of the input string (start, end)
|
||||
///
|
||||
/// See [Spanned](crate::ast::Spanned) for more information.
|
||||
#[derive(Eq, PartialEq, Hash, Clone, PartialOrd, Ord, Copy)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
|
@ -483,12 +522,15 @@ impl Span {
|
|||
// We need a const instance for pattern matching
|
||||
const EMPTY: Span = Self::empty();
|
||||
|
||||
/// Create a new span from a start and end [`Location`]
|
||||
pub fn new(start: Location, end: Location) -> Span {
|
||||
Span { start, end }
|
||||
}
|
||||
|
||||
/// Returns an empty span (0, 0) -> (0, 0)
|
||||
/// Returns an empty span `(0, 0) -> (0, 0)`
|
||||
///
|
||||
/// Empty spans represent no knowledge of source location
|
||||
/// See [Spanned](crate::ast::Spanned) for more information.
|
||||
pub const fn empty() -> Span {
|
||||
Span {
|
||||
start: Location { line: 0, column: 0 },
|
||||
|
@ -498,6 +540,19 @@ impl Span {
|
|||
|
||||
/// Returns the smallest Span that contains both `self` and `other`
|
||||
/// If either span is [Span::empty], the other span is returned
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use sqlparser::tokenizer::{Span, Location};
|
||||
/// // line 1, column1 -> line 2, column 5
|
||||
/// let span1 = Span::new(Location::new(1, 1), Location::new(2, 5));
|
||||
/// // line 2, column 3 -> line 3, column 7
|
||||
/// let span2 = Span::new(Location::new(2, 3), Location::new(3, 7));
|
||||
/// // Union of the two is the min/max of the two spans
|
||||
/// // line 1, column 1 -> line 3, column 7
|
||||
/// let union = span1.union(&span2);
|
||||
/// assert_eq!(union, Span::new(Location::new(1, 1), Location::new(3, 7)));
|
||||
/// ```
|
||||
pub fn union(&self, other: &Span) -> Span {
|
||||
// If either span is empty, return the other
|
||||
// this prevents propagating (0, 0) through the tree
|
||||
|
@ -512,6 +567,7 @@ impl Span {
|
|||
}
|
||||
|
||||
/// Same as [Span::union] for `Option<Span>`
|
||||
///
|
||||
/// If `other` is `None`, `self` is returned
|
||||
pub fn union_opt(&self, other: &Option<Span>) -> Span {
|
||||
match other {
|
||||
|
@ -519,13 +575,57 @@ impl Span {
|
|||
None => *self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the [Span::union] of all spans in the iterator
|
||||
///
|
||||
/// If the iterator is empty, an empty span is returned
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use sqlparser::tokenizer::{Span, Location};
|
||||
/// let spans = vec![
|
||||
/// Span::new(Location::new(1, 1), Location::new(2, 5)),
|
||||
/// Span::new(Location::new(2, 3), Location::new(3, 7)),
|
||||
/// Span::new(Location::new(3, 1), Location::new(4, 2)),
|
||||
/// ];
|
||||
/// // line 1, column 1 -> line 4, column 2
|
||||
/// assert_eq!(
|
||||
/// Span::union_iter(spans),
|
||||
/// Span::new(Location::new(1, 1), Location::new(4, 2))
|
||||
/// );
|
||||
pub fn union_iter<I: IntoIterator<Item = Span>>(iter: I) -> Span {
|
||||
iter.into_iter()
|
||||
.reduce(|acc, item| acc.union(&item))
|
||||
.unwrap_or(Span::empty())
|
||||
}
|
||||
}
|
||||
|
||||
/// Backwards compatibility struct for [`TokenWithSpan`]
|
||||
#[deprecated(since = "0.53.0", note = "please use `TokenWithSpan` instead")]
|
||||
pub type TokenWithLocation = TokenWithSpan;
|
||||
|
||||
/// A [Token] with [Location] attached to it
|
||||
/// A [Token] with [Span] attached to it
|
||||
///
|
||||
/// This is used to track the location of a token in the input string
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use sqlparser::tokenizer::{Location, Span, Token, TokenWithSpan};
|
||||
/// // commas @ line 1, column 10
|
||||
/// let tok1 = TokenWithSpan::new(
|
||||
/// Token::Comma,
|
||||
/// Span::new(Location::new(1, 10), Location::new(1, 11)),
|
||||
/// );
|
||||
/// assert_eq!(tok1, Token::Comma); // can compare the token
|
||||
///
|
||||
/// // commas @ line 2, column 20
|
||||
/// let tok2 = TokenWithSpan::new(
|
||||
/// Token::Comma,
|
||||
/// Span::new(Location::new(2, 20), Location::new(2, 21)),
|
||||
/// );
|
||||
/// // same token but different locations are not equal
|
||||
/// assert_ne!(tok1, tok2);
|
||||
/// ```
|
||||
#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||
|
@ -535,16 +635,24 @@ pub struct TokenWithSpan {
|
|||
}
|
||||
|
||||
impl TokenWithSpan {
|
||||
pub fn new(token: Token, span: Span) -> TokenWithSpan {
|
||||
TokenWithSpan { token, span }
|
||||
/// Create a new [`TokenWithSpan`] from a [`Token`] and a [`Span`]
|
||||
pub fn new(token: Token, span: Span) -> Self {
|
||||
Self { token, span }
|
||||
}
|
||||
|
||||
pub fn wrap(token: Token) -> TokenWithSpan {
|
||||
TokenWithSpan::new(token, Span::empty())
|
||||
/// Wrap a token with an empty span
|
||||
pub fn wrap(token: Token) -> Self {
|
||||
Self::new(token, Span::empty())
|
||||
}
|
||||
|
||||
pub fn at(token: Token, start: Location, end: Location) -> TokenWithSpan {
|
||||
TokenWithSpan::new(token, Span::new(start, end))
|
||||
/// Wrap a token with a location from `start` to `end`
|
||||
pub fn at(token: Token, start: Location, end: Location) -> Self {
|
||||
Self::new(token, Span::new(start, end))
|
||||
}
|
||||
|
||||
/// Return an EOF token with no location
|
||||
pub fn new_eof() -> Self {
|
||||
Self::wrap(Token::EOF)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue