Skip to content

Commit ab45b7c

Browse files
authored
ide: goto def with cte & select (#782)
1 parent fe64453 commit ab45b7c

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

crates/squawk_ide/src/goto_definition.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,77 @@ select * from t group by t.b$0;
13071307
");
13081308
}
13091309

1310+
#[test]
1311+
fn goto_cte_table() {
1312+
assert_snapshot!(goto("
1313+
with x as (select 1 as a)
1314+
select a from x$0;
1315+
"), @r"
1316+
╭▸
1317+
2 │ with x as (select 1 as a)
1318+
│ ─ 2. destination
1319+
3 │ select a from x;
1320+
╰╴ ─ 1. source
1321+
");
1322+
}
1323+
1324+
#[test]
1325+
fn goto_cte_column() {
1326+
assert_snapshot!(goto("
1327+
with x as (select 1 as a)
1328+
select a$0 from x;
1329+
"), @r"
1330+
╭▸
1331+
2 │ with x as (select 1 as a)
1332+
│ ─ 2. destination
1333+
3 │ select a from x;
1334+
╰╴ ─ 1. source
1335+
");
1336+
}
1337+
1338+
#[test]
1339+
fn goto_cte_multiple_columns() {
1340+
assert_snapshot!(goto("
1341+
with x as (select 1 as a, 2 as b)
1342+
select b$0 from x;
1343+
"), @r"
1344+
╭▸
1345+
2 │ with x as (select 1 as a, 2 as b)
1346+
│ ─ 2. destination
1347+
3 │ select b from x;
1348+
╰╴ ─ 1. source
1349+
");
1350+
}
1351+
1352+
#[test]
1353+
fn goto_cte_nested() {
1354+
assert_snapshot!(goto("
1355+
with x as (select 1 as a),
1356+
y as (select a from x)
1357+
select a$0 from y;
1358+
"), @r"
1359+
╭▸
1360+
3 │ y as (select a from x)
1361+
│ ─ 2. destination
1362+
4 │ select a from y;
1363+
╰╴ ─ 1. source
1364+
");
1365+
}
1366+
1367+
#[test]
1368+
fn goto_cte_unnamed_column() {
1369+
assert_snapshot!(goto(r#"
1370+
with x as (select 1)
1371+
select "?column?"$0 from x;
1372+
"#), @r#"
1373+
╭▸
1374+
2 │ with x as (select 1)
1375+
│ ─ 2. destination
1376+
3 │ select "?column?" from x;
1377+
╰╴ ─ 1. source
1378+
"#);
1379+
}
1380+
13101381
#[test]
13111382
fn goto_insert_table() {
13121383
assert_snapshot!(goto("

crates/squawk_ide/src/resolve.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use squawk_syntax::{
55
};
66

77
use crate::binder::Binder;
8+
use crate::column_name::ColumnName;
89
pub(crate) use crate::symbols::Schema;
910
use crate::symbols::{Name, SymbolKind};
1011

@@ -56,6 +57,13 @@ pub(crate) fn resolve_name_ref(binder: &Binder, name_ref: &ast::NameRef) -> Opti
5657
} else {
5758
None
5859
};
60+
61+
if schema.is_none()
62+
&& let Some(cte_ptr) = resolve_cte_table(name_ref, &table_name)
63+
{
64+
return Some(cte_ptr);
65+
}
66+
5967
let position = name_ref.syntax().text_range().start();
6068
resolve_table(binder, &table_name, &schema, position)
6169
}
@@ -593,6 +601,12 @@ fn resolve_select_column(binder: &Binder, name_ref: &ast::NameRef) -> Option<Syn
593601
(table_name, Some(schema))
594602
};
595603

604+
if schema.is_none()
605+
&& let Some(cte_column_ptr) = resolve_cte_column(&select, &table_name, &column_name)
606+
{
607+
return Some(cte_column_ptr);
608+
}
609+
596610
let position = name_ref.syntax().text_range().start();
597611
let table_ptr = resolve_table(binder, &table_name, &schema, position)?;
598612

@@ -757,6 +771,60 @@ pub(crate) fn find_column_in_table(
757771
})
758772
}
759773

774+
fn resolve_cte_table(name_ref: &ast::NameRef, cte_name: &Name) -> Option<SyntaxNodePtr> {
775+
let select = name_ref.syntax().ancestors().find_map(ast::Select::cast)?;
776+
let with_clause = select.with_clause()?;
777+
778+
for with_table in with_clause.with_tables() {
779+
if let Some(name) = with_table.name()
780+
&& Name::new(name.syntax().text().to_string()) == *cte_name
781+
{
782+
return Some(SyntaxNodePtr::new(name.syntax()));
783+
}
784+
}
785+
786+
None
787+
}
788+
789+
fn resolve_cte_column(
790+
select: &ast::Select,
791+
cte_name: &Name,
792+
column_name: &Name,
793+
) -> Option<SyntaxNodePtr> {
794+
let with_clause = select.with_clause()?;
795+
796+
for with_table in with_clause.with_tables() {
797+
if let Some(name) = with_table.name()
798+
&& Name::new(name.syntax().text().to_string()) == *cte_name
799+
{
800+
let query = with_table.query()?;
801+
802+
let cte_select = match query {
803+
ast::WithQuery::Select(s) => s,
804+
ast::WithQuery::ParenSelect(ps) => match ps.select()? {
805+
ast::SelectVariant::Select(s) => s,
806+
_ => continue,
807+
},
808+
_ => continue,
809+
};
810+
811+
let select_clause = cte_select.select_clause()?;
812+
let target_list = select_clause.target_list()?;
813+
814+
for target in target_list.targets() {
815+
if let Some((col_name, node)) = ColumnName::from_target(target)
816+
&& let Some(col_name_str) = col_name.to_string()
817+
&& Name::new(col_name_str) == *column_name
818+
{
819+
return Some(SyntaxNodePtr::new(&node));
820+
}
821+
}
822+
}
823+
}
824+
825+
None
826+
}
827+
760828
pub(crate) fn resolve_insert_table_columns(
761829
file: &ast::SourceFile,
762830
binder: &Binder,

0 commit comments

Comments
 (0)