sqlparser/ast/helpers/
attached_token.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
19use core::fmt::{self, Debug, Formatter};
20use core::hash::{Hash, Hasher};
21
22use crate::tokenizer::TokenWithSpan;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Serialize};
26
27#[cfg(feature = "visitor")]
28use yachtsql_sqlparser_derive::{Visit, VisitMut};
29
30/// A wrapper over [`TokenWithSpan`]s that ignores the token and source
31/// location in comparisons and hashing.
32///
33/// This type is used when the token and location is not relevant for semantics,
34/// but is still needed for accurate source location tracking, for example, in
35/// the nodes in the [ast](crate::ast) module.
36///
37/// Note: **All** `AttachedTokens` are equal.
38///
39/// # Examples
40///
41/// Same token, different location are equal
42/// ```
43/// # use sqlparser::ast::helpers::attached_token::AttachedToken;
44/// # use sqlparser::tokenizer::{Location, Span, Token, TokenWithLocation};
45/// // commas @ line 1, column 10
46/// let tok1 = TokenWithLocation::new(
47///   Token::Comma,
48///   Span::new(Location::new(1, 10), Location::new(1, 11)),
49/// );
50/// // commas @ line 2, column 20
51/// let tok2 = TokenWithLocation::new(
52///   Token::Comma,
53///   Span::new(Location::new(2, 20), Location::new(2, 21)),
54/// );
55///
56/// assert_ne!(tok1, tok2); // token with locations are *not* equal
57/// assert_eq!(AttachedToken(tok1), AttachedToken(tok2)); // attached tokens are
58/// ```
59///
60/// Different token, different location are equal 🤯
61///
62/// ```
63/// # use sqlparser::ast::helpers::attached_token::AttachedToken;
64/// # use sqlparser::tokenizer::{Location, Span, Token, TokenWithLocation};
65/// // commas @ line 1, column 10
66/// let tok1 = TokenWithLocation::new(
67///   Token::Comma,
68///   Span::new(Location::new(1, 10), Location::new(1, 11)),
69/// );
70/// // period @ line 2, column 20
71/// let tok2 = TokenWithLocation::new(
72///  Token::Period,
73///   Span::new(Location::new(2, 10), Location::new(2, 21)),
74/// );
75///
76/// assert_ne!(tok1, tok2); // token with locations are *not* equal
77/// assert_eq!(AttachedToken(tok1), AttachedToken(tok2)); // attached tokens are
78/// ```
79/// // period @ line 2, column 20
80#[derive(Clone)]
81#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
82#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
83pub struct AttachedToken(pub TokenWithSpan);
84
85impl AttachedToken {
86    /// Return a new Empty AttachedToken
87    pub fn empty() -> Self {
88        AttachedToken(TokenWithSpan::new_eof())
89    }
90}
91
92// Conditional Implementations
93impl Debug for AttachedToken {
94    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
95        self.0.fmt(f)
96    }
97}
98
99// Blanket Implementations
100impl PartialEq for AttachedToken {
101    fn eq(&self, _: &Self) -> bool {
102        true
103    }
104}
105
106impl Eq for AttachedToken {}
107
108impl PartialOrd for AttachedToken {
109    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
110        Some(self.cmp(other))
111    }
112}
113
114impl Ord for AttachedToken {
115    fn cmp(&self, _: &Self) -> Ordering {
116        Ordering::Equal
117    }
118}
119
120impl Hash for AttachedToken {
121    fn hash<H: Hasher>(&self, _state: &mut H) {
122        // Do nothing
123    }
124}
125
126impl From<TokenWithSpan> for AttachedToken {
127    fn from(value: TokenWithSpan) -> Self {
128        AttachedToken(value)
129    }
130}
131
132impl From<AttachedToken> for TokenWithSpan {
133    fn from(value: AttachedToken) -> Self {
134        value.0
135    }
136}