@@ -18,7 +18,7 @@ impl CompletionFilter<'_> {
1818 pub fn is_relevant ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
1919 self . completable_context ( ctx) ?;
2020
21- self . check_node_type ( ctx)
21+ self . check_specific_node_type ( ctx)
2222 // we want to rely on treesitter more, so checking the clause is a fallback
2323 . or_else ( || self . check_clause ( ctx) ) ?;
2424
@@ -33,11 +33,7 @@ impl CompletionFilter<'_> {
3333 return None ;
3434 }
3535
36- let current_node_kind = ctx
37- . node_under_cursor
38- . as_ref ( )
39- . map ( |n| n. kind ( ) )
40- . unwrap_or ( "" ) ;
36+ let current_node_kind = ctx. node_under_cursor . kind ( ) ;
4137
4238 if current_node_kind. starts_with ( "keyword_" )
4339 || current_node_kind == "="
@@ -70,37 +66,92 @@ impl CompletionFilter<'_> {
7066 }
7167 }
7268
69+ if ctx. node_under_cursor . kind ( ) == "any_identifier"
70+ && ctx. history_ends_with ( & [ "alias" , "any_identifier" ] )
71+ {
72+ return None ;
73+ }
74+
7375 // No autocompletions if there are two identifiers without a separator.
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- } )
76+ if ctx. node_under_cursor . prev_sibling ( ) . is_some_and ( |p| {
77+ ( p. kind ( ) == "any_identifier" || p. kind ( ) == "object_reference" )
78+ && ctx. node_under_cursor . kind ( ) == "any_identifier"
7979 } ) {
8080 return None ;
8181 }
8282
8383 // no completions if we're right after an asterisk:
8484 // `select * {}`
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" )
85+ if ctx. node_under_cursor . prev_sibling ( ) . is_some_and ( |p| {
86+ ( p. kind ( ) == "all_fields" ) && ctx. node_under_cursor . kind ( ) == "any_identifier"
8887 } ) {
8988 return None ;
9089 }
9190
9291 Some ( ( ) )
9392 }
9493
95- fn check_node_type ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
96- let kind = ctx. node_under_cursor . as_ref ( ) . map ( |n| n . kind ( ) ) ? ;
94+ fn check_specific_node_type ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
95+ let kind = ctx. node_under_cursor . kind ( ) ;
9796
9897 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- }
98+ "column_identifier" => matches ! ( self . data, CompletionRelevanceData :: Column ( _) ) ,
99+ "role_identifier" => matches ! ( self . data, CompletionRelevanceData :: Role ( _) ) ,
100+ "function_identifier" => matches ! ( self . data, CompletionRelevanceData :: Function ( _) ) ,
101+ "schema_identifier" => matches ! ( self . data, CompletionRelevanceData :: Schema ( _) ) ,
102+ "table_identifier" => matches ! ( self . data, CompletionRelevanceData :: Table ( _) ) ,
103+ "policy_identifier" => matches ! ( self . data, CompletionRelevanceData :: Policy ( _) ) ,
104+
105+ "any_identifier" => match self . data {
106+ CompletionRelevanceData :: Column ( _) => {
107+ ctx. node_under_cursor_is_within_field ( & [
108+ "object_reference_1of1" ,
109+ "object_reference_2of2" ,
110+ "object_reference_3of3" ,
111+ "column_reference_1of1" ,
112+ "column_reference_2of2" ,
113+ "column_reference_3of3" ,
114+ ] ) && !ctx. node_under_cursor_is_within_field ( & [ "binary_expr_right" ] )
115+ }
116+
117+ CompletionRelevanceData :: Schema ( _) => ctx. node_under_cursor_is_within_field ( & [
118+ "object_reference_1of1" ,
119+ "object_reference_1of2" ,
120+ "object_reference_1of3" ,
121+ "type_reference_1of1" ,
122+ "table_reference_1of1" ,
123+ "column_reference_1of1" ,
124+ "column_reference_1of2" ,
125+ "function_reference_1of1" ,
126+ ] ) ,
127+
128+ CompletionRelevanceData :: Function ( f) => {
129+ ctx. node_under_cursor_is_within_field ( & [
130+ "object_reference_1of1" ,
131+ "object_reference_2of2" ,
132+ "function_reference_1of1" ,
133+ ] ) && !( ctx. history_ends_with ( & [
134+ "check_or_using_clause" ,
135+ "binary_expression" ,
136+ "object_reference" ,
137+ "any_identifier" ,
138+ ] ) && matches ! ( f. kind, ProcKind :: Aggregate ) )
139+ }
140+
141+ CompletionRelevanceData :: Table ( _) => ctx. node_under_cursor_is_within_field ( & [
142+ "object_reference_1of1" ,
143+ "object_reference_1of2" ,
144+ "object_reference_2of2" ,
145+ "object_reference_2of3" ,
146+ "table_reference_1of1" ,
147+ "column_reference_1of1" ,
148+ "column_reference_1of2" ,
149+ "column_reference_2of2" ,
150+ ] ) ,
151+
152+ _ => false ,
153+ } ,
154+
104155 _ => false ,
105156 } ;
106157
@@ -116,21 +167,27 @@ impl CompletionFilter<'_> {
116167 WrappingClause :: From | WrappingClause :: Update => true ,
117168
118169 WrappingClause :: RevokeStatement | WrappingClause :: GrantStatement => ctx
119- . matches_ancestor_history ( & [ "grantable_on_table" , "object_reference" ] ) ,
170+ . history_ends_with ( & [
171+ "grantable_on_table" ,
172+ "object_reference" ,
173+ "any_identifier" ,
174+ ] ) ,
120175
121176 WrappingClause :: Join { on_node : None } => true ,
122- WrappingClause :: Join { on_node : Some ( on) } => ctx
123- . node_under_cursor
124- . as_ref ( )
125- . is_some_and ( |cn| cn. start_byte ( ) < on. end_byte ( ) ) ,
177+ WrappingClause :: Join { on_node : Some ( on) } => {
178+ ctx. node_under_cursor . start_byte ( ) < on. end_byte ( )
179+ }
126180
127181 WrappingClause :: Insert => {
128182 ctx. wrapping_node_kind
129183 . as_ref ( )
130184 . is_none_or ( |n| n != & WrappingNode :: List )
131185 && ( ctx. before_cursor_matches_kind ( & [ "keyword_into" ] )
132186 || ( ctx. before_cursor_matches_kind ( & [ "." ] )
133- && ctx. matches_ancestor_history ( & [ "object_reference" ] ) ) )
187+ && ctx. history_ends_with ( & [
188+ "object_reference" ,
189+ "any_identifier" ,
190+ ] ) ) )
134191 }
135192
136193 WrappingClause :: DropTable | WrappingClause :: AlterTable => ctx
@@ -143,7 +200,7 @@ impl CompletionFilter<'_> {
143200 WrappingClause :: CreatePolicy
144201 | WrappingClause :: AlterPolicy
145202 | WrappingClause :: DropPolicy => {
146- ctx. matches_ancestor_history ( & [ "object_reference" ] )
203+ ctx. history_ends_with ( & [ "object_reference" , "any_identifier "] )
147204 && ctx. before_cursor_matches_kind ( & [ "keyword_on" , "." ] )
148205 }
149206
@@ -166,10 +223,9 @@ impl CompletionFilter<'_> {
166223
167224 // We can complete columns in JOIN cluases, but only if we are after the
168225 // ON node in the "ON u.id = posts.user_id" part.
169- WrappingClause :: Join { on_node : Some ( on) } => ctx
170- . node_under_cursor
171- . as_ref ( )
172- . is_some_and ( |cn| cn. start_byte ( ) >= on. end_byte ( ) ) ,
226+ WrappingClause :: Join { on_node : Some ( on) } => {
227+ ctx. node_under_cursor . start_byte ( ) >= on. end_byte ( )
228+ }
173229
174230 // we are in a JOIN, but definitely not after an ON
175231 WrappingClause :: Join { on_node : None } => false ,
@@ -183,7 +239,7 @@ impl CompletionFilter<'_> {
183239 WrappingClause :: Where => {
184240 ctx. before_cursor_matches_kind ( & [ "keyword_and" , "keyword_where" ] )
185241 || ( ctx. before_cursor_matches_kind ( & [ "field_qualifier" ] )
186- && ctx. matches_ancestor_history ( & [ "field" ] ) )
242+ && ctx. history_ends_with ( & [ "field" , "any_identifier "] ) )
187243 }
188244
189245 WrappingClause :: CheckOrUsingClause => {
@@ -216,17 +272,17 @@ impl CompletionFilter<'_> {
216272
217273 CompletionRelevanceData :: Schema ( _) => match clause {
218274 WrappingClause :: Select
219- | WrappingClause :: From
220275 | WrappingClause :: Join { .. }
221276 | WrappingClause :: Update
222277 | WrappingClause :: Delete => true ,
223278
224279 WrappingClause :: RevokeStatement | WrappingClause :: GrantStatement => {
225- ( ctx. matches_ancestor_history ( & [
280+ ( ctx. history_ends_with ( & [
226281 "grantable_on_table" ,
227282 "object_reference" ,
228- ] ) && ctx. schema_or_alias_name . is_none ( ) )
229- || ctx. matches_ancestor_history ( & [ "grantable_on_all" ] )
283+ "any_identifier" ,
284+ ] ) && !ctx. has_any_qualifier ( ) )
285+ || ctx. history_ends_with ( & [ "grantable_on_all" , "any_identifier" ] )
230286 }
231287
232288 WrappingClause :: Where => {
@@ -271,20 +327,18 @@ impl CompletionFilter<'_> {
271327 . before_cursor_matches_kind ( & [ "keyword_role" , "keyword_authorization" ] ) ,
272328
273329 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- } )
330+ ctx. history_ends_with ( & [ "role_specification" , "any_identifier" ] )
331+ || ( ctx. node_under_cursor . kind ( ) == "any_identifier"
332+ && ctx. before_cursor_matches_kind ( & [
333+ "keyword_grant" ,
334+ "keyword_revoke" ,
335+ "keyword_for" ,
336+ ] ) )
283337 }
284338
285339 WrappingClause :: AlterPolicy | WrappingClause :: CreatePolicy => {
286340 ctx. before_cursor_matches_kind ( & [ "keyword_to" ] )
287- && ctx. matches_ancestor_history ( & [ "policy_to_role" ] )
341+ && ctx. history_ends_with ( & [ "policy_to_role" , "any_identifier "] )
288342 }
289343
290344 _ => false ,
@@ -308,18 +362,24 @@ impl CompletionFilter<'_> {
308362 }
309363
310364 fn check_mentioned_schema_or_alias ( & self , ctx : & TreesitterContext ) -> Option < ( ) > {
311- if ctx. schema_or_alias_name . is_none ( ) {
312- return Some ( ( ) ) ;
313- }
314-
315- let schema_or_alias = ctx. schema_or_alias_name . as_ref ( ) . unwrap ( ) . replace ( '"' , "" ) ;
365+ let tail_qualifier = match ctx. tail_qualifier_sanitized ( ) {
366+ Some ( q) => q,
367+ None => return Some ( ( ) ) , // no qualifier = this check passes
368+ } ;
316369
317370 let matches = match self . data {
318- CompletionRelevanceData :: Table ( table) => table. schema == schema_or_alias,
319- CompletionRelevanceData :: Function ( f) => f. schema == schema_or_alias,
320- CompletionRelevanceData :: Column ( col) => ctx
321- . get_mentioned_table_for_alias ( & schema_or_alias)
322- . is_some_and ( |t| t == & col. table_name ) ,
371+ CompletionRelevanceData :: Table ( table) => table. schema == tail_qualifier,
372+ CompletionRelevanceData :: Function ( f) => f. schema == tail_qualifier,
373+ CompletionRelevanceData :: Column ( col) => {
374+ let table = ctx
375+ . get_mentioned_table_for_alias ( & tail_qualifier)
376+ . unwrap_or ( & tail_qualifier) ;
377+
378+ col. table_name == table. as_str ( )
379+ && ctx
380+ . head_qualifier_sanitized ( )
381+ . is_none_or ( |schema| col. schema_name == schema. as_str ( ) )
382+ }
323383
324384 // we should never allow schema suggestions if there already was one.
325385 CompletionRelevanceData :: Schema ( _) => false ,
0 commit comments