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
6 changes: 6 additions & 0 deletions crates/squawk_ide/src/code_actions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod add_schema;
mod convert_comment;
mod quote_identifier;
mod remove_else_clause;
mod remove_function_param_in;
mod remove_redundant_alias;
mod rewrite_as_dollar_quoted_string;
mod rewrite_as_regular_string;
Expand All @@ -23,6 +24,7 @@ mod rewrite_double_colon_to_cast;
mod rewrite_extract_as_function_call;
mod rewrite_from;
mod rewrite_function_param_default_as_equals;
mod rewrite_function_param_in_out_as_inout;
mod rewrite_in_as_expression;
mod rewrite_integer_radix;
mod rewrite_is_normalized_as_function_call;
Expand Down Expand Up @@ -58,6 +60,7 @@ use add_schema::add_schema;
use convert_comment::convert_comment;
use quote_identifier::quote_identifier;
use remove_else_clause::remove_else_clause;
use remove_function_param_in::remove_function_param_in;
use remove_redundant_alias::remove_redundant_alias;
use rewrite_as_dollar_quoted_string::rewrite_as_dollar_quoted_string;
use rewrite_as_regular_string::rewrite_as_regular_string;
Expand All @@ -72,6 +75,7 @@ use rewrite_double_colon_to_cast::rewrite_double_colon_to_cast;
use rewrite_extract_as_function_call::rewrite_extract_as_function_call;
use rewrite_from::rewrite_from;
use rewrite_function_param_default_as_equals::rewrite_function_param_default_as_equals;
use rewrite_function_param_in_out_as_inout::rewrite_function_param_in_out_as_inout;
use rewrite_in_as_expression::rewrite_in_as_expression;
use rewrite_integer_radix::rewrite_integer_radix;
use rewrite_is_normalized_as_function_call::rewrite_is_normalized_as_function_call;
Expand Down Expand Up @@ -121,6 +125,8 @@ pub fn code_actions(db: &dyn Db, position: InFile<TextSize>) -> Option<Vec<CodeA
rewrite_select_as_table(db, position, &mut actions);
rewrite_from(db, position, &mut actions);
rewrite_function_param_default_as_equals(db, position, &mut actions);
rewrite_function_param_in_out_as_inout(db, position, &mut actions);
remove_function_param_in(db, position, &mut actions);
rewrite_integer_radix(db, position, &mut actions);
rewrite_leading_from(db, position, &mut actions);
rewrite_values_as_select(db, position, &mut actions);
Expand Down
107 changes: 107 additions & 0 deletions crates/squawk_ide/src/code_actions/remove_function_param_in.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use rowan::{TextRange, TextSize};
use salsa::Database as Db;
use squawk_linter::Edit;
use squawk_syntax::{
SyntaxKind,
ast::{self, AstNode},
};

use crate::{file::InFile, offsets::token_from_offset};

use super::{ActionKind, CodeAction};

pub(super) fn remove_function_param_in(
db: &dyn Db,
position: InFile<TextSize>,
actions: &mut Vec<CodeAction>,
) -> Option<()> {
let token = token_from_offset(db, position)?;
let param = token.parent_ancestors().find_map(ast::Param::cast)?;
param
.syntax()
.ancestors()
.find_map(ast::CreateFunction::cast)?;
let ast::ParamMode::ParamIn(mode) = param.mode()? else {
return None;
};
let in_token = mode.in_token()?;
let delete_range = in_token
.next_token()
.filter(|token| token.kind() == SyntaxKind::WHITESPACE)
.map(|token| TextRange::new(in_token.text_range().start(), token.text_range().end()))
.unwrap_or_else(|| in_token.text_range());

actions.push(CodeAction {
title: "Remove redundant `IN`".to_owned(),
edits: vec![Edit::delete(delete_range)],
kind: ActionKind::RefactorRewrite,
});

Some(())
}

