Skip to content

Commit 317435f

Browse files
authored
ide: add initial goto def support for types (#798)
we're only supporting create/drop initially
1 parent a8e2135 commit 317435f

File tree

8 files changed

+392
-1
lines changed

8 files changed

+392
-1
lines changed

β€Žcrates/squawk_ide/src/binder.rsβ€Ž

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ fn bind_stmt(b: &mut Binder, stmt: ast::Stmt) {
8383
ast::Stmt::CreateAggregate(create_aggregate) => bind_create_aggregate(b, create_aggregate),
8484
ast::Stmt::CreateProcedure(create_procedure) => bind_create_procedure(b, create_procedure),
8585
ast::Stmt::CreateSchema(create_schema) => bind_create_schema(b, create_schema),
86+
ast::Stmt::CreateType(create_type) => bind_create_type(b, create_type),
8687
ast::Stmt::Set(set) => bind_set(b, set),
8788
_ => {}
8889
}
@@ -238,6 +239,32 @@ fn bind_create_schema(b: &mut Binder, create_schema: ast::CreateSchema) {
238239
b.scopes[root].insert(schema_name, schema_id);
239240
}
240241

242+
fn bind_create_type(b: &mut Binder, create_type: ast::CreateType) {
243+
let Some(path) = create_type.path() else {
244+
return;
245+
};
246+
247+
let Some(type_name) = item_name(&path) else {
248+
return;
249+
};
250+
251+
let name_ptr = path_to_ptr(&path);
252+
253+
let Some(schema) = schema_name(b, &path, false) else {
254+
return;
255+
};
256+
257+
let type_id = b.symbols.alloc(Symbol {
258+
kind: SymbolKind::Type,
259+
ptr: name_ptr,
260+
schema,
261+
params: None,
262+
});
263+
264+
let root = b.root_scope();
265+
b.scopes[root].insert(type_name, type_id);
266+
}
267+
241268
fn item_name(path: &ast::Path) -> Option<Name> {
242269
let segment = path.segment()?;
243270

β€Žcrates/squawk_ide/src/document_symbols.rsβ€Ž

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use rowan::TextRange;
22
use squawk_syntax::ast::{self, AstNode};
33

44
use crate::binder;
5-
use crate::resolve::{resolve_function_info, resolve_table_info};
5+
use crate::resolve::{resolve_function_info, resolve_table_info, resolve_type_info};
66

77
#[derive(Debug)]
88
pub enum DocumentSymbolKind {
99
Table,
1010
Function,
11+
Type,
1112
Column,
1213
}
1314

@@ -40,6 +41,11 @@ pub fn document_symbols(file: &ast::SourceFile) -> Vec<DocumentSymbol> {
4041
symbols.push(symbol);
4142
}
4243
}
44+
ast::Stmt::CreateType(create_type) => {
45+
if let Some(symbol) = create_type_symbol(&binder, create_type) {
46+
symbols.push(symbol);
47+
}
48+
}
4349
_ => {}
4450
}
4551
}
@@ -106,6 +112,30 @@ fn create_function_symbol(
106112
})
107113
}
108114

