]> crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/parso/normalizer.py
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / parso / normalizer.py
1 from contextlib import contextmanager
2 from typing import Dict, List
3
4
5 class _NormalizerMeta(type):
6 def __new__(cls, name, bases, dct):
7 new_cls = type.__new__(cls, name, bases, dct)
8 new_cls.rule_value_classes = {}
9 new_cls.rule_type_classes = {}
10 return new_cls
11
12
13 class Normalizer(metaclass=_NormalizerMeta):
14 _rule_type_instances: Dict[str, List[type]] = {}
15 _rule_value_instances: Dict[str, List[type]] = {}
16
17 def __init__(self, grammar, config):
18 self.grammar = grammar
19 self._config = config
20 self.issues = []
21
22 self._rule_type_instances = self._instantiate_rules('rule_type_classes')
23 self._rule_value_instances = self._instantiate_rules('rule_value_classes')
24
25 def _instantiate_rules(self, attr):
26 dct = {}
27 for base in type(self).mro():
28 rules_map = getattr(base, attr, {})
29 for type_, rule_classes in rules_map.items():
30 new = [rule_cls(self) for rule_cls in rule_classes]
31 dct.setdefault(type_, []).extend(new)
32 return dct
33
34 def walk(self, node):
35 self.initialize(node)
36 value = self.visit(node)
37 self.finalize()
38 return value
39
40 def visit(self, node):
41 try:
42 children = node.children
43 except AttributeError:
44 return self.visit_leaf(node)
45 else:
46 with self.visit_node(node):
47 return ''.join(self.visit(child) for child in children)
48
49 @contextmanager
50 def visit_node(self, node):
51 self._check_type_rules(node)
52 yield
53
54 def _check_type_rules(self, node):
55 for rule in self._rule_type_instances.get(node.type, []):
56 rule.feed_node(node)
57
58 def visit_leaf(self, leaf):
59 self._check_type_rules(leaf)
60
61 for rule in self._rule_value_instances.get(leaf.value, []):
62 rule.feed_node(leaf)
63
64 return leaf.prefix + leaf.value
65
66 def initialize(self, node):
67 pass
68
69 def finalize(self):
70 pass
71
72 def add_issue(self, node, code, message):
73 issue = Issue(node, code, message)
74 if issue not in self.issues:
75 self.issues.append(issue)
76 return True
77
78 @classmethod
79 def register_rule(cls, *, value=None, values=(), type=None, types=()):
80 """
81 Use it as a class decorator::
82
83 normalizer = Normalizer('grammar', 'config')
84 @normalizer.register_rule(value='foo')
85 class MyRule(Rule):
86 error_code = 42
87 """
88 values = list(values)
89 types = list(types)
90 if value is not None:
91 values.append(value)
92 if type is not None:
93 types.append(type)
94
95 if not values and not types:
96 raise ValueError("You must register at least something.")
97
98 def decorator(rule_cls):
99 for v in values:
100 cls.rule_value_classes.setdefault(v, []).append(rule_cls)
101 for t in types:
102 cls.rule_type_classes.setdefault(t, []).append(rule_cls)
103 return rule_cls
104
105 return decorator
106
107
108 class NormalizerConfig:
109 normalizer_class = Normalizer
110
111 def create_normalizer(self, grammar):
112 if self.normalizer_class is None:
113 return None
114
115 return self.normalizer_class(grammar, self)
116
117
118 class Issue:
119 def __init__(self, node, code, message):
120 self.code = code
121 """
122 An integer code that stands for the type of error.
123 """
124 self.message = message
125 """
126 A message (string) for the issue.
127 """
128 self.start_pos = node.start_pos
129 """
130 The start position position of the error as a tuple (line, column). As
131 always in |parso| the first line is 1 and the first column 0.
132 """
133 self.end_pos = node.end_pos
134
135 def __eq__(self, other):
136 return self.start_pos == other.start_pos and self.code == other.code
137
138 def __ne__(self, other):
139 return not self.__eq__(other)
140
141 def __hash__(self):
142 return hash((self.code, self.start_pos))
143
144 def __repr__(self):
145 return '<%s: %s>' % (self.__class__.__name__, self.code)
146
147
148 class Rule:
149 code: int
150 message: str
151
152 def __init__(self, normalizer):
153 self._normalizer = normalizer
154
155 def is_issue(self, node):
156 raise NotImplementedError()
157
158 def get_node(self, node):
159 return node
160
161 def _get_message(self, message, node):
162 if message is None:
163 message = self.message
164 if message is None:
165 raise ValueError("The message on the class is not set.")
166 return message
167
168 def add_issue(self, node, code=None, message=None):
169 if code is None:
170 code = self.code
171 if code is None:
172 raise ValueError("The error code on the class is not set.")
173
174 message = self._get_message(message, node)
175
176 self._normalizer.add_issue(node, code, message)
177
178 def feed_node(self, node):
179 if self.is_issue(node):
180 issue_node = self.get_node(node)
181 self.add_issue(issue_node)
182
183
184 class RefactoringNormalizer(Normalizer):
185 def __init__(self, node_to_str_map):
186 self._node_to_str_map = node_to_str_map
187
188 def visit(self, node):
189 try:
190 return self._node_to_str_map[node]
191 except KeyError:
192 return super().visit(node)
193
194 def visit_leaf(self, leaf):
195 try:
196 return self._node_to_str_map[leaf]
197 except KeyError:
198 return super().visit_leaf(leaf)