Exemple #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 ) )
Exemple #2
0
    def _HasCompletionsThatCouldBeCompletedWithMoreText(self, completions):
        completed_item = vimsupport.GetVariableValue('v:completed_item')
        if not completed_item:
            return False

        completed_word = utils.ToUnicode(completed_item['word'])
        if not completed_word:
            return False

        # Sometimes CompleteDone is called after the next character is inserted.
        # If so, use inserted character to filter possible completions further.
        text = vimsupport.TextBeforeCursor()
        reject_exact_match = True
        if text and text[-1] != completed_word[-1]:
            reject_exact_match = False
            completed_word += text[-1]

        for completion in completions:
            word = utils.ToUnicode(
                ConvertCompletionDataToVimData(completion)['word'])
            if reject_exact_match and word == completed_word:
                continue
            if word.startswith(completed_word):
                return True
        return False
Exemple #3
0
  def _SetUpServer( self ):
    self._available_completers = {}
    self._user_notified_about_crash = False
    self._filetypes_with_keywords_loaded = set()
    self._server_is_ready_with_cache = False
    self._message_poll_request = None

    self._user_options = base.GetUserOptions()
    self._omnicomp = OmniCompleter( self._user_options )
    self._buffers = BufferDict( self._user_options )

    self._SetLogLevel()

    hmac_secret = os.urandom( HMAC_SECRET_LENGTH )
    options_dict = dict( self._user_options )
    options_dict[ 'hmac_secret' ] = utils.ToUnicode(
      base64.b64encode( hmac_secret ) )
    options_dict[ 'server_keep_logfiles' ] = self._user_options[
      'keep_logfiles' ]

    # The temp options file is deleted by ycmd during startup.
    with NamedTemporaryFile( delete = False, mode = 'w+' ) as options_file:
      json.dump( options_dict, options_file )

    server_port = utils.GetUnusedLocalhostPort()

    BaseRequest.server_location = 'http://127.0.0.1:' + str( server_port )
    BaseRequest.hmac_secret = hmac_secret

    try:
      python_interpreter = paths.PathToPythonInterpreter()
    except RuntimeError as error:
      error_message = (
        "Unable to start the ycmd server. {0}. "
        "Correct the error then restart the server "
        "with ':YcmRestartServer'.".format( str( error ).rstrip( '.' ) ) )
      self._logger.exception( error_message )
      vimsupport.PostVimMessage( error_message )
      return

    args = [ python_interpreter,
             paths.PathToServerScript(),
             '--port={0}'.format( server_port ),
             '--options_file={0}'.format( options_file.name ),
             '--log={0}'.format( self._user_options[ 'log_level' ] ),
             '--idle_suicide_seconds={0}'.format(
                SERVER_IDLE_SUICIDE_SECONDS ) ]

    self._server_stdout = utils.CreateLogfile(
        SERVER_LOGFILE_FORMAT.format( port = server_port, std = 'stdout' ) )
    self._server_stderr = utils.CreateLogfile(
        SERVER_LOGFILE_FORMAT.format( port = server_port, std = 'stderr' ) )
    args.append( '--stdout={0}'.format( self._server_stdout ) )
    args.append( '--stderr={0}'.format( self._server_stderr ) )

    if self._user_options[ 'keep_logfiles' ]:
      args.append( '--keep_logfiles' )

    self._server_popen = utils.SafePopen( args, stdin_windows = PIPE,
                                          stdout = PIPE, stderr = PIPE )
Exemple #4
0
    def _GoToDefinition(self, request_data):
        def find_end_of_command(line, match):
            if match is None:
                return -1
            for i in range(match.start(), len(line)):
                e = line[i]
                if e == "}":
                    return i
            return -1

        line = utils.ToUnicode(request_data["line_value"])
        match = self._ref_reg.search(line)
        end_of_command = find_end_of_command(line, match)
        if end_of_command == -1:
            raise RuntimeError(
                'Can\'t jump to definition or declaration: not implemented yet'
            )
        else:
            ref = line[match.end():end_of_command]
            if ref not in self._goto_labels:
                raise RuntimeError(
                    'Can\'t jump to definition or declaration: not implemented yet'
                )
            filename, line, col = self._goto_labels[ref]
            return responses.BuildGoToResponse(filename, line, col)
