Skip to content

Commit 49ced5a

Browse files
authored
Merge pull request #4150 from puremourning/semantic-highlighting-optimisation
Semantic highlighting optimisation
2 parents 78ba06e + 187489d commit 49ced5a

File tree

12 files changed

+270
-221
lines changed

12 files changed

+270
-221
lines changed

autoload/youcompleteme.vim

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -822,24 +822,29 @@ function! s:OnFileReadyToParse( ... )
822822
\ s:pollers.file_parse_response.wait_milliseconds,
823823
\ function( 's:PollFileParseResponse' ) )
824824

825-
call s:UpdateSemanticHighlighting( bufnr() )
825+
call s:UpdateSemanticHighlighting( bufnr(), 1, 0 )
826826
call s:UpdateInlayHints( bufnr(), 1, 0 )
827827

828828
endif
829829
endfunction
830830

831-
function! s:UpdateSemanticHighlighting( bufnr ) abort
831+
function! s:UpdateSemanticHighlighting( bufnr, force, redraw_anyway ) abort
832832
call s:StopPoller( s:pollers.semantic_highlighting )
833833
if !s:is_neovim &&
834834
\ get( b:, 'ycm_enable_semantic_highlighting',
835835
\ get( g:, 'ycm_enable_semantic_highlighting', 0 ) )
836836

837-
py3 ycm_state.Buffer(
838-
\ int( vim.eval( "a:bufnr" ) ) ).SendSemanticTokensRequest()
839-
let s:pollers.semantic_highlighting.id = timer_start(
840-
\ s:pollers.semantic_highlighting.wait_milliseconds,
841-
\ function( 's:PollSemanticHighlighting', [ a:bufnr ] ) )
842-
837+
if py3eval(
838+
\ 'ycm_state.Buffer( int( vim.eval( "a:bufnr" ) ) ).'
839+
\ . 'semantic_highlighting.Request( '
840+
\ . ' force=int( vim.eval( "a:force" ) ) )' )
841+
let s:pollers.semantic_highlighting.id = timer_start(
842+
\ s:pollers.semantic_highlighting.wait_milliseconds,
843+
\ function( 's:PollSemanticHighlighting', [ a:bufnr ] ) )
844+
elseif a:redraw_anyway
845+
py3 ycm_state.Buffer(
846+
\ int( vim.eval( "a:bufnr" ) ) ).semantic_highlighting.Refresh()
847+
endif
843848
endif
844849
endfunction
845850

@@ -850,7 +855,7 @@ function s:ShouldUseInlayHintsNow( bufnr )
850855
\ get( g:, 'ycm_enable_inlay_hints', 0 ) )
851856
endfunction
852857

853-
function! s:UpdateInlayHints( bufnr, force, redraw_anyway )
858+
function! s:UpdateInlayHints( bufnr, force, redraw_anyway ) abort
854859
call s:StopPoller( s:pollers.inlay_hints )
855860

856861
if s:ShouldUseInlayHintsNow( a:bufnr )
@@ -883,36 +888,29 @@ function! s:PollFileParseResponse( ... )
883888
endfunction
884889

885890

886-
function! s:PollSemanticHighlighting( bufnr, ... )
887-
if !py3eval(
888-
\ 'ycm_state.Buffer( int( vim.eval( "a:bufnr" ) ) )'
889-
\ . '.SemanticTokensRequestReady()' )
890-
let s:pollers.semantic_highlighting.id = timer_start(
891-
\ s:pollers.semantic_highlighting.wait_milliseconds,
892-
\ function( 's:PollSemanticHighlighting', [ a:bufnr ] ) )
893-
elseif !py3eval(
894-
\ 'ycm_state.Buffer( int( vim.eval( "a:bufnr" ) ) )'
895-
\ . '.UpdateSemanticTokens()' )
896-
let s:pollers.semantic_highlighting.id = timer_start(
897-
\ s:pollers.semantic_highlighting.wait_milliseconds,
898-
\ function( 's:PollSemanticHighlighting', [ a:bufnr ] ) )
899-
endif
891+
function! s:PollSemanticHighlighting( bufnr, ... ) abort
892+
return s:PollScrollable( a:bufnr, 'semantic_highlighting' )
893+
endfunction
894+
895+
896+
function! s:PollInlayHints( bufnr, ... ) abort
897+
return s:PollScrollable( a:bufnr, 'inlay_hints' )
900898
endfunction
901899

