Refactored completion request creation

- OmniCompleter is now more similar to other Completers.
- CompletionRequest doesn't store start_column anymore.
- Calling BuildRequestData only once per request.
This commit is contained in:
Strahinja Val Markovic 2014-05-27 17:38:34 -07:00
parent 876eaf9c33
commit 9100044afc
4 changed files with 37 additions and 63 deletions

View File

@ -663,11 +663,11 @@ function! youcompleteme#Complete( findstart, base )
return -2 return -2
endif endif
py request = ycm_state.CreateCompletionRequest() if !pyeval( 'ycm_state.IsServerAlive()' )
if !pyeval( 'bool(request)' )
return -2 return -2
endif endif
return pyeval( 'request.CompletionStartColumn()' ) py ycm_state.CreateCompletionRequest()
return pyeval( 'base.CompletionStartColumn()' )
else else
return s:GetCompletions() return s:GetCompletions()
endif endif
@ -676,9 +676,12 @@ endfunction
function! youcompleteme#OmniComplete( findstart, base ) function! youcompleteme#OmniComplete( findstart, base )
if a:findstart if a:findstart
if !pyeval( 'ycm_state.IsServerAlive()' )
return -2
endif
let s:omnifunc_mode = 1 let s:omnifunc_mode = 1
py request = ycm_state.CreateCompletionRequest( force_semantic = True ) py ycm_state.CreateCompletionRequest( force_semantic = True )
return pyeval( 'request.CompletionStartColumn()' ) return pyeval( 'base.CompletionStartColumn()' )
else else
return s:GetCompletions() return s:GetCompletions()
endif endif

View File

@ -17,28 +17,16 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
from ycm import base
from ycm import vimsupport from ycm import vimsupport
from ycmd.utils import ToUtf8IfNeeded from ycmd.utils import ToUtf8IfNeeded
from ycm.client.base_request import ( BaseRequest, BuildRequestData, from ycm.client.base_request import BaseRequest, JsonFromFuture
JsonFromFuture )
TIMEOUT_SECONDS = 0.5 TIMEOUT_SECONDS = 0.5
class CompletionRequest( BaseRequest ): class CompletionRequest( BaseRequest ):
def __init__( self, extra_data = None ): def __init__( self, request_data ):
super( CompletionRequest, self ).__init__() super( CompletionRequest, self ).__init__()
self.request_data = request_data
self._completion_start_column = base.CompletionStartColumn()
# This field is also used by the omni_completion_request subclass
self.request_data = BuildRequestData()
if extra_data:
self.request_data.update( extra_data )
def CompletionStartColumn( self ):
return self._completion_start_column
def Start( self ): def Start( self ):

View File