Exemple #5
0
 def ShouldUseNow(self, request_data):
     self._omnifunc = utils.ToUnicode(vimsupport.Eval('&omnifunc'))
     if not self._omnifunc:
         return False
     if self.ShouldUseCache():
         return super(OmniCompleter, self).ShouldUseNow(request_data)
     return self.ShouldUseNowInner(request_data)
Exemple #6
0
    def _NotifyUserIfServerCrashed(self):
        if self._user_notified_about_crash or self.IsServerAlive():
            return
        self._user_notified_about_crash = True

        return_code = self._server_popen.poll()
        if return_code == server_utils.CORE_UNEXPECTED_STATUS:
            error_message = CORE_UNEXPECTED_MESSAGE
        elif return_code == server_utils.CORE_MISSING_STATUS:
            error_message = CORE_MISSING_MESSAGE
        elif return_code == server_utils.CORE_PYTHON2_STATUS:
            error_message = CORE_PYTHON2_MESSAGE
        elif return_code == server_utils.CORE_PYTHON3_STATUS:
            error_message = CORE_PYTHON3_MESSAGE
        elif return_code == server_utils.CORE_OUTDATED_STATUS:
            error_message = CORE_OUTDATED_MESSAGE
        else:
            error_message = EXIT_CODE_UNEXPECTED_MESSAGE.format(
                code=return_code)

        server_stderr = '\n'.join(
            utils.ToUnicode(self._server_popen.stderr.read()).splitlines())
        if server_stderr:
            self._logger.error(server_stderr)

        error_message = SERVER_SHUTDOWN_MESSAGE + ' ' + error_message
        self._logger.error(error_message)
        vimsupport.PostVimMessage(error_message)
Exemple #7
0
    def _SetUpServer(self):
        self._available_completers = {}
        self._user_notified_about_crash = False
        self._filetypes_with_keywords_loaded = set()
        self._server_is_ready_with_cache = False
        self._message_poll_request = None

        base.LoadJsonDefaultsIntoVim()
        user_options_store.SetAll(base.BuildServerConf())
        self._user_options = user_options_store.GetAll()
        self._omnicomp = OmniCompleter(self._user_options)
        self._buffers = BufferDict(self._user_options)

        self._SetLogLevel()

        hmac_secret = os.urandom(HMAC_SECRET_LENGTH)
        options_dict = dict(self._user_options)
        options_dict['hmac_secret'] = utils.ToUnicode(
            base64.b64encode(hmac_secret))
        options_dict['server_keep_logfiles'] = self._user_options[
            'keep_logfiles']

        # The temp options file is deleted by ycmd during startup.
        with NamedTemporaryFile(delete=False, mode='w+') as options_file:
            json.dump(options_dict, options_file)

        server_port = utils.GetUnusedLocalhostPort()

        BaseRequest.server_location = 'http://127.0.0.1:' + str(server_port)
        BaseRequest.hmac_secret = hmac_secret

        this_file_path = os.path.dirname(os.path.realpath(__file__))
        tabnine_binary_path = os.path.join(this_file_path, '../../binaries/')

        args = [
            '--client=vim', '--port={0}'.format(server_port),
            '--options_file={0}'.format(options_file.name),
            '--log={0}'.format(self._user_options['log_level']),
            '--idle_suicide_seconds={0}'.format(SERVER_IDLE_SUICIDE_SECONDS)
        ]

        self._server_stdout = utils.CreateLogfile(
            SERVER_LOGFILE_FORMAT.format(port=server_port, std='stdout'))
        self._server_stderr = utils.CreateLogfile(
            SERVER_LOGFILE_FORMAT.format(port=server_port, std='stderr'))
        args.append('--stdout={0}'.format(self._server_stdout))
        args.append('--stderr={0}'.format(self._server_stderr))

        if self._user_options['keep_logfiles']:
            args.append('--keep_logfiles')

        try:
            self._server_popen = start_tabnine_proc(
                cmd_args=args, binary_dir=tabnine_binary_path)
        except RuntimeError as error:
            error_message = str(error)
            self._logger.exception(error_message)
            vimsupport.PostVimMessage(error_message)
            return
Exemple #8
0
 def _HasCompletionsThatCouldBeCompletedWithMoreText_OlderVim( self,
                                                               completions ):
   # No support for multiple line completions
   text = vimsupport.TextBeforeCursor()
   for completion in completions:
     word = utils.ToUnicode(
         ConvertCompletionDataToVimData( completion )[ 'word' ] )
     for i in range( 1, len( word ) - 1 ): # Excluding full word
       if text[ -1 * i : ] == word[ : i ]:
         return True
   return False
