Updating to latest ycmd

This commit is contained in:
Val Markovic 2016-02-19 11:02:58 -08:00
parent be0de73c42
commit f986bf19db
11 changed files with 70 additions and 40 deletions

View File

@ -139,12 +139,13 @@ import subprocess
script_folder = vim.eval( 's:script_folder_path' ) script_folder = vim.eval( 's:script_folder_path' )
sys.path.insert( 0, os.path.join( script_folder, '../python' ) ) sys.path.insert( 0, os.path.join( script_folder, '../python' ) )
sys.path.insert( 0, os.path.join( script_folder, '../third_party/ycmd' ) ) sys.path.insert( 0, os.path.join( script_folder, '../third_party/ycmd' ) )
from ycmd import utils from ycmd import server_utils
utils.AddNearestThirdPartyFoldersToSysPath( script_folder ) server_utils.AddNearestThirdPartyFoldersToSysPath( script_folder )
# We need to import ycmd's third_party folders as well since we import and # We need to import ycmd's third_party folders as well since we import and
# use ycmd code in the client. # use ycmd code in the client.
utils.AddNearestThirdPartyFoldersToSysPath( utils.__file__ ) server_utils.AddNearestThirdPartyFoldersToSysPath( server_utils.__file__ )
from ycmd import utils
from ycm import base from ycm import base
base.LoadJsonDefaultsIntoVim() base.LoadJsonDefaultsIntoVim()
from ycmd import user_options_store from ycmd import user_options_store

View File

@ -6,6 +6,11 @@ import sys
import os.path as p import os.path as p
import glob import glob
major, minor = sys.version_info[ 0 : 2 ]
if major != 2 or minor < 6:
sys.exit( 'The build script requires Python version >= 2.6 and < 3.0; '
'your version of Python is ' + sys.version )
DIR_OF_THIS_SCRIPT = p.dirname( p.abspath( __file__ ) ) DIR_OF_THIS_SCRIPT = p.dirname( p.abspath( __file__ ) )
DIR_OF_OLD_LIBS = p.join( DIR_OF_THIS_SCRIPT, 'python' ) DIR_OF_OLD_LIBS = p.join( DIR_OF_THIS_SCRIPT, 'python' )

View File

@ -2,3 +2,5 @@ flake8>=2.0
mock>=1.0.1 mock>=1.0.1
nose>=1.3.0 nose>=1.3.0
PyHamcrest>=1.8.0 PyHamcrest>=1.8.0
# This needs to be kept in sync with submodule checkout in third_party/ycmd/third_party
future==0.15.2

View File

