File: semantic_highlighting.py

package info (click to toggle)
vim-youcompleteme 0%2B20230109%2Bgit7620d87%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 3,404 kB
  • sloc: python: 10,569; sh: 203; cpp: 121; makefile: 24; f90: 5; xml: 1
file content (152 lines) | stat: -rw-r--r-- 4,343 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Copyright (C) 2020, YouCompleteMe Contributors
#
# This file is part of YouCompleteMe.
#
# YouCompleteMe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# YouCompleteMe is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe.  If not, see <http://www.gnu.org/licenses/>.


from ycm.client.semantic_tokens_request import SemanticTokensRequest
from ycm.client.base_request import BuildRequestData
from ycm import vimsupport
from ycm import text_properties as tp


HIGHLIGHT_GROUP = {
  'namespace': 'Type',
  'type': 'Type',
  'class': 'Structure',
  'enum': 'Structure',
  'interface': 'Structure',
  'struct': 'Structure',
  'typeParameter': 'Identifier',
  'parameter': 'Identifier',
  'variable': 'Identifier',
  'property': 'Identifier',
  'enumMember': 'Identifier',
  'enumConstant': 'Constant',
  'event': 'Identifier',
  'function': 'Function',
  'member': 'Identifier',
  'macro': 'Macro',
  'method': 'Function',
  'keyword': 'Keyword',
  'modifier': 'Keyword',
  'comment': 'Comment',
  'string': 'String',
  'number': 'Number',
  'regexp': 'String',
  'operator': 'Operator',
  'unknown': 'Normal',
}
REPORTED_MISSING_TYPES = set()


def Initialise():
  if vimsupport.VimIsNeovim():
    return

  props = tp.GetTextPropertyTypes()
  if 'YCM_HL_UNKNOWN' not in props:
    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,
                              priority = 0 )


# "arbitrary" base id
NEXT_TEXT_PROP_ID = 70784


def NextPropID():
  global NEXT_TEXT_PROP_ID
  try:
    return NEXT_TEXT_PROP_ID
  finally:
    NEXT_TEXT_PROP_ID += 1



class SemanticHighlighting:
  """Stores the semantic highlighting state for a Vim buffer"""

  def __init__( self, bufnr, user_options ):
    self._request = None
    self._bufnr = bufnr
    self._prop_id = NextPropID()
    self.tick = -1


  def SendRequest( self ):
    if self._request and not self.IsResponseReady():
      return

    self.tick = vimsupport.GetBufferChangedTick( self._bufnr )

    request: dict = BuildRequestData( self._bufnr )
    request.update( {
      'range': vimsupport.RangeVisibleInBuffer( self._bufnr )
    } )
    self._request = SemanticTokensRequest( request )
    self._request.Start()

  def IsResponseReady( self ):
    return self._request is not None and self._request.Done()

  def Update( self ):
    if not self._request:
      # Nothing to update
      return True

    assert self.IsResponseReady()

    # We're ready to use this response. Clear it (to avoid repeatedly
    # re-polling).
    response = self._request.Response()
    self._request = None

    if self.tick != vimsupport.GetBufferChangedTick( self._bufnr ):
      # Buffer has changed, we should ignore the data and retry
      self.SendRequest()
      return False # poll again

    # We requested a snapshot
    tokens = response.get( 'tokens', [] )

    prev_prop_id = self._prop_id
    self._prop_id = NextPropID()

    for token in tokens:
      if token[ 'type' ] not in HIGHLIGHT_GROUP:
        if token[ 'type' ] not in REPORTED_MISSING_TYPES:
          REPORTED_MISSING_TYPES.add( token[ 'type' ] )
          vimsupport.PostVimMessage(
            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' ] )

    tp.ClearTextProperties( self._bufnr, prop_id = prev_prop_id )

    # No need to re-poll
    return True