Ver código fonte

Inlay hints: allow easy customisation of the highlight groups, fix priorities and ensure start_incl is set

Ben Jackson 2 anos atrás
pai
commit
fa4eb61ded

+ 18 - 6
autoload/youcompleteme.vim

@@ -181,6 +181,10 @@ function! youcompleteme#Enable()
 
   call s:SetUpOptions()
 
+  py3 ycm_semantic_highlighting.Initialise()
+  py3 vim.command( 'let s:enable_inlay_hints = ' +
+        \ '1' if ycm_inlay_hints.Initialise() else '0' )
+
   call youcompleteme#EnableCursorMovedAutocommands()
   augroup youcompleteme
     autocmd!
@@ -301,9 +305,6 @@ try:
     default_options = {}
 
   ycm_state = youcompleteme.YouCompleteMe( default_options )
-  ycm_semantic_highlighting.Initialise()
-  vim.command( 'let s:enable_inlay_hints = ' +
-    '1' if ycm_inlay_hints.Initialise() else '0' )
 except Exception as error:
   # We don't use PostVimMessage or EchoText from the vimsupport module because
   # importing this module may fail.
@@ -433,11 +434,21 @@ function! s:SetUpSyntaxHighlighting()
   endif
   if s:PropertyTypeNotDefined( 'YcmErrorProperty' )
     call prop_type_add( 'YcmErrorProperty', {
-          \ 'highlight': 'YcmErrorSection' } )
+          \ 'highlight': 'YcmErrorSection',
+          \ 'priority': 30 } )
+  endif
+
+  " Used for virtual text
+  if !hlexists( 'YcmInvisible' )
+    highlight default link YcmInvisible Normal
+  endif
+  if !hlexists( 'YcmInlayHint' )
+    highlight default link YcmInlayHint NonText
   endif
   if s:PropertyTypeNotDefined( 'YcmPadding' )
     call prop_type_add( 'YcmPadding',
-          \ { 'highlight': 'Normal' } )
+          \ { 'highlight': 'YcmInvisible',
+          \   'priority': 100 } )
   endif
 
   if !hlexists( 'YcmWarningSection' )
@@ -449,7 +460,8 @@ function! s:SetUpSyntaxHighlighting()
   endif
   if s:PropertyTypeNotDefined( 'YcmWarningProperty' )
     call prop_type_add( 'YcmWarningProperty', {
-          \ 'highlight': 'YcmWarningSection' } )
+          \ 'highlight': 'YcmWarningSection',
+          \ 'priority': 30 } )
   endif
 endfunction
 

+ 48 - 11
python/ycm/inlay_hints.py

@@ -25,8 +25,8 @@ from ycm import text_properties as tp
 HIGHLIGHT_GROUP = {
   # 1-based inedexes
   0: '',
-  1: 'Comment',        # Type
-  2: 'Comment'   # Parameter
+  1: 'YcmInlayHint',  # Type
+  2: 'YcmInlayHint'   # Parameter
 }
 REPORTED_MISSING_TYPES = set()
 
@@ -37,13 +37,21 @@ def Initialise():
 
   props = tp.GetTextPropertyTypes()
   if 'YCM_INLAY_UNKNOWN' not in props:
-    tp.AddTextPropertyType( 'YCM_INLAY_UNKNOWN', highlight = 'Comment' )
+    tp.AddTextPropertyType( 'YCM_INLAY_UNKNOWN',
+                            highlight = 'YcmInlayHint',
+                            start_incl = 1 )
+  if 'YCM_INLAY_PADDING' not in props:
+    tp.AddTextPropertyType( 'YCM_INLAY_PADDING',
+                            highlight = 'YcmInvisible',
+                            start_incl = 1 )
 
   for token_type, group in HIGHLIGHT_GROUP.items():
     prop = f'YCM_INLAY_{ token_type }'
     if prop not in props and vimsupport.GetIntValue(
         f"hlexists( '{ vimsupport.EscapeForVim( group ) }' )" ):
-      tp.AddTextPropertyType( prop, highlight = group )
+      tp.AddTextPropertyType( prop,
+                              highlight = group,
+                              start_incl = 1 )
 
   return True
 
@@ -88,9 +96,15 @@ class InlayHints:
 
 
   def Clear( self ):
-    for prop_id in self._prop_ids:
-      tp.ClearTextProperties( self._bufnr, prop_id )
-    self._prop_ids.clear()
+    # FIXME: ClearTextProperties is slow as it must scan the whole buffer
+    # We should use _last_requested_range to specify the range to clear
+    for type in HIGHLIGHT_GROUP.keys():
+      if type == 0:
+        continue
+      tp.ClearTextProperties( self._bufnr, type=f'YCM_INLAY_{ type }' )
+
+    tp.ClearTextProperties( self._bufnr, type='YCM_INLAY_UNKNOWN' )
+    tp.ClearTextProperties( self._bufnr, type='YCM_INLAY_PADDING' )
 
 
   def Update( self ):
@@ -140,14 +154,37 @@ class InlayHints:
       else:
         prop_type = 'YCM_INLAY_' + str( inlay_hint[ 'kind' ] )
 
