示例#1
0
  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 ) )
示例#2
0
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.")
示例#3
0
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." )
示例#4
0
    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')
示例#5
0
        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)))
                }))
        }))
示例#7
0
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))
示例#8
0
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
示例#9
0
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'))
示例#10
0
    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')
示例#11
0
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
示例#12
0
    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
示例#13
0
    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
示例#14
0
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
示例#15
0
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." )
示例#16
0
    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')
示例#17
0
    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')
示例#18
0
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!')
示例#19
0
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.")
示例#20
0
 def test_PathToFirstExistingExecutable_Basic(self):
     if utils.OnWindows():
         assert_that(utils.PathToFirstExistingExecutable(['notepad.exe']))
     else:
         assert_that(utils.PathToFirstExistingExecutable(['cat']))
示例#21
0
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.')
示例#22
0
    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')
示例#23
0
文件: __main__.py 项目: winkar/ycmd
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)
示例#24
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
  ) )


  # 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 ) ) )
      } ) )
    } )
  )
示例#25
0
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 ) )
示例#26
0
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 )
示例#27
0
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
示例#29
0
文件: utils_test.py 项目: rust20/ycmd
def PathToFirstExistingExecutable_Basic_test():
    if utils.OnWindows():
        ok_(utils.PathToFirstExistingExecutable(['notepad.exe']))
    else:
        ok_(utils.PathToFirstExistingExecutable(['cat']))
示例#30
0
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 )