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
27 changes: 27 additions & 0 deletions crates/squawk_ide/src/binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ fn bind_stmt(b: &mut Binder, stmt: ast::Stmt) {
ast::Stmt::Listen(listen) => bind_listen(b, listen),
ast::Stmt::Set(set) => bind_set(b, set),
ast::Stmt::CreatePolicy(create_policy) => bind_create_policy(b, create_policy),
ast::Stmt::CreatePropertyGraph(create_property_graph) => {
bind_create_property_graph(b, create_property_graph)
}
_ => (),
}
}
Expand Down Expand Up @@ -773,6 +776,30 @@ fn bind_create_policy(b: &mut Binder, create_policy: ast::CreatePolicy) {
b.scopes[root].insert(policy_name, policy_id);
}

fn bind_create_property_graph(b: &mut Binder, create_property_graph: ast::CreatePropertyGraph) {
let Some(path) = create_property_graph.path() else {
return;
};
let Some(property_graph_name) = item_name(&path) else {
return;
};
let name_ptr = path_to_ptr(&path);
let Some(schema) = schema_name(b, &path, false) else {
return;
};

let property_graph_id = b.symbols.alloc(Symbol {
kind: SymbolKind::PropertyGraph,
ptr: name_ptr,
schema: Some(schema),
params: None,
table: None,
});

let root = b.root_scope();
b.scopes[root].insert(property_graph_name, property_graph_id);
}

