예제 #1
0
    def _StartServerNoLock(self):
        if self._ServerIsRunning():
            return

        self._logfile = utils.CreateLogfile(LOGFILE_FORMAT)
        tsserver_log = f'-file { self._logfile } -level {_LogLevel()}'
        # TSServer gets the configuration for the log file through the
        # environment variable 'TSS_LOG'. This seems to be undocumented but
        # looking at the source code it seems like this is the way:
        # https://github.com/Microsoft/TypeScript/blob/8a93b489454fdcbdf544edef05f73a913449be1d/src/server/server.ts#L136
        environ = os.environ.copy()
        environ['TSS_LOG'] = tsserver_log

        # TSServer runs out of memory on larger projects. This is the value that
        # VSCode uses.
        environ['NODE_OPTIONS'] = '--max_old_space_size=3072'

        LOGGER.info('TSServer log file: %s', self._logfile)

        # We need to redirect the error stream to the output one on Windows.
        self._tsserver_handle = utils.SafePopen(self._tsserver_executable,
                                                stdin=subprocess.PIPE,
                                                stdout=subprocess.PIPE,
                                                stderr=subprocess.STDOUT,
                                                env=environ)

        LOGGER.info("TSServer started with PID %s", self._tsserver_handle.pid)
        self._tsserver_is_running.set()

        utils.StartThread(self._SetServerVersion)
예제 #2
0
    def _StartServer(self):
        with self._tsserver_lock:
            if self._ServerIsRunning():
                return

            self._logfile = utils.CreateLogfile(LOGFILE_FORMAT)
            tsserver_log = '-file {path} -level {level}'.format(
                path=self._logfile, level=_LogLevel())
            # TSServer gets the configuration for the log file through the
            # environment variable 'TSS_LOG'. This seems to be undocumented but
            # looking at the source code it seems like this is the way:
            # https://github.com/Microsoft/TypeScript/blob/8a93b489454fdcbdf544edef05f73a913449be1d/src/server/server.ts#L136
            environ = os.environ.copy()
            environ['TSS_LOG'] = tsserver_log

            LOGGER.info('TSServer log file: %s', self._logfile)

            # We need to redirect the error stream to the output one on Windows.
            self._tsserver_handle = utils.SafePopen(self._tsserver_executable,
                                                    stdin=subprocess.PIPE,
                                                    stdout=subprocess.PIPE,
                                                    stderr=subprocess.STDOUT,
                                                    env=environ)

            self._tsserver_is_running.set()

            utils.StartThread(self._SetServerVersion)
def ServerManagement_ServerDiesWhileShuttingDown_test( app ):
  StartClangd( app )
  process = psutil.Process( GetPid( app ) )
  completer = handlers._server_state.GetFiletypeCompleter( [ 'cpp' ] )

  # We issue a shutdown but make sure it never reaches server by mocking
  # WriteData in Connection. Then we kill the server and check shutdown still
  # succeeds.
  with patch.object( completer.GetConnection(), 'WriteData' ):
    stop_server_task = utils.StartThread( StopCompleterServer, app, 'cpp', '' )
    process.terminate()
    stop_server_task.join()

  CheckStopped( app )
예제 #4
0
    def __init__(self, user_options):
        super().__init__(user_options)

        self._logfile = None

        self._tsserver_lock = threading.RLock()
        self._tsserver_handle = None
        self._tsserver_version = None
        self._tsserver_executable = FindTSServer(
            user_options['tsserver_binary_path'])
        # Used to read response only if TSServer is running.
        self._tsserver_is_running = threading.Event()

        # Used to prevent threads from concurrently writing to
        # the tsserver process' stdin
        self._write_lock = threading.Lock()

        # Each request sent to tsserver must have a sequence id.
        # Responses contain the id sent in the corresponding request.
        self._sequenceid = itertools.count()

        # Used to prevent threads from concurrently accessing the sequence counter
        self._sequenceid_lock = threading.Lock()

        # Start a thread to read response from TSServer.
        utils.StartThread(self._ReaderLoop)

        # Used to map sequence id's to their corresponding DeferredResponse
        # objects. The reader loop uses this to hand out responses.
        self._pending = {}

        # Used to prevent threads from concurrently reading and writing to
        # the pending response dictionary
        self._pending_lock = threading.Lock()

        self._StartServer()

        self._latest_diagnostics_for_file_lock = threading.Lock()
        self._latest_diagnostics_for_file = defaultdict(list)

        # There's someting in the API that lists the trigger characters, but
        # there is no way to request that from the server, so we just hard-code
        # the signature triggers.
        self.SetSignatureHelpTriggers(['(', ',', '<'])

        LOGGER.info('Enabling TypeScript completion')
