habit-hooks-php 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- habit_hooks_php/__init__.py +1 -0
- habit_hooks_php/config.toml +5 -0
- habit_hooks_php/guides/unused-variable.md +4 -0
- habit_hooks_php/sensors/phpmd.phar +0 -0
- habit_hooks_php/sensors/phpmd.toml +1 -0
- habit_hooks_php/sensors/phpmd_sensor.py +91 -0
- habit_hooks_php-1.0.0.dist-info/METADATA +5 -0
- habit_hooks_php-1.0.0.dist-info/RECORD +10 -0
- habit_hooks_php-1.0.0.dist-info/WHEEL +4 -0
- habit_hooks_php-1.0.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""The php Habit Hooks plugin: package data discovered via the habit_hooks.plugins entry point."""
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{% include "includes/line_level_issues.md" %}
|
|
2
|
+
An unused local variable is dead weight: the reader has to prove to themselves it does not matter. It usually signals one of three things — a computation whose result is never consumed (delete the computation, not just the assignment), a leftover from a refactor that moved logic elsewhere, or a value you meant to use and forgot to wire in (the real bug).
|
|
3
|
+
|
|
4
|
+
Decide which it is before deleting. If the right-hand side has side effects you still need, keep the call but drop the binding. If it was meant to be returned or passed on, finish that thread rather than silencing the warning. Suppressing it with a throwaway name hides the question instead of answering it.
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
command = "python ${dir}/phpmd_sensor.py ${files}"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Run PHPMD and print canonical smell findings.
|
|
2
|
+
|
|
3
|
+
PHPMD exits 2 when it finds violations and 1 on a real error, so a bare pipe
|
|
4
|
+
cannot tell a clean run from a crash. This wrapper runs PHPMD against the scoped
|
|
5
|
+
files, treats only 0/2 as success, and shapes each rule into the canonical
|
|
6
|
+
finding, mapping PHPMD rule names to smell keys.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import subprocess
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
RULE_SMELLS = {
|
|
17
|
+
"ExcessiveParameterList": "too-many-parameters",
|
|
18
|
+
"CyclomaticComplexity": "high-complexity",
|
|
19
|
+
"ExcessiveMethodLength": "oversized-function",
|
|
20
|
+
"UnusedLocalVariable": "unused-variable",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
RULESETS = "codesize,unusedcode"
|
|
24
|
+
SUCCESS_EXIT_CODES = (0, 2)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def run_phpmd(files: list[str]) -> subprocess.CompletedProcess[str]:
|
|
28
|
+
phar = str(Path(__file__).with_name("phpmd.phar"))
|
|
29
|
+
command = [
|
|
30
|
+
"php",
|
|
31
|
+
"-d",
|
|
32
|
+
"error_reporting=0",
|
|
33
|
+
"-d",
|
|
34
|
+
"display_errors=0",
|
|
35
|
+
phar,
|
|
36
|
+
",".join(files),
|
|
37
|
+
"json",
|
|
38
|
+
RULESETS,
|
|
39
|
+
]
|
|
40
|
+
return subprocess.run(command, capture_output=True, text=True)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def violations(report: dict) -> list[dict]:
|
|
44
|
+
return [
|
|
45
|
+
{"file": file["file"], "violation": violation}
|
|
46
|
+
for file in report.get("files", [])
|
|
47
|
+
for violation in file["violations"]
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def issue(entry: dict) -> dict:
|
|
52
|
+
violation = entry["violation"]
|
|
53
|
+
return {
|
|
54
|
+
"key": entry["file"],
|
|
55
|
+
"details": {
|
|
56
|
+
"file": entry["file"],
|
|
57
|
+
"line": violation["beginLine"],
|
|
58
|
+
"message": violation["description"],
|
|
59
|
+
"source": "phpmd:" + violation["rule"],
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def findings(entries: list[dict]) -> list[dict]:
|
|
65
|
+
by_smell: dict[str, list[dict]] = {}
|
|
66
|
+
for entry in entries:
|
|
67
|
+
smell = RULE_SMELLS.get(entry["violation"]["rule"])
|
|
68
|
+
if smell is not None:
|
|
69
|
+
by_smell.setdefault(smell, []).append(issue(entry))
|
|
70
|
+
return [
|
|
71
|
+
{"smell": smell, "details": {}, "issues": issues}
|
|
72
|
+
for smell, issues in by_smell.items()
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def main() -> int:
|
|
77
|
+
files = sys.argv[1:]
|
|
78
|
+
if not files:
|
|
79
|
+
print("[]")
|
|
80
|
+
return 0
|
|
81
|
+
result = run_phpmd(files)
|
|
82
|
+
if result.returncode not in SUCCESS_EXIT_CODES:
|
|
83
|
+
sys.stderr.write(result.stderr or result.stdout)
|
|
84
|
+
return 2
|
|
85
|
+
report = json.loads(result.stdout)
|
|
86
|
+
print(json.dumps(findings(violations(report))))
|
|
87
|
+
return 0
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
if __name__ == "__main__":
|
|
91
|
+
sys.exit(main())
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
habit_hooks_php/__init__.py,sha256=Ri-WRtCwo7MgXzR3hDP9UZQb_IOeWABCSTz7OjQizn0,99
|
|
2
|
+
habit_hooks_php/config.toml,sha256=AhNY0IkvREB_OQPckLnRzlSpVWVoQ9bWm1ntZv6Tn-w,99
|
|
3
|
+
habit_hooks_php/guides/unused-variable.md,sha256=FzsT05P9gsslRtZSFHoc9vnyxVQpiSlrW4nU95m2IWg,714
|
|
4
|
+
habit_hooks_php/sensors/phpmd.phar,sha256=aijvVd4MdTsHDR0VgLsIoNFGAW-J8O3c72CsT8EINUQ,3168622
|
|
5
|
+
habit_hooks_php/sensors/phpmd.toml,sha256=pn4Aq_4OSvT7my03Js3TtrEed61HxrSlLtvII_sC-Pg,51
|
|
6
|
+
habit_hooks_php/sensors/phpmd_sensor.py,sha256=0OGgMSJSNbCqbbpDR9z1Wc2V68D7i-i19dPqKQFgWSU,2449
|
|
7
|
+
habit_hooks_php-1.0.0.dist-info/METADATA,sha256=ftUpJ0Vmrd02oezvdJa1lCa9pcaRkAwqHApMu1IgnJc,119
|
|
8
|
+
habit_hooks_php-1.0.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
9
|
+
habit_hooks_php-1.0.0.dist-info/entry_points.txt,sha256=7Uepfg4PE7W_V74t0xOsKo9VrUUXMOqxPCBl14Baf4M,44
|
|
10
|
+
habit_hooks_php-1.0.0.dist-info/RECORD,,
|