#[cfg(test)]
mod test {
use insta::assert_snapshot;

use crate::code_actions::test_utils::{apply_code_action, code_action_not_applicable};

use super::remove_function_param_in;

#[test]
fn removes_in() {
assert_snapshot!(
apply_code_action(
remove_function_param_in,
"create function f(i$0n value int) returns int language sql as $$ select value $$;",
),
@"create function f(value int) returns int language sql as $$ select value $$;"
);
}

#[test]
fn preserves_comments() {
assert_snapshot!(
apply_code_action(
remove_function_param_in,
"create function f(i$0n /* before value */ value int) returns int language sql as $$ select value $$;",
),
@"create function f(/* before value */ value int) returns int language sql as $$ select value $$;"
);
}

#[test]
fn applies_when_mode_follows_name() {
assert_snapshot!(
apply_code_action(
remove_function_param_in,
"create function f(value i$0n int) returns int language sql as $$ select value $$;",
),
@"create function f(value int) returns int language sql as $$ select value $$;"
);
}

#[test]
fn not_applicable_to_out() {
assert!(code_action_not_applicable(
remove_function_param_in,
"create function f(o$0ut value int) returns int language sql as $$ select value $$;"
));
}

#[test]
fn not_applicable_to_inout() {
assert!(code_action_not_applicable(
remove_function_param_in,
"create function f(ino$0ut value int) returns int language sql as $$ select value $$;"
));
}

#[test]
fn not_applicable_to_procedure_param() {
assert!(code_action_not_applicable(
remove_function_param_in,
"create procedure p(i$0n value int) language sql as $$ select value $$;"
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use rowan::TextSize;
use salsa::Database as Db;
use squawk_linter::Edit;
use squawk_syntax::ast::{self, AstNode};

use crate::{file::InFile, offsets::token_from_offset};

use super::{ActionKind, CodeAction};

pub(super) fn rewrite_function_param_in_out_as_inout(
db: &dyn Db,
position: InFile<TextSize>,
actions: &mut Vec<CodeAction>,
) -> Option<()> {
let token = token_from_offset(db, position)?;
let param = token.parent_ancestors().find_map(ast::Param::cast)?;
param
.syntax()
.ancestors()
.find_map(ast::CreateFunction::cast)?;
let ast::ParamMode::ParamInOut(mode) = param.mode()? else {
return None;
};
mode.in_token()?;
mode.out_token()?;

actions.push(CodeAction {
title: "Rewrite `IN OUT` as `INOUT`".to_owned(),
edits: vec![Edit::replace(
mode.syntax().text_range(),
"inout".to_owned(),
)],
kind: ActionKind::RefactorRewrite,
});

Some(())
}

#[cfg(test)]
mod test {
use insta::assert_snapshot;

use crate::code_actions::test_utils::{apply_code_action, code_action_not_applicable};

use super::rewrite_function_param_in_out_as_inout;

#[test]
fn rewrites_in_out_as_inout() {
assert_snapshot!(
apply_code_action(
rewrite_function_param_in_out_as_inout,
"create function f(in $0out value int) returns int language sql as $$ select value $$;",
),
@"create function f(inout value int) returns int language sql as $$ select value $$;"
);
}

#[test]
fn applies_when_mode_follows_name() {
assert_snapshot!(
apply_code_action(
rewrite_function_param_in_out_as_inout,
"create function f(value in o$0ut int) returns int language sql as $$ select value $$;",
),
@"create function f(value inout int) returns int language sql as $$ select value $$;"
);
}

#[test]
fn not_applicable_to_inout() {
assert!(code_action_not_applicable(
rewrite_function_param_in_out_as_inout,
"create function f(ino$0ut value int) returns int language sql as $$ select value $$;"
));
}

#[test]
fn not_applicable_to_procedure_param() {
assert!(code_action_not_applicable(
rewrite_function_param_in_out_as_inout,
"create procedure p(in o$0ut value int) language sql as $$ select value $$;"
));
}
}
Loading