def _ReadMessage( self ): """Read a response message from TSServer.""" # The headers are pretty similar to HTTP. # At the time of writing, 'Content-Length' is the only supplied header. headers = {} while True: headerline = self._tsserver_handle.stdout.readline().strip() if not headerline: break key, value = utils.ToUnicode( headerline ).split( ':', 1 ) headers[ key.strip() ] = value.strip() # The response message is a JSON object which comes back on one line. # Since this might change in the future, we use the 'Content-Length' # header. if 'Content-Length' not in headers: raise RuntimeError( "Missing 'Content-Length' header" ) contentlength = int( headers[ 'Content-Length' ] ) # TSServer adds a newline at the end of the response message and counts it # as one character (\n) towards the content length. However, newlines are # two characters on Windows (\r\n), so we need to take care of that. See # issue https://github.com/Microsoft/TypeScript/issues/3403 content = self._tsserver_handle.stdout.read( contentlength ) if utils.OnWindows() and content.endswith( b'\r' ): content += self._tsserver_handle.stdout.read( 1 ) return json.loads( utils.ToUnicode( content ) )
def PathToPythonInterpreter(): # Not calling the Python interpreter to check its version as it significantly # impacts startup time. from ycmd import utils python_interpreter = vim.eval('g:ycm_server_python_interpreter') if python_interpreter: python_interpreter = utils.FindExecutable(python_interpreter) if python_interpreter: return python_interpreter raise RuntimeError("Path in 'g:ycm_server_python_interpreter' option " "does not point to a valid Python 3.5+.") python_interpreter = _PathToPythonUsedDuringBuild() if python_interpreter and utils.GetExecutable(python_interpreter): return python_interpreter # On UNIX platforms, we use sys.executable as the Python interpreter path. # We cannot use sys.executable on Windows because for unknown reasons, it # returns the Vim executable. Instead, we use sys.exec_prefix to deduce the # interpreter path. python_interpreter = (WIN_PYTHON_PATH if utils.OnWindows() else sys.executable) if _EndsWithPython(python_interpreter): return python_interpreter python_interpreter = utils.PathToFirstExistingExecutable( ['python3', 'python']) if python_interpreter: return python_interpreter raise RuntimeError("Cannot find Python 3.5+. " "Set the 'g:ycm_server_python_interpreter' option " "to a Python interpreter path.")
def PathToPythonInterpreter(): from ycmd import utils python_interpreter = vim.eval( 'g:ycm_path_to_python_interpreter' ) if python_interpreter: if IsPythonVersionCorrect( python_interpreter ): return python_interpreter raise RuntimeError( "Path in 'g:ycm_path_to_python_interpreter' option " "does not point to a valid Python 2.6 or 2.7." ) # On UNIX platforms, we use sys.executable as the Python interpreter path. # We cannot use sys.executable on Windows because for unknown reasons, it # returns the Vim executable. Instead, we use sys.exec_prefix to deduce the # interpreter path. python_interpreter = ( WIN_PYTHON_PATH if utils.OnWindows() else sys.executable ) if IsPythonVersionCorrect( python_interpreter ): return python_interpreter # As a last resort, we search python in the PATH. We check 'python2' before # 'python' because on some distributions (Arch Linux for example), python # refers to python3. python_interpreter = utils.PathToFirstExistingExecutable( [ 'python2', 'python' ] ) if IsPythonVersionCorrect( python_interpreter ): return python_interpreter raise RuntimeError( "Cannot find Python 2.6 or 2.7. You can set its path " "using the 'g:ycm_path_to_python_interpreter' " "option." )
def _StartServer(self): """ Start the OmniSharp server if not already running. Use a lock to avoid starting the server multiple times for the same solution. """ with self._server_state_lock: if self._ServerIsRunning(): return LOGGER.info('Starting OmniSharp server') LOGGER.info('Loading solution file %s', self._solution_path) self._ChooseOmnisharpPort() # Roslyn fails unless you open it in shell in Window on Python 2 # Shell isn't preferred, but I don't see any other way to resolve shell_required = PY2 and utils.OnWindows() command = [ PATH_TO_ROSLYN_OMNISHARP_BINARY, '-p', str(self._omnisharp_port), '-s', str(self._solution_path) ] if (not utils.OnWindows() and PATH_TO_ROSLYN_OMNISHARP_BINARY.endswith('.exe')): command.insert(0, 'mono') LOGGER.info('Starting OmniSharp server with: %s', command) solutionfile = os.path.basename(self._solution_path) self._filename_stdout = utils.CreateLogfile( LOGFILE_FORMAT.format(port=self._omnisharp_port, sln=solutionfile, std='stdout')) self._filename_stderr = utils.CreateLogfile( LOGFILE_FORMAT.format(port=self._omnisharp_port, sln=solutionfile, std='stderr')) with utils.OpenForStdHandle(self._filename_stderr) as fstderr: with utils.OpenForStdHandle(self._filename_stdout) as fstdout: self._omnisharp_phandle = utils.SafePopen( command, stdout=fstdout, stderr=fstderr, shell=shell_required) LOGGER.info('Started OmniSharp server')
def FreeFileFromOtherProcesses(file_object): if utils.OnWindows(): from ctypes import windll import msvcrt file_handle = msvcrt.get_osfhandle(file_object.fileno()) windll.kernel32.SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0)
def WorkspaceEditToFixIt_test(): if utils.OnWindows(): filepath = 'C:\\test.test' uri = 'file:///c:/test.test' else: filepath = '/test.test' uri = 'file:/test.test' contents = 'line1\nline2\nline3' request_data = RequestWrap( BuildRequest(filetype='ycmtest', filepath=filepath, contents=contents)) # We don't support versioned documentChanges assert_that( lsc.WorkspaceEditToFixIt(request_data, {'documentChanges': []}), equal_to(None)) workspace_edit = { 'changes': { uri: [ { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 5 }, 'end': { 'line': 0, 'character': 5 }, } }, ] } } response = responses.BuildFixItResponse( [lsc.WorkspaceEditToFixIt(request_data, workspace_edit, 'test')]) print('Response: {0}'.format(response)) print('Type Response: {0}'.format(type(response))) assert_that( response, has_entries({ 'fixits': contains( has_entries({ 'text': 'test', 'chunks': contains( ChunkMatcher('blah', LocationMatcher(filepath, 1, 6), LocationMatcher(filepath, 1, 6))) })) }))
def _LauncherConfiguration(): if utils.OnMac(): config = 'config_mac' elif utils.OnWindows(): config = 'config_win' else: config = 'config_linux' return os.path.abspath(os.path.join(LANGUAGE_SERVER_HOME, config))
def PossiblyDetachFromTerminal(): # If not on windows, detach from controlling terminal to prevent # SIGINT from killing us. if not utils.OnWindows(): try: os.setsid() # setsid() can fail if the user started ycmd directly from a shell. except OSError: pass
def FindTsserverBinary(): tsserver = utils.FindExecutable('tsserver') if not tsserver: return None if not utils.OnWindows(): return tsserver # On Windows, tsserver is a batch script that calls the tsserver binary with # node. return os.path.abspath( os.path.join(os.path.dirname(tsserver), 'node_modules', 'typescript', 'bin', 'tsserver'))
def _StartServer(self, request_data): """ Start the OmniSharp server """ self._logger.info('startup') # NOTE: detection could throw an exception if an extra_conf_store needs to # be confirmed path_to_solutionfile = solutiondetection.FindSolutionPath( request_data['filepath']) if not path_to_solutionfile: raise RuntimeError('Autodetection of solution file failed.\n') self._logger.info( u'Loading solution file {0}'.format(path_to_solutionfile)) self._ChooseOmnisharpPort() # we need to pass the command to Popen as a string since we're passing # shell=True (as recommended by Python's doc) command = ' '.join([ PATH_TO_OMNISHARP_BINARY, '-p', str(self._omnisharp_port), '-s', u'"{0}"'.format(path_to_solutionfile) ]) if not utils.OnWindows() and not utils.OnCygwin(): command = u'mono ' + command if utils.OnCygwin(): command = command + ' --client-path-mode Cygwin' filename_format = os.path.join(utils.PathToTempDir(), u'omnisharp_{port}_{sln}_{std}.log') solutionfile = os.path.basename(path_to_solutionfile) self._filename_stdout = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stdout') self._filename_stderr = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stderr') with open(self._filename_stderr, 'w') as fstderr: with open(self._filename_stdout, 'w') as fstdout: # shell=True is needed for Windows so OmniSharp does not spawn # in a new visible window self._omnisharp_phandle = utils.SafePopen(command, stdout=fstdout, stderr=fstderr, shell=True) self._solution_path = path_to_solutionfile self._logger.info('Starting OmniSharp server')
def ShouldEnableCsCompleter(user_options): user_roslyn_path = user_options['roslyn_binary_path'] if user_roslyn_path and not os.path.isfile(user_roslyn_path): LOGGER.error('No omnisharp-roslyn executable at %s', user_roslyn_path) # We should trust the user who specifically asked for a custom path. return False if os.path.isfile(user_roslyn_path): roslyn = user_roslyn_path else: roslyn = PATH_TO_OMNISHARP_ROSLYN_BINARY mono = FindExecutableWithFallback(user_options['mono_binary_path'], FindExecutable('mono')) if roslyn and (mono or utils.OnWindows()): return True LOGGER.info('No mono executable at %s', mono) return False
def _StartServer(self): """ Start the OmniSharp server if not already running. Use a lock to avoid starting the server multiple times for the same solution. """ with self._server_state_lock: if self.ServerIsRunning(): return self._logger.info('Starting OmniSharp server') path_to_solutionfile = self._solution_path self._logger.info( u'Loading solution file {0}'.format(path_to_solutionfile)) self._ChooseOmnisharpPort() command = [ PATH_TO_OMNISHARP_BINARY, '-p', str(self._omnisharp_port), '-s', u'{0}'.format(path_to_solutionfile) ] if not utils.OnWindows() and not utils.OnCygwin(): command.insert(0, 'mono') if utils.OnCygwin(): command.extend(['--client-path-mode', 'Cygwin']) filename_format = os.path.join( utils.PathToCreatedTempDir(), u'omnisharp_{port}_{sln}_{std}.log') solutionfile = os.path.basename(path_to_solutionfile) self._filename_stdout = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stdout') self._filename_stderr = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stderr') with open(self._filename_stderr, 'w') as fstderr: with open(self._filename_stdout, 'w') as fstdout: self._omnisharp_phandle = utils.SafePopen(command, stdout=fstdout, stderr=fstderr) self._external_omnisharp = False self._solution_path = path_to_solutionfile
def _StartServer(self): """ Start the OmniSharp server if not already running. Use a lock to avoid starting the server multiple times for the same solution. """ with self._server_state_lock: if self._ServerIsRunning(): return self._logger.info('Starting OmniSharp server') path_to_solutionfile = self._solution_path self._logger.info( u'Loading solution file {0}'.format(path_to_solutionfile)) self._ChooseOmnisharpPort() command = [ PATH_TO_OMNISHARP_BINARY, '-p', str(self._omnisharp_port), '-s', u'{0}'.format(path_to_solutionfile) ] if not utils.OnWindows() and not utils.OnCygwin(): command.insert(0, 'mono') if utils.OnCygwin(): command.extend(['--client-path-mode', 'Cygwin']) solutionfile = os.path.basename(path_to_solutionfile) self._filename_stdout = utils.CreateLogfile( LOGFILE_FORMAT.format(port=self._omnisharp_port, sln=solutionfile, std='stdout')) self._filename_stderr = utils.CreateLogfile( LOGFILE_FORMAT.format(port=self._omnisharp_port, sln=solutionfile, std='stderr')) with utils.OpenForStdHandle(self._filename_stderr) as fstderr: with utils.OpenForStdHandle(self._filename_stdout) as fstdout: self._omnisharp_phandle = utils.SafePopen(command, stdout=fstdout, stderr=fstderr) self._solution_path = path_to_solutionfile
def _LauncherConfiguration( workspace_root, wipe_config ): if utils.OnMac(): config = 'config_mac' elif utils.OnWindows(): config = 'config_win' else: config = 'config_linux' CONFIG_FILENAME = 'config.ini' # The 'config' directory is a bit of a misnomer. It is really a working area # for eclipse to store things that eclipse feels entitled to store, # that are not specific to a particular project or workspace. # Importantly, the server writes to this directory, which means that in order # to allow installations of ycmd on readonly filesystems (or shared # installations of ycmd), we have to make it somehow unique at least per user, # and possibly per ycmd instance. # # To allow this, we let the client specify the workspace root and we always # put the (mutable) config directory under the workspace root path. The config # directory is simply a writable directory with the config.ini in it. # # Note that we must re-copy the config when it changes. Otherwise, eclipse # just won't start. As the file is generated part of the jdt.ls build, we just # always copy and overwrite it. working_config = os.path.abspath( os.path.join( workspace_root, config ) ) working_config_file = os.path.join( working_config, CONFIG_FILENAME ) base_config_file = os.path.abspath( os.path.join( LANGUAGE_SERVER_HOME, config, CONFIG_FILENAME ) ) if os.path.isdir( working_config ): if wipe_config: shutil.rmtree( working_config ) os.makedirs( working_config ) elif os.path.isfile( working_config_file ): os.remove( working_config_file ) else: os.makedirs( working_config ) shutil.copy2( base_config_file, working_config_file ) return working_config
def PathToPythonInterpreter(): # Not calling the Python interpreter to check its version as it significantly # impacts startup time. from ycmd import utils python_interpreter = vim.eval( 'g:ycm_server_python_interpreter' ) if python_interpreter: python_interpreter = utils.FindExecutable( python_interpreter ) if python_interpreter: return python_interpreter raise RuntimeError( "Path in 'g:ycm_server_python_interpreter' option " "does not point to a valid Python 2.6+ or 3.3+." ) python_interpreter = _PathToPythonUsedDuringBuild() if python_interpreter and utils.GetExecutable( python_interpreter ): return python_interpreter # On UNIX platforms, we use sys.executable as the Python interpreter path. # We cannot use sys.executable on Windows because for unknown reasons, it # returns the Vim executable. Instead, we use sys.exec_prefix to deduce the # interpreter path. python_interpreter = ( WIN_PYTHON_PATH if utils.OnWindows() else sys.executable ) if _EndsWithPython( python_interpreter ): return python_interpreter # As a last resort, we search python in the PATH. We prefer Python 2 over 3 # for the sake of backwards compatibility with ycm_extra_conf.py files out # there; few people wrote theirs to work on py3. # So we check 'python2' before 'python' because on some distributions (Arch # Linux for example), python refers to python3. python_interpreter = utils.PathToFirstExistingExecutable( [ 'python2', 'python', 'python3' ] ) if python_interpreter: return python_interpreter raise RuntimeError( "Cannot find Python 2.6+ or 3.3+. " "Set the 'g:ycm_server_python_interpreter' option " "to a Python interpreter path." )
def _StartServer(self): """ Start the OmniSharp server if not already running. Use a lock to avoid starting the server multiple times for the same solution. """ with self._server_state_lock: if self._ServerIsRunning(): return LOGGER.info('Starting OmniSharp server') LOGGER.info('Loading solution file %s', self._solution_path) self._ChooseOmnisharpPort() command = [ PATH_TO_OMNISHARP_ROSLYN_BINARY, '-p', str(self._omnisharp_port), '-s', str(self._solution_path) ] if (not utils.OnWindows() and self._roslyn_path.endswith('.exe')): command.insert(0, 'mono') LOGGER.info('Starting OmniSharp server with: %s', command) solutionfile = os.path.basename(self._solution_path) self._filename_stdout = utils.CreateLogfile( LOGFILE_FORMAT.format(port=self._omnisharp_port, sln=solutionfile, std='stdout')) self._filename_stderr = utils.CreateLogfile( LOGFILE_FORMAT.format(port=self._omnisharp_port, sln=solutionfile, std='stderr')) with utils.OpenForStdHandle(self._filename_stderr) as fstderr: with utils.OpenForStdHandle(self._filename_stdout) as fstdout: self._omnisharp_phandle = utils.SafePopen(command, stdout=fstdout, stderr=fstderr) LOGGER.info('Started OmniSharp server')
def _StartServer(self): """ Start the OmniSharp server """ self._logger.info('startup') path_to_solutionfile = self._solution_path self._logger.info( u'Loading solution file {0}'.format(path_to_solutionfile)) self._ChooseOmnisharpPort() command = [ PATH_TO_OMNISHARP_BINARY, '-p', str(self._omnisharp_port), '-s', u'{0}'.format(path_to_solutionfile) ] if not utils.OnWindows() and not utils.OnCygwin(): command.insert(0, 'mono') if utils.OnCygwin(): command.extend(['--client-path-mode', 'Cygwin']) filename_format = os.path.join(utils.PathToTempDir(), u'omnisharp_{port}_{sln}_{std}.log') solutionfile = os.path.basename(path_to_solutionfile) self._filename_stdout = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stdout') self._filename_stderr = filename_format.format( port=self._omnisharp_port, sln=solutionfile, std='stderr') with open(self._filename_stderr, 'w') as fstderr: with open(self._filename_stdout, 'w') as fstdout: self._omnisharp_phandle = utils.SafePopen(command, stdout=fstdout, stderr=fstderr) self._solution_path = path_to_solutionfile self._logger.info('Starting OmniSharp server')
def PathToPythonInterpreter(): user_path_to_python = vim.eval('g:ycm_path_to_python_interpreter') if user_path_to_python: return user_path_to_python # We check for 'python2' before 'python' because some OS's (I'm looking at # you Arch Linux) have made the... interesting decision to point # /usr/bin/python to python3. python_names = ['python2', 'python'] path_to_python = utils.PathToFirstExistingExecutable(python_names) if path_to_python: return path_to_python # On Windows, Python may not be on the PATH at all, so we check some common # install locations. if utils.OnWindows(): if os.path.exists(WIN_PYTHON27_PATH): return WIN_PYTHON27_PATH elif os.path.exists(WIN_PYTHON26_PATH): return WIN_PYTHON26_PATH raise RuntimeError('Python 2.7/2.6 not installed!')
def PathToPythonInterpreter(): from ycmd import utils python_interpreter = vim.eval('g:ycm_path_to_python_interpreter') if python_interpreter: if IsPythonVersionCorrect(python_interpreter): return python_interpreter raise RuntimeError("Path in 'g:ycm_path_to_python_interpreter' option " "does not point to a valid Python 2.6+ or 3.3+.") # On UNIX platforms, we use sys.executable as the Python interpreter path. # We cannot use sys.executable on Windows because for unknown reasons, it # returns the Vim executable. Instead, we use sys.exec_prefix to deduce the # interpreter path. python_interpreter = (WIN_PYTHON_PATH if utils.OnWindows() else sys.executable) if IsPythonVersionCorrect(python_interpreter): return python_interpreter # As a last resort, we search python in the PATH. We prefer Python 2 over 3 # for the sake of backwards compatibility with ycm_extra_conf.py files out # there; few people wrote theirs to work on py3. # So we check 'python2' before 'python' because on some distributions (Arch # Linux for example), python refers to python3. python_interpreter = utils.PathToFirstExistingExecutable( ['python2', 'python', 'python3']) if IsPythonVersionCorrect(python_interpreter): return python_interpreter raise RuntimeError("Cannot find Python 2.6+ or 3.3+. You can set its path " "using the 'g:ycm_path_to_python_interpreter' " "option.")
def test_PathToFirstExistingExecutable_Basic(self): if utils.OnWindows(): assert_that(utils.PathToFirstExistingExecutable(['notepad.exe'])) else: assert_that(utils.PathToFirstExistingExecutable(['cat']))
import json import tempfile import base64 import binascii import threading import os from os import path as p _logger = logging.getLogger(__name__) DIR_OF_THIS_SCRIPT = p.dirname(p.abspath(__file__)) DIR_OF_THIRD_PARTY = p.join(DIR_OF_THIS_SCRIPT, '..', '..', '..', 'third_party') RACERD_BINARY_NAME = 'racerd' + ('.exe' if utils.OnWindows() else '') RACERD_BINARY_RELEASE = p.join(DIR_OF_THIRD_PARTY, 'racerd', 'target', 'release', RACERD_BINARY_NAME) RACERD_BINARY_DEBUG = p.join(DIR_OF_THIRD_PARTY, 'racerd', 'target', 'debug', RACERD_BINARY_NAME) RACERD_HMAC_HEADER = 'x-racerd-hmac' HMAC_SECRET_LENGTH = 16 BINARY_NOT_FOUND_MESSAGE = ('racerd binary not found. Did you build it? ' + 'You can do so by running ' + '"./build.py --racer-completer".') ERROR_FROM_RACERD_MESSAGE = ( 'Received error from racerd while retrieving completions. You did not ' 'set the rust_src_path option, which is probably causing this issue. ' 'See YCM docs for details.')
def _StartServerNoLock(self): """Start the server, under the lock. Callers must hold self._server_state_mutex""" if self._ServerIsRunning(): return _logger.info('Starting Tern.js server...') self._server_port = utils.GetUnusedLocalhostPort() if _logger.isEnabledFor(logging.DEBUG): extra_args = ['--verbose'] else: extra_args = [] command = [ PATH_TO_NODE, PATH_TO_TERNJS_BINARY, '--port', str(self._server_port), '--host', SERVER_HOST, '--persistent', '--no-port-file' ] + extra_args _logger.debug('Starting tern with the following command: ' + ' '.join(command)) try: if utils.OnWindows(): # FIXME: # For unknown reasons, redirecting stdout and stderr on windows for this # particular Completer does not work. It causes tern to crash with an # access error on startup. Rather than spending too much time trying to # understand this (it's either a bug in Python, node or our code, and it # isn't obvious which), we just suppress the log files on this platform. # ATOW the only output from the server is the line saying it is # listening anyway. Verbose logging includes requests and responses, but # they can be tested on other platforms. self._server_stdout = "<Not supported on this platform>" self._server_stderr = "<Not supported on this platform>" self._server_handle = utils.SafePopen(command) else: logfile_format = os.path.join(utils.PathToTempDir(), u'tern_{port}_{std}.log') self._server_stdout = logfile_format.format( port=self._server_port, std='stdout') self._server_stderr = logfile_format.format( port=self._server_port, std='stderr') with open(self._server_stdout, 'w') as stdout: with open(self._server_stderr, 'w') as stderr: self._server_handle = utils.SafePopen(command, stdout=stdout, stderr=stderr) except Exception: _logger.warning('Unable to start Tern.js server: ' + traceback.format_exc()) self._Reset() if self._server_port > 0 and self._ServerIsRunning(): _logger.info('Tern.js Server started with pid: ' + str(self._server_handle.pid) + ' listening on port ' + str(self._server_port)) _logger.info('Tern.js Server log files are: ' + self._server_stdout + ' and ' + self._server_stderr) self._do_tern_project_check = True else: _logger.warning('Tern.js server did not start successfully')
def Main(): parser = argparse.ArgumentParser() parser.add_argument('--host', type=str, default='localhost', help='server hostname') # Default of 0 will make the OS pick a free port for us parser.add_argument('--port', type=int, default=0, help='server port') parser.add_argument('--log', type=str, default='info', help='log level, one of ' '[debug|info|warning|error|critical]') parser.add_argument('--idle_suicide_seconds', type=int, default=0, help='num idle seconds before server shuts down') parser.add_argument('--options_file', type=str, default='', help='file with user options, in JSON format') parser.add_argument('--stdout', type=str, default=None, help='optional file to use for stdout') parser.add_argument('--stderr', type=str, default=None, help='optional file to use for stderr') parser.add_argument('--keep_logfiles', action='store_true', default=None, help='retain logfiles after the server exits') args = parser.parse_args() if args.stdout is not None: sys.stdout = open(args.stdout, "w") if args.stderr is not None: sys.stderr = open(args.stderr, "w") numeric_level = getattr(logging, args.log.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: %s' % args.log) # Has to be called before any call to logging.getLogger() logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s', level=numeric_level) options = (json.load(open(args.options_file, 'r')) if args.options_file else user_options_store.DefaultOptions()) utils.RemoveIfExists(args.options_file) options['hmac_secret'] = base64.b64decode(options['hmac_secret']) user_options_store.SetAll(options) # This ensures that ycm_core is not loaded before extra conf # preload was run. YcmCoreSanityCheck() extra_conf_store.CallGlobalExtraConfYcmCorePreloadIfExists() # If not on windows, detach from controlling terminal to prevent # SIGINT from killing us. if not utils.OnWindows(): try: os.setsid() # setsid() can fail if the user started ycmd directly from a shell. except OSError: pass # This can't be a top-level import because it transitively imports # ycm_core which we want to be imported ONLY after extra conf # preload has executed. from ycmd import handlers handlers.UpdateUserOptions(options) SetUpSignalHandler(args.stdout, args.stderr, args.keep_logfiles) handlers.app.install(WatchdogPlugin(args.idle_suicide_seconds)) handlers.app.install(HmacPlugin(options['hmac_secret'])) waitress.serve(handlers.app, host=args.host, port=args.port, threads=30)
def WorkspaceEditToFixIt_test(): if utils.OnWindows(): filepath = 'C:\\test.test' uri = 'file:///c:/test.test' else: filepath = '/test.test' uri = 'file:/test.test' contents = 'line1\nline2\nline3' request_data = RequestWrap( BuildRequest( filetype = 'ycmtest', filepath = filepath, contents = contents ) ) # Null response to textDocument/codeActions is valid assert_that( lsc.WorkspaceEditToFixIt( request_data, None ), equal_to( None ) ) # Empty WorkspaceEdit is not explicitly forbidden assert_that( lsc.WorkspaceEditToFixIt( request_data, {} ), equal_to( None ) ) # We don't support versioned documentChanges workspace_edit = { 'documentChanges': [ { 'textDocument': { 'version': 1, 'uri': uri }, 'edits': [ { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 5 }, 'end': { 'line': 0, 'character': 5 }, } } ] } ] } response = responses.BuildFixItResponse( [ lsc.WorkspaceEditToFixIt( request_data, workspace_edit, 'test' ) ] ) print( f'Response: { response }' ) assert_that( response, has_entries( { 'fixits': contains_exactly( has_entries( { 'text': 'test', 'chunks': contains_exactly( ChunkMatcher( 'blah', LocationMatcher( filepath, 1, 6 ), LocationMatcher( filepath, 1, 6 ) ) ) } ) ) } ) ) workspace_edit = { 'changes': { uri: [ { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 5 }, 'end': { 'line': 0, 'character': 5 }, } }, ] } } response = responses.BuildFixItResponse( [ lsc.WorkspaceEditToFixIt( request_data, workspace_edit, 'test' ) ] ) print( f'Response: { response }' ) print( f'Type Response: { type( response ) }' ) assert_that( response, has_entries( { 'fixits': contains_exactly( has_entries( { 'text': 'test', 'chunks': contains_exactly( ChunkMatcher( 'blah', LocationMatcher( filepath, 1, 6 ), LocationMatcher( filepath, 1, 6 ) ) ) } ) ) } ) )
def GetCompletions_RejectInvalid_test(): if utils.OnWindows(): filepath = 'C:\\test.test' else: filepath = '/test.test' contents = 'line1.\nline2.\nline3.' request_data = RequestWrap( BuildRequest( filetype = 'ycmtest', filepath = filepath, contents = contents, line_num = 1, column_num = 7 ) ) text_edit = { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 6 }, 'end': { 'line': 0, 'character': 6 }, } } assert_that( lsc._GetCompletionItemStartCodepointOrReject( text_edit, request_data ), equal_to( 7 ) ) text_edit = { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 6 }, 'end': { 'line': 1, 'character': 6 }, } } assert_that( calling( lsc._GetCompletionItemStartCodepointOrReject ).with_args( text_edit, request_data ), raises( lsc.IncompatibleCompletionException ) ) text_edit = { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 20 }, 'end': { 'line': 0, 'character': 20 }, } } assert_that( lsc._GetCompletionItemStartCodepointOrReject( text_edit, request_data ), equal_to( 7 ) ) text_edit = { 'newText': 'blah', 'range': { 'start': { 'line': 0, 'character': 6 }, 'end': { 'line': 0, 'character': 5 }, } } assert_that( lsc._GetCompletionItemStartCodepointOrReject( text_edit, request_data ), equal_to( 7 ) )
def LanguageServerCompleter_GoTo_test( app ): if utils.OnWindows(): filepath = 'C:\\test.test' uri = 'file:///c:/test.test' else: filepath = '/test.test' uri = 'file:/test.test' contents = 'line1\nline2\nline3' completer = MockCompleter() # LSP server supports all code navigation features. completer._server_capabilities = { 'definitionProvider': True, 'declarationProvider': True, 'typeDefinitionProvider': True, 'implementationProvider': True, 'referencesProvider': True } request_data = RequestWrap( BuildRequest( filetype = 'ycmtest', filepath = filepath, contents = contents, line_num = 2, column_num = 3 ) ) @patch.object( completer, '_ServerIsInitialized', return_value = True ) def Test( responses, command, exception, throws, *args ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = responses ): if throws: assert_that( calling( completer.OnUserCommand ).with_args( [ command ], request_data ), raises( exception ) ) else: result = completer.OnUserCommand( [ command ], request_data ) print( f'Result: { result }' ) assert_that( result, exception ) location = { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 0 }, } } goto_response = has_entries( { 'filepath': filepath, 'column_num': 1, 'line_num': 1, 'description': 'line1' } ) cases = [ ( [ { 'result': None } ], 'GoToDefinition', RuntimeError, True ), ( [ { 'result': location } ], 'GoToDeclaration', goto_response, False ), ( [ { 'result': {} } ], 'GoToType', RuntimeError, True ), ( [ { 'result': [] } ], 'GoToImplementation', RuntimeError, True ), ( [ { 'result': [ location ] } ], 'GoToReferences', goto_response, False ), ( [ { 'result': [ location, location ] } ], 'GoToReferences', contains_exactly( goto_response, goto_response ), False ), ] for response, goto_handlers, exception, throws in cases: Test( response, goto_handlers, exception, throws ) # All requests return an invalid URI. with patch( 'ycmd.completers.language_server.language_server_protocol.UriToFilePath', side_effect = lsp.InvalidUriException ): Test( [ { 'result': { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 0 } } } } ], 'GoTo', LocationMatcher( '', 1, 1 ), False ) with patch( 'ycmd.completers.completer_utils.GetFileContents', side_effect = IOError ): Test( [ { 'result': { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 0 } } } } ], 'GoToDefinition', LocationMatcher( filepath, 1, 1 ), False ) # Both requests return the location where the cursor is. Test( [ { 'result': { 'uri': uri, 'range': { 'start': { 'line': 1, 'character': 0 }, 'end': { 'line': 1, 'character': 4 } } } }, { 'result': { 'uri': uri, 'range': { 'start': { 'line': 1, 'character': 0 }, 'end': { 'line': 1, 'character': 4 }, } } } ], 'GoTo', LocationMatcher( filepath, 2, 1 ), False ) # First request returns two locations. Test( [ { 'result': [ { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 4 } } }, { 'uri': uri, 'range': { 'start': { 'line': 1, 'character': 0 }, 'end': { 'line': 1, 'character': 4 }, } } ], } ], 'GoTo', contains_exactly( LocationMatcher( filepath, 1, 1 ), LocationMatcher( filepath, 2, 1 ) ), False ) # First request returns the location where the cursor is and second request # returns a different URI. if utils.OnWindows(): other_filepath = 'C:\\another.test' other_uri = 'file:///c:/another.test' else: other_filepath = '/another.test' other_uri = 'file:/another.test' Test( [ { 'result': { 'uri': uri, 'range': { 'start': { 'line': 1, 'character': 0 }, 'end': { 'line': 1, 'character': 4 } } } }, { 'result': { 'uri': other_uri, 'range': { 'start': { 'line': 1, 'character': 0 }, 'end': { 'line': 1, 'character': 4 }, } } } ], 'GoTo', LocationMatcher( other_filepath, 2, 1 ), False ) # First request returns a location before the cursor. Test( [ { 'result': { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 1 }, 'end': { 'line': 1, 'character': 1 } } } } ], 'GoTo', LocationMatcher( filepath, 1, 2 ), False ) # First request returns a location after the cursor. Test( [ { 'result': { 'uri': uri, 'range': { 'start': { 'line': 1, 'character': 3 }, 'end': { 'line': 2, 'character': 3 } } } } ], 'GoTo', LocationMatcher( filepath, 2, 4 ), False )
from ycmd import responses from ycmd import utils from ycmd.completers.completer import Completer GO_FILETYPES = set(['go']) BINARY_NOT_FOUND_MESSAGE = ('Gocode binary not found. Did you build it? ' + 'You can do so by running ' + '"./install.py --gocode-completer".') COMPLETION_ERROR_MESSAGE = 'Gocode shell call failed.' PARSE_ERROR_MESSAGE = 'Gocode returned invalid JSON response.' NO_COMPLETIONS_MESSAGE = 'Gocode returned empty JSON response.' GOCODE_PANIC_MESSAGE = ('Gocode panicked trying to find completions, ' + 'you likely have a syntax error.') PATH_TO_GOCODE_BINARY = os.path.join( os.path.abspath(os.path.dirname(__file__)), '..', '..', '..', 'third_party', 'gocode', 'gocode' + ('.exe' if utils.OnWindows() else '')) _logger = logging.getLogger(__name__) class GoCodeCompleter(Completer): def __init__(self, user_options): super(GoCodeCompleter, self).__init__(user_options) self._popener = utils.SafePopen # Overridden in test. self._binary = self.FindGoCodeBinary(user_options) if not self._binary: _logger.error(BINARY_NOT_FOUND_MESSAGE) raise RuntimeError(BINARY_NOT_FOUND_MESSAGE) _logger.info('Enabling go completion using %s binary', self._binary)
def LanguageServerCompleter_GoToDeclaration_test(): if utils.OnWindows(): filepath = 'C:\\test.test' uri = 'file:///c:/test.test' else: filepath = '/test.test' uri = 'file:/test.test' contents = 'line1\nline2\nline3' completer = MockCompleter() request_data = RequestWrap( BuildRequest(filetype='ycmtest', filepath=filepath, contents=contents)) @patch.object(completer, 'ServerIsReady', return_value=True) def Test(response, checker, throws, *args): with patch.object(completer.GetConnection(), 'GetResponse', return_value=response): if throws: assert_that( calling(completer.GoToDeclaration).with_args(request_data), raises(checker)) else: result = completer.GoToDeclaration(request_data) print('Result: {0}'.format(result)) assert_that(result, checker) location = { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 0 }, } } goto_response = has_entries({ 'filepath': filepath, 'column_num': 1, 'line_num': 1, 'description': 'line1' }) cases = [ ({ 'result': None }, RuntimeError, True), ({ 'result': location }, goto_response, False), ({ 'result': {} }, RuntimeError, True), ({ 'result': [] }, RuntimeError, True), ({ 'result': [location] }, goto_response, False), ({ 'result': [location, location] }, contains(goto_response, goto_response), False), ] for response, checker, throws in cases: yield Test, response, checker, throws with patch( 'ycmd.completers.language_server.language_server_protocol.UriToFilePath', side_effect=lsp.InvalidUriException): yield Test, { 'result': { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 0 }, } } }, has_entries({ 'filepath': '', 'column_num': 1, 'line_num': 1, }), False with patch('ycmd.completers.completer_utils.GetFileContents', side_effect=lsp.IOError): yield Test, { 'result': { 'uri': uri, 'range': { 'start': { 'line': 0, 'character': 0 }, 'end': { 'line': 0, 'character': 0 }, } } }, has_entries({ 'filepath': filepath, 'column_num': 1, 'line_num': 1, }), False
def PathToFirstExistingExecutable_Basic_test(): if utils.OnWindows(): ok_(utils.PathToFirstExistingExecutable(['notepad.exe'])) else: ok_(utils.PathToFirstExistingExecutable(['cat']))
from ycmd.utils import ToBytes, ToUnicode from ycmd.completers.completer import Completer GO_FILETYPES = set( [ 'go' ] ) BINARY_NOT_FOUND_MESSAGE = ( '{0} binary not found. Did you build it? ' + 'You can do so by running ' + '"./install.py --gocode-completer".' ) SHELL_ERROR_MESSAGE = '{0} shell call failed.' PARSE_ERROR_MESSAGE = 'Gocode returned invalid JSON response.' NO_COMPLETIONS_MESSAGE = 'Gocode returned empty JSON response.' GOCODE_PANIC_MESSAGE = ( 'Gocode panicked trying to find completions, ' + 'you likely have a syntax error.' ) PATH_TO_GOCODE_BINARY = os.path.join( os.path.abspath( os.path.dirname( __file__ ) ), '..', '..', '..', 'third_party', 'gocode', 'gocode' + ( '.exe' if utils.OnWindows() else '' ) ) PATH_TO_GODEF_BINARY = os.path.join( os.path.abspath( os.path.dirname( __file__ ) ), '..', '..', '..', 'third_party', 'godef', 'godef' + ( '.exe' if utils.OnWindows() else '' ) ) _logger = logging.getLogger( __name__ ) class GoCodeCompleter( Completer ): def __init__( self, user_options ): super( GoCodeCompleter, self ).__init__( user_options ) self._popener = utils.SafePopen # Overridden in test. self._binary_gocode = self.FindBinary( 'gocode', user_options ) self._binary_godef = self.FindBinary( 'godef', user_options )