Avoid evaluating Vim globals in Python
On Python 3, evaluating a Vim expression will raise a unicode exception if it contains an invalid sequence of bytes for the current encoding. We can't really do anything about it because this is the way Vim and Python 3 interact. However, we can prevent this situation to occur by not evaluating Vim data that we have no control over: in particular, the Vim globals. This is done by: - adding one by one the YCM default options instead of extending the Vim globals with them; - only evaluating the Vim global variable names (and not their values) when building the YCM options for the ycmd server.
This commit is contained in:
parent
87f0f7e16d
commit
b923431d7d
@ -35,17 +35,16 @@ YCM_VAR_PREFIX = 'ycm_'
|
||||
def BuildServerConf():
|
||||
"""Builds a dictionary mapping YCM Vim user options to values. Option names
|
||||
don't have the 'ycm_' prefix."""
|
||||
|
||||
vim_globals = vimsupport.GetReadOnlyVimGlobals( force_python_objects = True )
|
||||
# We only evaluate the keys of the vim globals and not the whole dictionary
|
||||
# to avoid unicode issues.
|
||||
# See https://github.com/Valloric/YouCompleteMe/pull/2151 for details.
|
||||
keys = vimsupport.GetVimGlobalsKeys()
|
||||
server_conf = {}
|
||||
for key, value in iteritems( vim_globals ):
|
||||
for key in keys:
|
||||
if not key.startswith( YCM_VAR_PREFIX ):
|
||||
continue
|
||||
try:
|
||||
new_value = int( value )
|
||||
except:
|
||||
new_value = value
|
||||
new_key = key[ len( YCM_VAR_PREFIX ): ]
|
||||
new_value = vimsupport.VimExpressionToPythonType( 'g:' + key )
|
||||
server_conf[ new_key ] = new_value
|
||||
|
||||
return server_conf
|
||||
@ -53,11 +52,10 @@ def BuildServerConf():
|
||||
|
||||
def LoadJsonDefaultsIntoVim():
|
||||
defaults = user_options_store.DefaultOptions()
|
||||
vim_defaults = {}
|
||||
for key, value in iteritems( defaults ):
|
||||
vim_defaults[ 'ycm_' + key ] = value
|
||||
|
||||
vimsupport.LoadDictIntoVimGlobals( vim_defaults, overwrite = False )
|
||||
new_key = 'g:ycm_' + key
|
||||
if not vimsupport.VariableExists( new_key ):
|
||||
vimsupport.SetVariableValue( new_key, value )
|
||||
|
||||
|
||||
def CompletionStartColumn():
|
||||
|
@ -294,27 +294,8 @@ def ConvertDiagnosticsToQfList( diagnostics ):
|
||||
return [ ConvertDiagnosticToQfFormat( x ) for x in diagnostics ]
|
||||
|
||||
|
||||
# Given a dict like {'a': 1}, loads it into Vim as if you ran 'let g:a = 1'
|
||||
# When |overwrite| is True, overwrites the existing value in Vim.
|
||||
def LoadDictIntoVimGlobals( new_globals, overwrite = True ):
|
||||
extend_option = '"force"' if overwrite else '"keep"'
|
||||
|
||||
# We need to use json.dumps because that won't use the 'u' prefix on strings
|
||||
# which Vim would bork on.
|
||||
vim.eval( 'extend( g:, {0}, {1})'.format( json.dumps( new_globals ),
|
||||
extend_option ) )
|
||||
|
||||
|
||||
# Changing the returned dict will NOT change the value in Vim.
|
||||
def GetReadOnlyVimGlobals( force_python_objects = False ):
|
||||
if force_python_objects:
|
||||
return vim.eval( 'g:' )
|
||||
|
||||
try:
|
||||
# vim.vars is fairly new so it might not exist
|
||||
return vim.vars
|
||||
except:
|
||||
return vim.eval( 'g:' )
|
||||
def GetVimGlobalsKeys():
|
||||
return vim.eval( 'keys( g: )' )
|
||||
|
||||
|
||||
def VimExpressionToPythonType( vim_expression ):
|
||||
@ -491,8 +472,8 @@ def EchoTextVimWidth( text ):
|
||||
|
||||
EchoText( truncated_text, False )
|
||||
|
||||
vim.command( 'let &ruler = {0}'.format( old_ruler ) )
|
||||
vim.command( 'let &showcmd = {0}'.format( old_showcmd ) )
|
||||
SetVariableValue( '&ruler', old_ruler )
|
||||
SetVariableValue( '&showcmd', old_showcmd )
|
||||
|
||||
|
||||
def EscapeForVim( text ):
|
||||
@ -514,7 +495,7 @@ def VariableExists( variable ):
|
||||
|
||||
|
||||
def SetVariableValue( variable, value ):
|
||||
vim.command( "let {0} = '{1}'".format( variable, EscapeForVim( value ) ) )
|
||||
vim.command( "let {0} = {1}".format( variable, json.dumps( value ) ) )
|
||||
|
||||
|
||||
def GetVariableValue( variable ):
|
||||
|
Loading…
Reference in New Issue
Block a user