Exemple #9
0
def _WorkspaceDirForProject(project_dir, use_clean_workspace):
    if use_clean_workspace:
        temp_path = os.path.join(WORKSPACE_ROOT_PATH, 'temp')

        try:
            os.makedirs(temp_path)
        except OSError:
            pass

        return tempfile.mkdtemp(dir=temp_path)

    project_dir_hash = hashlib.sha256(utils.ToBytes(project_dir))
    return os.path.join(WORKSPACE_ROOT_PATH,
                        utils.ToUnicode(project_dir_hash.hexdigest()))
Exemple #10
0
    def _SetupServer(self):
        self._available_completers = {}
        self._user_notified_about_crash = False
        self._filetypes_with_keywords_loaded = set()
        self._server_is_ready_with_cache = False

        server_port = utils.GetUnusedLocalhostPort()
        # The temp options file is deleted by ycmd during startup
        with NamedTemporaryFile(delete=False, mode='w+') as options_file:
            hmac_secret = os.urandom(HMAC_SECRET_LENGTH)
            options_dict = dict(self._user_options)
            options_dict['hmac_secret'] = utils.ToUnicode(
                base64.b64encode(hmac_secret))
            options_dict['server_keep_logfiles'] = self._user_options[
                'keep_logfiles']
            json.dump(options_dict, options_file)
            options_file.flush()

            args = [
                paths.PathToPythonInterpreter(),
                paths.PathToServerScript(), '--port={0}'.format(server_port),
                '--options_file={0}'.format(options_file.name),
                '--log={0}'.format(self._user_options['log_level']),
                '--idle_suicide_seconds={0}'.format(
                    SERVER_IDLE_SUICIDE_SECONDS)
            ]

            self._server_stdout = utils.CreateLogfile(
                SERVER_LOGFILE_FORMAT.format(port=server_port, std='stdout'))
            self._server_stderr = utils.CreateLogfile(
                SERVER_LOGFILE_FORMAT.format(port=server_port, std='stderr'))
            args.append('--stdout={0}'.format(self._server_stdout))
            args.append('--stderr={0}'.format(self._server_stderr))

            if self._user_options['keep_logfiles']:
                args.append('--keep_logfiles')

            self._server_popen = utils.SafePopen(args,
                                                 stdin_windows=PIPE,
                                                 stdout=PIPE,
                                                 stderr=PIPE)
            BaseRequest.server_location = 'http://127.0.0.1:' + str(
                server_port)
            BaseRequest.hmac_secret = hmac_secret

        self._NotifyUserIfServerCrashed()
Exemple #11
0
    def ShouldUseNowInner(self, request_data):
        #q    = utils.ToUtf8IfNeeded(request_data['query'])
        #col  = request_data["start_column"]
        line = utils.ToUnicode(request_data["line_value"])

        if self._main_directory is None:
            self._ComputeMainDirectory(request_data)

        should_use = False
        line_splitted = line
        match = self._cite_reg.search(line_splitted)
        if match is not None:
            self._completion_target = 'cite'
            should_use = True

        match = self._ref_reg.search(line_splitted)
        if match is not None:
            if self._completion_target == 'cite':
                self._completion_target = 'all'
            else:
                self._completion_target = 'label'
            should_use = True

        return should_use
Exemple #12
0
def ToUnicode_Str_test():
    value = utils.ToUnicode(u'abc')
    eq_(value, u'abc')
    ok_(isinstance(value, str))
Exemple #13
0
def ToUnicode_Bytes_test():
    value = utils.ToUnicode(bytes(b'abc'))
    eq_(value, u'abc')
    ok_(isinstance(value, str))
Exemple #14
0
def ToUnicode_Py2FutureStr_test():
    value = utils.ToUnicode(str('abc'))
    eq_(value, u'abc')
    ok_(isinstance(value, str))
Exemple #15
0
 def matcher(key):
     return (utils.ToUnicode(completed.get(key,
                                           "")) == utils.ToUnicode(
                                               item.get(key, "")))
 def OnFileReadyToParse(self, request_data):
     self._omnifunc = utils.ToUnicode(vim.eval('&omnifunc'))