fn bind_create_event_trigger(b: &mut Binder, create_event_trigger: ast::CreateEventTrigger) {
let Some(name) = create_event_trigger.name() else {
return;
Expand Down
22 changes: 22 additions & 0 deletions crates/squawk_ide/src/classify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pub(crate) enum NameRefClass {
PreparedStatement,
Procedure,
ProcedureCall,
PropertyGraph,
QualifiedColumn,
Role,
Routine,
Expand Down Expand Up @@ -310,6 +311,16 @@ pub(crate) fn classify_name_ref(node: &SyntaxNode) -> Option<NameRefClass> {
return Some(NameRefClass::Schema);
}

if let Some(parent) = node.parent()
&& let Some(path) = ast::PathSegment::cast(parent)
.and_then(|p| p.syntax().parent().and_then(ast::Path::cast))
&& let Some(stmt_parent) = path.syntax().parent()
&& (ast::AlterPropertyGraph::can_cast(stmt_parent.kind())
|| ast::DropPropertyGraph::can_cast(stmt_parent.kind()))
{
return Some(NameRefClass::PropertyGraph);
}

// Check for function/procedure reference in CREATE OPERATOR / CREATE AGGREGATE
// before the type check
for ancestor in node.ancestors() {
Expand Down Expand Up @@ -373,6 +384,10 @@ pub(crate) fn classify_name_ref(node: &SyntaxNode) -> Option<NameRefClass> {
|| ast::Table::can_cast(ancestor.kind())
|| ast::Inherits::can_cast(ancestor.kind())
|| ast::PartitionOf::can_cast(ancestor.kind())
|| ast::VertexTableDef::can_cast(ancestor.kind())
|| ast::EdgeTableDef::can_cast(ancestor.kind())
|| ast::SourceVertexTable::can_cast(ancestor.kind())
|| ast::DestVertexTable::can_cast(ancestor.kind())
{
return Some(NameRefClass::Table);
}
Expand Down Expand Up @@ -754,6 +769,7 @@ pub(crate) enum NameClass {
name: ast::Name,
},
CreateView(ast::CreateView),
CreatePropertyGraph(ast::CreatePropertyGraph),
DeclareCursor(ast::Declare),
PrepareStatement(ast::Prepare),
Listen(ast::Listen),
Expand Down Expand Up @@ -829,6 +845,9 @@ pub(crate) fn classify_name(name: &ast::Name) -> Option<NameClass> {
}
return Some(NameClass::CreateView(create_view));
}
if let Some(create_property_graph) = ast::CreatePropertyGraph::cast(ancestor.clone()) {
return Some(NameClass::CreatePropertyGraph(create_property_graph));
}
if let Some(declare) = ast::Declare::cast(ancestor.clone()) {
return Some(NameClass::DeclareCursor(declare));
}
Expand Down Expand Up @@ -931,6 +950,9 @@ pub(crate) fn classify_def_node(def_node: &SyntaxNode) -> Option<NameRefClass> {
if ast::CreatePolicy::can_cast(ancestor.kind()) {
return Some(NameRefClass::Policy);
}
if ast::CreatePropertyGraph::can_cast(ancestor.kind()) {
return Some(NameRefClass::PropertyGraph);
}
if ast::Declare::can_cast(ancestor.kind()) {
return Some(NameRefClass::Cursor);
}
Expand Down
45 changes: 45 additions & 0 deletions crates/squawk_ide/src/document_symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub enum DocumentSymbolKind {
EventTrigger,
Role,
Policy,
PropertyGraph,
Type,
Enum,
Index,
Expand Down Expand Up @@ -152,6 +153,11 @@ pub fn document_symbols(db: &dyn Db, file: File) -> Vec<DocumentSymbol> {
symbols.push(symbol);
}
}
ast::Stmt::CreatePropertyGraph(create_property_graph) => {
if let Some(symbol) = create_property_graph_symbol(create_property_graph) {
symbols.push(symbol);
}
}
ast::Stmt::CreateType(create_type) => {
if let Some(symbol) = create_type_symbol(&binder, create_type) {
symbols.push(symbol);
Expand Down Expand Up @@ -679,6 +685,27 @@ fn create_policy_symbol(create_policy: ast::CreatePolicy) -> Option<DocumentSymb
})
}

fn create_property_graph_symbol(
create_property_graph: ast::CreatePropertyGraph,
) -> Option<DocumentSymbol> {
let path = create_property_graph.path()?;
let name_node = path.segment()?.name()?;

let name = path.syntax().text().to_string();

let full_range = create_property_graph.syntax().text_range();
let focus_range = name_node.syntax().text_range();

Some(DocumentSymbol {
name,
detail: None,
kind: DocumentSymbolKind::PropertyGraph,
full_range,
focus_range,
children: vec![],
})
}

fn create_type_symbol(
binder: &binder::Binder,
create_type: ast::CreateType,
Expand Down Expand Up @@ -892,6 +919,7 @@ mod tests {
DocumentSymbolKind::EventTrigger => "event trigger",
DocumentSymbolKind::Role => "role",
DocumentSymbolKind::Policy => "policy",
DocumentSymbolKind::PropertyGraph => "property graph",
DocumentSymbolKind::Type => "type",
DocumentSymbolKind::Enum => "enum",
DocumentSymbolKind::Index => "index",
Expand Down Expand Up @@ -1395,6 +1423,23 @@ create function my_schema.hello() returns void as $$ select 1; $$ language sql;
");
}

#[test]
fn create_property_graph() {
assert_snapshot!(symbols("
create property graph foo.bar
vertex tables (t key (a) no properties);
"), @"
info: property graph: foo.bar
╭▸
2 │ create property graph foo.bar
│ │ ━━━ focus range
│ ┌─┘
│ │
3 │ │ vertex tables (t key (a) no properties);
╰╴└─────────────────────────────────────────┘ full range
");
}

#[test]
fn create_type() {
assert_snapshot!(
Expand Down
67 changes: 67 additions & 0 deletions crates/squawk_ide/src/goto_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ pub enum LocationKind {
Policy,
PreparedStatement,
Procedure,
PropertyGraph,
Role,
Schema,
Sequence,
Expand Down Expand Up @@ -188,6 +189,7 @@ impl From<NameRefClass> for LocationKind {
NameRefClass::NamedArgParameter => LocationKind::NamedArgParameter,
NameRefClass::Policy => LocationKind::Policy,
NameRefClass::PreparedStatement => LocationKind::PreparedStatement,
NameRefClass::PropertyGraph => LocationKind::PropertyGraph,
NameRefClass::Role => LocationKind::Role,
NameRefClass::Schema => LocationKind::Schema,
NameRefClass::Sequence => LocationKind::Sequence,
Expand Down Expand Up @@ -9343,4 +9345,69 @@ select '10'::dec$0;
╰╴ ─ 1. source
");
}

#[test]
fn goto_create_property_graph() {
assert_snapshot!(goto("
create table buzz.boo(a int, b int);
create property graph foo.bar
vertex tables (buzz.boo$0 key (a, b) no properties)
edge tables (foo.bar key (x, y)
source key (a, b) references k (t, y)
destination key (q, t) references a (r, j)
properties all columns);
"), @"
╭▸
2 │ create table buzz.boo(a int, b int);
│ ─── 2. destination
3 │ create property graph foo.bar
4 │ vertex tables (buzz.boo key (a, b) no properties)
╰╴ ─ 1. source
");

assert_snapshot!(goto("
create table foo.bar(x int, y int);
create property graph g
vertex tables (boo key (a, b) no properties)
edge tables (foo.bar$0 key (x, y)
source key (a, b) references k (t, y)
destination key (q, t) references a (r, j)
properties all columns);
"), @"
╭▸
2 │ create table foo.bar(x int, y int);
│ ─── 2. destination
5 │ edge tables (foo.bar key (x, y)
╰╴ ─ 1. source
");
}

#[test]
fn goto_drop_property_graph() {
assert_snapshot!(goto("
create property graph foo.bar vertex tables (t key (a) no properties);
drop property graph foo.ba$0r;
"), @"
╭▸
2 │ create property graph foo.bar vertex tables (t key (a) no properties);
│ ─── 2. destination
3 │ drop property graph foo.bar;
╰╴ ─ 1. source
");
}

#[test]
fn goto_alter_property_graph() {
assert_snapshot!(goto("
create property graph foo.bar vertex tables (t key (a) no properties);
alter property graph foo.ba$0r rename to baz;
"), @"
╭▸
2 │ create property graph foo.bar vertex tables (t key (a) no properties);
│ ─── 2. destination
3 │ alter property graph foo.bar rename to baz;
╰╴ ─ 1. source
");
}
}
74 changes: 73 additions & 1 deletion crates/squawk_ide/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ pub fn hover(db: &dyn Db, file: File, offset: TextSize) -> Option<Hover> {
NameClass::CreateView(create_view) => {
return format_create_view(&create_view, &binder);
}
NameClass::CreatePropertyGraph(create_property_graph) => {
return format_create_property_graph(&create_property_graph, &binder);
}
NameClass::DeclareCursor(declare) => {
return format_declare_cursor(&declare);
}
Expand Down Expand Up @@ -286,6 +289,7 @@ fn hover_name_ref(
NameRefClass::PreparedStatement => hover_prepared_statement(root, name_ref, binder),
NameRefClass::Channel => hover_channel(root, name_ref, binder),
NameRefClass::Window => hover_window(root, name_ref, binder),
NameRefClass::PropertyGraph => hover_property_graph(root, name_ref, binder),
}
}

Expand Down Expand Up @@ -1107,6 +1111,24 @@ fn hover_policy(
format_create_policy(&create_policy, binder)
}

fn hover_property_graph(
root: &SyntaxNode,
name_ref: &ast::NameRef,
binder: &binder::Binder,
) -> Option<Hover> {
let property_graph_ptr = resolve::resolve_name_ref_ptrs(binder, root, name_ref)?
.into_iter()
.next()?;

let property_graph_name_node = property_graph_ptr.to_node(root);

let create_property_graph = property_graph_name_node
.ancestors()
.find_map(ast::CreatePropertyGraph::cast)?;

format_create_property_graph(&create_property_graph, binder)
}

fn hover_event_trigger(
root: &SyntaxNode,
name_ref: &ast::NameRef,
Expand Down Expand Up @@ -1447,6 +1469,18 @@ fn format_create_policy(
)))
}

fn format_create_property_graph(
create_property_graph: &ast::CreatePropertyGraph,
binder: &binder::Binder,
) -> Option<Hover> {
let path = create_property_graph.path()?;
let (schema, name) = resolve::resolve_property_graph_info(binder, &path)?;
Some(Hover::snippet(format!(
"property graph {}.{}",
schema, name
)))
}

fn format_create_event_trigger(create_event_trigger: &ast::CreateEventTrigger) -> Option<Hover> {
let name = create_event_trigger.name()?.syntax().text().to_string();
Some(Hover::snippet(format!("event trigger {}", name)))
Expand Down Expand Up @@ -4972,11 +5006,49 @@ notify updates$0;
assert_snapshot!(check_hover("
listen updates;
unlisten updates$0;
"), @r"
"), @"
hover: listen updates
╭▸
3 │ unlisten updates;
╰╴ ─ hover
");
}

#[test]
fn hover_property_graph_on_create() {
assert_snapshot!(check_hover("
create property graph foo.ba$0r vertex tables (t key (a) no properties);
"), @"
hover: property graph foo.bar
╭▸
2 │ create property graph foo.bar vertex tables (t key (a) no properties);
╰╴ ─ hover
");
}

#[test]
fn hover_property_graph_on_drop() {
assert_snapshot!(check_hover("
create property graph foo.bar vertex tables (t key (a) no properties);
drop property graph foo.ba$0r;
"), @"
hover: property graph foo.bar
╭▸
3 │ drop property graph foo.bar;
╰╴ ─ hover
");
}

#[test]
fn hover_property_graph_on_alter() {
assert_snapshot!(check_hover("
create property graph foo.bar vertex tables (t key (a) no properties);
alter property graph foo.ba$0r rename to baz;
"), @"
hover: property graph foo.bar
╭▸
3 │ alter property graph foo.bar rename to baz;
╰╴ ─ hover
");
}
}
Loading
Loading