mirror of
https://github.com/davidhalter/parso.git
synced 2026-01-10 21:42:44 +08:00
Refactor the Rule class a bit.
This commit is contained in:
@@ -44,6 +44,8 @@ class Normalizer(object):
|
|||||||
|
|
||||||
class NormalizerConfig(object):
|
class NormalizerConfig(object):
|
||||||
normalizer_class = Normalizer
|
normalizer_class = Normalizer
|
||||||
|
rule_value_map = {}
|
||||||
|
rule_type_map = {}
|
||||||
|
|
||||||
def create_normalizer(self, grammar):
|
def create_normalizer(self, grammar):
|
||||||
if self.normalizer_class is None:
|
if self.normalizer_class is None:
|
||||||
@@ -52,21 +54,30 @@ class NormalizerConfig(object):
|
|||||||
return self.normalizer_class(grammar, self)
|
return self.normalizer_class(grammar, self)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register_rule(cls, rule):
|
def register_rule(cls, **kwargs):
|
||||||
"""
|
"""
|
||||||
Use it as a class decorator:
|
Use it as a class decorator:
|
||||||
|
|
||||||
>>> normalizer = NormalizerConfig()
|
>>> normalizer = NormalizerConfig()
|
||||||
>>> @normalizer.register_rule
|
>>> @normalizer.register_rule(value='foo')
|
||||||
... class MyRule(Rule):
|
... class MyRule(Rule):
|
||||||
... error_code = 42
|
... error_code = 42
|
||||||
"""
|
"""
|
||||||
try:
|
return cls._register_rule(**kwargs)
|
||||||
rules = cls.rules
|
|
||||||
except AttributeError:
|
@classmethod
|
||||||
rules = cls.rules = []
|
def _register_rule(cls, value=None, type=None):
|
||||||
rules.append(rule)
|
if value is None and type is None:
|
||||||
return rule
|
raise ValueError("You must register at least something.")
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
if value is not None:
|
||||||
|
cls.rule_value_map[value] = func
|
||||||
|
if type is not None:
|
||||||
|
cls.rule_type_map[type] = func
|
||||||
|
return func
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
class Issue(object):
|
class Issue(object):
|
||||||
@@ -93,4 +104,24 @@ class Issue(object):
|
|||||||
class Rule(object):
|
class Rule(object):
|
||||||
error_code = None
|
error_code = None
|
||||||
message = None
|
message = None
|
||||||
type = None
|
|
||||||
|
def check(self, node):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_error_node(self, node):
|
||||||
|
return node
|
||||||
|
|
||||||
|
def add_error(self, error_code=None, message=None):
|
||||||
|
if error_code is None:
|
||||||
|
error_code = self.error_code
|
||||||
|
if error_code is None:
|
||||||
|
raise ValueError("The error code on the class is not set.")
|
||||||
|
|
||||||
|
if message is None:
|
||||||
|
message = self.message
|
||||||
|
if message is None:
|
||||||
|
raise ValueError("The message on the class is not set.")
|
||||||
|
|
||||||
|
def feed_node(self, node):
|
||||||
|
if self.check(node):
|
||||||
|
error_node = self.get_error_node(node)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import warnings
|
|||||||
import re
|
import re
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from parso.normalizer import Normalizer, NormalizerConfig, Issue
|
from parso.normalizer import Normalizer, NormalizerConfig, Issue, Rule
|
||||||
from parso.python.tree import search_ancestor
|
from parso.python.tree import search_ancestor
|
||||||
|
|
||||||
_BLOCK_STMTS = ('if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt')
|
_BLOCK_STMTS = ('if_stmt', 'while_stmt', 'for_stmt', 'try_stmt', 'with_stmt')
|
||||||
@@ -671,9 +671,6 @@ class ErrorFinder(Normalizer):
|
|||||||
and leaf.get_next_leaf() != 'from' \
|
and leaf.get_next_leaf() != 'from' \
|
||||||
and self._version == (3, 5):
|
and self._version == (3, 5):
|
||||||
self._add_syntax_error("'yield' inside async function", leaf.parent)
|
self._add_syntax_error("'yield' inside async function", leaf.parent)
|
||||||
elif leaf.value == 'await':
|
|
||||||
if not self._context.is_async_funcdef():
|
|
||||||
self._add_syntax_error("'await' outside async function", leaf.parent)
|
|
||||||
elif leaf.value == 'from' and leaf.parent.type == 'yield_arg' \
|
elif leaf.value == 'from' and leaf.parent.type == 'yield_arg' \
|
||||||
and self._context.is_async_funcdef():
|
and self._context.is_async_funcdef():
|
||||||
yield_ = leaf.parent.parent
|
yield_ = leaf.parent.parent
|
||||||
@@ -783,3 +780,22 @@ class ErrorFinder(Normalizer):
|
|||||||
|
|
||||||
class ErrorFinderConfig(NormalizerConfig):
|
class ErrorFinderConfig(NormalizerConfig):
|
||||||
normalizer_class = ErrorFinder
|
normalizer_class = ErrorFinder
|
||||||
|
|
||||||
|
|
||||||
|
class SyntaxRule(Rule):
|
||||||
|
code = 901
|
||||||
|
|
||||||
|
|
||||||
|
class IndentationRule(Rule):
|
||||||
|
code = 903
|
||||||
|
|
||||||
|
|
||||||
|
@ErrorFinderConfig.register_rule(value='await')
|
||||||
|
class AwaitOutsideAsync(SyntaxRule):
|
||||||
|
message = "'await' outside async function"
|
||||||
|
|
||||||
|
def check_leaf_value(self, leaf):
|
||||||
|
return not self._context.is_async_funcdef()
|
||||||
|
|
||||||
|
def get_error_node(self, node):
|
||||||
|
return node.parent # Return the whole await statement.
|
||||||
|
|||||||
@@ -712,17 +712,10 @@ class PEP8NormalizerConfig(ErrorFinderConfig):
|
|||||||
self.spaces_before_comment = spaces_before_comment
|
self.spaces_before_comment = spaces_before_comment
|
||||||
|
|
||||||
|
|
||||||
@PEP8NormalizerConfig.register_rule
|
@PEP8NormalizerConfig.register_rule(type='endmarker')
|
||||||
class FooRule(Rule):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
@PEP8NormalizerConfig.register_rule
|
|
||||||
class BlankLineAtEnd(Rule):
|
class BlankLineAtEnd(Rule):
|
||||||
code = 392
|
code = 392
|
||||||
message = 'Blank line at end of file'
|
message = 'Blank line at end of file'
|
||||||
|
|
||||||
leaf_event = ['endmarker']
|
|
||||||
|
|
||||||
def check(self, leaf):
|
def check(self, leaf):
|
||||||
return self._newline_count >= 2
|
return self._newline_count >= 2
|
||||||
|
|||||||
Reference in New Issue
Block a user