-      self._prop_ids.add(
+      if inlay_hint.get( 'paddingLeft', False ):
+        tp.AddTextProperty( self._bufnr,
+                            None,
+                            'YCM_INLAY_PADDING',
+                            {
+                              'start': inlay_hint[ 'position' ],
+                              'end': inlay_hint[ 'position' ],
+                            },
+                            {
+                              'text': ' '
+                            } )
+
+      tp.AddTextProperty( self._bufnr,
+                          None,
+                          prop_type,
+                          {
+                            'start': inlay_hint[ 'position' ],
+                            'end': inlay_hint[ 'position' ],
+                          },
+                          {
+                            'text': inlay_hint[ 'label' ]
+                          } )
+
+      if inlay_hint.get( 'paddingRight', False ):
         tp.AddTextProperty( self._bufnr,
                             None,
-                            prop_type,
+                            'YCM_INLAY_PADDING',
                             {
                               'start': inlay_hint[ 'position' ],
                               'end': inlay_hint[ 'position' ],
                             },
                             {
-                              'text': inlay_hint[ 'label' ]
-                            } ) )
+                              'text': ' '
+                            } )

+ 6 - 2
python/ycm/semantic_highlighting.py

@@ -58,13 +58,17 @@ def Initialise():
 
   props = tp.GetTextPropertyTypes()
   if 'YCM_HL_UNKNOWN' not in props:
-    tp.AddTextPropertyType( 'YCM_HL_UNKNOWN', highlight = 'WarningMsg' )
+    tp.AddTextPropertyType( 'YCM_HL_UNKNOWN',
+                            highlight = 'WarningMsg',
+                            priority = 0 )
 
   for token_type, group in HIGHLIGHT_GROUP.items():
     prop = f'YCM_HL_{ token_type }'
     if prop not in props and vimsupport.GetIntValue(
         f"hlexists( '{ vimsupport.EscapeForVim( group ) }' )" ):
-      tp.AddTextPropertyType( prop, highlight = group )
+      tp.AddTextPropertyType( prop,
+                              highlight = group,
+                              priority = 0 )
 
 
 # "arbitrary" base id

+ 15 - 7
python/ycm/text_properties.py

@@ -29,15 +29,16 @@ import json
 def AddTextPropertyType( name, **kwargs ):
   props = {
     'highlight': 'Ignore',
-    'combine': False,
-    'start_incl': False,
-    'end_incl': False,
+    'combine': 0,
+    'override': 0,
+    'start_incl': 0,
+    'end_incl': 0,
     'priority': 10
   }
   props.update( kwargs )
 
   vim.eval( f"prop_type_add( '{ vimsupport.EscapeForVim( name ) }', "
-            f"               { json.dumps( kwargs ) } )" )
+            f"               { json.dumps( props ) } )" )
 
 
 def GetTextPropertyTypes( *args, **kwargs ):
@@ -56,7 +57,7 @@ def AddTextProperty( bufnr,
     'type': prop_type
   }
   if prop_id is not None:
-    props[ 'id' ]: prop_id
+    props[ 'id' ] = prop_id
   if extra_args:
     props.update( extra_args )
   return vim.eval( f"prop_add( { range[ 'start' ][ 'line_num' ] },"
@@ -64,10 +65,17 @@ def AddTextProperty( bufnr,
                    f"          { json.dumps( props ) } )" )
 
 
-def ClearTextProperties( bufnr, prop_id ):
+def ClearTextProperties( bufnr, prop_id=None, type=None ):
   props = {
-    'id': prop_id,
     'bufnr': bufnr,
     'all': 1,
   }
+  if prop_id is not None:
+    props[ 'id' ] = prop_id
+  if type is not None:
+    props[ 'type' ] = type
+
+  if prop_id is not None and type is not None:
+    props[ 'both' ] = 1
+
   vim.eval( f"prop_remove( { json.dumps( props ) } )" )

+ 4 - 3
python/ycm/vimsupport.py

@@ -188,7 +188,7 @@ def GetBufferChangedTick( bufnr ):
 # Returns a range covering the earliest and latest lines visible in the current
 # tab page for the supplied buffer number. By default this range is then
 # extended by half of the resulting range size
-def RangeVisibleInBuffer( bufnr, factor=0.5 ):
+def RangeVisibleInBuffer( bufnr, grow_factor=0.5 ):
   windows = [ w for w in vim.eval( f'win_findbuf( { bufnr } )' )
               if GetIntValue( vim.eval( f'win_id2tabwin( { w } )[ 0 ]' ) ) ==
                 vim.current.tabpage.number ]
@@ -207,6 +207,7 @@ def RangeVisibleInBuffer( bufnr, factor=0.5 ):
     return None
 
   r = Range()
+  # Note, for this we ignore horizontal scrolling
   for winid in windows:
     win_info = vim.eval( f'getwininfo( { winid } )[ 0 ]' )
     if r.start.line is None or r.start.line > int( win_info[ 'topline' ] ):
@@ -216,9 +217,9 @@ def RangeVisibleInBuffer( bufnr, factor=0.5 ):
 
   # Extend the range by 1 factor, and calculate the columns
   num_lines = r.end.line - r.start.line + 1
-  r.start.line = max( r.start.line - int( num_lines * factor ), 1 )
+  r.start.line = max( r.start.line - int( num_lines * grow_factor ), 1 )
   r.start.col = 1
-  r.end.line = min( r.end.line + int( num_lines * factor ), len( buffer ) )
+  r.end.line = min( r.end.line + int( num_lines * grow_factor ), len( buffer ) )
   r.end.col = len( buffer[ r.end.line - 1 ] )
 
   filepath = GetBufferFilepath( buffer )