Skip to content

Commit 903f24a

Browse files
committed
pr feedback
1 parent 6bfe13f commit 903f24a

File tree

7 files changed

+27
-48
lines changed

7 files changed

+27
-48
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ issues and distinguish different syntaxes in the AST.
102102

103103
## WIP: Extracting source locations from AST nodes
104104

105-
This crate allows recovering source locations from AST nodes via the [Spanned](https://docs.rs/sqlparser/latest/sqlparser/ast/trait.Spanned.html) trait, which can be used for advanced diagnostics tooling. Node that this feature is a work in progress and many nodes report missing or inaccurate spans. Please see [this document](./docs/source_spans.md#source-span-contributing-guidelines) for information on how to contribute missing improvements.
105+
This crate allows recovering source locations from AST nodes via the [Spanned](https://docs.rs/sqlparser/latest/sqlparser/ast/trait.Spanned.html) trait, which can be used for advanced diagnostics tooling. Note that this feature is a work in progress and many nodes report missing or inaccurate spans. Please see [this document](./docs/source_spans.md#source-span-contributing-guidelines) for information on how to contribute missing improvements.
106106

107107
```rust
108108
use sqlparser::ast::Spanned;

docs/source_spans.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ These are the current breaking changes introduced by the source spans feature:
88
- `Select`, `With`, `Cte`, `WildcardAdditionalOptions` now store a `TokenWithLocation`
99

1010
#### Misc.
11-
- `TokenWithLocation` stores a full `Span`, rathern than just a source location. Users relying on `token.location` should use `token.location.start` instead.
11+
- `TokenWithLocation` stores a full `Span`, rather than just a source location. Users relying on `token.location` should use `token.location.start` instead.
1212
## Source Span Contributing Guidelines
1313

1414
For contributing source spans improvement in addition to the general [contribution guidelines](../README.md#contributing), please make sure to pay attention to the following:
@@ -25,7 +25,7 @@ The primary reason for missing and inaccurate source spans at this time is missi
2525

2626
When considering adding support for source spans on a type, consider the impact to consumers of that type and whether your change would require a consumer to do non-trivial changes to their code.
2727

28-
f.e. of a trivial change
28+
Example of a trivial change
2929
```rust
3030
match node {
3131
ast::Query {
@@ -39,11 +39,11 @@ If adding source spans to a type would require a significant change like wrappin
3939

4040
### AST Node Equality and Hashes
4141

42-
When adding tokens to AST nodes, make sure to wrap them in the [IgnoreField](https://docs.rs/sqlparser/latest/sqlparser/ast/helpers/struct.IgnoreField.html) helper to ensure that semantically equivalent AST nodes always compare as equal and hash to the same value. F.e. `select 5` and `SELECT 5` would compare as different `Select` nodes, if the select token was stored directly. f.e.
42+
When adding tokens to AST nodes, make sure to store them using the [AttachedToken](https://docs.rs/sqlparser/latest/sqlparser/ast/helpers/struct.AttachedToken.html) helper to ensure that semantically equivalent AST nodes always compare as equal and hash to the same value. F.e. `select 5` and `SELECT 5` would compare as different `Select` nodes, if the select token was stored directly. f.e.
4343

4444
```rust
4545
struct Select {
46-
select_token: IgnoreField<TokenWithLocation>, // only used for spans
46+
select_token: AttachedToken, // only used for spans
4747
/// remaining fields
4848
field1,
4949
field2,

src/ast/helpers/attached_token.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@ use core::hash::{Hash, Hasher};
2121

2222
use crate::tokenizer::TokenWithLocation;
2323

24+
#[cfg(feature = "serde")]
25+
use serde::{Deserialize, Serialize};
26+
27+
#[cfg(feature = "visitor")]
28+
use sqlparser_derive::{Visit, VisitMut};
29+
2430
/// A wrapper type for attaching tokens to AST nodes that should be ignored in comparisons and hashing.
2531
/// This should be used when a token is not relevant for semantics, but is still needed for
2632
/// accurate source location tracking.
2733
#[derive(Clone)]
34+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2836
pub struct AttachedToken(pub TokenWithLocation);
2937

3038
// Conditional Implementations

src/ast/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use alloc::{
2323
string::{String, ToString},
2424
vec::Vec,
2525
};
26+
use helpers::attached_token::AttachedToken;
2627

2728
use core::ops::Deref;
2829
use core::{
@@ -36,7 +37,7 @@ use serde::{Deserialize, Serialize};
3637
#[cfg(feature = "visitor")]
3738
use sqlparser_derive::{Visit, VisitMut};
3839

39-
use crate::tokenizer::{Span, TokenWithLocation};
40+
use crate::tokenizer::Span;
4041

4142
pub use self::data_type::{
4243
ArrayElemTypeDef, CharLengthUnits, CharacterLength, DataType, ExactNumberInfo,
@@ -967,10 +968,10 @@ pub enum Expr {
967968
/// `<search modifier>`
968969
opt_search_modifier: Option<SearchModifier>,
969970
},
970-
Wildcard(TokenWithLocation),
971+
Wildcard(AttachedToken),
971972
/// Qualified wildcard, e.g. `alias.*` or `schema.table.*`.
972973
/// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.)
973-
QualifiedWildcard(ObjectName, TokenWithLocation),
974+
QualifiedWildcard(ObjectName, AttachedToken),
974975
/// Some dialects support an older syntax for outer joins where columns are
975976
/// marked with the `(+)` operator in the WHERE clause, for example:
976977
///

src/ast/spans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,13 +1372,13 @@ impl Spanned for Expr {
13721372
Expr::Map(_) => Span::empty(),
13731373
Expr::Subscript { expr, subscript } => expr.span().union(&subscript.span()),
13741374
Expr::Interval(interval) => interval.value.span(),
1375-
Expr::Wildcard(token) => token.span,
1375+
Expr::Wildcard(token) => token.0.span,
13761376
Expr::QualifiedWildcard(object_name, token) => union_spans(
13771377
object_name
13781378
.0
13791379
.iter()
13801380
.map(|i| i.span)
1381-
.chain(iter::once(token.span)),
1381+
.chain(iter::once(token.0.span)),
13821382
),
13831383
Expr::OuterJoin(expr) => expr.span(),
13841384
Expr::Prior(expr) => expr.span(),

src/parser/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ impl<'a> Parser<'a> {
886886
Token::Mul => {
887887
return Ok(Expr::QualifiedWildcard(
888888
ObjectName(id_parts),
889-
next_token,
889+
AttachedToken(next_token),
890890
));
891891
}
892892
_ => {
@@ -898,7 +898,7 @@ impl<'a> Parser<'a> {
898898
}
899899
}
900900
Token::Mul => {
901-
return Ok(Expr::Wildcard(next_token));
901+
return Ok(Expr::Wildcard(AttachedToken(next_token)));
902902
}
903903
_ => (),
904904
};
@@ -1143,7 +1143,7 @@ impl<'a> Parser<'a> {
11431143
}
11441144

11451145
if let Some(ending_wildcard_token) = ending_wildcard {
1146-
Ok(Expr::QualifiedWildcard(ObjectName(id_parts), ending_wildcard_token))
1146+
Ok(Expr::QualifiedWildcard(ObjectName(id_parts), AttachedToken(ending_wildcard_token)))
11471147
} else if self.consume_token(&Token::LParen) {
11481148
if dialect_of!(self is SnowflakeDialect | MsSqlDialect)
11491149
&& self.consume_tokens(&[Token::Plus, Token::RParen])
@@ -9203,8 +9203,7 @@ impl<'a> Parser<'a> {
92039203
}
92049204
}
92059205

9206-
/// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`),
9207-
/// assuming the initial `SELECT` was not yet consumed
9206+
/// Parse a restricted `SELECT` statement (no CTEs / `UNION` / `ORDER BY`)
92089207
pub fn parse_select(&mut self) -> Result<Select, ParserError> {
92099208
let select_token = self.expect_keyword(Keyword::SELECT)?;
92109209
let value_table_mode =
@@ -11290,10 +11289,10 @@ impl<'a> Parser<'a> {
1129011289
match self.parse_wildcard_expr()? {
1129111290
Expr::QualifiedWildcard(prefix, token) => Ok(SelectItem::QualifiedWildcard(
1129211291
prefix,
11293-
self.parse_wildcard_additional_options(token)?,
11292+
self.parse_wildcard_additional_options(token.0)?,
1129411293
)),
1129511294
Expr::Wildcard(token) => Ok(SelectItem::Wildcard(
11296-
self.parse_wildcard_additional_options(token)?,
11295+
self.parse_wildcard_additional_options(token.0)?,
1129711296
)),
1129811297
Expr::Identifier(v) if v.value.to_lowercase() == "from" && v.quote_style.is_none() => {
1129911298
parser_err!(

src/tokenizer.rs

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ use alloc::{
2929
vec,
3030
vec::Vec,
3131
};
32+
use core::iter::Peekable;
3233
use core::num::NonZeroU8;
3334
use core::str::Chars;
3435
use core::{cmp, fmt};
35-
use core::{hash, iter::Peekable};
3636

3737
#[cfg(feature = "serde")]
3838
use serde::{Deserialize, Serialize};
@@ -522,7 +522,7 @@ impl Span {
522522
}
523523

524524
/// A [Token] with [Location] attached to it
525-
#[derive(Debug, Eq, Clone)]
525+
#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
526526
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
527527
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
528528
pub struct TokenWithLocation {
@@ -544,35 +544,6 @@ impl TokenWithLocation {
544544
}
545545
}
546546

547-
impl core::hash::Hash for TokenWithLocation {
548-
fn hash<H: hash::Hasher>(&self, state: &mut H) {
549-
let TokenWithLocation { token, span: _ } = self;
550-
551-
token.hash(state);
552-
}
553-
}
554-
555-
impl PartialEq<TokenWithLocation> for TokenWithLocation {
556-
fn eq(&self, other: &TokenWithLocation) -> bool {
557-
let TokenWithLocation { token, span: _ } = self;
558-
559-
token == &other.token
560-
}
561-
}
562-
563-
impl PartialOrd<TokenWithLocation> for TokenWithLocation {
564-
fn partial_cmp(&self, other: &TokenWithLocation) -> Option<cmp::Ordering> {
565-
Some(self.cmp(other))
566-
}
567-
}
568-
569-
impl Ord for TokenWithLocation {
570-
fn cmp(&self, other: &Self) -> cmp::Ordering {
571-
let TokenWithLocation { token, span: _ } = self;
572-
token.cmp(&other.token)
573-
}
574-
}
575-
576547
impl PartialEq<Token> for TokenWithLocation {
577548
fn eq(&self, other: &Token) -> bool {
578549
&self.token == other

0 commit comments

Comments
 (0)