Sfoglia il codice sorgente

Grow the requested range based on what we receive

This means that if the servers return a wider range of semantic tokens
or inlay hints than we requested, we don't constantly re-request them
whenever the viewport moves.

Importantly, clangd doesn't support range tokens, so we previously
requested and re-parsed, deleted and re-added every single token on
every single scroll event. This meant that scrolling was very slow and
lots of wasted effort. This should help reduce that. We should
essentially re-use the tokens on scolling and pretty much never
re-request them unless the buffer changes or we have a
file-ready-to-parse.
Ben Jackson 1 anno fa
parent
commit
724218e06b

+ 9 - 0
python/ycm/inlay_hints.py

@@ -85,6 +85,15 @@ class InlayHints( sr.ScrollingBufferRange ):
       else:
         prop_type = 'YCM_INLAY_' + inlay_hint[ 'kind' ]
 
+      self.GrowRangeIfNeeded( {
+        'start': inlay_hint[ 'position' ],
+        'end': {
+          'line_num': inlay_hint[ 'position' ][ 'line_num' ],
+          'column_num': inlay_hint[ 'position' ][ 'column_num' ] + len(
+            inlay_hint[ 'label' ] )
+        }
+      } )
+
       if inlay_hint.get( 'paddingLeft', False ):
         tp.AddTextProperty( self._bufnr,
                             None,

+ 25 - 0
python/ycm/scrolling_range.py

@@ -99,6 +99,31 @@ class ScrollingBufferRange( object ):
     self._Draw()
 
 
+  def GrowRangeIfNeeded( self, rng ):
+    """When processing results, we may receive a wider range than requested. In
+    that case, grow our 'last requested' range to minimise requesting more
+    frequently than we need to."""
+    # Note: references (pointers) so no need to re-assign
+    rmin = self._last_requested_range[ 'start' ]
+    rmax = self._last_requested_range[ 'end' ]
+
+    start = rng[ 'start' ]
+    end = rng[ 'end' ]
+
+    if rmin[ 'line_num' ] is None or start[ 'line_num' ] < rmin[ 'line_num' ]:
+      rmin[ 'line_num' ] = start[ 'line_num' ]
+      rmin[ 'column_num' ] = start[ 'column_num' ]
+    elif start[ 'line_num' ] == rmin[ 'line_num' ]:
+      rmin[ 'column_num' ] = min( start[ 'column_num' ],
+                                  rmin[ 'column_num' ] )
+
+    if rmax[ 'line_num' ] is None or end[ 'line_num' ] > rmax[ 'line_num' ]:
+      rmax[ 'line_num' ] = end[ 'line_num' ]
+      rmax[ 'column_num' ] = end[ 'column_num' ]
+    elif end[ 'line_num' ] == rmax[ 'line_num' ]:
+      rmax[ 'column_num' ] = max( end[ 'column_num' ], rmax[ 'column_num' ] )
+
+
   # API; just implement the following, using self._bufnr and
   # self._latest_response as required
 

+ 4 - 4
python/ycm/semantic_highlighting.py

@@ -114,9 +114,9 @@ class SemanticHighlighting( sr.ScrollingBufferRange ):
             f"Missing property type for { token[ 'type' ] }" )
         continue
       prop_type = f"YCM_HL_{ token[ 'type' ] }"
-      tp.AddTextProperty( self._bufnr,
-                          self._prop_id,
-                          prop_type,
-                          token[ 'range' ] )
+
+      rng = token[ 'range' ]
+      self.GrowRangeIfNeeded( rng )
+      tp.AddTextProperty( self._bufnr, self._prop_id, prop_type, rng )
 
     tp.ClearTextProperties( self._bufnr, prop_id = prev_prop_id )