11use pgt_schema_cache:: ProcKind ;
2- use pgt_treesitter:: context:: { NodeUnderCursor , TreesitterContext , WrappingClause , WrappingNode } ;
2+ use pgt_treesitter:: context:: { TreesitterContext , WrappingClause , WrappingNode } ;
33
44use super :: CompletionRelevanceData ;
55
@@ -17,7 +17,11 @@ impl<'a> From<CompletionRelevanceData<'a>> for CompletionFilter<'a> {
1717impl CompletionFilter < ' _ > {
1818 pub fn is_relevant ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
1919 self . completable_context ( ctx) ?;
20- self . check_clause ( ctx) ?;
20+
21+ self . check_node_type ( ctx)
22+ // we want to rely on treesitter more, so checking the clause is a fallback
23+ . or_else ( || self . check_clause ( ctx) ) ?;
24+
2125 self . check_invocation ( ctx) ?;
2226 self . check_mentioned_schema_or_alias ( ctx) ?;
2327
@@ -67,30 +71,42 @@ impl CompletionFilter<'_> {
6771 }
6872
6973 // No autocompletions if there are two identifiers without a separator.
70- if ctx. node_under_cursor . as_ref ( ) . is_some_and ( |n| match n {
71- NodeUnderCursor :: TsNode ( node) => node. prev_sibling ( ) . is_some_and ( |p| {
72- ( p. kind ( ) == "identifier" || p. kind ( ) == "object_reference" )
73- && n. kind ( ) == "identifier"
74- } ) ,
75- NodeUnderCursor :: CustomNode { .. } => false ,
74+ if ctx. node_under_cursor . as_ref ( ) . is_some_and ( |node| {
75+ node. prev_sibling ( ) . is_some_and ( |p| {
76+ ( p. kind ( ) == "any_identifier" || p. kind ( ) == "object_reference" )
77+ && node. kind ( ) == "any_identifier"
78+ } )
7679 } ) {
7780 return None ;
7881 }
7982
8083 // no completions if we're right after an asterisk:
8184 // `select * {}`
82- if ctx. node_under_cursor . as_ref ( ) . is_some_and ( |n| match n {
83- NodeUnderCursor :: TsNode ( node) => node
84- . prev_sibling ( )
85- . is_some_and ( |p| ( p. kind ( ) == "all_fields" ) && n. kind ( ) == "identifier" ) ,
86- NodeUnderCursor :: CustomNode { .. } => false ,
85+ if ctx. node_under_cursor . as_ref ( ) . is_some_and ( |node| {
86+ node. prev_sibling ( )
87+ . is_some_and ( |p| ( p. kind ( ) == "all_fields" ) && node. kind ( ) == "any_identifier" )
8788 } ) {
8889 return None ;
8990 }
9091
9192 Some ( ( ) )
9293 }
9394
95+ fn check_node_type ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
96+ let kind = ctx. node_under_cursor . as_ref ( ) . map ( |n| n. kind ( ) ) ?;
97+
98+ let is_allowed = match kind {
99+ "column_identifier" => {
100+ matches ! ( self . data, CompletionRelevanceData :: Column ( _) )
101+ && !ctx. matches_ancestor_history ( & [ "insert_values" , "field" ] )
102+ && !ctx. node_under_cursor_is_within_field_name ( "binary_expr_right" )
103+ }
104+ _ => false ,
105+ } ;
106+
107+ if is_allowed { Some ( ( ) ) } else { None }
108+ }
109+
94110 fn check_clause ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
95111 ctx. wrapping_clause_type
96112 . as_ref ( )
@@ -99,6 +115,9 @@ impl CompletionFilter<'_> {
99115 CompletionRelevanceData :: Table ( _) => match clause {
100116 WrappingClause :: From | WrappingClause :: Update => true ,
101117
118+ WrappingClause :: RevokeStatement | WrappingClause :: GrantStatement => ctx
119+ . matches_ancestor_history ( & [ "grantable_on_table" , "object_reference" ] ) ,
120+
102121 WrappingClause :: Join { on_node : None } => true ,
103122 WrappingClause :: Join { on_node : Some ( on) } => ctx
104123 . node_under_cursor
@@ -202,6 +221,14 @@ impl CompletionFilter<'_> {
202221 | WrappingClause :: Update
203222 | WrappingClause :: Delete => true ,
204223
224+ WrappingClause :: RevokeStatement | WrappingClause :: GrantStatement => {
225+ ( ctx. matches_ancestor_history ( & [
226+ "grantable_on_table" ,
227+ "object_reference" ,
228+ ] ) && ctx. schema_or_alias_name . is_none ( ) )
229+ || ctx. matches_ancestor_history ( & [ "grantable_on_all" ] )
230+ }
231+
205232 WrappingClause :: Where => {
206233 ctx. before_cursor_matches_kind ( & [ "keyword_and" , "keyword_where" ] )
207234 }
@@ -238,13 +265,23 @@ impl CompletionFilter<'_> {
238265 }
239266
240267 CompletionRelevanceData :: Role ( _) => match clause {
241- WrappingClause :: DropRole
242- | WrappingClause :: AlterRole
243- | WrappingClause :: ToRoleAssignment => true ,
268+ WrappingClause :: DropRole | WrappingClause :: AlterRole => true ,
244269
245270 WrappingClause :: SetStatement => ctx
246271 . before_cursor_matches_kind ( & [ "keyword_role" , "keyword_authorization" ] ) ,
247272
273+ WrappingClause :: RevokeStatement | WrappingClause :: GrantStatement => {
274+ ctx. matches_ancestor_history ( & [ "role_specification" ] )
275+ || ctx. node_under_cursor . as_ref ( ) . is_some_and ( |k| {
276+ k. kind ( ) == "any_identifier"
277+ && ctx. before_cursor_matches_kind ( & [
278+ "keyword_grant" ,
279+ "keyword_revoke" ,
280+ "keyword_for" ,
281+ ] )
282+ } )
283+ }
284+
248285 WrappingClause :: AlterPolicy | WrappingClause :: CreatePolicy => {
249286 ctx. before_cursor_matches_kind ( & [ "keyword_to" ] )
250287 && ctx. matches_ancestor_history ( & [ "policy_to_role" ] )
0 commit comments