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
29 changes: 24 additions & 5 deletions crates/pgt_completions/src/relevance/filtering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ impl<'a> From<CompletionRelevanceData<'a>> for CompletionFilter<'a> {
impl CompletionFilter<'_> {
pub fn is_relevant(&self, ctx: &TreesitterContext) -> Option<()> {
self.completable_context(ctx)?;
self.check_clause(ctx)?;

self.check_node_type(ctx)
// we want to rely on treesitter more, so checking the clause is a fallback
.or_else(|| self.check_clause(ctx))?;

self.check_invocation(ctx)?;
self.check_mentioned_schema_or_alias(ctx)?;

Expand Down Expand Up @@ -69,8 +73,8 @@ impl CompletionFilter<'_> {
// No autocompletions if there are two identifiers without a separator.
if ctx.node_under_cursor.as_ref().is_some_and(|node| {
node.prev_sibling().is_some_and(|p| {
(p.kind() == "identifier" || p.kind() == "object_reference")
&& node.kind() == "identifier"
(p.kind() == "any_identifier" || p.kind() == "object_reference")
&& node.kind() == "any_identifier"
})
}) {
return None;
Expand All @@ -80,14 +84,29 @@ impl CompletionFilter<'_> {
// `select * {}`
if ctx.node_under_cursor.as_ref().is_some_and(|node| {
node.prev_sibling()
.is_some_and(|p| (p.kind() == "all_fields") && node.kind() == "identifier")
.is_some_and(|p| (p.kind() == "all_fields") && node.kind() == "any_identifier")
}) {
return None;
}

Some(())
}

fn check_node_type(&self, ctx: &TreesitterContext) -> Option<()> {
let kind = ctx.node_under_cursor.as_ref().map(|n| n.kind())?;

let is_allowed = match kind {
"column_identifier" => {
matches!(self.data, CompletionRelevanceData::Column(_))
&& !ctx.matches_ancestor_history(&["insert_values", "field"])
&& !ctx.node_under_cursor_is_within_field_name("binary_expr_right")
}
_ => false,
};

if is_allowed { Some(()) } else { None }
}

fn check_clause(&self, ctx: &TreesitterContext) -> Option<()> {
ctx.wrapping_clause_type
.as_ref()
Expand Down Expand Up @@ -254,7 +273,7 @@ impl CompletionFilter<'_> {
WrappingClause::RevokeStatement | WrappingClause::GrantStatement => {
ctx.matches_ancestor_history(&["role_specification"])
|| ctx.node_under_cursor.as_ref().is_some_and(|k| {
k.kind() == "identifier"
k.kind() == "any_identifier"
&& ctx.before_cursor_matches_kind(&[
"keyword_grant",
"keyword_revoke",
Expand Down
14 changes: 8 additions & 6 deletions crates/pgt_hover/src/hovered_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl HoveredNode {
let under_cursor = ctx.node_under_cursor.as_ref()?;

match under_cursor.kind() {
"identifier"
"any_identifier"
if ctx.matches_ancestor_history(&["relation", "object_reference"])
|| ctx
.matches_ancestor_history(&["grantable_on_table", "object_reference"]) =>
Expand All @@ -52,7 +52,7 @@ impl HoveredNode {
}
}

"identifier"
"any_identifier"
if ctx.matches_ancestor_history(&["object_reference"])
&& ctx.wrapping_clause_type.as_ref().is_some_and(|clause| {
matches!(
Expand All @@ -73,7 +73,7 @@ impl HoveredNode {
}
}

"identifier" if ctx.matches_ancestor_history(&["field"]) => {
"column_identifier" => {
if let Some(table_or_alias) = ctx.schema_or_alias_name.as_ref() {
Some(HoveredNode::Column(NodeIdentification::SchemaAndName((
table_or_alias.clone(),
Expand All @@ -84,7 +84,9 @@ impl HoveredNode {
}
}

"identifier" if ctx.matches_ancestor_history(&["invocation", "object_reference"]) => {
"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(),
Expand All @@ -97,7 +99,7 @@ impl HoveredNode {
}
}

"identifier"
"any_identifier"
if ctx.matches_one_of_ancestors(&[
"alter_role",
"policy_to_role",
Expand All @@ -110,7 +112,7 @@ impl HoveredNode {
Some(HoveredNode::Role(NodeIdentification::Name(node_content)))
}

"identifier"
"any_identifier"
if (
// hover over custom type in `create table` or `returns`
(ctx.matches_ancestor_history(&["type", "object_reference"])
Expand Down
17 changes: 8 additions & 9 deletions crates/pgt_treesitter/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -590,8 +590,7 @@ impl<'a> TreesitterContext<'a> {
// `node.child_by_field_id(..)` does not work as expected
let mut on_node = None;
for child in node.children(cursor) {
// 28 is the id for "keyword_on"
if child.kind_id() == 28 {
if child.kind() == "keyword_on" {
on_node = Some(child);
}
}
Expand Down Expand Up @@ -620,7 +619,7 @@ impl<'a> TreesitterContext<'a> {
/// Verifies whether the node_under_cursor has the passed in ancestors in the right order.
/// Note that you need to pass in the ancestors in the order as they would appear in the tree:
///
/// If the tree shows `relation > object_reference > identifier` and the "identifier" is a leaf node,
/// If the tree shows `relation > object_reference > any_identifier` and the "any_identifier" is a leaf node,
/// you need to pass `&["relation", "object_reference"]`.
pub fn matches_ancestor_history(&self, expected_ancestors: &[&'static str]) -> bool {
self.node_under_cursor.as_ref().is_some_and(|node| {
Expand All @@ -642,7 +641,7 @@ impl<'a> TreesitterContext<'a> {
/// Verifies whether the node_under_cursor has the passed in ancestors in the right order.
/// Note that you need to pass in the ancestors in the order as they would appear in the tree:
///
/// If the tree shows `relation > object_reference > identifier` and the "identifier" is a leaf node,
/// If the tree shows `relation > object_reference > any_identifier` and the "any_identifier" is a leaf node,
/// you need to pass `&["relation", "object_reference"]`.
pub fn matches_one_of_ancestors(&self, expected_ancestors: &[&'static str]) -> bool {
self.node_under_cursor.as_ref().is_some_and(|node| {
Expand All @@ -663,9 +662,9 @@ impl<'a> TreesitterContext<'a> {
/// * keyword_from [9..13] 'from'
/// * relation [14..28] '"auth"."users"'
/// * object_reference [14..28] '"auth"."users"'
/// * identifier [14..20] '"auth"'
/// * any_identifier [14..20] '"auth"'
/// * . [20..21] '.'
/// * identifier [21..28] '"users"'
/// * any_identifier [21..28] '"users"'
/// */
///
/// if node_under_cursor_is_nth_child(1) {
Expand Down Expand Up @@ -1132,13 +1131,13 @@ mod tests {
keyword_where [29..34] 'where'
binary_expression [35..43] 'id = @id'
field [35..37] 'id'
identifier [35..37] 'id'
any_identifier [35..37] 'id'
= [38..39] '='
field [40..43] '@id'
identifier [40..43] '@id'
any_identifier [40..43] '@id'
@ [40..41] '@'

You can see that the '@' is a child of the "identifier" but has a range smaller than its parent's.
You can see that the '@' is a child of the "any_identifier" but has a range smaller than its parent's.
This would crash our context parsing because, at position 42, we weren't at the leaf node but also couldn't
go to a child on that position.
*/
Expand Down
10 changes: 2 additions & 8 deletions crates/pgt_treesitter/src/queries/insert_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,8 @@ use super::QueryTryFrom;

static TS_QUERY: LazyLock<tree_sitter::Query> = LazyLock::new(|| {
static QUERY_STR: &str = r#"
(insert
(object_reference)
(list
"("?
(column) @column
","?
")"?
)
(insert_columns
(column_identifier) @column
)
"#;
tree_sitter::Query::new(&pgt_treesitter_grammar::LANGUAGE.into(), QUERY_STR)
Expand Down
2 changes: 1 addition & 1 deletion crates/pgt_treesitter/src/queries/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ static TS_QUERY: LazyLock<tree_sitter::Query> = LazyLock::new(|| {
[
(field
(field_qualifier)?
(identifier)
(column_identifier)
) @reference

(parameter) @parameter
Expand Down
12 changes: 6 additions & 6 deletions crates/pgt_treesitter/src/queries/relations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ static TS_QUERY: LazyLock<tree_sitter::Query> = LazyLock::new(|| {
(relation
(object_reference
.
(identifier) @schema_or_table
(any_identifier) @schema_or_table
"."?
(identifier)? @table
(any_identifier)? @table
)+
)
(insert
(object_reference
.
(identifier) @schema_or_table
(any_identifier) @schema_or_table
"."?
(identifier)? @table
(any_identifier)? @table
)+
)
(alter_table
(keyword_alter)
(keyword_table)
(object_reference
.
(identifier) @schema_or_table
(any_identifier) @schema_or_table
"."?
(identifier)? @table
(any_identifier)? @table
)+
)
"#;
Expand Down
2 changes: 1 addition & 1 deletion crates/pgt_treesitter/src/queries/select_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static TS_QUERY: LazyLock<tree_sitter::Query> = LazyLock::new(|| {
(object_reference) @alias
"."
)?
(identifier) @column
(column_identifier) @column
)
)
","?
Expand Down
6 changes: 3 additions & 3 deletions crates/pgt_treesitter/src/queries/table_aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ static TS_QUERY: LazyLock<tree_sitter::Query> = LazyLock::new(|| {
(relation
(object_reference
.
(identifier) @schema_or_table
(any_identifier) @schema_or_table
"."?
(identifier)? @table
(any_identifier)? @table
)
(keyword_as)?
(identifier) @alias
(any_identifier) @alias
)
"#;
tree_sitter::Query::new(&pgt_treesitter_grammar::LANGUAGE.into(), QUERY_STR)
Expand Down
2 changes: 1 addition & 1 deletion crates/pgt_treesitter/src/queries/where_columns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ static TS_QUERY: LazyLock<tree_sitter::Query> = LazyLock::new(|| {
(object_reference) @alias
"."
)?
(identifier) @column
(column_identifier) @column
)
)
)
Expand Down
Loading