|
3 | 3 | from tree_sitter import Language, Parser |
4 | 4 |
|
5 | 5 | import staticcodecov_languages |
| 6 | +from codecov_cli.services.staticanalysis.analyzers.general import BaseAnalyzer |
6 | 7 | from codecov_cli.services.staticanalysis.analyzers.python.node_wrappers import ( |
7 | 8 | NodeVisitor, |
8 | 9 | ) |
|
41 | 42 | """ |
42 | 43 |
|
43 | 44 |
|
44 | | -class PythonAnalyzer(object): |
| 45 | +class PythonAnalyzer(BaseAnalyzer): |
45 | 46 |
|
46 | 47 | condition_statements = [ |
47 | 48 | "if_statement", |
48 | 49 | "while_statement", |
49 | 50 | "for_statement", |
50 | 51 | "conditional_expression", |
51 | 52 | ] |
| 53 | + wrappers = ["class_definition", "function_definition"] |
52 | 54 |
|
53 | 55 | def __init__(self, path, actual_code, **options): |
54 | 56 | self.actual_code = actual_code |
@@ -127,64 +129,7 @@ def process(self): |
127 | 129 | "import_lines": sorted(self.import_lines), |
128 | 130 | } |
129 | 131 |
|
130 | | - def _count_elements(self, node, types): |
131 | | - count = 0 |
132 | | - for c in node.children: |
133 | | - count += self._count_elements(c, types) |
134 | | - if node.type in types: |
135 | | - count += 1 |
136 | | - return count |
137 | | - |
138 | | - def _get_max_nested_conditional(self, node): |
139 | | - return (1 if node.type in self.condition_statements else 0) + max( |
140 | | - (self._get_max_nested_conditional(x) for x in node.children), default=0 |
141 | | - ) |
142 | | - |
143 | | - def _get_complexity_metrics(self, body_node): |
144 | | - number_conditions = self._count_elements( |
145 | | - body_node, |
146 | | - [ |
147 | | - "if_statement", |
148 | | - "while_statement", |
149 | | - "for_statement", |
150 | | - "conditional_expression", |
151 | | - ], |
152 | | - ) |
153 | | - return { |
154 | | - "conditions": number_conditions, |
155 | | - "mccabe_cyclomatic_complexity": number_conditions + 1, |
156 | | - "returns": self._count_elements(body_node, ["return_statement"]), |
157 | | - "max_nested_conditional": self._get_max_nested_conditional(body_node), |
158 | | - } |
159 | | - |
160 | 132 | def _get_code_hash(self, start_byte, end_byte): |
161 | 133 | j = hashlib.md5() |
162 | 134 | j.update(self.actual_code[start_byte:end_byte].strip()) |
163 | 135 | return j.hexdigest() |
164 | | - |
165 | | - def _get_parent_chain(self, node): |
166 | | - cur = node.parent |
167 | | - while cur: |
168 | | - yield cur |
169 | | - cur = cur.parent |
170 | | - |
171 | | - def _get_name(self, node): |
172 | | - name_node = node.child_by_field_name("name") |
173 | | - actual_name = self.actual_code[ |
174 | | - name_node.start_byte : name_node.end_byte |
175 | | - ].decode() |
176 | | - try: |
177 | | - wrapping_class = next( |
178 | | - x |
179 | | - for x in self._get_parent_chain(node) |
180 | | - if x.type in ("class_definition", "function_definition") |
181 | | - ) |
182 | | - except StopIteration: |
183 | | - wrapping_class = None |
184 | | - if wrapping_class is not None: |
185 | | - class_name_node = wrapping_class.child_by_field_name("name") |
186 | | - class_name = self.actual_code[ |
187 | | - class_name_node.start_byte : class_name_node.end_byte |
188 | | - ].decode() |
189 | | - return f"{class_name}::{actual_name}" |
190 | | - return actual_name |
0 commit comments