Exemple #17
0
 def test_ToUnicode_Int(self):
     value = utils.ToUnicode(123)
     assert_that(value, equal_to(u'123'))
     assert_that(isinstance(value, str))
Exemple #18
0
 def test_ToUnicode_None(self):
     value = utils.ToUnicode(None)
     assert_that(value, equal_to(u''))
     assert_that(isinstance(value, str))
Exemple #19
0
def _GetCommandOutput(command):
    return utils.ToUnicode(
        utils.SafePopen(command, stdin_windows=PIPE, stdout=PIPE,
                        stderr=PIPE).communicate()[0].rstrip())
Exemple #20
0
 def test_ToUnicode_Str(self):
     value = utils.ToUnicode(u'abc')
     assert_that(value, equal_to(u'abc'))
     assert_that(isinstance(value, str))
def GetTextPropertyTypes( *args, **kwargs ):
  return [ utils.ToUnicode( p ) for p in vim.eval( 'prop_type_list()' ) ]
Exemple #22
0
def ToUnicode_Int_test():
    value = utils.ToUnicode(123)
    eq_(value, u'123')
    ok_(isinstance(value, str))
def UpdateSignatureHelp(state, signature_info):  # noqa
    if not ShouldUseSignatureHelp():
        return state

    signatures = signature_info.get('signatures') or []

    if not signatures:
        if state.popup_win_id:
            # TODO/FIXME: Should we use popup_hide() instead ?
            vim.eval(f"popup_close( { state.popup_win_id } )")
        return SignatureHelpState(None, SignatureHelpState.INACTIVE)

    if state.state != SignatureHelpState.ACTIVE:
        state.anchor = vimsupport.CurrentLineAndColumn()

    state.state = SignatureHelpState.ACTIVE

    # Generate the buffer as a list of lines
    buf_lines = _MakeSignatureHelpBuffer(signature_info)
    screen_pos = vimsupport.ScreenPositionForLineColumnInWindow(
        vim.current.window,
        state.anchor[0] + 1,  # anchor 0-based
        state.anchor[1] + 1)  # anchor 0-based

    # Simulate 'flip' at the screen boundaries by using screenpos and hiding the
    # signature help menu if it overlaps the completion popup (pum).
    #
    # FIXME: revert to cursor-relative positioning and the 'flip' option when that
    # is implemented (if that is indeed better).

    # By default display above the anchor
    line = int(screen_pos['row']) - 1  # -1 to display above the cur line
    pos = "botleft"

    cursor_line = vimsupport.CurrentLineAndColumn()[0] + 1
    if int(screen_pos['row']) <= len(buf_lines):
        # No room at the top, display below
        line = int(screen_pos['row']) + 1
        pos = "topleft"

    # Don't allow the popup to overlap the cursor
    if (pos == 'topleft' and line < cursor_line
            and line + len(buf_lines) >= cursor_line):
        line = 0

    # Don't allow the popup to overlap the pum
    if line > 0 and GetIntValue('pumvisible()'):
        pum_line = GetIntValue('pum_getpos().row') + 1
        if pos == 'botleft' and pum_line <= line:
            line = 0
        elif (pos == 'topleft' and pum_line >= line and pum_line <
              (line + len(buf_lines))):
            line = 0

    if line <= 0:
        # Nowhere to put it so hide it
        if state.popup_win_id:
            # TODO/FIXME: Should we use popup_hide() instead ?
            vim.eval(f"popup_close( { state.popup_win_id } )")
        return SignatureHelpState(None, SignatureHelpState.INACTIVE)

    if int(screen_pos['curscol']) <= 1:
        col = 1
    else:
        # -1 for padding,
        # -1 for the trigger character inserted (the anchor is set _after_ the
        # character is inserted, so we remove it).
        # FIXME: multi-byte characters would be wrong. Need to set anchor before
        # inserting the char ?
        col = int(screen_pos['curscol']) - 2

    if col <= 0:
        col = 1

    options = {
        "line": line,
        "col": col,
        "pos": pos,
        "wrap": 0,
        # NOTE: We *dont'* use "cursorline" here - that actually uses PMenuSel,
        # which is just too invasive for us (it's more selected item than actual
        # cursorline. So instead, we manually set 'cursorline' in the popup window
        # and enable sytax based on the current file syntax)
        "flip": 1,
        "padding": [0, 1, 0,
                    1],  # Pad 1 char in X axis to match completion menu
    }

    if not state.popup_win_id:
        state.popup_win_id = GetIntValue(
            f'popup_create( { json.dumps( buf_lines ) }, '
            f'{ json.dumps( options ) } )')
    else:
        vim.eval(f'popup_settext( { state.popup_win_id }, '
                 f'{ json.dumps( buf_lines ) } )')

    # Should do nothing if already visible
    vim.eval(
        f'popup_move( { state.popup_win_id }, { json.dumps( options ) } )')
    vim.eval(f'popup_show( { state.popup_win_id } )')

    syntax = utils.ToUnicode(vim.current.buffer.options['syntax'])
    active_signature = int(signature_info.get('activeSignature', 0))
    vim.eval(f"win_execute( { state.popup_win_id }, "
             f"'set syntax={ syntax } cursorline | "
             f"call cursor( [ { active_signature + 1 }, 1 ] )' )")

    return state
 def OnBufferUnload(self, deleted_buffer_file):
     SendEventNotificationAsync(
         'BufferUnload', filepath=utils.ToUnicode(deleted_buffer_file))
