Commit 2f672642 authored by Onur Aslan's avatar Onur Aslan

New upstream version 0+20161219+git194ff33

parent ee7d73fd
[report]
omit =
*/tests/*
......@@ -12,8 +12,8 @@ the brackets) _before_ filing your issue:**
search.][search])
- [ ] If filing a bug report, I have included the output of `vim --version`.
- [ ] If filing a bug report, I have included the output of `:YcmDebugInfo`.
- [ ] If filing a bug report, I have included the output of
`:YcmToggleLogs stderr`.
- [ ] If filing a bug report, I have attached the contents of the logfiles using
the `:YcmToggleLogs` command.
- [ ] If filing a bug report, I have included which OS (including specific OS
version) I am using.
- [ ] If filing a bug report, I have included a minimal test case that reproduces
......
......@@ -7,8 +7,9 @@ YCM to work on my machine" and the reason why is obviously related to your
machine configuration and the problem would not be resolved with _reasonable_
changes to the YCM codebase, then the issue is likely to be closed.
**A good place to ask questions is the [ycm-users][] Google group**. Rule of
thumb: if you're not sure whether your problem is a real bug, ask on the group.
**A good place to ask questions is the [Gitter room][gitter] or the
[ycm-users][] Google group**. Rule of thumb: if you're not sure whether your
problem is a real bug, ask on the room or the group.
**YCM compiles just fine**; [the build bots say so][build-bots]. If the bots are
green and YCM doesn't compile on your machine, then _your machine is the root
......@@ -44,16 +45,16 @@ Here are the things you should do when creating an issue:
1. **Write a step-by-step procedure that when performed repeatedly reproduces
your issue.** If we can't reproduce the issue, then we can't fix it. It's
that simple.
2. Put the following options in your vimrc:
2. Add the output of [the `:YcmDebugInfo` command][ycm-debug-info-command].
3. Put the following options in your vimrc:
```viml
let g:ycm_server_keep_logfiles = 1
let g:ycm_server_log_level = 'debug'
let g:ycm_keep_logfiles = 1
let g:ycm_log_level = 'debug'
```
Run `:YcmToggleLogs stderr` in vim to open the logfile. Attach the contents
of this file to your issue.
3. Add the output of the `:YcmDebugInfo` command.
Reproduce your issue and attach the contents of the logfiles. Use [the
`:YcmToggleLogs` command][ycm-toggle-logs-command] to directly open them in
Vim.
4. **Create a test case for your issue**. This is critical. Don't talk about how
"when I have X in my file" or similar, _create a file with X in it_ and put
the contents inside code blocks in your issue description. Try to make this
......@@ -110,3 +111,6 @@ Creating good pull requests
[build-bots]: https://travis-ci.org/Valloric/YouCompleteMe
[ycm-users]: https://groups.google.com/forum/?hl=en#!forum/ycm-users
[gitter]: https://gitter.im/Valloric/YouCompleteMe
[ycm-debug-info-command]: https://github.com/Valloric/YouCompleteMe#the-ycmdebuginfo-command
[ycm-toggle-logs-command]: https://github.com/Valloric/YouCompleteMe#the-ycmtogglelogs-command
This diff is collapsed.
version: '{build}'
environment:
COVERAGE: true
matrix:
- arch: 32
python: 35
......@@ -12,6 +13,8 @@ install:
- ci\appveyor\appveyor_install.bat
build_script:
- python run_tests.py
after_build:
- codecov
# Disable automatic tests
test: off
cache:
......
This diff is collapsed.
......@@ -16,13 +16,6 @@ if %arch% == 32 (
set PATH=%python_path%;%python_path%\Scripts;%PATH%
python --version
:: When using Python 3 on AppVeyor, CMake will always pick the 64 bit
:: libraries. We specifically tell CMake the right path to the libraries
:: according to the architecture.
if %python% == 35 (
set EXTRA_CMAKE_ARGS="-DPYTHON_LIBRARY=%python_path%\libs\python%python%.lib"
)
appveyor DownloadFile https://bootstrap.pypa.io/get-pip.py
python get-pip.py
pip install -r python\test_requirements.txt
......
# Linux installation
# Linux-specific installation
# We can't use sudo, so we have to approximate the behaviour of setting the
# default system compiler.
mkdir ${HOME}/bin
ln -s /usr/bin/g++-4.8 ${HOME}/bin/c++
ln -s /usr/bin/gcc-4.8 ${HOME}/bin/cc
export PATH=${HOME}/bin:${PATH}
# In order to work with ycmd, python *must* be built as a shared library. This
# is set via the PYTHON_CONFIGURE_OPTS option.
export PYTHON_CONFIGURE_OPTS="--enable-shared"
......@@ -15,16 +15,17 @@ source ci/travis/travis_install.${TRAVIS_OS_NAME}.sh
# pyenv setup
#############
# DON'T exit if error
set +e
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
export PYENV_ROOT="${HOME}/.pyenv"
if [ ! -d "${PYENV_ROOT}/.git" ]; then
git clone https://github.com/yyuu/pyenv.git ${PYENV_ROOT}
fi
pushd ${PYENV_ROOT}
git fetch --tags
git checkout v20160202
# Exit if error
set -e
popd
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
export PATH="${PYENV_ROOT}/bin:${PATH}"
eval "$(pyenv init -)"
......
codecov:
notify:
require_ci_to_pass: yes
coverage:
precision: 2
round: down
range: 70...100
status:
# Learn more at https://codecov.io/docs#yaml_default_commit_status
project: true
patch: true
changes: true
comment:
layout: "header, diff, changes, uncovered"
behavior: default # update if exists else create new
This diff is collapsed.
#!/usr/bin/env python
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals
from __future__ import absolute_import
import os
import subprocess
import sys
import os.path as p
import glob
PY_MAJOR, PY_MINOR = sys.version_info[ 0 : 2 ]
if not ( ( PY_MAJOR == 2 and PY_MINOR >= 6 ) or
( PY_MAJOR == 3 and PY_MINOR >= 3 ) or
PY_MAJOR > 3 ):
sys.exit( 'YouCompleteMe requires Python >= 2.6 or >= 3.3; '
'your version of Python is ' + sys.version )
DIR_OF_THIS_SCRIPT = p.dirname( p.abspath( __file__ ) )
DIR_OF_OLD_LIBS = p.join( DIR_OF_THIS_SCRIPT, 'python' )
def CheckCall( args, **kwargs ):
try:
subprocess.check_call( args, **kwargs )
except subprocess.CalledProcessError as error:
sys.exit( error.returncode )
def Main():
build_file = p.join( DIR_OF_THIS_SCRIPT, 'third_party', 'ycmd', 'build.py' )
if not p.isfile( build_file ):
sys.exit( 'File ' + build_file + ' does not exist; you probably forgot '
'to run:\n\tgit submodule update --init --recursive\n\n' )
sys.exit(
'File {0} does not exist; you probably forgot to run:\n'
'\tgit submodule update --init --recursive\n'.format( build_file ) )
python_binary = sys.executable
subprocess.check_call( [ python_binary, build_file ] + sys.argv[1:] )
CheckCall( [ sys.executable, build_file ] + sys.argv[ 1: ] )
# Remove old YCM libs if present so that YCM can start.
old_libs = (
......
......@@ -27,9 +27,9 @@ endfunction
if exists( "g:loaded_youcompleteme" )
call s:restore_cpo()
finish
elseif v:version < 703 || (v:version == 703 && !has('patch598'))
elseif v:version < 704 || (v:version == 704 && !has('patch143'))
echohl WarningMsg |
\ echomsg "YouCompleteMe unavailable: requires Vim 7.3.598+" |
\ echomsg "YouCompleteMe unavailable: requires Vim 7.4.143+" |
\ echohl None
call s:restore_cpo()
finish
......@@ -42,43 +42,6 @@ elseif !has( 'python' ) && !has( 'python3' )
finish
endif
let s:script_folder_path = escape( expand( '<sfile>:p:h' ), '\' )
let s:python_folder_path = s:script_folder_path . '/../python/'
let s:ycmd_folder_path = s:script_folder_path . '/../third_party/ycmd/'
function! s:YcmLibsPresentIn( path_prefix )
if filereadable(a:path_prefix . 'ycm_core.so')
return 1
elseif filereadable(a:path_prefix . 'ycm_core.pyd')
return 1
elseif filereadable(a:path_prefix . 'ycm_core.dll')
return 1
endif
return 0
endfunction
if s:YcmLibsPresentIn( s:python_folder_path )
echohl WarningMsg |
\ echomsg "YCM libraries found in old YouCompleteMe/python location; " .
\ "please RECOMPILE YCM." |
\ echohl None
call s:restore_cpo()
finish
endif
let g:ycm_check_if_ycm_core_present =
\ get( g:, 'ycm_check_if_ycm_core_present', 1 )
if g:ycm_check_if_ycm_core_present &&
\ !s:YcmLibsPresentIn( s:ycmd_folder_path )
echohl WarningMsg |
\ echomsg "ycm_core.[so|pyd|dll] not detected; you need to compile " .
\ "YCM before using it. Read the docs!" |
\ echohl None
call s:restore_cpo()
finish
endif
let g:loaded_youcompleteme = 1
" NOTE: Most defaults are in third_party/ycmd/ycmd/default_settings.json. They
......@@ -117,11 +80,13 @@ let g:ycm_key_detailed_diagnostics =
let g:ycm_cache_omnifunc =
\ get( g:, 'ycm_cache_omnifunc', 1 )
let g:ycm_server_log_level =
\ get( g:, 'ycm_server_log_level', 'info' )
let g:ycm_log_level =
\ get( g:, 'ycm_log_level',
\ get( g:, 'ycm_server_log_level', 'info' ) )
let g:ycm_server_keep_logfiles =
\ get( g:, 'ycm_server_keep_logfiles', 0 )
let g:ycm_keep_logfiles =
\ get( g:, 'ycm_keep_logfiles',
\ get( g:, 'ycm_server_keep_logfiles', 0 ) )
let g:ycm_extra_conf_vim_data =
\ get( g:, 'ycm_extra_conf_vim_data', [] )
......@@ -131,8 +96,7 @@ let g:ycm_server_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 ) )
\ get( g:, 'ycm_show_diagnostics_ui', 1 )
let g:ycm_enable_diagnostic_signs =
\ get( g:, 'ycm_enable_diagnostic_signs',
......@@ -166,10 +130,14 @@ let g:ycm_disable_for_files_larger_than_kb =
" On-demand loading. Let's use the autoload folder and not slow down vim's
" startup procedure.
augroup youcompletemeStart
autocmd!
autocmd VimEnter * call youcompleteme#Enable()
augroup END
if has( 'vim_starting' ) " loading at startup
augroup youcompletemeStart
autocmd!
autocmd VimEnter * call youcompleteme#Enable()
augroup END
else " manual loading with :packadd
call youcompleteme#Enable()
endif
" This is basic vim plugin boilerplate
call s:restore_cpo()
flake8>=2.0
mock>=1.0.1
nose>=1.3.0
PyHamcrest>=1.8.0
# This needs to be kept in sync with submodule checkout in third_party/ycmd/third_party
future==0.15.2
# Flake8 3.x dropped support of Python 2.6 and 3.3
flake8 < 3.0.0; python_version == '2.6' or python_version == '3.3'
flake8 >= 3.0.0; python_version == '2.7' or python_version > '3.3'
mock >= 1.0.1
nose >= 1.3.7
PyHamcrest >= 1.8.0
# This needs to be kept in sync with submodule checkout in
# third_party/ycmd/third_party
future == 0.15.2
codecov >= 2.0.5
......@@ -35,17 +35,16 @@ YCM_VAR_PREFIX = 'ycm_'
def BuildServerConf():
"""Builds a dictionary mapping YCM Vim user options to values. Option names
don't have the 'ycm_' prefix."""
vim_globals = vimsupport.GetReadOnlyVimGlobals( force_python_objects = True )
# We only evaluate the keys of the vim globals and not the whole dictionary
# to avoid unicode issues.
# See https://github.com/Valloric/YouCompleteMe/pull/2151 for details.
keys = vimsupport.GetVimGlobalsKeys()
server_conf = {}
for key, value in iteritems( vim_globals ):
for key in keys:
if not key.startswith( YCM_VAR_PREFIX ):
continue
try:
new_value = int( value )
except:
new_value = value
new_key = key[ len( YCM_VAR_PREFIX ): ]
new_value = vimsupport.VimExpressionToPythonType( 'g:' + key )
server_conf[ new_key ] = new_value
return server_conf
......@@ -53,11 +52,10 @@ def BuildServerConf():
def LoadJsonDefaultsIntoVim():
defaults = user_options_store.DefaultOptions()
vim_defaults = {}
for key, value in iteritems( defaults ):
vim_defaults[ 'ycm_' + key ] = value
vimsupport.LoadDictIntoVimGlobals( vim_defaults, overwrite = False )
new_key = 'g:ycm_' + key
if not vimsupport.VariableExists( new_key ):
vimsupport.SetVariableValue( new_key, value )
def CompletionStartColumn():
......
......@@ -154,20 +154,29 @@ class BaseRequest( object ):
hmac_secret = ''
def BuildRequestData( include_buffer_data = True ):
def BuildRequestData( filepath = None ):
"""Build request for the current buffer or the buffer corresponding to
|filepath| if specified."""
current_filepath = vimsupport.GetCurrentBufferFilepath()
if filepath and current_filepath != filepath:
# Cursor position is irrelevant when filepath is not the current buffer.
return {
'filepath': filepath,
'line_num': 1,
'column_num': 1,
'file_data': vimsupport.GetUnsavedAndSpecifiedBufferData( filepath )
}
line, column = vimsupport.CurrentLineAndColumn()
filepath = vimsupport.GetCurrentBufferFilepath()
request_data = {
return {
'filepath': current_filepath,
'line_num': line + 1,
'column_num': column + 1,
'filepath': filepath
'file_data': vimsupport.GetUnsavedAndSpecifiedBufferData( current_filepath )
}
if include_buffer_data:
request_data[ 'file_data' ] = vimsupport.GetUnsavedAndCurrentBufferData()
return request_data
def JsonFromFuture( future ):
response = future.result()
......@@ -184,14 +193,14 @@ def JsonFromFuture( future ):
return None
def HandleServerException( exception ):
def HandleServerException( exception, truncate = False ):
serialized_exception = str( exception )
# We ignore the exception about the file already being parsed since it comes
# up often and isn't something that's actionable by the user.
if 'already being parsed' in serialized_exception:
return
vimsupport.PostMultiLineNotice( serialized_exception )
vimsupport.PostVimMessage( serialized_exception, truncate = truncate )
def _ToUtf8Json( data ):
......
......@@ -24,7 +24,6 @@ standard_library.install_aliases()
from builtins import * # noqa
from requests.exceptions import ReadTimeout
import vim
from ycmd.responses import ServerError
from ycm.client.base_request import ( BaseRequest, BuildRequestData,
......@@ -93,8 +92,9 @@ class CommandRequest( BaseRequest ):
def _HandleGotoResponse( self ):
if isinstance( self._response, list ):
vimsupport.SetQuickFixList(
[ _BuildQfListItem( x ) for x in self._response ] )
vim.eval( 'youcompleteme#OpenGoToList()' )
[ _BuildQfListItem( x ) for x in self._response ],
focus = True,
autoclose = True )
else:
vimsupport.JumpToLocation( self._response[ 'filepath' ],
self._response[ 'line_num' ],
......@@ -103,21 +103,32 @@ class CommandRequest( BaseRequest ):
def _HandleFixitResponse( self ):
if not len( self._response[ 'fixits' ] ):
vimsupport.EchoText( "No fixits found for current line" )
vimsupport.PostVimMessage( 'No fixits found for current line',
warning = False )
else:
chunks = self._response[ 'fixits' ][ 0 ][ 'chunks' ]
try:
vimsupport.ReplaceChunks( chunks )
fixit_index = 0
# When there are multiple fixit suggestions, present them as a list to
# the user hand have her choose which one to apply.
if len( self._response[ 'fixits' ] ) > 1:
fixit_index = vimsupport.SelectFromList(
"Multiple FixIt suggestions are available at this location. "
"Which one would you like to apply?",
[ fixit[ 'text' ] for fixit in self._response[ 'fixits' ] ] )
vimsupport.ReplaceChunks(
self._response[ 'fixits' ][ fixit_index ][ 'chunks' ] )
except RuntimeError as e:
vimsupport.PostMultiLineNotice( str( e ) )
vimsupport.PostVimMessage( str( e ) )
def _HandleBasicResponse( self ):
vimsupport.EchoText( self._response )
vimsupport.PostVimMessage( self._response, warning = False )
def _HandleMessageResponse( self ):
vimsupport.EchoText( self._response[ 'message' ] )
vimsupport.PostVimMessage( self._response[ 'message' ], warning = False )
def _HandleDetailedInfoResponse( self ):
......
......@@ -62,7 +62,7 @@ class CompletionRequest( BaseRequest ):
return JsonFromFuture( self._response_future )[ 'completions' ]
except ( ServerError, ReadTimeout ) as e:
HandleServerException( e )
HandleServerException( e, truncate = True )
return []
......
......@@ -32,15 +32,16 @@ from ycm.client.base_request import ( BaseRequest, BuildRequestData,
class EventNotification( BaseRequest ):
def __init__( self, event_name, extra_data = None ):
def __init__( self, event_name, filepath = None, extra_data = None ):
super( EventNotification, self ).__init__()
self._event_name = event_name
self._filepath = filepath
self._extra_data = extra_data
self._cached_response = None
def Start( self ):
request_data = BuildRequestData()
request_data = BuildRequestData( self._filepath )
if self._extra_data:
request_data.update( self._extra_data )
request_data[ 'event_name' ] = self._event_name
......@@ -74,8 +75,10 @@ class EventNotification( BaseRequest ):
return self._cached_response if self._cached_response else []
def SendEventNotificationAsync( event_name, extra_data = None ):
event = EventNotification( event_name, extra_data )
def SendEventNotificationAsync( event_name,
filepath = None,
extra_data = None ):
event = EventNotification( event_name, filepath, extra_data )
event.Start()
......
# 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 __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import * # noqa
from requests.exceptions import ReadTimeout
from ycm.client.base_request import BaseRequest
TIMEOUT_SECONDS = 0.1
class ShutdownRequest( BaseRequest ):
def __init__( self ):
super( BaseRequest, self ).__init__()
def Start( self ):
try:
self.PostDataToHandler( {},
'shutdown',
TIMEOUT_SECONDS )
except ReadTimeout:
pass
def SendShutdownRequest():
request = ShutdownRequest()
# This is a blocking call.
request.Start()
# 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 __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import * # noqa
from future.utils import iterkeys, iteritems
from ycm import vimsupport
import re
class DiagnosticFilter( object ):
def __init__( self, config_or_filters ):
if isinstance( config_or_filters, list ):
self._filters = config_or_filters
else:
self._filters = _CompileFilters( config_or_filters )
def IsAllowed( self, diagnostic ):
# NOTE: a diagnostic IsAllowed() ONLY if NO filters match it
for filterMatches in self._filters:
if filterMatches( diagnostic ):
return False
return True
def SubsetForTypes( self, filetypes ):
"""Return a sub-filter limited to the given filetypes"""
# NOTE: actually, this class is already filtered
return self
@staticmethod
def CreateFromOptions( user_options ):
all_filters = dict( user_options.get( 'filter_diagnostics', {} ) )
compiled_by_type = {}
for type_spec, filter_value in iteritems( dict( all_filters ) ):
filetypes = [ type_spec ]
if type_spec.find( ',' ) != -1:
filetypes = type_spec.split( ',' )
for filetype in filetypes:
compiled_by_type[ filetype ] = _CompileFilters( filter_value )
return _MasterDiagnosticFilter( compiled_by_type )
class _MasterDiagnosticFilter( object ):
def __init__( self, all_filters ):
self._all_filters = all_filters
self._cache = {}
def IsAllowed( self, diagnostic ):
# NOTE: in this class's implementation, we ask vimsupport for
# the current filetypes and delegate automatically; it is probably,
# more efficient, however, to call SubsetForTypes() and reuse
# the returned DiagnosticFilter if it will be checked repeatedly.
filetypes = vimsupport.CurrentFiletypes()
return self.SubsetForTypes( filetypes ).IsAllowed( diagnostic )
def SubsetForTypes( self, filetypes ):
# check cache
cache_key = ','.join( filetypes )
cached = self._cache.get( cache_key )
if cached is not None:
return cached
# build a new DiagnosticFilter merging all filters
# for the provided filetypes
spec = []
for filetype in filetypes:
type_specific = self._all_filters.get( filetype, [] )
spec.extend( type_specific )
new_filter = DiagnosticFilter( spec )
self._cache[ cache_key ] = new_filter
return new_filter
def _ListOf( config_entry ):
if isinstance( config_entry, list ):
return config_entry
if config_entry is None:
return []
return [ config_entry ]
def CompileRegex( raw_regex ):
pattern = re.compile( raw_regex, re.IGNORECASE )
def FilterRegex( diagnostic ):
return pattern.search( diagnostic[ 'text' ] ) is not None
return FilterRegex
def CompileLevel( level ):
# valid kinds are WARNING and ERROR;
# expected input levels are `warning` and `error`
# NOTE: we don't validate the input...
expected_kind = level.upper()
def FilterLevel( diagnostic ):
return diagnostic[ 'kind' ] == expected_kind
return FilterLevel
FILTER_COMPILERS = { 'regex' : CompileRegex,
'level' : CompileLevel }
def _CompileFilters( config ):
"""Given a filter config dictionary, return a list of compiled filters"""
filters = []
for filter_type in iterkeys( config ):
compiler = FILTER_COMPILERS.get( filter_type )
if compiler is not None:
for filter_config in _ListOf( config[ filter_type ] ):
compiledFilter = compiler( filter_config )
filters.append( compiledFilter )
return filters
......@@ -26,12 +26,14 @@ from builtins import * # noqa
from future.utils import itervalues, iteritems