Replaced Syntastic support with YCM-native code
Currently, the only supported Syntastic features are the error signs in the gutter. Other features will be added in the future.
This commit is contained in:
parent
e8d1a4cef8
commit
6c01881e1a
@ -29,7 +29,7 @@ let s:cursor_moved = 0
|
|||||||
let s:moved_vertically_in_insert_mode = 0
|
let s:moved_vertically_in_insert_mode = 0
|
||||||
let s:previous_num_chars_on_current_line = -1
|
let s:previous_num_chars_on_current_line = -1
|
||||||
|
|
||||||
let s:forced_syntastic_checker_for = {
|
let s:diagnostic_ui_filetypes = {
|
||||||
\ 'cpp': 1,
|
\ 'cpp': 1,
|
||||||
\ 'c': 1,
|
\ 'c': 1,
|
||||||
\ 'objc': 1,
|
\ 'objc': 1,
|
||||||
@ -70,10 +70,12 @@ function! youcompleteme#Enable()
|
|||||||
call s:SetUpCompleteopt()
|
call s:SetUpCompleteopt()
|
||||||
call s:SetUpKeyMappings()
|
call s:SetUpKeyMappings()
|
||||||
|
|
||||||
if g:ycm_register_as_syntastic_checker
|
if g:ycm_show_diagnostics_ui
|
||||||
call s:TweakSyntasticOptions()
|
call s:TurnOffSyntasticForCFamily()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
call s:SetUpSigns()
|
||||||
|
|
||||||
if g:ycm_allow_changing_updatetime
|
if g:ycm_allow_changing_updatetime
|
||||||
set ut=2000
|
set ut=2000
|
||||||
endif
|
endif
|
||||||
@ -157,6 +159,41 @@ function! s:SetUpKeyMappings()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:SetUpSigns()
|
||||||
|
" We try to ensure backwards compatibility with Syntastic if the user has
|
||||||
|
" already defined styling for Syntastic highlight groups.
|
||||||
|
|
||||||
|
if !hlexists( 'YcmErrorSign' )
|
||||||
|
if hlexists( 'SyntasticErrorSign')
|
||||||
|
highlight link YcmErrorSign SyntasticErrorSign
|
||||||
|
else
|
||||||
|
highlight link YcmErrorSign error
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !hlexists( 'YcmWarningSign' )
|
||||||
|
if hlexists( 'SyntasticWarningSign')
|
||||||
|
highlight link YcmWarningSign SyntasticWarningSign
|
||||||
|
else
|
||||||
|
highlight link YcmWarningSign todo
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !hlexists( 'YcmErrorLine' )
|
||||||
|
highlight link YcmErrorLine SyntasticErrorLine
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !hlexists( 'YcmWarningLine' )
|
||||||
|
highlight link YcmWarningLine SyntasticWarningLine
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe 'sign define YcmError text=' . g:ycm_error_symbol .
|
||||||
|
\ ' texthl=YcmErrorSign linehl=YcmErrorLine'
|
||||||
|
exe 'sign define YcmWarning text=' . g:ycm_warning_symbol .
|
||||||
|
\ ' texthl=YcmWarningSign linehl=YcmWarningLine'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:SetUpBackwardsCompatibility()
|
function! s:SetUpBackwardsCompatibility()
|
||||||
let complete_in_comments_and_strings =
|
let complete_in_comments_and_strings =
|
||||||
\ get( g:, 'ycm_complete_in_comments_and_strings', 0 )
|
\ get( g:, 'ycm_complete_in_comments_and_strings', 0 )
|
||||||
@ -173,38 +210,17 @@ function! s:SetUpBackwardsCompatibility()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! s:TweakSyntasticOptions()
|
" Needed so that YCM is used instead of Syntastic
|
||||||
call s:ForceCFamilyFiletypesSyntasticPassiveMode()
|
function! s:TurnOffSyntasticForCFamily()
|
||||||
call s:ForceSyntasticCFamilyChecker()
|
let g:syntastic_cpp_checkers = []
|
||||||
|
let g:syntastic_c_checkers = []
|
||||||
" We set this to work around segfaults in old versions of Vim
|
let g:syntastic_objc_checkers = []
|
||||||
" See here for details: https://github.com/scrooloose/syntastic/issues/834
|
let g:syntastic_objcpp_checkers = []
|
||||||
let g:syntastic_delayed_redraws = 1
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Needed so that YCM is used as the syntastic checker
|
function! s:DiagnosticUiSupportedForCurrentFiletype()
|
||||||
function! s:ForceSyntasticCFamilyChecker()
|
return get( s:diagnostic_ui_filetypes, &filetype, 0 )
|
||||||
let g:syntastic_cpp_checkers = ['ycm']
|
|
||||||
let g:syntastic_c_checkers = ['ycm']
|
|
||||||
let g:syntastic_objc_checkers = ['ycm']
|
|
||||||
let g:syntastic_objcpp_checkers = ['ycm']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" Needed so that Syntastic doesn't call :SyntasticCheck (and thus YCM code) on
|
|
||||||
" file save unnecessarily. We call :SyntasticCheck ourselves often enough.
|
|
||||||
function! s:ForceCFamilyFiletypesSyntasticPassiveMode()
|
|
||||||
let mode_map = get( g:, 'syntastic_mode_map', {} )
|
|
||||||
let mode_map.passive_filetypes = get( mode_map, 'passive_filetypes', [] ) +
|
|
||||||
\ ['cpp', 'c', 'objc', 'objcpp']
|
|
||||||
let g:syntastic_mode_map = mode_map
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! s:ForcedAsSyntasticCheckerForCurrentFiletype()
|
|
||||||
return g:ycm_register_as_syntastic_checker &&
|
|
||||||
\ get( s:forced_syntastic_checker_for, &filetype, 0 )
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@ -464,18 +480,15 @@ endfunction
|
|||||||
|
|
||||||
|
|
||||||
function! s:UpdateDiagnosticNotifications()
|
function! s:UpdateDiagnosticNotifications()
|
||||||
let should_display_diagnostics =
|
let should_display_diagnostics = g:ycm_show_diagnostics_ui &&
|
||||||
\ get( g:, 'loaded_syntastic_plugin', 0 ) &&
|
\ s:DiagnosticUiSupportedForCurrentFiletype() &&
|
||||||
\ s:ForcedAsSyntasticCheckerForCurrentFiletype() &&
|
|
||||||
\ pyeval( 'ycm_state.NativeFiletypeCompletionUsable()' )
|
\ pyeval( 'ycm_state.NativeFiletypeCompletionUsable()' )
|
||||||
|
|
||||||
if !should_display_diagnostics
|
if !should_display_diagnostics
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if pyeval( 'ycm_state.DiagnosticsForCurrentFileReady()' )
|
py ycm_state.UpdateDiagnosticInterface()
|
||||||
SyntasticCheck
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@ -639,14 +652,6 @@ endfunction
|
|||||||
command! YcmShowDetailedDiagnostic call s:ShowDetailedDiagnostic()
|
command! YcmShowDetailedDiagnostic call s:ShowDetailedDiagnostic()
|
||||||
|
|
||||||
|
|
||||||
" This is what Syntastic calls indirectly when it decides an auto-check is
|
|
||||||
" required (currently that's on buffer save) OR when the SyntasticCheck command
|
|
||||||
" is invoked
|
|
||||||
function! youcompleteme#CurrentFileDiagnostics()
|
|
||||||
return pyeval( 'ycm_state.GetDiagnosticsFromStoredRequest()' )
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! s:DebugInfo()
|
function! s:DebugInfo()
|
||||||
echom "Printing YouCompleteMe debug information..."
|
echom "Printing YouCompleteMe debug information..."
|
||||||
let debug_info = pyeval( 'ycm_state.DebugInfo()' )
|
let debug_info = pyeval( 'ycm_state.DebugInfo()' )
|
||||||
|
@ -71,9 +71,6 @@ let g:loaded_youcompleteme = 1
|
|||||||
" The only defaults that are here are the ones that are only relevant to the YCM
|
" The only defaults that are here are the ones that are only relevant to the YCM
|
||||||
" Vim client and not the server.
|
" Vim client and not the server.
|
||||||
|
|
||||||
let g:ycm_register_as_syntastic_checker =
|
|
||||||
\ get( g:, 'ycm_register_as_syntastic_checker', 1 )
|
|
||||||
|
|
||||||
let g:ycm_allow_changing_updatetime =
|
let g:ycm_allow_changing_updatetime =
|
||||||
\ get( g:, 'ycm_allow_changing_updatetime', 1 )
|
\ get( g:, 'ycm_allow_changing_updatetime', 1 )
|
||||||
|
|
||||||
@ -116,6 +113,17 @@ let g:ycm_extra_conf_vim_data =
|
|||||||
let g:ycm_path_to_python_interpreter =
|
let g:ycm_path_to_python_interpreter =
|
||||||
\ get( g:, 'ycm_path_to_python_interpreter', '' )
|
\ get( g:, 'ycm_path_to_python_interpreter', '' )
|
||||||
|
|
||||||
|
let g:ycm_show_diagnostics_ui =
|
||||||
|
\ get( g:, 'ycm_show_diagnostics_ui',
|
||||||
|
\ get( g:, 'ycm_register_as_syntastic_checker', 1 ) )
|
||||||
|
|
||||||
|
let g:ycm_error_symbol =
|
||||||
|
\ get( g:, 'ycm_error_symbol',
|
||||||
|
\ get( g:, 'syntastic_error_symbol', '>>' ) )
|
||||||
|
|
||||||
|
let g:ycm_warning_symbol =
|
||||||
|
\ get( g:, 'ycm_warning_symbol',
|
||||||
|
\ get( g:, 'syntastic_warning_symbol', '>>' ) )
|
||||||
|
|
||||||
" On-demand loading. Let's use the autoload folder and not slow down vim's
|
" On-demand loading. Let's use the autoload folder and not slow down vim's
|
||||||
" startup procedure.
|
" startup procedure.
|
||||||
|
55
python/ycm/diagnostic_interface.py
Normal file
55
python/ycm/diagnostic_interface.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 Strahinja Val Markovic <val@markovic.io>
|
||||||
|
#
|
||||||
|
# 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 collections import defaultdict
|
||||||
|
from operator import itemgetter
|
||||||
|
from ycm import vimsupport
|
||||||
|
|
||||||
|
|
||||||
|
class DiagnosticInterface( object ):
|
||||||
|
def __init__( self ):
|
||||||
|
self._buffer_number_to_diags = {}
|
||||||
|
self._next_sign_id = 1
|
||||||
|
|
||||||
|
|
||||||
|
def UpdateWithNewDiagnostics( self, diags ):
|
||||||
|
self._buffer_number_to_diags = ConvertDiagListToDict( diags )
|
||||||
|
for buffer_number, buffer_diags in self._buffer_number_to_diags.iteritems():
|
||||||
|
if not vimsupport.BufferIsVisible( buffer_number ):
|
||||||
|
continue
|
||||||
|
|
||||||
|
vimsupport.UnplaceAllSignsInBuffer( buffer_number )
|
||||||
|
for diag in buffer_diags:
|
||||||
|
vimsupport.PlaceSign( self._next_sign_id,
|
||||||
|
diag[ 'lnum' ],
|
||||||
|
buffer_number,
|
||||||
|
diag[ 'type' ] == 'E' )
|
||||||
|
self._next_sign_id += 1
|
||||||
|
|
||||||
|
|
||||||
|
def ConvertDiagListToDict( diags ):
|
||||||
|
buffer_to_diags = defaultdict( list )
|
||||||
|
for diag in diags:
|
||||||
|
buffer_to_diags[ diag[ 'bufnr' ] ].append( diag )
|
||||||
|
for buffer_diags in buffer_to_diags.itervalues():
|
||||||
|
# We also want errors to be listed before warnings so that errors aren't
|
||||||
|
# hidden by the warnings; Vim won't place a sign oven an existing one.
|
||||||
|
buffer_diags.sort( key = lambda diag: itemgetter( 'lnum', 'col', 'type' ) )
|
||||||
|
return buffer_to_diags
|
||||||
|
|
@ -83,15 +83,22 @@ def GetUnsavedAndCurrentBufferData():
|
|||||||
|
|
||||||
|
|
||||||
def GetBufferNumberForFilename( filename, open_file_if_needed = True ):
|
def GetBufferNumberForFilename( filename, open_file_if_needed = True ):
|
||||||
return int( vim.eval( "bufnr('{0}', {1})".format(
|
return GetIntValue( "bufnr('{0}', {1})".format(
|
||||||
os.path.realpath( filename ),
|
os.path.realpath( filename ),
|
||||||
int( open_file_if_needed ) ) ) )
|
int( open_file_if_needed ) ) )
|
||||||
|
|
||||||
|
|
||||||
def GetCurrentBufferFilepath():
|
def GetCurrentBufferFilepath():
|
||||||
return GetBufferFilepath( vim.current.buffer )
|
return GetBufferFilepath( vim.current.buffer )
|
||||||
|
|
||||||
|
|
||||||
|
def BufferIsVisible( buffer_number ):
|
||||||
|
if buffer_number < 0:
|
||||||
|
return False
|
||||||
|
window_number = GetIntValue( "bufwinnr({0})".format( buffer_number ) )
|
||||||
|
return window_number != -1
|
||||||
|
|
||||||
|
|
||||||
def GetBufferFilepath( buffer_object ):
|
def GetBufferFilepath( buffer_object ):
|
||||||
if buffer_object.name:
|
if buffer_object.name:
|
||||||
return buffer_object.name
|
return buffer_object.name
|
||||||
@ -100,6 +107,18 @@ def GetBufferFilepath( buffer_object ):
|
|||||||
return os.path.join( os.getcwd(), str( buffer_object.number ) )
|
return os.path.join( os.getcwd(), str( buffer_object.number ) )
|
||||||
|
|
||||||
|
|
||||||
|
def UnplaceAllSignsInBuffer( buffer_number ):
|
||||||
|
if buffer_number < 0:
|
||||||
|
return
|
||||||
|
vim.command( 'sign unplace * buffer={0}'.format( buffer_number ) )
|
||||||
|
|
||||||
|
|
||||||
|
def PlaceSign( sign_id, line_num, buffer_num, is_error = True ):
|
||||||
|
sign_name = 'YcmError' if is_error else 'YcmWarning'
|
||||||
|
vim.command( 'sign place {0} line={1} name={2} buffer={3}'.format(
|
||||||
|
sign_id, line_num, sign_name, buffer_num ) )
|
||||||
|
|
||||||
|
|
||||||
# Given a dict like {'a': 1}, loads it into Vim as if you ran 'let g:a = 1'
|
# Given a dict like {'a': 1}, loads it into Vim as if you ran 'let g:a = 1'
|
||||||
# When |overwrite| is True, overwrites the existing value in Vim.
|
# When |overwrite| is True, overwrites the existing value in Vim.
|
||||||
def LoadDictIntoVimGlobals( new_globals, overwrite = True ):
|
def LoadDictIntoVimGlobals( new_globals, overwrite = True ):
|
||||||
@ -164,6 +183,7 @@ def PostVimMessage( message ):
|
|||||||
vim.command( "echohl WarningMsg | echom '{0}' | echohl None"
|
vim.command( "echohl WarningMsg | echom '{0}' | echohl None"
|
||||||
.format( EscapeForVim( str( message ) ) ) )
|
.format( EscapeForVim( str( message ) ) ) )
|
||||||
|
|
||||||
|
|
||||||
# Unlike PostVimMesasge, this supports messages with newlines in them because it
|
# Unlike PostVimMesasge, this supports messages with newlines in them because it
|
||||||
# uses 'echo' instead of 'echomsg'. This also means that the message will NOT
|
# uses 'echo' instead of 'echomsg'. This also means that the message will NOT
|
||||||
# appear in Vim's message log.
|
# appear in Vim's message log.
|
||||||
|
@ -23,6 +23,7 @@ import tempfile
|
|||||||
import json
|
import json
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
from ycm import utils
|
from ycm import utils
|
||||||
|
from ycm.diagnostic_interface import DiagnosticInterface
|
||||||
from ycm.completers.all.omni_completer import OmniCompleter
|
from ycm.completers.all.omni_completer import OmniCompleter
|
||||||
from ycm.completers.general import syntax_parse
|
from ycm.completers.general import syntax_parse
|
||||||
from ycm.completers.completer_utils import FiletypeCompleterExistsForFiletype
|
from ycm.completers.completer_utils import FiletypeCompleterExistsForFiletype
|
||||||
@ -64,6 +65,7 @@ class YouCompleteMe( object ):
|
|||||||
def __init__( self, user_options ):
|
def __init__( self, user_options ):
|
||||||
self._user_options = user_options
|
self._user_options = user_options
|
||||||
self._user_notified_about_crash = False
|
self._user_notified_about_crash = False
|
||||||
|
self._diag_interface = DiagnosticInterface()
|
||||||
self._omnicomp = OmniCompleter( user_options )
|
self._omnicomp = OmniCompleter( user_options )
|
||||||
self._latest_completion_request = None
|
self._latest_completion_request = None
|
||||||
self._latest_file_parse_request = None
|
self._latest_file_parse_request = None
|
||||||
@ -271,6 +273,13 @@ class YouCompleteMe( object ):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def UpdateDiagnosticInterface( self ):
|
||||||
|
if not self.DiagnosticsForCurrentFileReady():
|
||||||
|
return
|
||||||
|
self._diag_interface.UpdateWithNewDiagnostics(
|
||||||
|
self.GetDiagnosticsFromStoredRequest() )
|
||||||
|
|
||||||
|
|
||||||
def ShowDetailedDiagnostic( self ):
|
def ShowDetailedDiagnostic( self ):
|
||||||
if not self._IsServerAlive():
|
if not self._IsServerAlive():
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user