115+
fn create_type_symbol(
116+
binder: &binder::Binder,
117+
create_type: ast::CreateType,
118+
) -> Option<DocumentSymbol> {
119+
let path = create_type.path()?;
120+
let segment = path.segment()?;
121+
let name_node = segment.name()?;
122+
123+
let (schema, type_name) = resolve_type_info(binder, &path)?;
124+
let name = format!("{}.{}", schema.0, type_name);
125+
126+
let full_range = create_type.syntax().text_range();
127+
let focus_range = name_node.syntax().text_range();
128+
129+
Some(DocumentSymbol {
130+
name,
131+
detail: None,
132+
kind: DocumentSymbolKind::Type,
133+
full_range,
134+
focus_range,
135+
children: vec![],
136+
})
137+
}
138+
109139
fn create_column_symbol(column: ast::Column) -> Option<DocumentSymbol> {
110140
let name_node = column.name()?;
111141
let name = name_node.syntax().text().to_string();
@@ -165,6 +195,7 @@ mod tests {
165195
let kind = match symbol.kind {
166196
DocumentSymbolKind::Table => "table",
167197
DocumentSymbolKind::Function => "function",
198+
DocumentSymbolKind::Type => "type",
168199
DocumentSymbolKind::Column => "column",
169200
};
170201

@@ -350,6 +381,54 @@ create function my_schema.hello() returns void as $$ select 1; $$ language sql;
350381
");
351382
}
352383

384+
#[test]
385+
fn create_type() {
386+
assert_snapshot!(
387+
symbols("create type status as enum ('active', 'inactive');"),
388+
@r"
389+
info: type: public.status
390+
β•­β–Έ
391+
1 β”‚ create type status as enum ('active', 'inactive');
392+
β”‚ ┬───────────┯━━━━━───────────────────────────────
393+
β”‚ β”‚ β”‚
394+
β”‚ β”‚ focus range
395+
β•°β•΄full range
396+
"
397+
);
398+
}
399+
400+
#[test]
401+
fn create_type_composite() {
402+
assert_snapshot!(
403+
symbols("create type person as (name text, age int);"),
404+
@r"
405+
info: type: public.person
406+
β•­β–Έ
407+
1 β”‚ create type person as (name text, age int);
408+
β”‚ ┬───────────┯━━━━━────────────────────────
409+
β”‚ β”‚ β”‚
410+
β”‚ β”‚ focus range
411+
β•°β•΄full range
412+
"
413+
);
414+
}
415+
416+
#[test]
417+
fn create_type_with_schema() {
418+
assert_snapshot!(
419+
symbols("create type myschema.status as enum ('active', 'inactive');"),
420+
@r"
421+
info: type: myschema.status
422+
β•­β–Έ
423+
1 β”‚ create type myschema.status as enum ('active', 'inactive');
424+
β”‚ ┬────────────────────┯━━━━━───────────────────────────────
425+
β”‚ β”‚ β”‚
426+
β”‚ β”‚ focus range
427+
β•°β•΄full range
428+
"
429+
);
430+
}
431+
353432
#[test]
354433
fn empty_file() {
355434
symbols_not_found("")

β€Žcrates/squawk_ide/src/goto_definition.rsβ€Ž

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,94 @@ create table t();
369369
");
370370
}
371371

372+
#[test]
373+
fn goto_drop_type() {
374+
assert_snapshot!(goto("
375+
create type t as enum ('a', 'b');
376+
drop type t$0;
377+
"), @r"
378+
β•­β–Έ
379+
2 β”‚ create type t as enum ('a', 'b');
380+
β”‚ ─ 2. destination
381+
3 β”‚ drop type t;
382+
β•°β•΄ ─ 1. source
383+
");
384+
}
385+
386+
#[test]
387+
fn goto_drop_type_with_schema() {
388+
assert_snapshot!(goto("
389+
create type public.t as enum ('a', 'b');
390+
drop type t$0;
391+
"), @r"
392+
β•­β–Έ
393+
2 β”‚ create type public.t as enum ('a', 'b');
394+
β”‚ ─ 2. destination
395+
3 β”‚ drop type t;
396+
β•°β•΄ ─ 1. source
397+
");
398+
399+
assert_snapshot!(goto("
400+
create type foo.t as enum ('a', 'b');
401+
drop type foo.t$0;
402+
"), @r"
403+
β•­β–Έ
404+
2 β”‚ create type foo.t as enum ('a', 'b');
405+
β”‚ ─ 2. destination
406+
3 β”‚ drop type foo.t;
407+
β•°β•΄ ─ 1. source
408+
");
409+
410+
goto_not_found(
411+
"
412+
create type t as enum ('a', 'b');
413+
drop type foo.t$0;
414+
",
415+
);
416+
}
417+
418+
#[test]
419+
fn goto_drop_type_defined_after() {
420+
assert_snapshot!(goto("
421+
drop type t$0;
422+
create type t as enum ('a', 'b');
423+
"), @r"
424+
β•­β–Έ
425+
2 β”‚ drop type t;
426+
β”‚ ─ 1. source
427+
3 β”‚ create type t as enum ('a', 'b');
428+
β•°β•΄ ─ 2. destination
429+
");
430+
}
431+
432+
#[test]
433+
fn goto_drop_type_composite() {
434+
assert_snapshot!(goto("
435+
create type person as (name text, age int);
436+
drop type person$0;
437+
"), @r"
438+
β•­β–Έ
439+
2 β”‚ create type person as (name text, age int);
440+
β”‚ ────── 2. destination
441+
3 β”‚ drop type person;
442+
β•°β•΄ ─ 1. source
443+
");
444+
}
445+
446+
#[test]
447+
fn goto_drop_type_range() {
448+
assert_snapshot!(goto("
449+
create type int4_range as range (subtype = int4);
450+
drop type int4_range$0;
451+
"), @r"
452+
β•­β–Έ
453+
2 β”‚ create type int4_range as range (subtype = int4);
454+
β”‚ ────────── 2. destination
455+
3 β”‚ drop type int4_range;
456+
β•°β•΄ ─ 1. source
457+
");
458+
}
459+
372460
#[test]
373461
fn begin_to_rollback() {
374462
assert_snapshot!(goto(

0 commit comments

Comments
Β (0)