@ -17,13 +17,14 @@
import requests import requests
import urlparse import urlparse
import json
from base64 import b64decode, b64encode from base64 import b64decode, b64encode
from retries import retries from retries import retries
from requests_futures.sessions import FuturesSession from requests_futures.sessions import FuturesSession
from ycm.unsafe_thread_pool_executor import UnsafeThreadPoolExecutor from ycm.unsafe_thread_pool_executor import UnsafeThreadPoolExecutor
from ycm import vimsupport from ycm import vimsupport
from ycmd.utils import ToUtf8Json from ycmd.utils import ToBytes
from ycmd.hmac_utils import CreateRequestHmac, CreateHmac, SecureStringsEqual from ycmd.hmac_utils import CreateRequestHmac, CreateHmac, SecureBytesEqual
from ycmd.responses import ServerError, UnknownExtraConf from ycmd.responses import ServerError, UnknownExtraConf
_HEADERS = {'content-type': 'application/json'} _HEADERS = {'content-type': 'application/json'}
@ -89,7 +90,7 @@ class BaseRequest( object ):
def SendRequest( data, handler, method, timeout ): def SendRequest( data, handler, method, timeout ):
request_uri = _BuildUri( handler ) request_uri = _BuildUri( handler )
if method == 'POST': if method == 'POST':
sent_data = ToUtf8Json( data ) sent_data = _ToUtf8Json( data )
return BaseRequest.session.post( return BaseRequest.session.post(
request_uri, request_uri,
data = sent_data, data = sent_data,
@ -107,7 +108,7 @@ class BaseRequest( object ):
def DelayedSendRequest( data, handler, method ): def DelayedSendRequest( data, handler, method ):
request_uri = _BuildUri( handler ) request_uri = _BuildUri( handler )
if method == 'POST': if method == 'POST':
sent_data = ToUtf8Json( data ) sent_data = _ToUtf8Json( data )
return requests.post( return requests.post(
request_uri, request_uri,
data = sent_data, data = sent_data,
@ -182,13 +183,18 @@ def HandleServerException( exception ):
vimsupport.PostVimMessage( serialized_exception ) vimsupport.PostVimMessage( serialized_exception )
def _ToUtf8Json( data ):
return ToBytes( json.dumps( data ) if data else None )
def _ValidateResponseObject( response ): def _ValidateResponseObject( response ):
hmac = CreateHmac( response.content, BaseRequest.hmac_secret ) our_hmac = CreateHmac( response.content, BaseRequest.hmac_secret )
if not SecureStringsEqual( hmac, their_hmac = ToBytes( b64decode( response.headers[ _HMAC_HEADER ] ) )
b64decode( response.headers[ _HMAC_HEADER ] ) ): if not SecureBytesEqual( our_hmac, their_hmac ):
raise RuntimeError( 'Received invalid HMAC for response!' ) raise RuntimeError( 'Received invalid HMAC for response!' )
return True return True
def _BuildUri( handler ): def _BuildUri( handler ):
return urlparse.urljoin( BaseRequest.server_location, handler ) return urlparse.urljoin( BaseRequest.server_location, handler )
@ -216,6 +222,7 @@ def _CheckServerIsHealthyWithCache():
except: except:
return False return False
def MakeServerException( data ): def MakeServerException( data ):
if data[ 'exception' ][ 'TYPE' ] == UnknownExtraConf.__name__: if data[ 'exception' ][ 'TYPE' ] == UnknownExtraConf.__name__:
return UnknownExtraConf( data[ 'exception' ][ 'extra_conf_file' ] ) return UnknownExtraConf( data[ 'exception' ][ 'extra_conf_file' ] )

View File

@ -18,7 +18,7 @@
import vim import vim
from ycm.client.base_request import BaseRequest, BuildRequestData, ServerError from ycm.client.base_request import BaseRequest, BuildRequestData, ServerError
from ycm import vimsupport from ycm import vimsupport
from ycmd.utils import ToUtf8IfNeeded from ycmd.utils import ToUnicode
def _EnsureBackwardsCompatibility( arguments ): def _EnsureBackwardsCompatibility( arguments ):
@ -123,9 +123,9 @@ def SendCommandRequest( arguments, completer ):
def _BuildQfListItem( goto_data_item ): def _BuildQfListItem( goto_data_item ):
qf_item = {} qf_item = {}
if 'filepath' in goto_data_item: if 'filepath' in goto_data_item:
qf_item[ 'filename' ] = ToUtf8IfNeeded( goto_data_item[ 'filepath' ] ) qf_item[ 'filename' ] = ToUnicode( goto_data_item[ 'filepath' ] )
if 'description' in goto_data_item: if 'description' in goto_data_item:
qf_item[ 'text' ] = ToUtf8IfNeeded( goto_data_item[ 'description' ] ) qf_item[ 'text' ] = ToUnicode( goto_data_item[ 'description' ] )
if 'line_num' in goto_data_item: if 'line_num' in goto_data_item:
qf_item[ 'lnum' ] = goto_data_item[ 'line_num' ] qf_item[ 'lnum' ] = goto_data_item[ 'line_num' ]
if 'column_num' in goto_data_item: if 'column_num' in goto_data_item:

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
from ycmd.utils import ToUtf8IfNeeded from ycmd.utils import ToBytes, ToUnicode
from ycm.client.base_request import ( BaseRequest, JsonFromFuture, from ycm.client.base_request import ( BaseRequest, JsonFromFuture,
HandleServerException, HandleServerException,
MakeServerException ) MakeServerException )
@ -69,22 +69,22 @@ def ConvertCompletionDataToVimData( completion_data ):
if ( 'extra_data' in completion_data and if ( 'extra_data' in completion_data and
'doc_string' in completion_data[ 'extra_data' ] ): 'doc_string' in completion_data[ 'extra_data' ] ):
doc_string = ToUtf8IfNeeded( doc_string = ToBytes( completion_data[ 'extra_data' ][ 'doc_string' ] )
completion_data[ 'extra_data' ][ 'doc_string' ] )
else: else:
doc_string = "" doc_string = ""
if 'insertion_text' in completion_data: if 'insertion_text' in completion_data:
vim_data[ 'word' ] = ToUtf8IfNeeded( completion_data[ 'insertion_text' ] ) vim_data[ 'word' ] = ToBytes( completion_data[ 'insertion_text' ] )
if 'menu_text' in completion_data: if 'menu_text' in completion_data:
vim_data[ 'abbr' ] = ToUtf8IfNeeded( completion_data[ 'menu_text' ] ) vim_data[ 'abbr' ] = ToBytes( completion_data[ 'menu_text' ] )
if 'extra_menu_info' in completion_data: if 'extra_menu_info' in completion_data:
vim_data[ 'menu' ] = ToUtf8IfNeeded( completion_data[ 'extra_menu_info' ] ) vim_data[ 'menu' ] = ToBytes( completion_data[ 'extra_menu_info' ] )
if 'kind' in completion_data: if 'kind' in completion_data:
vim_data[ 'kind' ] = ToUtf8IfNeeded( kind = ToUnicode( completion_data[ 'kind' ] )
completion_data[ 'kind' ] )[ 0 ].lower() if kind:
vim_data[ 'kind' ] = ToBytes( kind[ 0 ].lower() )
if 'detailed_info' in completion_data: if 'detailed_info' in completion_data:
vim_data[ 'info' ] = ToUtf8IfNeeded( completion_data[ 'detailed_info' ] ) vim_data[ 'info' ] = ToBytes( completion_data[ 'detailed_info' ] )
if doc_string: if doc_string:
vim_data[ 'info' ] += '\n' + doc_string vim_data[ 'info' ] += '\n' + doc_string
elif doc_string: elif doc_string:

View File

@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
from ycmd.utils import ToUtf8IfNeeded from ycmd.utils import ToBytes
from ycm.client.completion_request import CompletionRequest from ycm.client.completion_request import CompletionRequest
@ -46,15 +46,15 @@ def ConvertVimDataToCompletionData( vim_data ):
completion_data = {} completion_data = {}
if 'word' in vim_data: if 'word' in vim_data:
completion_data[ 'insertion_text' ] = ToUtf8IfNeeded( vim_data[ 'word' ] ) completion_data[ 'insertion_text' ] = ToBytes( vim_data[ 'word' ] )
if 'abbr' in vim_data: if 'abbr' in vim_data:
completion_data[ 'menu_text' ] = ToUtf8IfNeeded( vim_data[ 'abbr' ] ) completion_data[ 'menu_text' ] = ToBytes( vim_data[ 'abbr' ] )
if 'menu' in vim_data: if 'menu' in vim_data:
completion_data[ 'extra_menu_info' ] = ToUtf8IfNeeded( vim_data[ 'menu' ] ) completion_data[ 'extra_menu_info' ] = ToBytes( vim_data[ 'menu' ] )
if 'kind' in vim_data: if 'kind' in vim_data:
completion_data[ 'kind' ] = [ ToUtf8IfNeeded( vim_data[ 'kind' ] ) ] completion_data[ 'kind' ] = [ ToBytes( vim_data[ 'kind' ] ) ]
if 'info' in vim_data: if 'info' in vim_data:
completion_data[ 'detailed_info' ] = ToUtf8IfNeeded( vim_data[ 'info' ] ) completion_data[ 'detailed_info' ] = ToBytes( vim_data[ 'info' ] )
return completion_data return completion_data

View File

@ -21,7 +21,7 @@ import tempfile
import json import json
import re import re
from collections import defaultdict from collections import defaultdict
from ycmd.utils import ToUtf8IfNeeded from ycmd.utils import ToBytes, ToUnicode
from ycmd import user_options_store from ycmd import user_options_store
BUFFER_COMMAND_MAP = { 'same-buffer' : 'edit', BUFFER_COMMAND_MAP = { 'same-buffer' : 'edit',
@ -277,7 +277,7 @@ def ConvertDiagnosticsToQfList( diagnostics ):
'bufnr' : GetBufferNumberForFilename( location[ 'filepath' ] ), 'bufnr' : GetBufferNumberForFilename( location[ 'filepath' ] ),
'lnum' : line_num, 'lnum' : line_num,
'col' : location[ 'column_num' ], 'col' : location[ 'column_num' ],
'text' : ToUtf8IfNeeded( text ), 'text' : ToBytes( text ),
'type' : diagnostic[ 'kind' ][ 0 ], 'type' : diagnostic[ 'kind' ][ 0 ],
'valid' : 1 'valid' : 1
} }
@ -409,7 +409,7 @@ def NumLinesInBuffer( buffer_object ):
# or type command to continue" prompt when editing a new C-family file. # or type command to continue" prompt when editing a new C-family file.
def PostVimMessage( message ): def PostVimMessage( message ):
vim.command( "redraw | echohl WarningMsg | echom '{0}' | echohl None" vim.command( "redraw | echohl WarningMsg | echom '{0}' | echohl None"
.format( EscapeForVim( str( message ) ) ) ) .format( EscapeForVim( ToUnicode( message ) ) ) )
# Unlike PostVimMesasge, this supports messages with newlines in them because it # Unlike PostVimMesasge, this supports messages with newlines in them because it
@ -417,7 +417,7 @@ def PostVimMessage( message ):
# appear in Vim's message log. # appear in Vim's message log.
def PostMultiLineNotice( message ): def PostMultiLineNotice( message ):
vim.command( "echohl WarningMsg | echo '{0}' | echohl None" vim.command( "echohl WarningMsg | echo '{0}' | echohl None"
.format( EscapeForVim( str( message ) ) ) ) .format( EscapeForVim( ToUnicode( message ) ) ) )
def PresentDialog( message, choices, default_choice_index = 0 ): def PresentDialog( message, choices, default_choice_index = 0 ):
@ -439,8 +439,10 @@ def PresentDialog( message, choices, default_choice_index = 0 ):
PresentDialog("Is this a nice example?", ["Yes", "No", "May&be"]) PresentDialog("Is this a nice example?", ["Yes", "No", "May&be"])
Is this a nice example? Is this a nice example?
[Y]es, (N)o, May(b)e:""" [Y]es, (N)o, May(b)e:"""
to_eval = "confirm('{0}', '{1}', {2})".format( EscapeForVim( message ), to_eval = "confirm('{0}', '{1}', {2})".format(
EscapeForVim( "\n" .join( choices ) ), default_choice_index + 1 ) EscapeForVim( ToUnicode( message ) ),
EscapeForVim( ToUnicode( "\n" .join( choices ) ) ),
default_choice_index + 1 )
return int( vim.eval( to_eval ) ) - 1 return int( vim.eval( to_eval ) ) - 1
@ -453,16 +455,17 @@ def Confirm( message ):
def EchoText( text, log_as_message = True ): def EchoText( text, log_as_message = True ):
def EchoLine( text ): def EchoLine( text ):
command = 'echom' if log_as_message else 'echo' command = 'echom' if log_as_message else 'echo'
vim.command( "{0} '{1}'".format( command, EscapeForVim( text ) ) ) vim.command( "{0} '{1}'".format( command,
EscapeForVim( text ) ) )
for line in str( text ).split( '\n' ): for line in ToUnicode( text ).split( '\n' ):
EchoLine( line ) EchoLine( line )
# Echos text but truncates it so that it all fits on one line # Echos text but truncates it so that it all fits on one line
def EchoTextVimWidth( text ): def EchoTextVimWidth( text ):
vim_width = GetIntValue( '&columns' ) vim_width = GetIntValue( '&columns' )
truncated_text = ToUtf8IfNeeded( text )[ : int( vim_width * 0.9 ) ] truncated_text = ToUnicode( text )[ : int( vim_width * 0.9 ) ]
truncated_text.replace( '\n', ' ' ) truncated_text.replace( '\n', ' ' )
old_ruler = GetIntValue( '&ruler' ) old_ruler = GetIntValue( '&ruler' )

View File

@ -117,7 +117,7 @@ class YouCompleteMe( object ):
'--idle_suicide_seconds={0}'.format( '--idle_suicide_seconds={0}'.format(
SERVER_IDLE_SUICIDE_SECONDS )] SERVER_IDLE_SUICIDE_SECONDS )]
filename_format = os.path.join( utils.PathToTempDir(), filename_format = os.path.join( utils.PathToCreatedTempDir(),
'server_{port}_{std}.log' ) 'server_{port}_{std}.log' )
self._server_stdout = filename_format.format( port = server_port, self._server_stdout = filename_format.format( port = server_port,
@ -131,12 +131,13 @@ class YouCompleteMe( object ):
args.append( '--keep_logfiles' ) args.append( '--keep_logfiles' )
self._server_popen = utils.SafePopen( args, stdin_windows = PIPE, self._server_popen = utils.SafePopen( args, stdin_windows = PIPE,
stdout = PIPE, stderr = PIPE) stdout = PIPE, stderr = PIPE )
BaseRequest.server_location = 'http://127.0.0.1:' + str( server_port ) BaseRequest.server_location = 'http://127.0.0.1:' + str( server_port )
BaseRequest.hmac_secret = hmac_secret BaseRequest.hmac_secret = hmac_secret
self._NotifyUserIfServerCrashed() self._NotifyUserIfServerCrashed()
def IsServerAlive( self ): def IsServerAlive( self ):
returncode = self._server_popen.poll() returncode = self._server_popen.poll()
# When the process hasn't finished yet, poll() returns None. # When the process hasn't finished yet, poll() returns None.

View File

@ -13,6 +13,17 @@ python_path = []
for folder in os.listdir( DIR_OF_THIRD_PARTY ): for folder in os.listdir( DIR_OF_THIRD_PARTY ):
python_path.append( p.abspath( p.join( DIR_OF_THIRD_PARTY, folder ) ) ) python_path.append( p.abspath( p.join( DIR_OF_THIRD_PARTY, folder ) ) )
for folder in os.listdir( DIR_OF_YCMD_THIRD_PARTY ): for folder in os.listdir( DIR_OF_YCMD_THIRD_PARTY ):
# We skip python-future because it needs to be inserted in sys.path AFTER
# the standard library imports but we can't do that with PYTHONPATH because
# the std lib paths are always appended to PYTHONPATH. We do it correctly in
# prod in ycmd/utils.py because we have access to the right sys.path.
# So for dev, we rely on python-future being installed correctly with
# pip install -r test_requirements.txt
#
# Pip knows how to install this correctly so that it doesn't matter where in
# sys.path the path is.
if folder == 'python-future':
continue
python_path.append( p.abspath( p.join( DIR_OF_YCMD_THIRD_PARTY, folder ) ) ) python_path.append( p.abspath( p.join( DIR_OF_YCMD_THIRD_PARTY, folder ) ) )
if os.environ.get( 'PYTHONPATH' ): if os.environ.get( 'PYTHONPATH' ):
python_path.append( os.environ[ 'PYTHONPATH' ] ) python_path.append( os.environ[ 'PYTHONPATH' ] )

2
third_party/ycmd vendored

@ -1 +1 @@
Subproject commit d0932eb1895644e982d3a1daf210c09ca479a620 Subproject commit 3ed1634afd7bfef872abde4e91bd012fbb08a9d8