Răsfoiți Sursa

Ignore case when comparing paths on Windows and macOS

micbou 5 ani în urmă
părinte
comite
5e3dd1d9b8

+ 30 - 10
python/ycm/tests/test_utils.py

@@ -34,7 +34,12 @@ import os
 import re
 import sys
 
-from ycmd.utils import GetCurrentDirectory, ToBytes, ToUnicode
+try:
+  from unittest import skipIf
+except ImportError:
+  from unittest2 import skipIf
+
+from ycmd.utils import GetCurrentDirectory, OnMac, OnWindows, ToBytes, ToUnicode
 
 
 BUFNR_REGEX = re.compile( '^bufnr\\(\'(?P<buffer_filename>.+)\', ([01])\\)$' )
@@ -102,6 +107,9 @@ REDIR = {
   'output': ''
 }
 
+WindowsAndMacOnly = skipIf( not OnWindows() or not OnMac(),
+                            'Windows and macOS only' )
+
 
 @contextlib.contextmanager
 def CurrentWorkingDirectory( path ):
@@ -293,7 +301,7 @@ def _MockVimEval( value ):
   if value == REDIR[ 'variable' ]:
     return REDIR[ 'output' ]
 
-  raise VimError( 'Unexpected evaluation: {0}'.format( value ) )
+  raise VimError( 'Unexpected evaluation: {}'.format( value ) )
 
 
 def _MockWipeoutBuffer( buffer_number ):
@@ -444,6 +452,11 @@ class VimBuffer( object ):
     raise ValueError( 'Unexpected mark: {name}'.format( name = name ) )
 
 
+  def __repr__( self ):
+    return "VimBuffer( name = '{}', number = {} )".format( self.name,
+                                                           self.number )
+
+
 class VimBuffers( object ):
   """An object that looks like a vim.buffers object."""
 
@@ -483,6 +496,13 @@ class VimWindow( object ):
     self.options = {}
 
 
+  def __repr__( self ):
+    return "VimWindow( number = {}, buffer = {}, cursor = {} )".format(
+      self.number,
+      self.buffer,
+      self.cursor )
+
+
 class VimWindows( object ):
   """An object that looks like a vim.windows object."""
 
@@ -534,8 +554,8 @@ class VimMatch( object ):
 
 
   def __repr__( self ):
-    return "VimMatch( group = '{0}', pattern = '{1}' )".format( self.group,
-                                                                self.pattern )
+    return "VimMatch( group = '{}', pattern = '{}' )".format( self.group,
+                                                              self.pattern )
 
 
   def __getitem__( self, key ):
@@ -562,11 +582,11 @@ class VimSign( object ):
 
 
   def __repr__( self ):
-    return ( "VimSign( id = {0}, line = {1}, "
-                      "name = '{2}', bufnr = {3} )".format( self.id,
-                                                            self.line,
-                                                            self.name,
-                                                            self.bufnr ) )
+    return ( "VimSign( id = {}, line = {}, "
+                      "name = '{}', bufnr = {} )".format( self.id,
+                                                          self.line,
+                                                          self.name,
+                                                          self.bufnr ) )
 
 
   def __getitem__( self, key ):
@@ -692,7 +712,7 @@ def ExpectedFailure( reason, *exception_matchers ):
         # Failed for the right reason
         raise nose.SkipTest( reason )
       else:
-        raise AssertionError( 'Test was expected to fail: {0}'.format(
+        raise AssertionError( 'Test was expected to fail: {}'.format(
           reason ) )
     return Wrapper
 

+ 30 - 1
python/ycm/tests/vimsupport_test.py

@@ -27,7 +27,7 @@ from builtins import *  # noqa
 from ycm.tests import PathToTestFile
 from ycm.tests.test_utils import ( CurrentWorkingDirectory, ExtendedMock,
                                    MockVimBuffers, MockVimModule, Version,
-                                   VimBuffer, VimError )
+                                   VimBuffer, VimError, WindowsAndMacOnly )
 MockVimModule()
 
 from ycm import vimsupport
@@ -1858,6 +1858,35 @@ def JumpToLocation_DifferentFile_Split_CurrentTab_AlreadyOpened_test(
     ] )
 
 
+@WindowsAndMacOnly
+@patch( 'vim.command', new_callable = ExtendedMock )
+def JumpToLocation_DifferentFile_Split_CurrentTab_AlreadyOpened_Case_test(
+    vim_command ):
+
+  current_buffer = VimBuffer( 'current_buffer' )
+  different_buffer = VimBuffer( 'AnotHer_buFfeR' )
+  current_window = MagicMock( buffer = current_buffer )
+  different_window = MagicMock( buffer = different_buffer )
+  current_tab = MagicMock( windows = [ current_window, different_window ] )
+  with MockVimBuffers( [ current_buffer, different_buffer ],
+                       [ current_buffer ] ) as vim:
+    vim.current.tabpage = current_tab
+
+    vimsupport.JumpToLocation( os.path.realpath( 'anOther_BuffEr' ),
+                               4,
+                               1,
+                               'belowright',
+                               'split-or-existing-window' )
+
+    assert_that( vim.current.tabpage, equal_to( current_tab ) )
+    assert_that( vim.current.window, equal_to( different_window ) )
+    assert_that( vim.current.window.cursor, equal_to( ( 4, 0 ) ) )
+    vim_command.assert_has_exact_calls( [
+      call( 'normal! m\'' ),
+      call( 'normal! zz' )
+    ] )
+
+
 @patch( 'vim.command', new_callable = ExtendedMock )
 def JumpToLocation_DifferentFile_Split_AllTabs_NotAlreadyOpened_test(
     vim_command ):

+ 19 - 3
python/ycm/vimsupport.py

@@ -28,8 +28,13 @@ import os
 import json
 import re
 from collections import defaultdict, namedtuple
-from ycmd.utils import ( ByteOffsetToCodepointOffset, GetCurrentDirectory,
-                         JoinLinesAsUnicode, ToBytes, ToUnicode )
+from ycmd.utils import ( ByteOffsetToCodepointOffset,
+                         GetCurrentDirectory,
+                         JoinLinesAsUnicode,
+                         OnMac,
+                         OnWindows,
+                         ToBytes,
+                         ToUnicode )
 
 BUFFER_COMMAND_MAP = { 'same-buffer'      : 'edit',
                        'split'            : 'split',
@@ -460,10 +465,21 @@ def EscapeFilepathForVimCommand( filepath ):
   return GetVariableValue( to_eval )
 
 
+def ComparePaths( path1, path2 ):
+  # Assume that the file system is case-insensitive on Windows and macOS and
+  # case-sensitive on other platforms. While this is not necessarily true, being
+  # completely correct here is not worth the trouble as this assumption
+  # represents the overwhelming use case and detecting the case sensitivity of a
+  # file system is tricky.
+  if OnWindows() or OnMac():
+    return path1.lower() == path2.lower()
+  return path1 == path2
+
+
 # Both |line| and |column| need to be 1-based
 def TryJumpLocationInTab( tab, filename, line, column ):
   for win in tab.windows:
-    if GetBufferFilepath( win.buffer ) == filename:
+    if ComparePaths( GetBufferFilepath( win.buffer ), filename ):
       vim.current.tabpage = tab
       vim.current.window = win
       vim.current.window.cursor = ( line, column - 1 )