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
81 changes: 53 additions & 28 deletions crates/squawk_fmt/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1943,13 +1943,13 @@ fn build_function_param<'a>(param: ast::Param) -> Doc<'a> {
}
});
}
if let Some(ty) = param.ty() {
if let Some(func_type) = param.func_type() {
if has_prefix {
doc = doc.append(Doc::space());
}
doc = doc
.append(leading_comments(ty.syntax()))
.append(build_type(ty));
.append(leading_comments(func_type.syntax()))
.append(build_func_type(func_type));
}
if let Some(default) = param.param_default() {
doc = doc
Expand Down Expand Up @@ -1982,10 +1982,10 @@ fn build_function_ret_type<'a>(ret_type: ast::RetType) -> Doc<'a> {
.append(leading_comments_token(&table_token))
.append(Doc::text("table"));
}
if let Some(args) = ret_type.table_arg_list() {
if let Some(args) = ret_type.return_table_arg_list() {
let mut body = Doc::list(
Itertools::intersperse(
args.args().map(build_table_arg),
args.args().map(build_return_table_column),
Doc::text(",").append(Doc::line_or_space()),
)
.collect(),
Expand All @@ -2007,15 +2007,32 @@ fn build_function_ret_type<'a>(ret_type: ast::RetType) -> Doc<'a> {
.append(Doc::space())
.append(leading_comments(args.syntax()))
.append(args_doc);
} else if let Some(ty) = ret_type.ty() {
} else if let Some(func_type) = ret_type.func_type() {
doc = doc
.append(Doc::space())
.append(leading_comments(ty.syntax()))
.append(build_type(ty));
.append(leading_comments(func_type.syntax()))
.append(build_func_type(func_type));
}
doc
}

fn build_return_table_column<'a>(column: ast::ReturnTableColumn) -> Doc<'a> {
let syntax = column.syntax().clone();
let mut doc = column
.name()
.map(|name| build_name(name.syntax()))
.unwrap_or_else(Doc::nil);
if let Some(func_type) = column.func_type() {
doc = doc
.append(Doc::space())
.append(leading_comments(func_type.syntax()))
.append(build_func_type(func_type));
}
leading_comments(&syntax)
.append(doc)
.append(trailing_comments(&syntax))
}

fn build_function_option<'a>(option: ast::FuncOption) -> Doc<'a> {
match option {
ast::FuncOption::AsFuncOption(option) => build_as_function_option(option),
Expand Down Expand Up @@ -22685,6 +22702,34 @@ fn format_string_token(t: &SyntaxToken) -> String {
}
}

fn build_func_type<'a>(func_type: ast::FuncType) -> Doc<'a> {
match func_type {
ast::FuncType::PercentType(percent_type) => build_percent_type(percent_type),
ast::FuncType::Type(ty) => build_type(ty),
}
}

fn build_percent_type<'a>(percent_type: ast::PercentType) -> Doc<'a> {
let mut doc = build_setof(percent_type.setof_token());
if let Some(path) = percent_type.path_ref() {
doc = doc
.append(leading_comments(path.syntax()))
.append(build_path_ref(&path));
}
if let Some(clause) = percent_type.percent_type_clause() {
doc = doc.append(comments_before(clause.syntax().clone()));
if clause.percent_token().is_some() {
doc = doc.append(Doc::text("%"));
}
if let Some(type_token) = clause.type_token() {
doc = doc
.append(comments_before(type_token))
.append(Doc::text("type"));
}
}
doc
}

fn build_type<'a>(ty: ast::Type) -> Doc<'a> {
match ty {
ast::Type::ArrayType(array_type) => {
Expand Down Expand Up @@ -22754,26 +22799,6 @@ fn build_type<'a>(ty: ast::Type) -> Doc<'a> {
}
doc.append(build_type_args(arg_list))
}
ast::Type::PercentType(percent_type) => {
let mut doc = build_setof(percent_type.setof_token());
if let Some(path) = percent_type.path_ref() {
doc = doc
.append(leading_comments(path.syntax()))
.append(build_path_ref(&path));
}
if let Some(clause) = percent_type.percent_type_clause() {
doc = doc.append(comments_before(clause.syntax().clone()));
if clause.percent_token().is_some() {
doc = doc.append(Doc::text("%"));
}
if let Some(type_token) = clause.type_token() {
doc = doc
.append(comments_before(type_token))
.append(Doc::text("type"));
}
}
doc
}
ast::Type::TimeType(time_type) => {
let mut doc = build_setof(time_type.setof_token());
if let Some(time_token) = time_type.time_token() {
Expand Down
12 changes: 12 additions & 0 deletions crates/squawk_fmt/tests/after/create_function.snap
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ create function returns_null_on_null_input_example() returns text
language sql
as $$ select null::text $$;

create function percent_type_param(
value accounts.id%type
) returns accounts.id%type
language sql
as $$ select value $$;

create function percent_type_table(
unused integer
) returns table (value accounts /*pct1*/.id /*pct2*/% /*pct3*/type)
language sql
as $$ select 1 $$;

-- comments in every position
create /*a*/ or /*b*/ replace /*c*/ function /*d*/ app /*e*/./*f*/ commented(
/*g*/ in /*h*/ value /*i*/ integer /*j*/ default /*k*/ 1 /*l*/,
Expand Down
4 changes: 4 additions & 0 deletions crates/squawk_fmt/tests/before/create_function.sql
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ create function option_examples(in first integer, out second text, inout third b

create function returns_null_on_null_input_example() returns text returns null on null input language sql as $$ select null::text $$;

create function percent_type_param(value accounts.id%type) returns accounts.id%type language sql as $$ select value $$;

create function percent_type_table(unused integer) returns table (value accounts /*pct1*/. id /*pct2*/% /*pct3*/type) language sql as $$ select 1 $$;

-- comments in every position
create /*a*/ or /*b*/ replace /*c*/ function /*d*/ app /*e*/. /*f*/ commented
(/*g*/ in /*h*/ value /*i*/ integer /*j*/ default /*k*/ 1 /*l*/, /*m*/ out /*n*/ result /*o*/ text /*p*/)
Expand Down
3 changes: 1 addition & 2 deletions crates/squawk_ide/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2099,8 +2099,7 @@ fn extract_param_signature(param_list: Option<ast::ParamList>) -> Option<Vec<Nam
let param_list = param_list?;
let mut params = vec![];
for param in param_list.all_params() {
if let Some(ty) = param.ty()
&& let ast::Type::PathType(path_type) = ty
if let Some(ast::FuncType::Type(ast::Type::PathType(path_type))) = param.func_type()
&& let Some(path) = path_type.path_ref()
&& let Some(segment) = path.segment()
{
Expand Down
1 change: 1 addition & 0 deletions crates/squawk_ide/src/expand_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const DELIMITED_LIST_KINDS: &[SyntaxKind] = &[
SyntaxKind::REINDEX_OPTION_LIST,
SyntaxKind::RELATION_LIST,
SyntaxKind::RETURNING_OPTION_LIST,
SyntaxKind::RETURN_TABLE_ARG_LIST,
SyntaxKind::REVOKE_COMMAND_LIST,
SyntaxKind::ROLE_REF_LIST,
SyntaxKind::ROW_LIST,
Expand Down
5 changes: 1 addition & 4 deletions crates/squawk_ide/src/find_references.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ fn is_reference_node(node: &SyntaxNode) -> bool {
| ast::Type::IntervalType(_)
| ast::Type::TimeType(_)
| ast::Type::TimestampType(_) => true,
ast::Type::ArrayType(_)
| ast::Type::ExprType(_)
| ast::Type::PathType(_)
| ast::Type::PercentType(_) => false,
ast::Type::ArrayType(_) | ast::Type::ExprType(_) | ast::Type::PathType(_) => false,
};
}

Expand Down
7 changes: 4 additions & 3 deletions crates/squawk_ide/src/folding_ranges.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,10 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
}

match kind {
SyntaxKind::ARG_LIST | SyntaxKind::TABLE_ARG_LIST | SyntaxKind::PARAM_LIST => {
Some(FoldKind::ArgList)
}
SyntaxKind::ARG_LIST
| SyntaxKind::TABLE_ARG_LIST
| SyntaxKind::RETURN_TABLE_ARG_LIST
| SyntaxKind::PARAM_LIST => Some(FoldKind::ArgList),
SyntaxKind::ARRAY_EXPR => Some(FoldKind::Array),
SyntaxKind::CALL_EXPR => Some(FoldKind::FunctionCall),
SyntaxKind::JOIN => Some(FoldKind::Join),
Expand Down
4 changes: 3 additions & 1 deletion crates/squawk_ide/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1887,7 +1887,9 @@ fn hover_named_arg_parameter(db: &dyn Db, def: Location) -> Option<Hover> {
let def_node = def.to_node(db)?;
let param = def_node.ancestors().find_map(ast::Param::cast)?;
let param_name = param.name().map(|name| Name::from_node(&name))?;
let param_type = param.ty().map(|ty| ty.syntax().text().to_string());
let param_type = param
.func_type()
.map(|func_type| func_type.syntax().text().to_string());

for ancestor in def_node.ancestors() {
if let Some(create_function) = ast::CreateFunction::cast(ancestor.clone()) {
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_ide/src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ pub(crate) fn schema_and_type_name(ty: &ast::Type) -> Option<(Option<Schema>, Na
};
Some((None, Name::from_string(name)))
}
ast::Type::PercentType(_) => None,
}
}

Expand Down
51 changes: 26 additions & 25 deletions crates/squawk_ide/src/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4963,13 +4963,11 @@ fn count_columns_for_call_expr_return_table(
.ancestors()
.find_map(ast::CreateFunction::cast)?;

if let Some(table_arg_list) = create_function.ret_type().and_then(|r| r.table_arg_list()) {
return Some(
table_arg_list
.args()
.filter(|arg| matches!(arg, ast::TableArg::Column(_)))
.count(),
);
if let Some(return_table_arg_list) = create_function
.ret_type()
.and_then(|ret_type| ret_type.return_table_arg_list())
{
return Some(return_table_arg_list.args().count());
}

if let Some(param_list) = create_function.param_list() {
Expand All @@ -4987,7 +4985,9 @@ fn count_columns_for_call_expr_return_table(
}
}

if let Some(ast::Type::PathType(path_type)) = create_function.ret_type().and_then(|r| r.ty())
if let Some(ast::FuncType::Type(ast::Type::PathType(path_type))) = create_function
.ret_type()
.and_then(|ret_type| ret_type.func_type())
&& let Some(path) = path_type.path_ref()
&& let Some(column_count) =
count_columns_for_path(db, InFile::new(function_loc.file, &path)).or_else(|| {
Expand Down Expand Up @@ -5019,21 +5019,20 @@ fn resolve_column_from_call_expr_return_table(
.find_map(ast::CreateFunction::cast)?;

// `returns table(col ...)`
if let Some(table_arg_list) = create_function.ret_type().and_then(|r| r.table_arg_list()) {
let mut index = 0usize;
for arg in table_arg_list.args() {
if let ast::TableArg::Column(column) = arg {
if let Some(name) = column.name()
&& Name::from_node(&name) == *column_name
&& index >= min_index
{
return Some(smallvec![Location::new(
file,
name.syntax().text_range(),
LocationKind::Column
)]);
}
index += 1;
if let Some(return_table_arg_list) = create_function
.ret_type()
.and_then(|ret_type| ret_type.return_table_arg_list())
{
for (index, column) in return_table_arg_list.args().enumerate() {
if let Some(name) = column.name()
&& Name::from_node(&name) == *column_name
&& index >= min_index
{
return Some(smallvec![Location::new(
file,
name.syntax().text_range(),
LocationKind::Column
)]);
}
}
}
Expand Down Expand Up @@ -5063,7 +5062,9 @@ fn resolve_column_from_call_expr_return_table(
}

// `returns setof <table>` or `returns setof <composite type>`
if let Some(ast::Type::PathType(path_type)) = create_function.ret_type().and_then(|r| r.ty())
if let Some(ast::FuncType::Type(ast::Type::PathType(path_type))) = create_function
.ret_type()
.and_then(|ret_type| ret_type.func_type())
&& let Some(path) = path_type.path_ref()
{
if let Some(ptr) =
Expand Down Expand Up @@ -5191,7 +5192,7 @@ fn resolve_symbol_info_from_parts(
fn param_signature(node: &ast::HasParamList) -> Option<Vec<Name>> {
let mut params = vec![];
for param in node.param_list()?.all_params() {
if let Some(ast::Type::PathType(path_type)) = param.ty()
if let Some(ast::FuncType::Type(ast::Type::PathType(path_type))) = param.func_type()
&& let Some(name_ref) = path_type.path_ref().and_then(|x| x.segment())
{
params.push(Name::from_node(&name_ref));
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_ide/src/semantic_tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ fn highlight_type(out: &mut SemanticTokenBuilder, ty: ast::Type) {
out.push_type(token.into());
}
}
ast::Type::PercentType(_) => (),
ast::Type::TimeType(time_type) => {
if let Some(token) = time_type.setof_token() {
out.push_type(token.into());
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_linter/src/rules/prefer_bigint_over_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ fn create_bigint_fix(ty: &ast::Type) -> Option<Fix> {
| ast::Type::CharacterType(_)
| ast::Type::DoubleType(_)
| ast::Type::ExprType(_)
| ast::Type::PercentType(_)
| ast::Type::TimeType(_)
| ast::Type::TimestampType(_)
| ast::Type::IntervalType(_) => return None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ fn create_bigint_fix(ty: &ast::Type) -> Option<Fix> {
| ast::Type::CharacterType(_)
| ast::Type::DoubleType(_)
| ast::Type::ExprType(_)
| ast::Type::PercentType(_)
| ast::Type::TimeType(_)
| ast::Type::TimestampType(_)
| ast::Type::IntervalType(_) => return None,
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_linter/src/rules/prefer_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ fn create_identity_fix(ty: &ast::Type) -> Option<Fix> {
| ast::Type::CharacterType(_)
| ast::Type::DoubleType(_)
| ast::Type::ExprType(_)
| ast::Type::PercentType(_)
| ast::Type::TimeType(_)
| ast::Type::TimestampType(_)
| ast::Type::IntervalType(_) => return None,
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_linter/src/rules/prefer_text_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ fn is_not_allowed_varchar(ty: &ast::Type) -> bool {
false
}
}
ast::Type::PercentType(_) => false,
ast::Type::PathType(path_type) => {
let Some(ty_name) = path_type
.path_ref()
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_linter/src/rules/prefer_timestamptz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ pub fn is_not_allowed_timestamp(ty: &ast::Type) -> bool {
false
}
}
ast::Type::PercentType(_) => false,
ast::Type::PathType(path_type) => {
let Some(ty_name) = path_type
.path_ref()
Expand Down
1 change: 0 additions & 1 deletion crates/squawk_linter/src/visitors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ pub(crate) fn is_not_valid_int_type(
false
}
}
ast::Type::PercentType(_) => false,
ast::Type::PathType(path_type) => {
let Some(ty_name) = path_type
.path_ref()
Expand Down
2 changes: 2 additions & 0 deletions 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.

Loading
Loading