Skip to content

Commit f858af2

Browse files
authored
ide: support hover & goto def for function call style columns in where (#776)
1 parent 79fd5d5 commit f858af2

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed

crates/squawk_ide/src/goto_definition.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,36 @@ select * from t where t.b$0 > 0;
12181218
");
12191219
}
12201220

1221+
#[test]
1222+
fn goto_function_call_style_table_arg_in_where() {
1223+
assert_snapshot!(goto("
1224+
create table t(a int);
1225+
select * from t where a(t$0) > 2;
1226+
"), @r"
1227+
╭▸
1228+
2 │ create table t(a int);
1229+
│ ─ 2. destination
1230+
3 │ select * from t where a(t) > 2;
1231+
╰╴ ─ 1. source
1232+
");
1233+
}
1234+
1235+
#[test]
1236+
fn goto_qualified_table_ref_in_where() {
1237+
assert_snapshot!(goto("
1238+
create table t(a int);
1239+
create function b(t) returns int as 'select 1' language sql;
1240+
select * from t where t$0.b > 2;
1241+
"), @r"
1242+
╭▸
1243+
2 │ create table t(a int);
1244+
│ ─ 2. destination
1245+
3 │ create function b(t) returns int as 'select 1' language sql;
1246+
4 │ select * from t where t.b > 2;
1247+
╰╴ ─ 1. source
1248+
");
1249+
}
1250+
12211251
#[test]
12221252
fn goto_function_call_style_in_order_by() {
12231253
assert_snapshot!(goto("

crates/squawk_ide/src/hover.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,9 @@ fn is_select_from_table(name_ref: &ast::NameRef) -> bool {
359359
}
360360

361361
fn is_select_column(name_ref: &ast::NameRef) -> bool {
362-
let mut in_target_list = false;
363362
let mut in_call_expr = false;
364363
let mut in_arg_list = false;
364+
let mut in_from_clause = false;
365365

366366
for ancestor in name_ref.syntax().ancestors() {
367367
if ast::ArgList::can_cast(ancestor.kind()) {
@@ -370,14 +370,19 @@ fn is_select_column(name_ref: &ast::NameRef) -> bool {
370370
if ast::CallExpr::can_cast(ancestor.kind()) {
371371
in_call_expr = true;
372372
}
373-
if ast::TargetList::can_cast(ancestor.kind()) {
374-
in_target_list = true;
373+
if ast::FromClause::can_cast(ancestor.kind()) {
374+
in_from_clause = true;
375375
}
376-
if ast::Select::can_cast(ancestor.kind()) && in_target_list {
376+
if ast::Select::can_cast(ancestor.kind()) {
377377
// if we're inside a call expr but not inside an arg list, this is a function call
378378
if in_call_expr && !in_arg_list {
379379
return false;
380380
}
381+
// if we're in FROM clause, this is a table reference, not a column
382+
if in_from_clause {
383+
return false;
384+
}
385+
// anything else in SELECT (target list, WHERE, ORDER BY, etc.) is a column
381386
return true;
382387
}
383388
}
@@ -1078,6 +1083,33 @@ select b(t$0) from t;
10781083
");
10791084
}
10801085

1086+
#[test]
1087+
fn hover_on_function_call_style_table_arg_in_where() {
1088+
assert_snapshot!(check_hover("
1089+
create table t(a int);
1090+
select * from t where a(t$0) > 2;
1091+
"), @r"
1092+
hover: table public.t(a int)
1093+
╭▸
1094+
3 │ select * from t where a(t) > 2;
1095+
╰╴ ─ hover
1096+
");
1097+
}
1098+
1099+
#[test]
1100+
fn hover_on_qualified_table_ref_in_where() {
1101+
assert_snapshot!(check_hover("
1102+
create table t(a int);
1103+
create function b(t) returns int as 'select 1' language sql;
1104+
select * from t where t$0.b > 2;
1105+
"), @r"
1106+
hover: table public.t(a int)
1107+
╭▸
1108+
4 │ select * from t where t.b > 2;
1109+
╰╴ ─ hover
1110+
");
1111+
}
1112+
10811113
#[test]
10821114
fn hover_on_field_style_function_call() {
10831115
assert_snapshot!(check_hover("

crates/squawk_ide/src/resolve.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ fn classify_name_ref_context(name_ref: &ast::NameRef) -> Option<NameRefContext>
127127
let mut in_column_list = false;
128128
let mut in_where_clause = false;
129129
let mut in_from_clause = false;
130-
let mut in_target_list = false;
131130

132131
// TODO: can we combine this if and the one that follows?
133132
if let Some(parent) = name_ref.syntax().parent()
@@ -149,8 +148,12 @@ fn classify_name_ref_context(name_ref: &ast::NameRef) -> Option<NameRefContext>
149148
.and_then(ast::FieldExpr::cast)
150149
.is_some();
151150

151+
let mut in_from_clause = false;
152152
for ancestor in parent.ancestors() {
153-
if ast::TargetList::can_cast(ancestor.kind()) {
153+
if ast::FromClause::can_cast(ancestor.kind()) {
154+
in_from_clause = true;
155+
}
156+
if ast::Select::can_cast(ancestor.kind()) && !in_from_clause {
154157
if is_function_call || is_schema_table_col {
155158
return Some(NameRefContext::SchemaQualifier);
156159
} else {
@@ -246,19 +249,16 @@ fn classify_name_ref_context(name_ref: &ast::NameRef) -> Option<NameRefContext>
246249
if ast::FromClause::can_cast(ancestor.kind()) {
247250
in_from_clause = true;
248251
}
249-
if ast::TargetList::can_cast(ancestor.kind()) {
250-
in_target_list = true;
251-
}
252252
if ast::Select::can_cast(ancestor.kind()) {
253253
if in_call_expr && !in_arg_list {
254254
return Some(NameRefContext::SelectFunctionCall);
255255
}
256256
if in_from_clause {
257257
return Some(NameRefContext::SelectFromTable);
258258
}
259-
if in_target_list {
260-
return Some(NameRefContext::SelectColumn);
261-
}
259+
// Classify as SelectColumn for target list, WHERE, ORDER BY, GROUP BY, etc.
260+
// (anything in SELECT except FROM clause)
261+
return Some(NameRefContext::SelectColumn);
262262
}
263263
if ast::ColumnList::can_cast(ancestor.kind()) {
264264
in_column_list = true;

0 commit comments

Comments
 (0)