"""Custom rule demonstrating pluggable extensibility (A1b).""" import ast from typing import Optional from app.dataset.rules.base import Mutation, MutationRule class UnusedVariableRule(MutationRule): """A custom rule: replace a variable read with an undefined name. This is intentionally simple and demonstrates that adding a new file under app/dataset/rules// is enough to register a rule. """ name = "unused_variable_demo" language = "python" defect_type = "custom_demo" def detect_and_mutate(self, source: str, filename: str = "") -> Optional[Mutation]: try: tree = ast.parse(source) except SyntaxError: return None for node in ast.walk(tree): if isinstance(node, ast.FunctionDef) and node.body: first = node.body[0] if isinstance(first, ast.Assign) and isinstance(first.targets[0], ast.Name): var_name = first.targets[0].id line_no = first.lineno lines = source.splitlines(keepends=True) line = lines[line_no - 1] mutated_line = line.replace(var_name, "__undefined_" + var_name, 1) if mutated_line == line: continue mutated = "".join(lines[:line_no - 1] + [mutated_line] + lines[line_no:]) return Mutation( defect_type=self.defect_type, language=self.language, line_start=line_no, line_end=line_no, mutated_source=mutated, reference_fix=f"Use the original variable name '{var_name}'.", description=f"Custom rule: replaced '{var_name}' with an undefined placeholder.", ) return None