<s> import re <EOL> import logging <EOL> from pathlib import Path <EOL> from vint . _bundles import vimlparser <EOL> from vint . ast . parsing import Parser , EncodingDetectionError <EOL> from vint . ast . node_type import NodeType <EOL> from vint . ast . traversing import traverse <EOL> from vint . ast . plugin . scope_plugin import ScopePlugin <EOL> from vint . linting . config . config_container import ConfigContainer <EOL> from vint . linting . config . config_dict_source import ConfigDictSource <EOL> from vint . linting . config . config_comment_source import ConfigCommentSource <EOL> from vint . linting . config . config_util import get_config_value <EOL> from vint . linting . level import Level <EOL> class Linter ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , policy_set , config_dict_global ) : <EOL> self . _plugins = { <EOL> '<STR_LIT>' : ScopePlugin ( ) , <EOL> } <EOL> self . _policy_set = policy_set <EOL> self . _config_comment_source = ConfigCommentSource ( ) <EOL> self . _config = self . _decorate_config ( config_dict_global , <EOL> self . _config_comment_source ) <EOL> self . _parser = self . build_parser ( ) <EOL> self . _listeners_map = { } <EOL> def build_parser ( self ) : <EOL> config_dict = self . _config . get_config_dict ( ) <EOL> enable_neovim = get_config_value ( config_dict , [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] , False ) <EOL> parser = Parser ( self . _plugins , enable_neovim = enable_neovim ) <EOL> return parser <EOL> def _decorate_config ( self , config_dict_global , config_comment_source ) : <EOL> config_dict_source = ConfigDictSource ( config_dict_global ) <EOL> config_container = ConfigContainer ( config_dict_source , <EOL> config_comment_source ) <EOL> return config_container <EOL> def _parse_vimlparser_error ( self , err_message ) : <EOL> match = re . match ( r'<STR_LIT>' , err_message ) <EOL> return match . groupdict ( ) <EOL> def _create_parse_error ( self , path , err_message ) : <EOL> parser_error = self . _parse_vimlparser_error ( err_message ) <EOL> return { <EOL> '<STR_LIT:name>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : Level . ERROR , <EOL> '<STR_LIT:description>' : parser_error [ '<STR_LIT:description>' ] , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : int ( parser_error [ '<STR_LIT>' ] ) , <EOL> '<STR_LIT>' : int ( parser_error [ '<STR_LIT>' ] ) , <EOL> '<STR_LIT:path>' : Path ( path ) , <EOL> } , <EOL> } <EOL> def _create_decoding_error ( self , path , err_message ) : <EOL> return { <EOL> '<STR_LIT:name>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : Level . ERROR , <EOL> '<STR_LIT:description>' : err_message , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : <NUM_LIT:0> , <EOL> '<STR_LIT>' : <NUM_LIT:0> , <EOL> '<STR_LIT:path>' : Path ( path ) , <EOL> } , <EOL> } <EOL> def _log_file_path_to_lint ( self , file_path ) : <EOL> msg = '<STR_LIT>' . format ( file_path = file_path ) <EOL> logging . debug ( msg ) <EOL> def lint_file ( self , path ) : <EOL> self . _log_file_path_to_lint ( path ) <EOL> try : <EOL> root_ast = self . _parser . parse_file ( path ) <EOL> except vimlparser . VimLParserException as exception : <EOL> parse_error = self . _create_parse_error ( path , str ( exception ) ) <EOL> return [ parse_error ] <EOL> except EncodingDetectionError as exception : <EOL> decoding_error = self . _create_decoding_error ( path , str ( exception ) ) <EOL> return [ decoding_error ] <EOL> self . _violations = [ ] <EOL> self . _update_listeners_map ( ) <EOL> lint_context = { <EOL> '<STR_LIT:path>' : path , <EOL> '<STR_LIT>' : root_ast , <EOL> '<STR_LIT>' : [ ] , <EOL> '<STR_LIT>' : self . _plugins , <EOL> '<STR_LIT>' : self . _config . get_config_dict ( ) , <EOL> } <EOL> traverse ( root_ast , <EOL> on_enter = lambda node : self . _handle_enter ( node , lint_context ) , <EOL> on_leave = lambda node : self . _handle_leave ( node , lint_context ) ) <EOL> return self . _violations <EOL> def _handle_enter ( self , node , lint_context ) : <EOL> self . _refresh_policies_if_necessary ( node ) <EOL> self . _fire_listeners ( node , lint_context ) <EOL> lint_context [ '<STR_LIT>' ] . append ( node ) <EOL> def _handle_leave ( self , node , lint_context ) : <EOL> lint_context [ '<STR_LIT>' ] . pop ( ) <EOL> def _fire_listeners ( self , node , lint_context ) : <EOL> node_type = NodeType ( node [ '<STR_LIT:type>' ] ) <EOL> if node_type not in self . _listeners_map : <EOL> return <EOL> listening_policies = self . _listeners_map [ node_type ] <EOL> for listening_policy in listening_policies : <EOL> violation = listening_policy . get_violation_if_found ( node , lint_context ) <EOL> if violation is not None : <EOL> self . _violations . append ( violation ) <EOL> def _refresh_policies_if_necessary ( self , node ) : <EOL> config_comment_source = self . _config_comment_source <EOL> if not config_comment_source . is_requesting_update ( node ) : <EOL> return <EOL> self . _refresh_policies ( node ) <EOL> def _refresh_policies ( self , node ) : <EOL> config_comment_source = self . _config_comment_source <EOL> config_comment_source . update_by_node ( node ) <EOL> self . _update_listeners_map ( ) <EOL> def _update_enabled_policies ( self ) : <EOL> policy_set = self . _policy_set <EOL> config = self . _config <EOL> config_dict = config . get_config_dict ( ) <EOL> policy_set . update_by_config ( config_dict ) <EOL> def _update_listeners_map ( self ) : <EOL> self . _update_enabled_policies ( ) <EOL> self . _listeners_map = { } <EOL> policy_set = self . _policy_set <EOL> for policy in policy_set . get_enabled_policies ( ) : <EOL> listened_node_types = policy . listen_node_types ( ) <EOL> for listened_node_type in listened_node_types : <EOL> if listened_node_type not in self . _listeners_map : <EOL> self . _listeners_map [ listened_node_type ] = [ policy ] <EOL> else : <EOL> self . _listeners_map [ listened_node_type ] . append ( policy ) </s>
