|
@@ -24,20 +24,19 @@ 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 ):
|
|
|
- self._filters = []
|
|
|
+ def __init__( self, config_or_filters ):
|
|
|
+ if isinstance( config_or_filters, list ):
|
|
|
+ self._filters = config_or_filters
|
|
|
+ print( 'NewFilter', config_or_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 )
|
|
|
- self._filters.append( compiledFilter )
|
|
|
+ else:
|
|
|
+ self._filters = _CompileFilters( config_or_filters )
|
|
|
+ print( 'CompileFilters', config_or_filters)
|
|
|
|
|
|
|
|
|
def IsAllowed( self, diagnostic ):
|
|
@@ -49,19 +48,59 @@ class DiagnosticFilter( object ):
|
|
|
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 from_filetype( user_options, filetypes ):
|
|
|
- spec = {}
|
|
|
+ def CreateFromOptions( user_options ):
|
|
|
all_filters = dict( user_options.get( 'filter_diagnostics', {} ) )
|
|
|
- for typeSpec, filterValue in iteritems( dict( all_filters ) ):
|
|
|
- if typeSpec.find(',') != -1:
|
|
|
- for filetype in typeSpec.split(','):
|
|
|
- all_filters[ filetype ] = filterValue
|
|
|
+ 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 mergin all filters
|
|
|
+ # for the provided filetypes
|
|
|
+ spec = []
|
|
|
for filetype in filetypes:
|
|
|
- type_specific = all_filters.get( filetype, {} )
|
|
|
- spec = _Merge( spec, type_specific )
|
|
|
- return DiagnosticFilter( spec )
|
|
|
+ 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 ):
|
|
@@ -74,13 +113,6 @@ def _ListOf( config_entry ):
|
|
|
return [ config_entry ]
|
|
|
|
|
|
|
|
|
-def _Merge( into, other ):
|
|
|
- for key in iterkeys( other ):
|
|
|
- into[ key ] = _ListOf( into.get( key ) ) + _ListOf( other[ key ] )
|
|
|
-
|
|
|
- return into
|
|
|
-
|
|
|
-
|
|
|
def _CompileRegex( raw_regex ):
|
|
|
pattern = re.compile( raw_regex, re.IGNORECASE )
|
|
|
|
|
@@ -104,3 +136,18 @@ def _CompileLevel( level ):
|
|
|
|
|
|
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
|