Exemple #25
0
def ToUnicode_Bytes_test():
    value = utils.ToUnicode(bytes(b'abc'))
    assert_that(value, equal_to(u'abc'))
    assert_that(isinstance(value, str))
Exemple #26
0
def ToUnicode_None_test():
    value = utils.ToUnicode(None)
    eq_(value, u'')
    ok_(isinstance(value, str))
Exemple #27
0
    def _SetUpServer(self):
        self._available_completers = {}
        self._user_notified_about_crash = False
        self._filetypes_with_keywords_loaded = set()
        self._server_is_ready_with_cache = False
        self._message_poll_requests = {}

        self._latest_completion_request = None
        self._latest_signature_help_request = None
        self._signature_help_available_requests = SigHelpAvailableByFileType()
        self._latest_command_reqeust = None

        self._signature_help_state = signature_help.SignatureHelpState()
        self._user_options = base.GetUserOptions(self._default_options)
        self._omnicomp = OmniCompleter(self._user_options)
        self._buffers = BufferDict(self._user_options)

        self._SetLogLevel()

        hmac_secret = os.urandom(HMAC_SECRET_LENGTH)
        options_dict = dict(self._user_options)
        options_dict['hmac_secret'] = utils.ToUnicode(
            base64.b64encode(hmac_secret))
        options_dict['server_keep_logfiles'] = self._user_options[
            'keep_logfiles']

        # The temp options file is deleted by ycmd during startup.
        with NamedTemporaryFile(delete=False, mode='w+') as options_file:
            json.dump(options_dict, options_file)

        server_port = utils.GetUnusedLocalhostPort()

        BaseRequest.server_location = 'http://127.0.0.1:' + str(server_port)
        BaseRequest.hmac_secret = hmac_secret

        try:
            python_interpreter = paths.PathToPythonInterpreter()
        except RuntimeError as error:
            error_message = (
                f"Unable to start the ycmd server. { str( error ).rstrip( '.' ) }. "
                "Correct the error then restart the server "
                "with ':YcmRestartServer'.")
            self._logger.exception(error_message)
            vimsupport.PostVimMessage(error_message)
            return

        args = [
            python_interpreter,
            paths.PathToServerScript(), f'--port={ server_port }',
            f'--options_file={ options_file.name }',
            f'--log={ self._user_options[ "log_level" ] }',
            f'--idle_suicide_seconds={ SERVER_IDLE_SUICIDE_SECONDS }'
        ]

        self._server_stdout = utils.CreateLogfile(
            SERVER_LOGFILE_FORMAT.format(port=server_port, std='stdout'))
        self._server_stderr = utils.CreateLogfile(
            SERVER_LOGFILE_FORMAT.format(port=server_port, std='stderr'))
        args.append(f'--stdout={ self._server_stdout }')
        args.append(f'--stderr={ self._server_stderr }')

        if self._user_options['keep_logfiles']:
            args.append('--keep_logfiles')

        if 'YCM_WITH_PTVSD' in os.environ:
            args[1:1] = [
                '-m', 'ptvsd', '--host', 'localhost', '--port', '1234',
                '--wait', '--no-subprocesses'
            ]

        self._logger.debug('Starting ycmd with: %s', args)

        self._server_popen = utils.SafePopen(args,
                                             stdin_windows=PIPE,
                                             stdout=PIPE,
                                             stderr=PIPE)