902900

903-
function! s:PollInlayHints( bufnr, ... )
901+
function! s:PollScrollable( bufnr, scrollable, ... ) abort
904902
if !py3eval(
905903
\ 'ycm_state.Buffer( int( vim.eval( "a:bufnr" ) ) )'
906-
\ . '.inlay_hints.Ready()' )
907-
let s:pollers.inlay_hints.id = timer_start(
908-
\ s:pollers.inlay_hints.wait_milliseconds,
909-
\ function( 's:PollInlayHints', [ a:bufnr ] ) )
904+
\ . '.' . a:scrollable . '.Ready()' )
905+
let s:pollers[a:scrollable].id = timer_start(
906+
\ s:pollers[a:scrollable].wait_milliseconds,
907+
\ function( 's:PollScrollable', [ a:bufnr, a:scrollable ] ) )
910908
elseif ! py3eval(
911909
\ 'ycm_state.Buffer( int( vim.eval( "a:bufnr" ) ) )'
912-
\ . '.inlay_hints.Update()' )
913-
let s:pollers.inlay_hints.id = timer_start(
914-
\ s:pollers.inlay_hints.wait_milliseconds,
915-
\ function( 's:PollInlayHints', [ a:bufnr ] ) )
910+
\ . '.' . a:scrollable . '.Update()' )
911+
let s:pollers[ a:scrollable ].id = timer_start(
912+
\ s:pollers[ a:scrollable ].wait_milliseconds,
913+
\ function( 's:PollScrollable', [ a:bufnr, a:scrollable ] ) )
916914
endif
917915
endfunction
918916

@@ -973,7 +971,7 @@ function! s:OnWinScrolled()
973971
return
974972
endif
975973
let bufnr = winbufnr( expand( '<afile>' ) )
976-
call s:UpdateSemanticHighlighting( bufnr )
974+
call s:UpdateSemanticHighlighting( bufnr, 0, 0 )
977975
call s:UpdateInlayHints( bufnr, 0, 0 )
978976
endfunction
979977

python/ycm/buffer.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ def __init__( self, bufnr, user_options, filetypes ):
3737
self._diag_interface = DiagnosticInterface( bufnr, user_options )
3838
self._open_loclist_on_ycm_diags = user_options[
3939
'open_loclist_on_ycm_diags' ]
40-
self._semantic_highlighting = SemanticHighlighting( bufnr, user_options )
41-
self.inlay_hints = InlayHints( bufnr, user_options )
40+
self.semantic_highlighting = SemanticHighlighting( bufnr )
41+
self.inlay_hints = InlayHints( bufnr )
4242
self.UpdateFromFileTypes( filetypes )
4343

4444

@@ -145,18 +145,6 @@ def UpdateFromFileTypes( self, filetypes ):
145145
self._async_diags = False
146146

147147

148-
def SendSemanticTokensRequest( self ):
149-
self._semantic_highlighting.SendRequest()
150-
151-
152-
def SemanticTokensRequestReady( self ):
153-
return self._semantic_highlighting.IsResponseReady()
154-
155-
156-
def UpdateSemanticTokens( self ):
157-
return self._semantic_highlighting.Update()
158-
159-
160148
def _ChangedTick( self ):
161149
return vimsupport.GetBufferChangedTick( self._number )
162150

python/ycm/inlay_hints.py

Lines changed: 15 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from ycm.client.base_request import BuildRequestData
2121
from ycm import vimsupport
2222
from ycm import text_properties as tp
23+
from ycm import scrolling_range as sr
2324

2425