@ -20,8 +20,6 @@
import vim import vim
from ycm import vimsupport from ycm import vimsupport
from ycmd.completers.completer import Completer from ycmd.completers.completer import Completer
from ycmd.request_wrap import RequestWrap
from ycm.client.base_request import BuildRequestData
OMNIFUNC_RETURNED_BAD_VALUE = 'Omnifunc returned bad value to YCM!' OMNIFUNC_RETURNED_BAD_VALUE = 'Omnifunc returned bad value to YCM!'
OMNIFUNC_NOT_LIST = ( 'Omnifunc did not return a list or a dict with a "words" ' OMNIFUNC_NOT_LIST = ( 'Omnifunc did not return a list or a dict with a "words" '
@ -41,17 +39,10 @@ class OmniCompleter( Completer ):
return bool( self.user_options[ 'cache_omnifunc' ] ) return bool( self.user_options[ 'cache_omnifunc' ] )
# We let the caller call this without passing in request_data. This is useful def ShouldUseNow( self, request_data ):
# for figuring out should we even be preparing the "real" request_data in
# omni_completion_request. The real request_data is much bigger and takes
# longer to prepare, and we want to avoid creating it twice.
def ShouldUseNow( self, request_data = None ):
if not self._omnifunc: if not self._omnifunc:
return False return False
if not request_data:
request_data = _BuildRequestDataSubstitute()
if self.ShouldUseCache(): if self.ShouldUseCache():
return super( OmniCompleter, self ).ShouldUseNow( request_data ) return super( OmniCompleter, self ).ShouldUseNow( request_data )
return self.ShouldUseNowInner( request_data ) return self.ShouldUseNowInner( request_data )
@ -103,9 +94,3 @@ class OmniCompleter( Completer ):
def OnFileReadyToParse( self, request_data ): def OnFileReadyToParse( self, request_data ):
self._omnifunc = vim.eval( '&omnifunc' ) self._omnifunc = vim.eval( '&omnifunc' )
def _BuildRequestDataSubstitute():
return RequestWrap( BuildRequestData() )

View File

@ -26,6 +26,7 @@ import base64
from subprocess import PIPE from subprocess import PIPE
from ycm import vimsupport from ycm import vimsupport
from ycmd import utils from ycmd import utils
from ycmd.request_wrap import RequestWrap
from ycm.diagnostic_interface import DiagnosticInterface from ycm.diagnostic_interface import DiagnosticInterface
from ycm.omni_completer import OmniCompleter from ycm.omni_completer import OmniCompleter
from ycm import syntax_parse from ycm import syntax_parse
@ -80,8 +81,8 @@ class YouCompleteMe( object ):
self._user_notified_about_crash = False self._user_notified_about_crash = False
self._diag_interface = DiagnosticInterface( user_options ) self._diag_interface = DiagnosticInterface( user_options )
self._omnicomp = OmniCompleter( user_options ) self._omnicomp = OmniCompleter( user_options )
self._latest_completion_request = None
self._latest_file_parse_request = None self._latest_file_parse_request = None
self._latest_completion_request = None
self._server_stdout = None self._server_stdout = None
self._server_stderr = None self._server_stderr = None
self._server_popen = None self._server_popen = None
@ -128,14 +129,14 @@ class YouCompleteMe( object ):
self._NotifyUserIfServerCrashed() self._NotifyUserIfServerCrashed()
def _IsServerAlive( self ): def IsServerAlive( self ):
returncode = self._server_popen.poll() returncode = self._server_popen.poll()
# When the process hasn't finished yet, poll() returns None. # When the process hasn't finished yet, poll() returns None.
return returncode is None return returncode is None
def _NotifyUserIfServerCrashed( self ): def _NotifyUserIfServerCrashed( self ):
if self._user_notified_about_crash or self._IsServerAlive(): if self._user_notified_about_crash or self.IsServerAlive():
return return
self._user_notified_about_crash = True self._user_notified_about_crash = True
if self._server_stderr: if self._server_stderr:
@ -158,7 +159,7 @@ class YouCompleteMe( object ):
def _ServerCleanup( self ): def _ServerCleanup( self ):
if self._IsServerAlive(): if self.IsServerAlive():
self._server_popen.terminate() self._server_popen.terminate()
@ -170,32 +171,29 @@ class YouCompleteMe( object ):
def CreateCompletionRequest( self, force_semantic = False ): def CreateCompletionRequest( self, force_semantic = False ):
# We have to store a reference to the newly created CompletionRequest request_data = BuildRequestData()
# 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 if ( not self.NativeFiletypeCompletionAvailable() and
self.CurrentFiletypeCompletionEnabled() and self.CurrentFiletypeCompletionEnabled() ):
self._omnicomp.ShouldUseNow() ): wrapped_request_data = RequestWrap( request_data )
self._latest_completion_request = OmniCompletionRequest( self._omnicomp ) if self._omnicomp.ShouldUseNow( wrapped_request_data ):
else: self._latest_completion_request = OmniCompletionRequest(
extra_data = {} self._omnicomp, wrapped_request_data )
self._AddExtraConfDataIfNeeded( extra_data ) return self._latest_completion_request
if force_semantic:
extra_data[ 'force_semantic' ] = True
self._latest_completion_request = ( CompletionRequest( extra_data ) self._AddExtraConfDataIfNeeded( request_data )
if self._IsServerAlive() else if force_semantic:
None ) request_data[ 'force_semantic' ] = True
self._latest_completion_request = CompletionRequest( request_data )
return self._latest_completion_request return self._latest_completion_request
def SendCommandRequest( self, arguments, completer ): def SendCommandRequest( self, arguments, completer ):
if self._IsServerAlive(): if self.IsServerAlive():
return SendCommandRequest( arguments, completer ) return SendCommandRequest( arguments, completer )
def GetDefinedSubcommands( self ): def GetDefinedSubcommands( self ):
if self._IsServerAlive(): if self.IsServerAlive():
try: try:
return BaseRequest.PostDataToHandler( BuildRequestData(), return BaseRequest.PostDataToHandler( BuildRequestData(),
'defined_subcommands' ) 'defined_subcommands' )
@ -226,7 +224,7 @@ class YouCompleteMe( object ):
def OnFileReadyToParse( self ): def OnFileReadyToParse( self ):
self._omnicomp.OnFileReadyToParse( None ) self._omnicomp.OnFileReadyToParse( None )
if not self._IsServerAlive(): if not self.IsServerAlive():
self._NotifyUserIfServerCrashed() self._NotifyUserIfServerCrashed()
extra_data = {} extra_data = {}
@ -240,14 +238,14 @@ class YouCompleteMe( object ):
def OnBufferUnload( self, deleted_buffer_file ): def OnBufferUnload( self, deleted_buffer_file ):
if not self._IsServerAlive(): if not self.IsServerAlive():
return return
SendEventNotificationAsync( 'BufferUnload', SendEventNotificationAsync( 'BufferUnload',
{ 'unloaded_buffer': deleted_buffer_file } ) { 'unloaded_buffer': deleted_buffer_file } )
def OnBufferVisit( self ): def OnBufferVisit( self ):
if not self._IsServerAlive(): if not self.IsServerAlive():
return return
extra_data = {} extra_data = {}
_AddUltiSnipsDataIfNeeded( extra_data ) _AddUltiSnipsDataIfNeeded( extra_data )
@ -255,7 +253,7 @@ class YouCompleteMe( object ):
def OnInsertLeave( self ): def OnInsertLeave( self ):
if not self._IsServerAlive(): if not self.IsServerAlive():
return return
SendEventNotificationAsync( 'InsertLeave' ) SendEventNotificationAsync( 'InsertLeave' )
@ -269,7 +267,7 @@ class YouCompleteMe( object ):
def OnCurrentIdentifierFinished( self ): def OnCurrentIdentifierFinished( self ):
if not self._IsServerAlive(): if not self.IsServerAlive():
return return
SendEventNotificationAsync( 'CurrentIdentifierFinished' ) SendEventNotificationAsync( 'CurrentIdentifierFinished' )
@ -302,7 +300,7 @@ class YouCompleteMe( object ):
def ShowDetailedDiagnostic( self ): def ShowDetailedDiagnostic( self ):
if not self._IsServerAlive(): if not self.IsServerAlive():
return return
try: try:
debug_info = BaseRequest.PostDataToHandler( BuildRequestData(), debug_info = BaseRequest.PostDataToHandler( BuildRequestData(),
@ -314,7 +312,7 @@ class YouCompleteMe( object ):
def DebugInfo( self ): def DebugInfo( self ):
if self._IsServerAlive(): if self.IsServerAlive():
debug_info = BaseRequest.PostDataToHandler( BuildRequestData(), debug_info = BaseRequest.PostDataToHandler( BuildRequestData(),
'debug_info' ) 'debug_info' )
else: else: