Merge remote-tracking branch 'origin/master' into CsAddImport
This commit is contained in:
commit
2a41101955
@ -1,7 +1,7 @@
|
||||
YouCompleteMe: a code-completion engine for Vim
|
||||
===============================================
|
||||
|
||||
[![Build Status](https://travis-ci.org/Valloric/YouCompleteMe.png?branch=master)](https://travis-ci.org/Valloric/YouCompleteMe)
|
||||
[![Build Status](https://travis-ci.org/Valloric/YouCompleteMe.svg?branch=master)](https://travis-ci.org/Valloric/YouCompleteMe)
|
||||
|
||||
- [Intro](#intro)
|
||||
- [Installation](#installation)
|
||||
@ -26,7 +26,6 @@ YouCompleteMe: a code-completion engine for Vim
|
||||
- [Options](#options)
|
||||
- [FAQ](#faq)
|
||||
- [Contact](#contact)
|
||||
- [Project Management](#project-management)
|
||||
- [License](#license)
|
||||
|
||||
Intro
|
||||
|
@ -159,7 +159,6 @@ Introduction ~
|
||||
- Options
|
||||
- FAQ
|
||||
- Contact
|
||||
- Project Management
|
||||
- License
|
||||
|
||||
===============================================================================
|
||||
@ -2322,7 +2321,7 @@ contributors
|
||||
References ~
|
||||
|
||||
[1] https://travis-ci.org/Valloric/YouCompleteMe
|
||||
[2] https://travis-ci.org/Valloric/YouCompleteMe.png?branch=master
|
||||
[2] https://travis-ci.org/Valloric/YouCompleteMe.svg?branch=master
|
||||
[3] http://clang.llvm.org/
|
||||
[4] https://github.com/davidhalter/jedi
|
||||
[5] https://github.com/nosami/OmniSharpServer
|
||||
|
@ -22,6 +22,7 @@ from ycm.client.base_request import BaseRequest, BuildRequestData, ServerError
|
||||
from ycm import vimsupport
|
||||
from ycmd.utils import ToUtf8IfNeeded
|
||||
|
||||
|
||||
def _EnsureBackwardsCompatibility( arguments ):
|
||||
if arguments and arguments[ 0 ] == 'GoToDefinitionElseDeclaration':
|
||||
arguments[ 0 ] = 'GoTo'
|
||||
@ -57,6 +58,7 @@ class CommandRequest( BaseRequest ):
|
||||
def Response( self ):
|
||||
return self._response
|
||||
|
||||
|
||||
def RunPostCommandActionsIfNeeded( self ):
|
||||
if not self.Done() or not self._response:
|
||||
return
|
||||
@ -68,6 +70,7 @@ class CommandRequest( BaseRequest ):
|
||||
elif 'message' in self._response:
|
||||
self._HandleMessageResponse()
|
||||
|
||||
|
||||
def _HandleGotoResponse( self ):
|
||||
if isinstance( self._response, list ):
|
||||
defs = [ _BuildQfListItem( x ) for x in self._response ]
|
||||
@ -78,53 +81,24 @@ class CommandRequest( BaseRequest ):
|
||||
self._response[ 'line_num' ],
|
||||
self._response[ 'column_num' ] )
|
||||
|
||||
|
||||
def _HandleFixitResponse( self ):
|
||||
if not len( self._response[ 'fixits' ] ):
|
||||
vimsupport.EchoText( "No fixits found for current line" )
|
||||
else:
|
||||
fixit = self._response[ 'fixits' ][ 0 ]
|
||||
chunks = self._response[ 'fixits' ][ 0 ][ 'chunks' ]
|
||||
|
||||
# We need to track the difference in length, but ensuring we apply fixes
|
||||
# in ascending order of insertion point.
|
||||
fixit[ 'chunks' ].sort( key = lambda chunk: (
|
||||
str(chunk[ 'range' ][ 'start' ][ 'line_num' ])
|
||||
+ ','
|
||||
+ str(chunk[ 'range' ][ 'start' ][ 'column_num' ])
|
||||
))
|
||||
vimsupport.ReplaceChunksList( chunks )
|
||||
|
||||
# Remember the line number we're processing. Negative line number means we
|
||||
# haven't processed any lines yet (by nature of being not equal to any
|
||||
# real line number).
|
||||
last_line = -1
|
||||
vimsupport.EchoTextVimWidth( "FixIt applied "
|
||||
+ str( len( chunks ) )
|
||||
+ " changes" )
|
||||
|
||||
# Counter of changes applied, so the user has a mental picture of the
|
||||
# undo history this change is creating.
|
||||
num_fixed = 0
|
||||
line_delta = 0
|
||||
for chunk in fixit[ 'chunks' ]:
|
||||
if chunk[ 'range' ][ 'start' ][ 'line_num' ] != last_line:
|
||||
# If this chunk is on a different line than the previous chunk,
|
||||
# then ignore previous deltas (as offsets won't have changed).
|
||||
last_line = chunk[ 'range' ][ 'end' ][ 'line_num' ]
|
||||
char_delta = 0
|
||||
|
||||
(new_line_delta, new_char_delta) = vimsupport.ReplaceChunk(
|
||||
chunk[ 'range' ][ 'start' ],
|
||||
chunk[ 'range' ][ 'end' ],
|
||||
chunk[ 'replacement_text' ],
|
||||
line_delta, char_delta )
|
||||
line_delta += new_line_delta
|
||||
char_delta += new_char_delta
|
||||
|
||||
num_fixed = num_fixed + 1
|
||||
|
||||
vimsupport.EchoTextVimWidth("FixIt applied "
|
||||
+ str(num_fixed)
|
||||
+ " changes")
|
||||
|
||||
def _HandleMessageResponse( self ):
|
||||
vimsupport.EchoText( self._response[ 'message' ] )
|
||||
|
||||
|
||||
def SendCommandRequest( arguments, completer ):
|
||||
request = CommandRequest( arguments, completer )
|
||||
# This is a blocking call.
|
||||
|
@ -21,6 +21,7 @@ from ycmd.utils import ToUtf8IfNeeded
|
||||
from ycm.client.base_request import ( BaseRequest, JsonFromFuture,
|
||||
HandleServerException,
|
||||
MakeServerException )
|
||||
import os
|
||||
|
||||
TIMEOUT_SECONDS = 0.5
|
||||
|
||||
@ -67,6 +68,13 @@ def ConvertCompletionDataToVimData( completion_data ):
|
||||
'dup' : 1,
|
||||
}
|
||||
|
||||
if ( 'extra_data' in completion_data and
|
||||
'doc_string' in completion_data[ 'extra_data' ] ):
|
||||
doc_string = ToUtf8IfNeeded(
|
||||
completion_data[ 'extra_data' ][ 'doc_string' ] )
|
||||
else:
|
||||
doc_string = ""
|
||||
|
||||
if 'menu_text' in completion_data:
|
||||
vim_data[ 'abbr' ] = ToUtf8IfNeeded( completion_data[ 'menu_text' ] )
|
||||
if 'extra_menu_info' in completion_data:
|
||||
@ -76,6 +84,10 @@ def ConvertCompletionDataToVimData( completion_data ):
|
||||
completion_data[ 'kind' ] )[ 0 ].lower()
|
||||
if 'detailed_info' in completion_data:
|
||||
vim_data[ 'info' ] = ToUtf8IfNeeded( completion_data[ 'detailed_info' ] )
|
||||
if doc_string:
|
||||
vim_data[ 'info' ] += os.linesep + doc_string
|
||||
elif doc_string:
|
||||
vim_data[ 'info' ] = doc_string
|
||||
|
||||
return vim_data
|
||||
|
||||
|
0
python/ycm/client/tests/__init__.py
Normal file
0
python/ycm/client/tests/__init__.py
Normal file
134
python/ycm/client/tests/completion_request_test.py
Normal file
134
python/ycm/client/tests/completion_request_test.py
Normal file
@ -0,0 +1,134 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2015 YouCompleteMe Contributors
|
||||
#
|
||||
# This file is part of YouCompleteMe.
|
||||
#
|
||||
# YouCompleteMe is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# YouCompleteMe is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from nose.tools import eq_
|
||||
from ycm.test_utils import MockVimModule
|
||||
vim_mock = MockVimModule()
|
||||
import os
|
||||
|
||||
from .. import completion_request
|
||||
|
||||
class ConvertCompletionResponseToVimDatas_test:
|
||||
""" This class tests the
|
||||
completion_request._ConvertCompletionResponseToVimDatas method """
|
||||
|
||||
def _Check( self, completion_data, expected_vim_data ):
|
||||
vim_data = completion_request._ConvertCompletionDataToVimData(
|
||||
completion_data )
|
||||
|
||||
try:
|
||||
eq_( expected_vim_data, vim_data )
|
||||
except:
|
||||
print "Expected:\n'{0}'\nwhen parsing:\n'{1}'\nBut found:\n'{2}'".format(
|
||||
expected_vim_data,
|
||||
completion_data,
|
||||
vim_data )
|
||||
raise
|
||||
|
||||
|
||||
def All_Fields_test( self ):
|
||||
self._Check( {
|
||||
'insertion_text': 'INSERTION TEXT',
|
||||
'menu_text': 'MENU TEXT',
|
||||
'extra_menu_info': 'EXTRA MENU INFO',
|
||||
'kind': 'K',
|
||||
'detailed_info': 'DETAILED INFO',
|
||||
'extra_data': {
|
||||
'doc_string': 'DOC STRING',
|
||||
},
|
||||
}, {
|
||||
'word': 'INSERTION TEXT',
|
||||
'abbr': 'MENU TEXT',
|
||||
'menu': 'EXTRA MENU INFO',
|
||||
'kind': 'k',
|
||||
'info': 'DETAILED INFO' + os.linesep + 'DOC STRING',
|
||||
'dup' : 1,
|
||||
} )
|
||||
|
||||
|
||||
def Just_Detailed_Info_test( self ):
|
||||
self._Check( {
|
||||
'insertion_text': 'INSERTION TEXT',
|
||||
'menu_text': 'MENU TEXT',
|
||||
'extra_menu_info': 'EXTRA MENU INFO',
|
||||
'kind': 'K',
|
||||
'detailed_info': 'DETAILED INFO',
|
||||
}, {
|
||||
'word': 'INSERTION TEXT',
|
||||
'abbr': 'MENU TEXT',
|
||||
'menu': 'EXTRA MENU INFO',
|
||||
'kind': 'k',
|
||||
'info': 'DETAILED INFO',
|
||||
'dup' : 1,
|
||||
} )
|
||||
|
||||
|
||||
def Just_Doc_String_test( self ):
|
||||
self._Check( {
|
||||
'insertion_text': 'INSERTION TEXT',
|
||||
'menu_text': 'MENU TEXT',
|
||||
'extra_menu_info': 'EXTRA MENU INFO',
|
||||
'kind': 'K',
|
||||
'extra_data': {
|
||||
'doc_string': 'DOC STRING',
|
||||
},
|
||||
}, {
|
||||
'word': 'INSERTION TEXT',
|
||||
'abbr': 'MENU TEXT',
|
||||
'menu': 'EXTRA MENU INFO',
|
||||
'kind': 'k',
|
||||
'info': 'DOC STRING',
|
||||
'dup' : 1,
|
||||
} )
|
||||
|
||||
|
||||
def Extra_Info_No_Doc_String_test( self ):
|
||||
self._Check( {
|
||||
'insertion_text': 'INSERTION TEXT',
|
||||
'menu_text': 'MENU TEXT',
|
||||
'extra_menu_info': 'EXTRA MENU INFO',
|
||||
'kind': 'K',
|
||||
'extra_data': {
|
||||
},
|
||||
}, {
|
||||
'word': 'INSERTION TEXT',
|
||||
'abbr': 'MENU TEXT',
|
||||
'menu': 'EXTRA MENU INFO',
|
||||
'kind': 'k',
|
||||
'dup' : 1,
|
||||
} )
|
||||
|
||||
|
||||
def Extra_Info_No_Doc_String_With_Detailed_Info_test( self ):
|
||||
self._Check( {
|
||||
'insertion_text': 'INSERTION TEXT',
|
||||
'menu_text': 'MENU TEXT',
|
||||
'extra_menu_info': 'EXTRA MENU INFO',
|
||||
'kind': 'K',
|
||||
'detailed_info': 'DETAILED INFO',
|
||||
'extra_data': {
|
||||
},
|
||||
}, {
|
||||
'word': 'INSERTION TEXT',
|
||||
'abbr': 'MENU TEXT',
|
||||
'menu': 'EXTRA MENU INFO',
|
||||
'kind': 'k',
|
||||
'info': 'DETAILED INFO',
|
||||
'dup' : 1,
|
||||
} )
|
@ -20,6 +20,7 @@
|
||||
from ycm import vimsupport
|
||||
from nose.tools import eq_
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Repl_1_test():
|
||||
# Replace with longer range
|
||||
# 12345678901234567
|
||||
@ -75,6 +76,7 @@ def ReplaceChunk_SingleLine_Repl_1_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, 10 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Repl_2_test():
|
||||
# Replace with shorter range
|
||||
# 12345678901234567
|
||||
@ -91,6 +93,7 @@ def ReplaceChunk_SingleLine_Repl_2_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, -2 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Repl_3_test():
|
||||
# Replace with equal range
|
||||
# 12345678901234567
|
||||
@ -107,6 +110,7 @@ def ReplaceChunk_SingleLine_Repl_3_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, 0 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Add_1_test():
|
||||
# Insert at start
|
||||
result_buffer = [ "is a string" ]
|
||||
@ -122,6 +126,7 @@ def ReplaceChunk_SingleLine_Add_1_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, 5 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Add_2_test():
|
||||
# Insert at end
|
||||
result_buffer = [ "This is a " ]
|
||||
@ -137,6 +142,7 @@ def ReplaceChunk_SingleLine_Add_2_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, 6 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Add_3_test():
|
||||
# Insert in the middle
|
||||
result_buffer = [ "This is a string" ]
|
||||
@ -152,6 +158,7 @@ def ReplaceChunk_SingleLine_Add_3_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, 4 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Del_1_test():
|
||||
# Delete from start
|
||||
result_buffer = [ "This is a string" ]
|
||||
@ -167,6 +174,7 @@ def ReplaceChunk_SingleLine_Del_1_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, -5 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Del_2_test():
|
||||
# Delete from end
|
||||
result_buffer = [ "This is a string" ]
|
||||
@ -182,6 +190,7 @@ def ReplaceChunk_SingleLine_Del_2_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, -8 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleLine_Del_3_test():
|
||||
# Delete from middle
|
||||
result_buffer = [ "This is not a string" ]
|
||||
@ -197,6 +206,7 @@ def ReplaceChunk_SingleLine_Del_3_test():
|
||||
eq_( line_offset, 0 )
|
||||
eq_( char_offset, -4 )
|
||||
|
||||
|
||||
def ReplaceChunk_RemoveSingleLine_test():
|
||||
result_buffer = [ "aAa", "aBa", "aCa" ]
|
||||
start, end = _BuildLocations( 2, 1, 3, 1 )
|
||||
@ -250,7 +260,7 @@ def ReplaceChunk_SingleToMultipleLines2_test():
|
||||
0,
|
||||
0,
|
||||
result_buffer )
|
||||
expected_buffer = [ "aAa", "aEb" ,"bFb", "GBa", "aCa" ]
|
||||
expected_buffer = [ "aAa", "aEb", "bFb", "GBa", "aCa" ]
|
||||
eq_( expected_buffer, result_buffer )
|
||||
eq_( line_offset, 2 )
|
||||
eq_( char_offset, 0 )
|
||||
@ -265,11 +275,12 @@ def ReplaceChunk_SingleToMultipleLines3_test():
|
||||
0,
|
||||
0,
|
||||
result_buffer )
|
||||
expected_buffer = [ "aAa", "aEb" ,"bFb", "bGbBa", "aCa" ]
|
||||
expected_buffer = [ "aAa", "aEb", "bFb", "bGbBa", "aCa" ]
|
||||
eq_( expected_buffer, result_buffer )
|
||||
eq_( line_offset, 2 )
|
||||
eq_( char_offset, 2 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleToMultipleLinesReplace_test():
|
||||
result_buffer = [ "aAa", "aBa", "aCa" ]
|
||||
start, end = _BuildLocations( 1, 2, 1, 4 )
|
||||
@ -284,6 +295,7 @@ def ReplaceChunk_SingleToMultipleLinesReplace_test():
|
||||
eq_( line_offset, 2 )
|
||||
eq_( char_offset, 0 )
|
||||
|
||||
|
||||
def ReplaceChunk_SingleToMultipleLinesReplace_2_test():
|
||||
result_buffer = [ "aAa",
|
||||
"aBa",
|
||||
@ -521,3 +533,46 @@ def _BuildLocations( start_line, start_column, end_line, end_column ):
|
||||
'line_num' : end_line,
|
||||
'column_num': end_column,
|
||||
}
|
||||
|
||||
|
||||
def ReplaceChunksList_SortedChunks_test():
|
||||
chunks = [
|
||||
_BuildChunk( 1, 4, 1, 4, '('),
|
||||
_BuildChunk( 1, 11, 1, 11, ')' )
|
||||
]
|
||||
|
||||
result_buffer = [ "CT<10 >> 2> ct" ]
|
||||
vimsupport.ReplaceChunksList( chunks, result_buffer )
|
||||
|
||||
expected_buffer = [ "CT<(10 >> 2)> ct" ]
|
||||
eq_( expected_buffer, result_buffer )
|
||||
|
||||
|
||||
def ReplaceChunksList_UnsortedChunks_test():
|
||||
chunks = [
|
||||
_BuildChunk( 1, 11, 1, 11, ')'),
|
||||
_BuildChunk( 1, 4, 1, 4, '(' )
|
||||
]
|
||||
|
||||
result_buffer = [ "CT<10 >> 2> ct" ]
|
||||
vimsupport.ReplaceChunksList( chunks, result_buffer )
|
||||
|
||||
expected_buffer = [ "CT<(10 >> 2)> ct" ]
|
||||
eq_( expected_buffer, result_buffer )
|
||||
|
||||
|
||||
def _BuildChunk( start_line, start_column, end_line, end_column,
|
||||
replacement_text ):
|
||||
return {
|
||||
'range': {
|
||||
'start': {
|
||||
'line_num': start_line,
|
||||
'column_num': start_column,
|
||||
},
|
||||
'end': {
|
||||
'line_num': end_line,
|
||||
'column_num': end_column,
|
||||
},
|
||||
},
|
||||
'replacement_text': replacement_text
|
||||
}
|
||||
|
@ -474,6 +474,40 @@ def GetIntValue( variable ):
|
||||
return int( vim.eval( variable ) )
|
||||
|
||||
|
||||
def ReplaceChunksList( chunks, vim_buffer = None ):
|
||||
if vim_buffer is None:
|
||||
vim_buffer = vim.current.buffer
|
||||
|
||||
# We need to track the difference in length, but ensuring we apply fixes
|
||||
# in ascending order of insertion point.
|
||||
chunks.sort( key = lambda chunk: (
|
||||
chunk[ 'range' ][ 'start' ][ 'line_num' ],
|
||||
chunk[ 'range' ][ 'start' ][ 'column_num' ]
|
||||
) )
|
||||
|
||||
# Remember the line number we're processing. Negative line number means we
|
||||
# haven't processed any lines yet (by nature of being not equal to any
|
||||
# real line number).
|
||||
last_line = -1
|
||||
|
||||
line_delta = 0
|
||||
for chunk in chunks:
|
||||
if chunk[ 'range' ][ 'start' ][ 'line_num' ] != last_line:
|
||||
# If this chunk is on a different line than the previous chunk,
|
||||
# then ignore previous deltas (as offsets won't have changed).
|
||||
last_line = chunk[ 'range' ][ 'end' ][ 'line_num' ]
|
||||
char_delta = 0
|
||||
|
||||
( new_line_delta, new_char_delta ) = ReplaceChunk(
|
||||
chunk[ 'range' ][ 'start' ],
|
||||
chunk[ 'range' ][ 'end' ],
|
||||
chunk[ 'replacement_text' ],
|
||||
line_delta, char_delta,
|
||||
vim_buffer )
|
||||
line_delta += new_line_delta
|
||||
char_delta += new_char_delta
|
||||
|
||||
|
||||
# Replace the chunk of text specified by a contiguous range with the supplied
|
||||
# text.
|
||||
# * start and end are objects with line_num and column_num properties
|
||||
@ -484,10 +518,7 @@ def GetIntValue( variable ):
|
||||
# returns the delta (in lines and characters) that any position after the end
|
||||
# needs to be adjusted by.
|
||||
def ReplaceChunk( start, end, replacement_text, line_delta, char_delta,
|
||||
vim_buffer = None ):
|
||||
if vim_buffer is None:
|
||||
vim_buffer = vim.current.buffer
|
||||
|
||||
vim_buffer ):
|
||||
# ycmd's results are all 1-based, but vim's/python's are all 0-based
|
||||
# (so we do -1 on all of the values)
|
||||
start_line = start[ 'line_num' ] - 1 + line_delta
|
||||
|
@ -193,6 +193,8 @@ class YouCompleteMe( object ):
|
||||
self._omnicomp, wrapped_request_data )
|
||||
return self._latest_completion_request
|
||||
|
||||
request_data[ 'working_dir' ] = os.getcwd()
|
||||
|
||||
self._AddExtraConfDataIfNeeded( request_data )
|
||||
if force_semantic:
|
||||
request_data[ 'force_semantic' ] = True
|
||||
|
2
third_party/ycmd
vendored
2
third_party/ycmd
vendored
@ -1 +1 @@
|
||||
Subproject commit 01d5f2df8da4a4d960ddc8ab0349d62813147f59
|
||||
Subproject commit b46b8f09e33ccb6c70dfd02bba879c0b77fff4d5
|
Loading…
Reference in New Issue
Block a user