2526
HIGHLIGHT_GROUP = {
@@ -55,110 +56,44 @@ def Initialise():
5556
return True
5657

5758

58-
class InlayHints:
59+
class InlayHints( sr.ScrollingBufferRange ):
5960
"""Stores the inlay hints state for a Vim buffer"""
6061

61-
# FIXME: Send a request per-disjoint range for this buffer rather than the
62-
# maximal range. then collaate the results when all responses are returned
63-
def __init__( self, bufnr, user_options ):
64-
self._request = None
65-
self._bufnr = bufnr
66-
self.tick = -1
67-
self._latest_inlay_hints = []
68-
self._last_requested_range = None
69-
70-
71-
def Request( self, force=False ):
72-
if self._request and not self.Ready():
73-
return True
74-
75-
# Check to see if the buffer ranges would actually change anything visible.
76-
# This avoids a round-trip for every single line scroll event
77-
if ( not force and
78-
self.tick == vimsupport.GetBufferChangedTick( self._bufnr ) and
79-
vimsupport.VisibleRangeOfBufferOverlaps(
80-
self._bufnr,
81-
self._last_requested_range ) ):
82-
return False # don't poll
83-
84-
# We're requesting changes, so the existing results are now invalid
85-
self._latest_inlay_hints = []
86-
# FIXME: This call is duplicated in the call to VisibleRangeOfBufferOverlaps
87-
# - remove the expansion param
88-
# - look up the actual visible range, then call this function
89-
# - if not overlapping, do the factor expansion and request
90-
self._last_requested_range = vimsupport.RangeVisibleInBuffer( self._bufnr )
91-
self.tick = vimsupport.GetBufferChangedTick( self._bufnr )
9262

63+
def _NewRequest( self, request_range ):
9364
request_data = BuildRequestData( self._bufnr )
94-
request_data.update( {
95-
'range': self._last_requested_range
96-
} )
97-
self._request = InlayHintsRequest( request_data )
98-
self._request.Start()
99-
return True
100-
101-
102-
def Ready( self ):
103-
return self._request is not None and self._request.Done()
65+
request_data[ 'range' ] = request_range
66+
return InlayHintsRequest( request_data )
10467

10568

10669
def Clear( self ):
107-
# ClearTextProperties is slow as it must scan the whole buffer
108-
# we shouldn't use _last_requested_range, because the server is free to
109-
# return a larger range, so we pick the first/last from the latest results
11070
types = [ 'YCM_INLAY_UNKNOWN', 'YCM_INLAY_PADDING' ] + [
11171
f'YCM_INLAY_{ prop_type }' for prop_type in HIGHLIGHT_GROUP.keys()
11272
]
11373

11474
tp.ClearTextProperties( self._bufnr, prop_types = types )
11575

116-
def Update( self ):
117-
if not self._request:
118-
# Nothing to update
119-
return True
120-
121-
assert self.Ready()
122-
123-
# We're ready to use this response. Clear it (to avoid repeatedly
124-
# re-polling).
125-
self._latest_inlay_hints = self._request.Response()
126-
self._request = None
127-
128-
if self.tick != vimsupport.GetBufferChangedTick( self._bufnr ):
129-
# Buffer has changed, we should ignore the data and retry
130-
self.Request( force=True )
131-
return False # poll again
132-
133-
self._Draw()
134-
135-
# No need to re-poll
136-
return True
137-
138-
139-
def Refresh( self ):
140-
if self.tick != vimsupport.GetBufferChangedTick( self._bufnr ):
141-
# stale data
142-
return
143-
144-
if self._request is not None:
145-
# request in progress; we''l handle refreshing when it's done.
146-
return
147-
148-
self._Draw()
149-
15076

15177
def _Draw( self ):
15278
self.Clear()
15379

154-
for inlay_hint in self._latest_inlay_hints:
80+
for inlay_hint in self._latest_response:
15581
if 'kind' not in inlay_hint:
15682
prop_type = 'YCM_INLAY_UNKNOWN'
15783
elif inlay_hint[ 'kind' ] not in HIGHLIGHT_GROUP:
15884
prop_type = 'YCM_INLAY_UNKNOWN'
15985
else:
16086
prop_type = 'YCM_INLAY_' + inlay_hint[ 'kind' ]
16187

88+
self.GrowRangeIfNeeded( {
89+
'start': inlay_hint[ 'position' ],
90+
'end': {
91+
'line_num': inlay_hint[ 'position' ][ 'line_num' ],
92+
'column_num': inlay_hint[ 'position' ][ 'column_num' ] + len(
93+
inlay_hint[ 'label' ] )
94+
}
95+
} )
96+
16297
if inlay_hint.get( 'paddingLeft', False ):
16398
tp.AddTextProperty( self._bufnr,
16499
None,

0 commit comments

Comments
 (0)