@@ -49,12 +49,29 @@ impl TryFrom<String> for ClauseType {
4949}
5050
5151pub ( crate ) struct CompletionContext < ' a > {
52- pub ts_node : Option < tree_sitter:: Node < ' a > > ,
52+ pub node_under_cursor : Option < tree_sitter:: Node < ' a > > ,
53+ pub previous_node : Option < tree_sitter:: Node < ' a > > ,
54+
5355 pub tree : Option < & ' a tree_sitter:: Tree > ,
5456 pub text : & ' a str ,
5557 pub schema_cache : & ' a SchemaCache ,
5658 pub position : usize ,
5759
60+ /// If the cursor of the user is offset to the right of the statement,
61+ /// we'll have to move it back to the last node, otherwise, tree-sitter will break.
62+ /// However, knowing that the user is typing on the "next" node lets us prioritize different completion results.
63+ /// We consider an offset of up to two characters as valid.
64+ ///
65+ /// Example:
66+ ///
67+ /// ```
68+ /// select * from {}
69+ /// ```
70+ ///
71+ /// We'll adjust the cursor position so it lies on the "from" token – but we're looking
72+ /// for table completions.
73+ pub cursor_offset_from_end : bool ,
74+
5875 pub schema_name : Option < String > ,
5976 pub wrapping_clause_type : Option < ClauseType > ,
6077 pub is_invocation : bool ,
@@ -70,7 +87,9 @@ impl<'a> CompletionContext<'a> {
7087 text : & params. text ,
7188 schema_cache : params. schema ,
7289 position : usize:: from ( params. position ) ,
73- ts_node : None ,
90+ cursor_offset_from_end : false ,
91+ previous_node : None ,
92+ node_under_cursor : None ,
7493 schema_name : None ,
7594 wrapping_clause_type : None ,
7695 wrapping_statement_range : None ,
@@ -81,8 +100,6 @@ impl<'a> CompletionContext<'a> {
81100 ctx. gather_tree_context ( ) ;
82101 ctx. gather_info_from_ts_queries ( ) ;
83102
84- println ! ( "Here's my node: {:?}" , ctx. ts_node. unwrap( ) ) ;
85-
86103 ctx
87104 }
88105
@@ -147,30 +164,34 @@ impl<'a> CompletionContext<'a> {
147164 * `select * from use {}` becomes `select * from use{}`.
148165 */
149166 let current_node = cursor. node ( ) ;
167+ let position_cache = self . position . clone ( ) ;
150168 while cursor. goto_first_child_for_byte ( self . position ) . is_none ( ) && self . position > 0 {
151169 self . position -= 1 ;
152170 }
153171
172+ let cursor_offset = position_cache - self . position ;
173+ self . cursor_offset_from_end = cursor_offset > 0 && cursor_offset <= 2 ;
174+
154175 self . gather_context_from_node ( cursor, current_node) ;
155176 }
156177
157178 fn gather_context_from_node (
158179 & mut self ,
159180 mut cursor : tree_sitter:: TreeCursor < ' a > ,
160- previous_node : tree_sitter:: Node < ' a > ,
181+ parent_node : tree_sitter:: Node < ' a > ,
161182 ) {
162183 let current_node = cursor. node ( ) ;
163184
164185 // prevent infinite recursion – this can happen if we only have a PROGRAM node
165- if current_node. kind ( ) == previous_node . kind ( ) {
166- self . ts_node = Some ( current_node) ;
186+ if current_node. kind ( ) == parent_node . kind ( ) {
187+ self . node_under_cursor = Some ( current_node) ;
167188 return ;
168189 }
169190
170- match previous_node . kind ( ) {
191+ match parent_node . kind ( ) {
171192 "statement" | "subquery" => {
172193 self . wrapping_clause_type = current_node. kind ( ) . try_into ( ) . ok ( ) ;
173- self . wrapping_statement_range = Some ( previous_node . range ( ) ) ;
194+ self . wrapping_statement_range = Some ( parent_node . range ( ) ) ;
174195 }
175196 "invocation" => self . is_invocation = true ,
176197
@@ -202,7 +223,23 @@ impl<'a> CompletionContext<'a> {
202223
203224 // We have arrived at the leaf node
204225 if current_node. child_count ( ) == 0 {
205- self . ts_node = Some ( current_node) ;
226+ if self . cursor_offset_from_end {
227+ self . node_under_cursor = None ;
228+ self . previous_node = Some ( current_node) ;
229+ } else {
230+ // for the previous node, either select the previous sibling,
231+ // or collect the parent's previous sibling's last child.
232+ let previous = match current_node. prev_sibling ( ) {
233+ Some ( n) => Some ( n) ,
234+ None => {
235+ let sib_of_parent = parent_node. prev_sibling ( ) ;
236+ sib_of_parent. and_then ( |p| p. children ( & mut cursor) . last ( ) )
237+ }
238+ } ;
239+ self . node_under_cursor = Some ( current_node) ;
240+ self . previous_node = previous;
241+ }
242+
206243 return ;
207244 }
208245
@@ -361,7 +398,7 @@ mod tests {
361398
362399 let ctx = CompletionContext :: new ( & params) ;
363400
364- let node = ctx. ts_node . unwrap ( ) ;
401+ let node = ctx. node_under_cursor . unwrap ( ) ;
365402
366403 assert_eq ! ( ctx. get_ts_node_content( node) , Some ( "select" ) ) ;
367404
@@ -389,7 +426,7 @@ mod tests {
389426
390427 let ctx = CompletionContext :: new ( & params) ;
391428
392- let node = ctx. ts_node . unwrap ( ) ;
429+ let node = ctx. node_under_cursor . unwrap ( ) ;
393430
394431 assert_eq ! ( ctx. get_ts_node_content( node) , Some ( "from" ) ) ;
395432 assert_eq ! (
@@ -415,7 +452,7 @@ mod tests {
415452
416453 let ctx = CompletionContext :: new ( & params) ;
417454
418- let node = ctx. ts_node . unwrap ( ) ;
455+ let node = ctx. node_under_cursor . unwrap ( ) ;
419456
420457 assert_eq ! ( ctx. get_ts_node_content( node) , Some ( "" ) ) ;
421458 assert_eq ! ( ctx. wrapping_clause_type, None ) ;
@@ -440,7 +477,7 @@ mod tests {
440477
441478 let ctx = CompletionContext :: new ( & params) ;
442479
443- let node = ctx. ts_node . unwrap ( ) ;
480+ let node = ctx. node_under_cursor . unwrap ( ) ;
444481
445482 assert_eq ! ( ctx. get_ts_node_content( node) , Some ( "fro" ) ) ;
446483 assert_eq ! ( ctx. wrapping_clause_type, Some ( ClauseType :: Select ) ) ;
0 commit comments