Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 13 additions & 35 deletions crates/squawk_ide/src/expand_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,23 @@ use squawk_syntax::{
ast::{self, AstToken},
};

const ALL_LIST_KINDS: &[SyntaxKind] = &[
const DELIMITED_LIST_KINDS: &[SyntaxKind] = &[
SyntaxKind::ARG_LIST,
SyntaxKind::ATTRIBUTE_LIST,
SyntaxKind::COLUMN_LIST,
SyntaxKind::CONSTRAINT_EXCLUSION_LIST,
// only separated by whitespace
// SyntaxKind::FUNC_OPTION_LIST,
SyntaxKind::JSON_TABLE_COLUMN_LIST,
SyntaxKind::OPTIONS_LIST,
SyntaxKind::PARAM_LIST,
// only separated by whitespace
// SyntaxKind::SEQUENCE_OPTION_LIST,
SyntaxKind::PARTITION_ITEM_LIST,
SyntaxKind::ROW_LIST,
SyntaxKind::SET_OPTIONS_LIST,
SyntaxKind::TABLE_ARG_LIST,
SyntaxKind::TABLE_LIST,
SyntaxKind::TARGET_LIST,
SyntaxKind::TRANSACTION_MODE_LIST,
SyntaxKind::VACUUM_OPTION_LIST,
SyntaxKind::VARIANT_LIST,
// only separated by whitespace
// SyntaxKind::XML_COLUMN_OPTION_LIST,
SyntaxKind::XML_TABLE_COLUMN_LIST,
];

Expand Down Expand Up @@ -117,7 +113,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option<TextRange

if node
.parent()
.is_some_and(|n| ALL_LIST_KINDS.contains(&n.kind()))
.is_some_and(|n| DELIMITED_LIST_KINDS.contains(&n.kind()))
{
if let Some(range) = extend_list_item(&node) {
return Some(range);
Expand Down Expand Up @@ -544,44 +540,26 @@ $0

#[test]
fn list_variants() {
// only separated by whitespace
const EXCLUDED_LIST_KINDS: &[SyntaxKind] = &[
let delimited_ws_list_kinds = &[
SyntaxKind::FUNC_OPTION_LIST,
SyntaxKind::SEQUENCE_OPTION_LIST,
SyntaxKind::XML_COLUMN_OPTION_LIST,
SyntaxKind::WHEN_CLAUSE_LIST,
];

let generated_list_kinds: Vec<SyntaxKind> = (0..SyntaxKind::__LAST as u16)
.map(SyntaxKind::from)
.filter(|kind| {
format!("{:?}", kind).ends_with("_LIST") && !EXCLUDED_LIST_KINDS.contains(kind)
format!("{:?}", kind).ends_with("_LIST") && !delimited_ws_list_kinds.contains(kind)
})
.collect();

assert_debug_snapshot!(generated_list_kinds, @r"
[
ARG_LIST,
ATTRIBUTE_LIST,
COLUMN_LIST,
CONSTRAINT_EXCLUSION_LIST,
JSON_TABLE_COLUMN_LIST,
OPTIONS_LIST,
PARAM_LIST,
SET_OPTIONS_LIST,
TABLE_ARG_LIST,
TABLE_LIST,
TARGET_LIST,
TRANSACTION_MODE_LIST,
VACUUM_OPTION_LIST,
VARIANT_LIST,
XML_TABLE_COLUMN_LIST,
]
");
let diff: Vec<SyntaxKind> = generated_list_kinds
.iter()
.filter(|kind| !DELIMITED_LIST_KINDS.contains(kind))
.copied()
.collect();

assert_eq!(
ALL_LIST_KINDS,
generated_list_kinds.as_slice(),
"ALL_LIST_KINDS constant is out of sync with actual _LIST variants"
);
assert_eq!(diff, vec![], "We shouldn't have any unhandled list kinds")
}
}
6 changes: 5 additions & 1 deletion crates/squawk_parser/src/generated/syntax_kind.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 51 additions & 27 deletions crates/squawk_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,20 +183,35 @@ fn case_expr(p: &mut Parser<'_>) -> CompletedMarker {
if !p.at(WHEN_KW) && expr(p).is_none() {
p.error("expected an expression");
}
when_clause_list(p);
opt_else_clause(p);
p.expect(END_KW);
m.complete(p, CASE_EXPR)
}

fn when_clause_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
when_clause(p);
if !p.at(WHEN_KW) {
break;
}
}
// case_default
// | ELSE a_expr
// | /* empty */
m.complete(p, WHEN_CLAUSE_LIST);
}

// case_default
// | ELSE a_expr
// | /* empty */
fn opt_else_clause(p: &mut Parser<'_>) {
if !p.at(ELSE_KW) {
return;
}
let m = p.start();
if p.eat(ELSE_KW) && expr(p).is_none() {
p.error("expected an expression");
}
p.expect(END_KW);
m.complete(p, CASE_EXPR)
m.complete(p, ELSE_CLAUSE);
}

// when_clause:
Expand Down Expand Up @@ -10917,21 +10932,23 @@ fn set_transaction(p: &mut Parser<'_>) -> CompletedMarker {
fn values(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
let m = m.unwrap_or_else(|| p.start());
p.bump(VALUES_KW);
// TODO: generalize this
row_list(p);
opt_order_by_clause(p);
opt_limit_clause(p);
opt_offset_clause(p);
opt_fetch_clause(p);
m.complete(p, VALUES)
}

// ( expression [, ...] ) [, ...]
fn row_list(p: &mut Parser<'_>) {
let m = p.start();
while !p.at(EOF) {
if !p.at(L_PAREN) {
p.err_and_bump("expected L_PAREN");
continue;
}
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "expected expression".to_string(),
EXPR_FIRST,
|p| expr(p).is_some(),
);
row(p);
if !p.eat(COMMA) {
if p.at(L_PAREN) {
p.error("expected COMMA");
Expand All @@ -10940,11 +10957,22 @@ fn values(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
}
}
}
opt_order_by_clause(p);
opt_limit_clause(p);
opt_offset_clause(p);
opt_fetch_clause(p);
m.complete(p, VALUES)
m.complete(p, ROW_LIST);
}

// ( expression [, ...] )
fn row(p: &mut Parser<'_>) {
let m = p.start();
delimited(
p,
L_PAREN,
R_PAREN,
COMMA,
|| "expected expression".to_string(),
EXPR_FIRST,
|p| expr(p).is_some(),
);
m.complete(p, ROW);
}

const REINDEX_OPTION_FIRST: TokenSet = TokenSet::new(&[CONCURRENTLY_KW, VERBOSE_KW, TABLESPACE_KW]);
Expand Down Expand Up @@ -12375,7 +12403,7 @@ fn create_index(p: &mut Parser<'_>) -> CompletedMarker {
// [ NULLS { FIRST | LAST } ]
// [, ...]
// )
index_params(p);
partition_items(p, true);
opt_include_columns(p);
opt_nulls_not_distinct(p);
opt_with_params(p);
Expand All @@ -12384,12 +12412,6 @@ fn create_index(p: &mut Parser<'_>) -> CompletedMarker {
m.complete(p, CREATE_INDEX)
}

fn index_params(p: &mut Parser<'_>) {
let m = p.start();
partition_items(p, true);
m.complete(p, INDEX_PARAMS);
}

// (
// { column_name | ( expression ) }
// [ COLLATE collation ]
Expand All @@ -12407,6 +12429,7 @@ fn index_params(p: &mut Parser<'_>) {
// [, ...]
// )
fn partition_items(p: &mut Parser<'_>, allow_extra_params: bool) {
let m = p.start();
delimited(
p,
L_PAREN,
Expand All @@ -12416,6 +12439,7 @@ fn partition_items(p: &mut Parser<'_>, allow_extra_params: bool) {
EXPR_FIRST,
|p| opt_partition_item(p, allow_extra_params).is_some(),
);
m.complete(p, PARTITION_ITEM_LIST);
}

// [ argmode ]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ SOURCE_FILE
NAME_REF
IDENT "t"
WHITESPACE " "
INDEX_PARAMS
PARTITION_ITEM_LIST
L_PAREN "("
PARTITION_ITEM
NAME_REF
Expand Down
Loading
Loading