Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
116 changes: 38 additions & 78 deletions crates/pgls_hover/src/hovered_node.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
use pgls_treesitter::WrappingClause;

#[derive(Debug)]
pub(crate) enum NodeIdentification {
Name(String),
SchemaAndName((String, String)),
#[allow(unused)]
SchemaAndTableAndName((String, String, String)),
}

#[allow(unused)]
#[derive(Debug)]
pub(crate) enum HoveredNode {
Schema(NodeIdentification),
Table(NodeIdentification),
Function(NodeIdentification),
Column(NodeIdentification),
Policy(NodeIdentification),
Trigger(NodeIdentification),
Role(NodeIdentification),
PostgresType(NodeIdentification),
Schema(String),
Table((Option<String>, String)),
Function((Option<String>, String)),
Column((Option<String>, Option<String>, String)),
Policy((Option<String>, String)),
Trigger((Option<String>, String)),
Role(String),
PostgresType((Option<String>, String)),
}

impl HoveredNode {
Expand All @@ -39,17 +31,13 @@ impl HoveredNode {
{
let num_sibs = ctx.num_siblings();
if ctx.node_under_cursor_is_nth_child(1) && num_sibs > 0 {
return Some(HoveredNode::Schema(NodeIdentification::Name(node_content)));
return Some(HoveredNode::Schema(node_content));
}

if let Some(schema) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::Table(NodeIdentification::SchemaAndName((
schema.clone(),
node_content,
))))
} else {
Some(HoveredNode::Table(NodeIdentification::Name(node_content)))
}
Some(HoveredNode::Table((
ctx.schema_or_alias_name.clone(),
node_content,
)))
}

"any_identifier"
Expand All @@ -63,40 +51,25 @@ impl HoveredNode {
)
}) =>
{
if let Some(schema) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::Table(NodeIdentification::SchemaAndName((
schema.clone(),
node_content,
))))
} else {
Some(HoveredNode::Table(NodeIdentification::Name(node_content)))
}
Some(HoveredNode::Table((
ctx.schema_or_alias_name.clone(),
node_content,
)))
}

"column_identifier" => {
if let Some(table_or_alias) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::Column(NodeIdentification::SchemaAndName((
table_or_alias.clone(),
node_content,
))))
} else {
Some(HoveredNode::Column(NodeIdentification::Name(node_content)))
}
}
"column_identifier" => Some(HoveredNode::Column((
None,
ctx.schema_or_alias_name.clone(),
node_content,
))),

"any_identifier"
if ctx.matches_ancestor_history(&["invocation", "object_reference"]) =>
{
if let Some(schema) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::Function(NodeIdentification::SchemaAndName((
schema.clone(),
node_content,
))))
} else {
Some(HoveredNode::Function(NodeIdentification::Name(
node_content,
)))
}
Some(HoveredNode::Function((
ctx.schema_or_alias_name.clone(),
node_content,
)))
}

"any_identifier"
Expand All @@ -106,19 +79,17 @@ impl HoveredNode {
"role_specification",
]) || ctx.before_cursor_matches_kind(&["keyword_revoke"]) =>
{
Some(HoveredNode::Role(NodeIdentification::Name(node_content)))
}
"grant_role" | "policy_role" => {
Some(HoveredNode::Role(NodeIdentification::Name(node_content)))
Some(HoveredNode::Role(node_content))
}
"grant_role" | "policy_role" => Some(HoveredNode::Role(node_content)),

"any_identifier"
if (
// hover over custom type in `create table` or `returns`
(ctx.matches_ancestor_history(&["type", "object_reference"])
&& ctx.node_under_cursor_is_within_field_name("custom_type"))

// hover over type in `select` clause etc…
// hover over type in `select` clause etc…
|| (ctx
.matches_ancestor_history(&["field_qualifier", "object_reference"])
&& ctx.before_cursor_matches_kind(&["("])))
Expand All @@ -131,32 +102,21 @@ impl HoveredNode {
.is_none() =>
{
let sanitized = node_content.replace(['(', ')'], "");
if let Some(schema) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::PostgresType(
NodeIdentification::SchemaAndName((schema.clone(), sanitized)),
))
} else {
Some(HoveredNode::PostgresType(NodeIdentification::Name(
sanitized,
)))
}
Some(HoveredNode::PostgresType((
ctx.schema_or_alias_name.clone(),
sanitized,
)))
}

// quoted columns
"literal" if ctx.matches_ancestor_history(&["select_expression", "term"]) => {
Some(HoveredNode::Column(NodeIdentification::Name(node_content)))
Some(HoveredNode::Column((None, None, node_content)))
}

