Auto merge of #1876 - puremourning:fix-goto-references, r=micbou
[READY] Fix GoTo lists arriving at the wrong column. ## Problem When a `GoTo` command returns a list of destinations, such as declarations and definitions in Python and references in JavaScript, we pop the Vim quick fix list with a list of destinations. however, we always jump to the character before the actual declaration/definition. ## Resolution Vim's QuickFix lists require 1-based columns, which is what is returned from ycmd's commands, so don't subtract 1 from the column number. As noted in the comments, the Vim documentation for `setqflist` is somewhat vague about this "byte offset", but it is confirmed to mean "1-based column number" both in testing and in `:help getqflist`. ## Manual testing Tested this with the Tern completer (`:YcmCompleter GoToReferences`) and Jedi completer (`:YcmCompleter GoToDeclaration`). For the Jedi completer, use something like: ```python x = 1 if False: x = 2 else: x = 3 print( str(x) ) ``` Then `:YcmCompleter GoToDeclaration` on `x`. This returns a list, which pops up the quick fix window. *Previous behaviour* Previously, the jump would go to the character before the actual declaration (i.e. the `<space>` before `x` in each line) ## Automated testing Just some simple execution of the changed code, proving that we don't take 1 from the column. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/1876) <!-- Reviewable:end -->
This commit is contained in:
commit
4168a829ac
@ -135,5 +135,13 @@ def _BuildQfListItem( goto_data_item ):
|
|||||||
if 'line_num' in goto_data_item:
|
if 'line_num' in goto_data_item:
|
||||||
qf_item[ 'lnum' ] = goto_data_item[ 'line_num' ]
|
qf_item[ 'lnum' ] = goto_data_item[ 'line_num' ]
|
||||||
if 'column_num' in goto_data_item:
|
if 'column_num' in goto_data_item:
|
||||||
qf_item[ 'col' ] = goto_data_item[ 'column_num' ] - 1
|
# ycmd returns columns 1-based, and QuickFix lists require "byte offsets".
|
||||||
|
# See :help getqflist and equivalent comment in
|
||||||
|
# vimsupport.ConvertDiagnosticsToQfList.
|
||||||
|
#
|
||||||
|
# When the Vim help says "byte index", it really means "1-based column
|
||||||
|
# number" (which is somewhat confusing). :help getqflist states "first
|
||||||
|
# column is 1".
|
||||||
|
qf_item[ 'col' ] = goto_data_item[ 'column_num' ]
|
||||||
|
|
||||||
return qf_item
|
return qf_item
|
||||||
|
91
python/ycm/client/tests/command_request_test.py
Normal file
91
python/ycm/client/tests/command_request_test.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2016 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 ycm.test_utils import MockVimModule
|
||||||
|
MockVimModule()
|
||||||
|
|
||||||
|
from mock import patch, call
|
||||||
|
from ycm.client.command_request import CommandRequest
|
||||||
|
|
||||||
|
|
||||||
|
class GoToResponse_QuickFix_test:
|
||||||
|
"""This class tests the generation of QuickFix lists for GoTo responses which
|
||||||
|
return multiple locations, such as the Python completer and JavaScript
|
||||||
|
completer. It mostly proves that we use 1-based indexing for the column
|
||||||
|
number."""
|
||||||
|
|
||||||
|
def setUp( self ):
|
||||||
|
self._request = CommandRequest( [ 'GoToTest' ] )
|
||||||
|
|
||||||
|
|
||||||
|
def tearDown( self ):
|
||||||
|
self._request = None
|
||||||
|
|
||||||
|
|
||||||
|
def GoTo_EmptyList_test( self ):
|
||||||
|
self._CheckGoToList( [], [] )
|
||||||
|
|
||||||
|
|
||||||
|
def GoTo_SingleItem_List_test( self ):
|
||||||
|
self._CheckGoToList( [ {
|
||||||
|
'filepath': 'dummy_file',
|
||||||
|
'line_num': 10,
|
||||||
|
'column_num': 1,
|
||||||
|
'description': 'this is some text',
|
||||||
|
} ], [ {
|
||||||
|
'filename': 'dummy_file',
|
||||||
|
'text': 'this is some text',
|
||||||
|
'lnum': 10,
|
||||||
|
'col': 1
|
||||||
|
} ] )
|
||||||
|
|
||||||
|
|
||||||
|
def GoTo_MultiItem_List_test( self ):
|
||||||
|
self._CheckGoToList( [ {
|
||||||
|
'filepath': 'dummy_file',
|
||||||
|
'line_num': 10,
|
||||||
|
'column_num': 1,
|
||||||
|
'description': 'this is some other text',
|
||||||
|
}, {
|
||||||
|
'filepath': 'dummy_file2',
|
||||||
|
'line_num': 1,
|
||||||
|
'column_num': 21,
|
||||||
|
'description': 'this is some text',
|
||||||
|
} ], [ {
|
||||||
|
'filename': 'dummy_file',
|
||||||
|
'text': 'this is some other text',
|
||||||
|
'lnum': 10,
|
||||||
|
'col': 1
|
||||||
|
}, {
|
||||||
|
'filename': 'dummy_file2',
|
||||||
|
'text': 'this is some text',
|
||||||
|
'lnum': 1,
|
||||||
|
'col': 21
|
||||||
|
} ] )
|
||||||
|
|
||||||
|
|
||||||
|
@patch( 'vim.eval' )
|
||||||
|
def _CheckGoToList( self, completer_response, expected_qf_list, vim_eval ):
|
||||||
|
self._request._response = completer_response
|
||||||
|
|
||||||
|
self._request.RunPostCommandActionsIfNeeded()
|
||||||
|
|
||||||
|
vim_eval.assert_has_calls( [
|
||||||
|
call( 'setqflist( {0} )'.format( repr( expected_qf_list ) ) ),
|
||||||
|
call( 'youcompleteme#OpenGoToList()' ),
|
||||||
|
] )
|
@ -240,10 +240,12 @@ def SetLocationList( diagnostics ):
|
|||||||
|
|
||||||
def ConvertDiagnosticsToQfList( diagnostics ):
|
def ConvertDiagnosticsToQfList( diagnostics ):
|
||||||
def ConvertDiagnosticToQfFormat( diagnostic ):
|
def ConvertDiagnosticToQfFormat( diagnostic ):
|
||||||
# see :h getqflist for a description of the dictionary fields
|
# See :h getqflist for a description of the dictionary fields.
|
||||||
# Note that, as usual, Vim is completely inconsistent about whether
|
# Note that, as usual, Vim is completely inconsistent about whether
|
||||||
# line/column numbers are 1 or 0 based in its various APIs. Here, it wants
|
# line/column numbers are 1 or 0 based in its various APIs. Here, it wants
|
||||||
# them to be 1-based.
|
# them to be 1-based. The documentation states quite clearly that it
|
||||||
|
# expects a byte offset, by which it means "1-based column number" as
|
||||||
|
# described in :h getqflist ("the first column is 1").
|
||||||
location = diagnostic[ 'location' ]
|
location = diagnostic[ 'location' ]
|
||||||
line_num = location[ 'line_num' ]
|
line_num = location[ 'line_num' ]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user