예제 #1
0
class CompletionRequest(BaseRequest):
    def __init__(self, request_data):
        super(CompletionRequest, self).__init__()
        self.request_data = request_data
        self._response_future = None
        self._response = {'completions': [], 'completion_start_column': -1}

    def Start(self):
        self._response_future = self.PostDataToHandlerAsync(
            self.request_data, 'completions')

    def Done(self):
        return bool(self._response_future) and self._response_future.done()

    def RawResponse(self):
        if not self._response_future:
            return self._response

        with HandleServerException(truncate=True):
            self._response = JsonFromFuture(self._response_future)

            # Vim may not be able to convert the 'errors' entry to its internal format
            # so we remove it from the response.
            errors = self._response.pop('errors', [])
            for e in errors:
                with HandleServerException(truncate=True):
                    raise MakeServerException(e)

        return self._response

    def Response(self):
        response = self.RawResponse()
        response['completions'] = _ConvertCompletionDatasToVimDatas(
            response['completions'])
        return response
예제 #2
0
class CompletionRequest( BaseRequest ):
  def __init__( self, request_data ):
    super( CompletionRequest, self ).__init__()
    self.request_data = request_data
    self._response_future = None
    self._response = { 'completions': [], 'completion_start_column': -1 }


  def Start( self ):
    self._response_future = self.PostDataToHandlerAsync( self.request_data,
                                                         'completions' )


  def Done( self ):
    return bool( self._response_future ) and self._response_future.done()


  def RawResponse( self ):
    if not self._response_future:
      return self._response

    with HandleServerException( truncate = True ):
      self._response = JsonFromFuture( self._response_future )

      # Vim may not be able to convert the 'errors' entry to its internal format
      # so we remove it from the response.
      errors = self._response.pop( 'errors', [] )
      for e in errors:
        with HandleServerException( truncate = True ):
          raise MakeServerException( e )

    return self._response


  def Response( self ):
    response = self.RawResponse()
    response[ 'completions' ] = _ConvertCompletionDatasToVimDatas(
        response[ 'completions' ] )
    return response
예제 #3
0
class CompletionRequest(BaseRequest):
    def __init__(self, request_data):
        super(CompletionRequest, self).__init__()
        self.request_data = request_data
        self._response_future = None
        self._response = {'completions': [], 'completion_start_column': -1}
        self._complete_done_hooks = {
            'cs': self._OnCompleteDone_Csharp,
            'java': self._OnCompleteDone_Java,
        }

    def Start(self):
        self._response_future = self.PostDataToHandlerAsync(
            self.request_data, 'completions')

    def Done(self):
        return bool(self._response_future) and self._response_future.done()

    def RawResponse(self):
        if not self._response_future:
            return self._response

        with HandleServerException(truncate=True):
            self._response = JsonFromFuture(self._response_future)

            # Vim may not be able to convert the 'errors' entry to its internal format
            # so we remove it from the response.
            errors = self._response.pop('errors', [])
            for e in errors:
                with HandleServerException(truncate=True):
                    raise MakeServerException(e)

        return self._response

    def Response(self):
        response = self.RawResponse()
        response['completions'] = _ConvertCompletionDatasToVimDatas(
            response['completions'])
        return response

    def OnCompleteDone(self):
        if not self.Done():
            return

        complete_done_actions = self._GetCompleteDoneHooks()
        for action in complete_done_actions:
            action()

    def _GetCompleteDoneHooks(self):
        filetypes = vimsupport.CurrentFiletypes()
        for key, value in iteritems(self._complete_done_hooks):
            if key in filetypes:
                yield value

    def _GetCompletionsUserMayHaveCompleted(self):
        completed_item = vimsupport.GetVariableValue('v:completed_item')

        # If Vim supports user_data (8.0.1493 or later), we actually know the
        # _exact_ element that was selected, having put its index in the
        # user_data field. Otherwise, we have to guess by matching the values in the
        # completed item and the list of completions. Sometimes this returns
        # multiple possibilities, which is essentially unresolvable.
        if 'user_data' not in completed_item:
            completions = self.RawResponse()['completions']
            return _FilterToMatchingCompletions(completed_item, completions)

        if completed_item['user_data']:
            completions = self.RawResponse()['completions']
            return [completions[int(completed_item['user_data'])]]

        return []

    def _OnCompleteDone_Csharp(self):
        completions = self._GetCompletionsUserMayHaveCompleted()
        namespaces = [_GetRequiredNamespaceImport(c) for c in completions]
        namespaces = [n for n in namespaces if n]
        if not namespaces:
            return

        if len(namespaces) > 1:
            choices = [
                "{0} {1}".format(i + 1, n) for i, n in enumerate(namespaces)
            ]
            choice = vimsupport.PresentDialog("Insert which namespace:",
                                              choices)
            if choice < 0:
                return
            namespace = namespaces[choice]
        else:
            namespace = namespaces[0]

        vimsupport.InsertNamespace(namespace)

    def _OnCompleteDone_Java(self):
        completions = self._GetCompletionsUserMayHaveCompleted()
        fixit_completions = [_GetFixItCompletion(c) for c in completions]
        fixit_completions = [f for f in fixit_completions if f]
        if not fixit_completions:
            return

        # If we have user_data in completions (8.0.1493 or later), then we would
        # only ever return max. 1 completion here. However, if we had to guess, it
        # is possible that we matched multiple completion items (e.g. for overloads,
        # or similar classes in multiple packages). In any case, rather than
        # prompting the user and disturbing her workflow, we just apply the first
        # one. This might be wrong, but the solution is to use a (very) new version
        # of Vim which supports user_data on completion items
        fixit_completion = fixit_completions[0]

        for fixit in fixit_completion:
            vimsupport.ReplaceChunks(fixit['chunks'], silent=True)
