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
106 changes: 106 additions & 0 deletions crates/squawk_ide/src/code_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub fn code_actions(file: ast::SourceFile, offset: TextSize) -> Option<Vec<CodeA
rewrite_cast_to_double_colon(&mut actions, &file, offset);
rewrite_double_colon_to_cast(&mut actions, &file, offset);
rewrite_between_as_binary_expression(&mut actions, &file, offset);
rewrite_timestamp_type(&mut actions, &file, offset);
Some(actions)
}

Expand Down Expand Up @@ -550,6 +551,15 @@ fn add_schema(
let position = token.text_range().start();
// TODO: we should salsa this
let binder = binder::bind(file);
// TODO: we don't need the search path at the current position, we need to
// lookup the definition of the item and see what the definition's search
// path is.
//
// It tries to rewrite:
// `select now()::timestamptz;` as
// `select now()::public.timestamptz;`
// instead of
// `select now()::pg_catalog.timestamptz;`
let schema = binder.search_path_at(position).first()?.to_string();
let replacement = format!("{}.", schema);

Expand Down Expand Up @@ -666,6 +676,40 @@ fn rewrite_between_as_binary_expression(
Some(())
}

fn rewrite_timestamp_type(
actions: &mut Vec<CodeAction>,
file: &ast::SourceFile,
offset: TextSize,
) -> Option<()> {
let token = token_from_offset(file, offset)?;
let time_type = token.parent_ancestors().find_map(ast::TimeType::cast)?;

let replacement = match time_type.timezone()? {
ast::Timezone::WithoutTimezone(_) => {
if time_type.timestamp_token().is_some() {
"timestamp"
} else {
"time"
}
}
ast::Timezone::WithTimezone(_) => {
if time_type.timestamp_token().is_some() {
"timestamptz"
} else {
"timetz"
}
}
};

actions.push(CodeAction {
title: format!("Rewrite as `{replacement}`"),
edits: vec![Edit::replace(time_type.syntax().text_range(), replacement)],
kind: ActionKind::RefactorRewrite,
});

Some(())
}

fn rewrite_values_as_select(
actions: &mut Vec<CodeAction>,
file: &ast::SourceFile,
Expand Down Expand Up @@ -2290,4 +2334,66 @@ select myschema.f$0();"
"sel$0ect c from t;"
));
}

#[test]
fn rewrite_timestamp_without_tz_column() {
assert_snapshot!(apply_code_action(
rewrite_timestamp_type,
"create table t(a time$0stamp without time zone);"),
@"create table t(a timestamp);"
);
}

#[test]
fn rewrite_timestamp_without_tz_cast() {
assert_snapshot!(apply_code_action(
rewrite_timestamp_type,
"select timestamp$0 without time zone '2021-01-01';"),
@"select timestamp '2021-01-01';"
);
}

#[test]
fn rewrite_time_without_tz() {
assert_snapshot!(apply_code_action(
rewrite_timestamp_type,
"create table t(a ti$0me without time zone);"),
@"create table t(a time);"
);
}

#[test]
fn rewrite_timestamp_without_tz_not_applicable_plain() {
assert!(code_action_not_applicable(
rewrite_timestamp_type,
"create table t(a time$0stamp);"
));
}

#[test]
fn rewrite_timestamp_with_tz_column() {
assert_snapshot!(apply_code_action(
rewrite_timestamp_type,
"create table t(a time$0stamp with time zone);"),
@"create table t(a timestamptz);"
);
}

#[test]
fn rewrite_timestamp_with_tz_cast() {
assert_snapshot!(apply_code_action(
rewrite_timestamp_type,
"select timestamp$0 with time zone '2021-01-01';"),
@"select timestamptz '2021-01-01';"
);
}

#[test]
fn rewrite_time_with_tz() {
assert_snapshot!(apply_code_action(
rewrite_timestamp_type,
"create table t(a ti$0me with time zone);"),
@"create table t(a timetz);"
);
}
}
5 changes: 1 addition & 4 deletions crates/squawk_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2066,10 +2066,7 @@ fn name_ref_(p: &mut Parser<'_>) -> Option<CompletedMarker> {
}
p.expect(R_PAREN);
}
if p.eat(WITH_KW) || p.eat(WITHOUT_KW) {
p.expect(TIME_KW);
p.expect(ZONE_KW);
}
opt_with_timezone(p);
TIME_TYPE
}
BIT_KW => {
Expand Down
44 changes: 24 additions & 20 deletions crates/squawk_parser/tests/snapshots/tests__select_casts_ok.snap
Original file line number Diff line number Diff line change
Expand Up @@ -953,11 +953,12 @@ SOURCE_FILE
TIME_TYPE
TIMESTAMP_KW "timestamp"
WHITESPACE " "
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WITH_TIMEZONE
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WHITESPACE " "
LITERAL
STRING "'2005-04-02 12:00:00-07'"
Expand All @@ -976,11 +977,12 @@ SOURCE_FILE
TIME_TYPE
TIMESTAMP_KW "timestamp"
WHITESPACE " "
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WITH_TIMEZONE
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WHITESPACE " "
LITERAL
STRING "'2001-02-16 20:38:40-05'"
Expand Down Expand Up @@ -1074,11 +1076,12 @@ SOURCE_FILE
TIME_TYPE
TIME_KW "time"
WHITESPACE " "
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WITH_TIMEZONE
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WHITESPACE " "
LITERAL
STRING "'20:38:40-05'"
Expand Down Expand Up @@ -1114,11 +1117,12 @@ SOURCE_FILE
TIME_TYPE
TIMESTAMP_KW "timestamp"
WHITESPACE " "
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WITH_TIMEZONE
WITH_KW "with"
WHITESPACE " "
TIME_KW "time"
WHITESPACE " "
ZONE_KW "zone"
WHITESPACE " "
LITERAL
STRING "'2001-02-16 20:38:40-05'"
Expand Down
Loading