예제 #5
0
def Shutdown_ServerDiesDuringShutdown_test(app):
    StartClangd(app)
    debug_info = GetDebugInfo(app)
    pid = debug_info['completer']['servers'][0]['pid']
    process = psutil.Process(pid)
    completer = handlers._server_state.GetFiletypeCompleter(['cpp'])

    # We issue a shutdown but make sure it never reaches server by mocking
    # WriteData in Connection. Then we kill the server and check shutdown still
    # succeeds.
    with patch.object(completer.GetConnection(), 'WriteData'):
        stop_server_task = utils.StartThread(StopCompleterServer, app, 'cpp',
                                             '')
        process.terminate()
        stop_server_task.join()

    CheckStopped(app)
예제 #6
0
def ServerManagement_ServerDiesWhileShuttingDown_test( app ):
  StartJavaCompleterServerInDirectory(
    app,
    PathToTestFile( 'simple_eclipse_project' ) )

  request_data = BuildRequest( filetype = 'java' )
  debug_info = app.post_json( '/debug_info', request_data ).json
  print( 'Debug info: {0}'.format( debug_info ) )
  pid = debug_info[ 'completer' ][ 'servers' ][ 0 ][ 'pid' ]
  print( 'pid: {0}'.format( pid ) )
  process = psutil.Process( pid )


  def StopServerInAnotherThread():
    app.post_json(
      '/run_completer_command',
      BuildRequest(
        filetype = 'java',
        command_arguments = [ 'StopServer' ],
      ),
    )

  completer = handlers._server_state.GetFiletypeCompleter( [ 'java' ] )

  # In this test we mock out the sending method so that we don't actually send
  # the shutdown request. We then assisted-suicide the downstream server, which
  # causes the shutdown request to be aborted. This is interpreted by the
  # shutdown code as a successful shutdown. We need to do the shutdown and
  # terminate in parallel as the post_json is a blocking call.
  with patch.object( completer.GetConnection(), 'WriteData' ):
    stop_server_task = utils.StartThread( StopServerInAnotherThread )
    process.terminate()
    stop_server_task.join()

  request_data = BuildRequest( filetype = 'java' )
  debug_info = app.post_json( '/debug_info', request_data ).json
  assert_that( debug_info,
               has_entry(
                 'completer',
                 has_entry( 'servers', contains(
                   has_entry( 'is_running', False )
                 ) )
               ) )
예제 #7
0
    def __init__(self, user_options):
        super(TypeScriptCompleter, self).__init__(user_options)

        self._logfile = None

        self._tsserver_lock = threading.RLock()
        self._tsserver_binary_path = FindTsserverBinary()
        self._tsserver_handle = None
        self._tsserver_version = None
        # Used to read response only if TSServer is running.
        self._tsserver_is_running = threading.Event()

        # Used to prevent threads from concurrently writing to
        # the tsserver process' stdin
        self._write_lock = threading.Lock()

        # Each request sent to tsserver must have a sequence id.
        # Responses contain the id sent in the corresponding request.
        self._sequenceid = itertools.count()

        # Used to prevent threads from concurrently accessing the sequence counter
        self._sequenceid_lock = threading.Lock()

        # Start a thread to read response from TSServer.
        utils.StartThread(self._ReaderLoop)

        # Used to map sequence id's to their corresponding DeferredResponse
        # objects. The reader loop uses this to hand out responses.
        self._pending = {}

        # Used to prevent threads from concurrently reading and writing to
        # the pending response dictionary
        self._pending_lock = threading.Lock()

        self._StartServer()

        self._max_diagnostics_to_display = user_options[
            'max_diagnostics_to_display']

        self._latest_diagnostics_for_file_lock = threading.Lock()
        self._latest_diagnostics_for_file = defaultdict(list)

        _logger.info('Enabling typescript completion')