예제 #4
0
class CompletionRequest( BaseRequest ):
  def __init__( self, request_data ):
    super( CompletionRequest, self ).__init__()
    self.request_data = request_data
    self._response_future = None
    self._response = { 'completions': [], 'completion_start_column': -1 }
    self._complete_done_hooks = {
      'cs': self._OnCompleteDone_Csharp,
      'java': self._OnCompleteDone_Java,
    }


  def Start( self ):
    self._response_future = self.PostDataToHandlerAsync( self.request_data,
                                                         'completions' )


  def Done( self ):
    return bool( self._response_future ) and self._response_future.done()


  def RawResponse( self ):
    if not self._response_future:
      return self._response

    with HandleServerException( truncate = True ):
      self._response = JsonFromFuture( self._response_future )

      # Vim may not be able to convert the 'errors' entry to its internal format
      # so we remove it from the response.
      errors = self._response.pop( 'errors', [] )
      for e in errors:
        with HandleServerException( truncate = True ):
          raise MakeServerException( e )

    return self._response


  def Response( self ):
    response = self.RawResponse()
    response[ 'completions' ] = _ConvertCompletionDatasToVimDatas(
        response[ 'completions' ] )
    return response


  def OnCompleteDone( self ):
    if not self.Done():
      return

    complete_done_actions = self._GetCompleteDoneHooks()
    for action in complete_done_actions:
      action()


  def _GetCompleteDoneHooks( self ):
    filetypes = vimsupport.CurrentFiletypes()
    for key, value in iteritems( self._complete_done_hooks ):
      if key in filetypes:
        yield value


  def _GetCompletionsUserMayHaveCompleted( self ):
    completed_item = vimsupport.GetVariableValue( 'v:completed_item' )
    completions = self.RawResponse()[ 'completions' ]

    if 'user_data' in completed_item and completed_item[ 'user_data' ]:
      # Vim supports user_data (8.0.1493) or later, so we actually know the
      # _exact_ element that was selected, having put its index in the
      # user_data field.
      return [ completions[ int( completed_item[ 'user_data' ] ) ] ]

    # Otherwise, we have to guess by matching the values in the completed item
    # and the list of completions. Sometimes this returns multiple
    # possibilities, which is essentially unresolvable.

    result = _FilterToMatchingCompletions( completed_item, completions, True )
    result = list( result )

    if result:
      return result

    if _HasCompletionsThatCouldBeCompletedWithMoreText( completed_item,
                                                        completions ):
      # Since the way that YCM works leads to CompleteDone called on every
      # character, return blank if the completion might not be done. This won't
      # match if the completion is ended with typing a non-keyword character.
      return []

    result = _FilterToMatchingCompletions( completed_item, completions, False )

    return list( result )


  def _OnCompleteDone_Csharp( self ):
    completions = self._GetCompletionsUserMayHaveCompleted()
    namespaces = [ _GetRequiredNamespaceImport( c ) for c in completions ]
    namespaces = [ n for n in namespaces if n ]
    if not namespaces:
      return

    if len( namespaces ) > 1:
      choices = [ "{0} {1}".format( i + 1, n )
                  for i, n in enumerate( namespaces ) ]
      choice = vimsupport.PresentDialog( "Insert which namespace:", choices )
      if choice < 0:
        return
      namespace = namespaces[ choice ]
    else:
      namespace = namespaces[ 0 ]

    vimsupport.InsertNamespace( namespace )


  def _OnCompleteDone_Java( self ):
    completions = self._GetCompletionsUserMayHaveCompleted()
    fixit_completions = [ _GetFixItCompletion( c ) for c in completions ]
    fixit_completions = [ f for f in fixit_completions if f ]
    if not fixit_completions:
      return

    # If we have user_data in completions (8.0.1493 or later), then we would
    # only ever return max. 1 completion here. However, if we had to guess, it
    # is possible that we matched multiple completion items (e.g. for overloads,
    # or similar classes in multiple packages). In any case, rather than
    # prompting the user and disturbing her workflow, we just apply the first
    # one. This might be wrong, but the solution is to use a (very) new version
    # of Vim which supports user_data on completion items
    fixit_completion = fixit_completions[ 0 ]

    for fixit in fixit_completion:
      vimsupport.ReplaceChunks( fixit[ 'chunks' ], silent=True )