"grant_table" => {
if let Some(schema) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::Table(NodeIdentification::SchemaAndName((
schema.clone(),
node_content,
))))
} else {
Some(HoveredNode::Table(NodeIdentification::Name(node_content)))
}
}
"grant_table" => Some(HoveredNode::Table((
ctx.schema_or_alias_name.clone(),
node_content,
))),

_ => None,
}
Expand Down
140 changes: 44 additions & 96 deletions crates/pgls_hover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,107 +33,55 @@ pub fn on_hover(params: OnHoverParams) -> Vec<String> {

if let Some(hovered_node) = HoveredNode::get(&ctx) {
let items: Vec<Hoverable> = match hovered_node {
HoveredNode::Table(node_identification) => match node_identification {
hovered_node::NodeIdentification::Name(n) => params
.schema_cache
.find_tables(n.as_str(), None)
.into_iter()
.map(Hoverable::from)
.collect(),

hovered_node::NodeIdentification::SchemaAndName((s, n)) => params
.schema_cache
.find_tables(n.as_str(), Some(&s))
.into_iter()
.map(Hoverable::from)
.collect(),

_ => vec![],
},

HoveredNode::Column(node_identification) => match node_identification {
hovered_node::NodeIdentification::Name(column_name) => params
.schema_cache
.find_cols(&column_name, None, None)
.into_iter()
.map(Hoverable::from)
.collect(),

hovered_node::NodeIdentification::SchemaAndName((table_or_alias, column_name)) => {
// resolve alias to actual table name if needed
let actual_table = ctx
.get_mentioned_table_for_alias(table_or_alias.as_str())
HoveredNode::Table((schema, name)) => params
.schema_cache
.find_tables(name.as_str(), schema.as_deref())
.into_iter()
.map(Hoverable::from)
.collect(),

HoveredNode::Column((schema, table_or_alias, column_name)) => {
let table = table_or_alias.as_ref().and_then(|t| {
ctx.get_mentioned_table_for_alias(t.as_str())
.map(|s| s.as_str())
.unwrap_or(table_or_alias.as_str());

params
.schema_cache
.find_cols(&column_name, Some(actual_table), None)
.into_iter()
.map(Hoverable::from)
.collect()
}

_ => vec![],
},

HoveredNode::Function(node_identification) => match node_identification {
hovered_node::NodeIdentification::Name(function_name) => params
.schema_cache
.find_functions(&function_name, None)
.into_iter()
.map(Hoverable::from)
.collect(),
.or(Some(t.as_str()))
});

hovered_node::NodeIdentification::SchemaAndName((schema, function_name)) => params
params
.schema_cache
.find_functions(&function_name, Some(&schema))
.find_cols(&column_name, table, schema.as_deref())
.into_iter()
.map(Hoverable::from)
.collect(),

_ => vec![],
},

HoveredNode::Role(node_identification) => match node_identification {
hovered_node::NodeIdentification::Name(role_name) => params
.schema_cache
.find_roles(&role_name)
.into_iter()
.map(Hoverable::from)
.collect(),

_ => vec![],
},

HoveredNode::Schema(node_identification) => match node_identification {
hovered_node::NodeIdentification::Name(schema_name) => params
.schema_cache
.find_schema(&schema_name)
.map(Hoverable::from)
.map(|s| vec![s])
.unwrap_or_default(),

_ => vec![],
},

HoveredNode::PostgresType(node_identification) => match node_identification {
hovered_node::NodeIdentification::Name(type_name) => params
.schema_cache
.find_type(&type_name, None)
.map(Hoverable::from)
.map(|s| vec![s])
.unwrap_or_default(),

hovered_node::NodeIdentification::SchemaAndName((schema, type_name)) => params
.schema_cache
.find_type(&type_name, Some(schema.as_str()))
.map(Hoverable::from)
.map(|s| vec![s])
.unwrap_or_default(),

_ => vec![],
},
.collect()
}

HoveredNode::Function((schema, function_name)) => params
.schema_cache
.find_functions(&function_name, schema.as_deref())
.into_iter()
.map(Hoverable::from)
.collect(),

HoveredNode::Role(role_name) => params
.schema_cache
.find_roles(&role_name)
.into_iter()
.map(Hoverable::from)
.collect(),

HoveredNode::Schema(schema_name) => params
.schema_cache
.find_schema(&schema_name)
.map(Hoverable::from)
.map(|s| vec![s])
.unwrap_or_default(),

HoveredNode::PostgresType((schema, type_name)) => params
.schema_cache
.find_type(&type_name, schema.as_deref())
.map(Hoverable::from)
.map(|s| vec![s])
.unwrap_or_default(),

_ => todo!(),
};
Expand Down