diff --git a/crates/squawk_ide/src/goto_definition.rs b/crates/squawk_ide/src/goto_definition.rs index b7f45c44..994ac25d 100644 --- a/crates/squawk_ide/src/goto_definition.rs +++ b/crates/squawk_ide/src/goto_definition.rs @@ -9117,4 +9117,60 @@ window w as ( ╰╴ ─ 2. destination "); } + + #[test] + fn goto_cast_float_with_small_arg() { + assert_snapshot!(goto(" +create type pg_catalog.float4; +select '1'::float$0(8); +"), @" + ╭▸ + 2 │ create type pg_catalog.float4; + │ ────── 2. destination + 3 │ select '1'::float(8); + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_cast_float_with_large_arg() { + assert_snapshot!(goto(" +create type pg_catalog.float8; +select '1'::float$0(25); +"), @" + ╭▸ + 2 │ create type pg_catalog.float8; + │ ────── 2. destination + 3 │ select '1'::float(25); + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_cast_dec_with_modifier() { + assert_snapshot!(goto(" +create type pg_catalog.numeric; +select '10'::dec$0(10, 2); +"), @" + ╭▸ + 2 │ create type pg_catalog.numeric; + │ ─────── 2. destination + 3 │ select '10'::dec(10, 2); + ╰╴ ─ 1. source + "); + } + + #[test] + fn goto_cast_dec() { + assert_snapshot!(goto(" +create type pg_catalog.numeric; +select '10'::dec$0; +"), @" + ╭▸ + 2 │ create type pg_catalog.numeric; + │ ─────── 2. destination + 3 │ select '10'::dec; + ╰╴ ─ 1. source + "); + } } diff --git a/crates/squawk_ide/src/resolve.rs b/crates/squawk_ide/src/resolve.rs index 4a6df5a3..bfe18b03 100644 --- a/crates/squawk_ide/src/resolve.rs +++ b/crates/squawk_ide/src/resolve.rs @@ -126,6 +126,7 @@ pub(crate) fn resolve_name_ref_ptrs( } else { extract_table_schema_from_name_ref(name_ref)? }; + let type_name = resolve_float_precision(name_ref, type_name); let position = name_ref.syntax().text_range().start(); resolve_type_name_ptr(binder, &type_name, &schema, position).map(|ptr| smallvec![ptr]) } @@ -609,7 +610,7 @@ fn fallback_type_alias(type_name: &Name) -> Option { match type_name.0.as_str() { "bigint" | "bigserial" | "serial8" => Some(Name::from_string("int8")), "boolean" => Some(Name::from_string("bool")), - "decimal" => Some(Name::from_string("numeric")), + "dec" | "decimal" => Some(Name::from_string("numeric")), "float" => Some(Name::from_string("float8")), "int" | "integer" | "serial" | "serial4" => Some(Name::from_string("int4")), "real" => Some(Name::from_string("float4")), @@ -618,6 +619,19 @@ fn fallback_type_alias(type_name: &Name) -> Option { } } +fn resolve_float_precision(name_ref: &ast::NameRef, type_name: Name) -> Name { + if type_name.0.as_str() == "float" + && let Some(path_type) = name_ref.syntax().ancestors().find_map(ast::PathType::cast) + && let Some(arg_list) = path_type.arg_list() + && let Some(first_arg) = arg_list.args_().next() + && let Some(ast::Expr::Literal(lit)) = first_arg.expr() + { + let precision: u32 = lit.syntax().text().to_string().parse().unwrap_or(0); + return Name::from_string(if precision <= 24 { "float4" } else { "float8" }); + } + type_name +} + fn resolve_view_name_ptr( binder: &Binder, view_name: &Name,