Finish refactoring rules.

This commit is contained in:
Dave Halter
2017-08-17 09:33:46 +02:00
parent e37e2e1ff6
commit 8d20f3d469
3 changed files with 38 additions and 19 deletions

View File

@@ -2,11 +2,23 @@ from contextlib import contextmanager
class Normalizer(object):
_rule_value_classes = {}
_rule_type_classes = {}
def __init__(self, grammar, config):
self._grammar = grammar
self._config = config
self.issues = []
self._rule_type_instances = self._instantiate_rules(self._rule_type_classes)
self._rule_value_instances = self._instantiate_rules(self._rule_value_classes)
def _instantiate_rules(self, rules_map):
dct = {}
for type_, rule_classes in rules_map.items():
dct[type_] = [rule_cls(self) for rule_cls in rule_classes]
return dct
def walk(self, node):
self.initialize(node)
value = self.visit(node)
@@ -24,9 +36,18 @@ class Normalizer(object):
@contextmanager
def visit_node(self, node):
for rule in self._rule_type_instances.get(node.type, []):
rule.feed_node(node)
yield
def visit_leaf(self, leaf):
for rule in self._rule_type_instances.get(leaf.type, []):
rule.feed_node(leaf)
for rule in self._rule_value_instances.get(leaf.value, []):
rule.feed_node(leaf)
return leaf.prefix + leaf.value
def initialize(self, node):
@@ -41,24 +62,12 @@ class Normalizer(object):
self.issues.append(issue)
return True
class NormalizerConfig(object):
normalizer_class = Normalizer
rule_value_map = {}
rule_type_map = {}
def create_normalizer(self, grammar):
if self.normalizer_class is None:
return None
return self.normalizer_class(grammar, self)
@classmethod
def register_rule(cls, **kwargs):
"""
Use it as a class decorator:
>>> normalizer = NormalizerConfig()
>>> normalizer = Normalizer('grammar', 'config')
>>> @normalizer.register_rule(value='foo')
... class MyRule(Rule):
... error_code = 42
@@ -70,16 +79,26 @@ class NormalizerConfig(object):
if value is None and type is None:
raise ValueError("You must register at least something.")
def decorator(func):
def decorator(rule_cls):
if value is not None:
cls.rule_value_map[value] = func
cls._rule_value_classes.setdefault(value, []).append(rule_cls)
if type is not None:
cls.rule_type_map[type] = func
return func
cls._rule_type_classes.setdefault(type, []).append(rule_cls)
return rule_cls
return decorator
class NormalizerConfig(object):
normalizer_class = Normalizer
def create_normalizer(self, grammar):
if self.normalizer_class is None:
return None
return self.normalizer_class(grammar, self)
class Issue(object):
def __init__(self, node, code, message):
self._node = node

View File

@@ -793,7 +793,7 @@ class IndentationRule(Rule):
code = 903
@ErrorFinderConfig.register_rule(value='await')
@ErrorFinder.register_rule(value='await')
class AwaitOutsideAsync(SyntaxRule):
message = "'await' outside async function"

View File

@@ -712,7 +712,7 @@ class PEP8NormalizerConfig(ErrorFinderConfig):
self.spaces_before_comment = spaces_before_comment
@PEP8NormalizerConfig.register_rule(type='endmarker')
@PEP8Normalizer.register_rule(type='endmarker')
class BlankLineAtEnd(Rule):
code = 392
message = 'Blank line at end of file'