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}