Beispiel #1
0
 def __init__(self, user_options):
     self._user_options = user_options
     self._omnicomp = OmniCompleter(user_options)
     self._latest_completion_request = None
     self._latest_file_parse_request = None
     self._server_stdout = None
     self._server_stderr = None
     self._server_popen = None
     self._filetypes_with_keywords_loaded = set()
     self._temp_options_filename = None
     self._SetupServer()
Beispiel #2
0
 def __init__(self, user_options):
     self._user_options = user_options
     self._user_notified_about_crash = False
     self._diag_interface = DiagnosticInterface(user_options)
     self._omnicomp = OmniCompleter(user_options)
     self._latest_completion_request = None
     self._latest_file_parse_request = None
     self._server_stdout = None
     self._server_stderr = None
     self._server_popen = None
     self._filetypes_with_keywords_loaded = set()
     self._ycmd_keepalive = YcmdKeepalive()
     self._SetupServer()
     self._ycmd_keepalive.Start()
Beispiel #3
0
class YouCompleteMe(object):
    def __init__(self, user_options):
        self._user_options = user_options
        self._omnicomp = OmniCompleter(user_options)
        self._latest_completion_request = None
        self._latest_file_parse_request = None
        self._server_stdout = None
        self._server_stderr = None
        self._server_popen = None
        self._filetypes_with_keywords_loaded = set()
        self._temp_options_filename = None
        self._SetupServer()

    def _SetupServer(self):
        server_port = utils.GetUnusedLocalhostPort()
        with tempfile.NamedTemporaryFile(delete=False) as options_file:
            self._temp_options_filename = options_file.name
            json.dump(dict(self._user_options), options_file)
            args = [
                utils.PathToPythonInterpreter(),
                _PathToServerScript(), '--port={0}'.format(server_port),
                '--options_file={0}'.format(options_file.name),
                '--log={0}'.format(self._user_options['server_log_level']),
                '--idle_suicide_seconds={0}'.format(
                    self._user_options['server_idle_suicide_seconds'])
            ]

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

            if self._user_options['server_use_vim_stdout']:
                self._server_popen = subprocess.Popen(args)
            else:
                filename_format = os.path.join(utils.PathToTempDir(),
                                               'server_{port}_{std}.log')

                self._server_stdout = filename_format.format(port=server_port,
                                                             std='stdout')
                self._server_stderr = filename_format.format(port=server_port,
                                                             std='stderr')
                # We need this on Windows otherwise bad things happen. See issue #637.
                stdin = subprocess.PIPE if utils.OnWindows() else None

                with open(self._server_stderr, 'w') as fstderr:
                    with open(self._server_stdout, 'w') as fstdout:
                        self._server_popen = subprocess.Popen(args,
                                                              stdin=stdin,
                                                              stdout=fstdout,
                                                              stderr=fstderr)
        self._NotifyUserIfServerCrashed()

    def _IsServerAlive(self):
        returncode = self._server_popen.poll()
        # When the process hasn't finished yet, poll() returns None.
        return returncode is None

    def _NotifyUserIfServerCrashed(self):
        if self._IsServerAlive():
            return
        if self._server_stderr:
            with open(self._server_stderr, 'r') as server_stderr_file:
                error_output = ''.join(server_stderr_file.readlines()
                                       [:-NUM_YCMD_STDERR_LINES_ON_CRASH])
                vimsupport.PostMultiLineNotice(
                    SERVER_CRASH_MESSAGE_STDERR_FILE + error_output)
        else:
            vimsupport.PostVimMessage(SERVER_CRASH_MESSAGE_SAME_STDERR)

    def ServerPid(self):
        if not self._server_popen:
            return -1
        return self._server_popen.pid

    def RestartServer(self):
        vimsupport.PostVimMessage('Restarting ycmd server...')
        self.OnVimLeave()
        self._SetupServer()

    def CreateCompletionRequest(self, force_semantic=False):
        # We have to store a reference to the newly created CompletionRequest
        # because VimScript can't store a reference to a Python object across
        # function calls... Thus we need to keep this request somewhere.
        if (not self.NativeFiletypeCompletionAvailable()
                and self.CurrentFiletypeCompletionEnabled()
                and self._omnicomp.ShouldUseNow()):
            self._latest_completion_request = OmniCompletionRequest(
                self._omnicomp)
        else:
            extra_data = {}
            self._AddExtraConfDataIfNeeded(extra_data)
            if force_semantic:
                extra_data['force_semantic'] = True

            self._latest_completion_request = (CompletionRequest(extra_data) if
                                               self._IsServerAlive() else None)
        return self._latest_completion_request

    def SendCommandRequest(self, arguments, completer):
        if self._IsServerAlive():
            return SendCommandRequest(arguments, completer)

    def GetDefinedSubcommands(self):
        if self._IsServerAlive():
            return BaseRequest.PostDataToHandler(BuildRequestData(),
                                                 'defined_subcommands')
        else:
            return []

    def GetCurrentCompletionRequest(self):
        return self._latest_completion_request

    def GetOmniCompleter(self):
        return self._omnicomp

    def NativeFiletypeCompletionAvailable(self):
        return any([
            FiletypeCompleterExistsForFiletype(x)
            for x in vimsupport.CurrentFiletypes()
        ])

    def NativeFiletypeCompletionUsable(self):
        return (self.CurrentFiletypeCompletionEnabled()
                and self.NativeFiletypeCompletionAvailable())

    def OnFileReadyToParse(self):
        self._omnicomp.OnFileReadyToParse(None)

        if not self._IsServerAlive():
            self._NotifyUserIfServerCrashed()

        extra_data = {}
        self._AddTagsFilesIfNeeded(extra_data)
        self._AddSyntaxDataIfNeeded(extra_data)
        self._AddExtraConfDataIfNeeded(extra_data)

        self._latest_file_parse_request = EventNotification(
            'FileReadyToParse', extra_data)
        self._latest_file_parse_request.Start()

    def OnBufferUnload(self, deleted_buffer_file):
        if not self._IsServerAlive():
            return
        SendEventNotificationAsync('BufferUnload',
                                   {'unloaded_buffer': deleted_buffer_file})

    def OnBufferVisit(self):
        if not self._IsServerAlive():
            return
        extra_data = {}
        _AddUltiSnipsDataIfNeeded(extra_data)
        SendEventNotificationAsync('BufferVisit', extra_data)

    def OnInsertLeave(self):
        if not self._IsServerAlive():
            return
        SendEventNotificationAsync('InsertLeave')

    def OnVimLeave(self):
        if self._IsServerAlive():
            self._server_popen.terminate()
        os.remove(self._temp_options_filename)

        if not self._user_options['server_keep_logfiles']:
            if self._server_stderr:
                os.remove(self._server_stderr)
            if self._server_stdout:
                os.remove(self._server_stdout)

    def OnCurrentIdentifierFinished(self):
        if not self._IsServerAlive():
            return
        SendEventNotificationAsync('CurrentIdentifierFinished')

    def DiagnosticsForCurrentFileReady(self):
        return bool(self._latest_file_parse_request
                    and self._latest_file_parse_request.Done())

    def GetDiagnosticsFromStoredRequest(self):
        if self.DiagnosticsForCurrentFileReady():
            to_return = self._latest_file_parse_request.Response()
            # We set the diagnostics request to None because we want to prevent
            # Syntastic from repeatedly refreshing the buffer with the same diags.
            # Setting this to None makes DiagnosticsForCurrentFileReady return False
            # until the next request is created.
            self._latest_file_parse_request = None
            return to_return
        return []

    def ShowDetailedDiagnostic(self):
        if not self._IsServerAlive():
            return
        try:
            debug_info = BaseRequest.PostDataToHandler(BuildRequestData(),
                                                       'detailed_diagnostic')
            if 'message' in debug_info:
                vimsupport.EchoText(debug_info['message'])
        except ServerError as e:
            vimsupport.PostVimMessage(str(e))

    def DebugInfo(self):
        if self._IsServerAlive():
            debug_info = BaseRequest.PostDataToHandler(BuildRequestData(),
                                                       'debug_info')
        else:
            debug_info = 'Server crashed, no debug info from server'
        debug_info += '\nServer running at: {0}'.format(
            BaseRequest.server_location)
        debug_info += '\nServer process ID: {0}'.format(self._server_popen.pid)
        if self._server_stderr or self._server_stdout:
            debug_info += '\nServer logfiles:\n  {0}\n  {1}'.format(
                self._server_stdout, self._server_stderr)

        return debug_info

    def CurrentFiletypeCompletionEnabled(self):
        filetypes = vimsupport.CurrentFiletypes()
        filetype_to_disable = self._user_options[
            'filetype_specific_completion_to_disable']
        return not all([x in filetype_to_disable for x in filetypes])

    def _AddSyntaxDataIfNeeded(self, extra_data):
        if not self._user_options['seed_identifiers_with_syntax']:
            return
        filetype = vimsupport.CurrentFiletypes()[0]
        if filetype in self._filetypes_with_keywords_loaded:
            return

        self._filetypes_with_keywords_loaded.add(filetype)
        extra_data['syntax_keywords'] = list(
            syntax_parse.SyntaxKeywordsForCurrentBuffer())

    def _AddTagsFilesIfNeeded(self, extra_data):
        def GetTagFiles():
            tag_files = vim.eval('tagfiles()')
            current_working_directory = os.getcwd()
            return [
                os.path.join(current_working_directory, x) for x in tag_files
            ]

        if not self._user_options['collect_identifiers_from_tags_files']:
            return
        extra_data['tag_files'] = GetTagFiles()

    def _AddExtraConfDataIfNeeded(self, extra_data):
        def BuildExtraConfData(extra_conf_vim_data):
            return dict((expr, vimsupport.VimExpressionToPythonType(expr))
                        for expr in extra_conf_vim_data)

        extra_conf_vim_data = self._user_options['extra_conf_vim_data']
        if extra_conf_vim_data:
            extra_data['extra_conf_data'] = BuildExtraConfData(
                extra_conf_vim_data)
Beispiel #4
0
 def __init__(self):
     self.gencomp = GeneralCompleterStore()
     self.omnicomp = OmniCompleter()
     self.filetype_completers = {}