codesift-mcp 0.7.0 → 0.8.2
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.
- package/README.md +3 -3
- package/dist/cli/git-hooks-installer.d.ts.map +1 -1
- package/dist/cli/git-hooks-installer.js +18 -5
- package/dist/cli/git-hooks-installer.js.map +1 -1
- package/dist/cli/hooks.d.ts.map +1 -1
- package/dist/cli/hooks.js +53 -0
- package/dist/cli/hooks.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +31 -5
- package/dist/cli/setup.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -1
- package/dist/config.js.map +1 -1
- package/dist/instructions.d.ts +1 -1
- package/dist/instructions.d.ts.map +1 -1
- package/dist/instructions.js +6 -1
- package/dist/instructions.js.map +1 -1
- package/dist/parser/extractors/hono.d.ts.map +1 -1
- package/dist/parser/extractors/hono.js +21 -13
- package/dist/parser/extractors/hono.js.map +1 -1
- package/dist/parser/extractors/php.d.ts +12 -0
- package/dist/parser/extractors/php.d.ts.map +1 -1
- package/dist/parser/extractors/php.js +440 -26
- package/dist/parser/extractors/php.js.map +1 -1
- package/dist/register-tool-loaders.d.ts +16 -0
- package/dist/register-tool-loaders.d.ts.map +1 -1
- package/dist/register-tool-loaders.js +26 -0
- package/dist/register-tool-loaders.js.map +1 -1
- package/dist/register-tools.d.ts +3 -1
- package/dist/register-tools.d.ts.map +1 -1
- package/dist/register-tools.js +354 -7
- package/dist/register-tools.js.map +1 -1
- package/dist/retrieval/codebase-retrieval.d.ts.map +1 -1
- package/dist/retrieval/codebase-retrieval.js +22 -0
- package/dist/retrieval/codebase-retrieval.js.map +1 -1
- package/dist/retrieval/retrieval-schemas.d.ts +4 -0
- package/dist/retrieval/retrieval-schemas.d.ts.map +1 -1
- package/dist/retrieval/semantic-handlers.js +1 -1
- package/dist/retrieval/semantic-handlers.js.map +1 -1
- package/dist/search/semantic.d.ts +21 -5
- package/dist/search/semantic.d.ts.map +1 -1
- package/dist/search/semantic.js +129 -4
- package/dist/search/semantic.js.map +1 -1
- package/dist/search/tool-ranker.js +1 -1
- package/dist/search/tool-ranker.js.map +1 -1
- package/dist/server-helpers.js +1 -1
- package/dist/server-helpers.js.map +1 -1
- package/dist/storage/index-store.d.ts.map +1 -1
- package/dist/storage/index-store.js +7 -5
- package/dist/storage/index-store.js.map +1 -1
- package/dist/storage/registry.d.ts +28 -4
- package/dist/storage/registry.d.ts.map +1 -1
- package/dist/storage/registry.js +126 -5
- package/dist/storage/registry.js.map +1 -1
- package/dist/storage/usage-stats.d.ts +2 -0
- package/dist/storage/usage-stats.d.ts.map +1 -1
- package/dist/storage/usage-stats.js +6 -0
- package/dist/storage/usage-stats.js.map +1 -1
- package/dist/tools/_helpers.d.ts.map +1 -1
- package/dist/tools/_helpers.js +14 -0
- package/dist/tools/_helpers.js.map +1 -1
- package/dist/tools/conversation-tools.js +1 -1
- package/dist/tools/conversation-tools.js.map +1 -1
- package/dist/tools/index-tools.d.ts +12 -0
- package/dist/tools/index-tools.d.ts.map +1 -1
- package/dist/tools/index-tools.js +52 -5
- package/dist/tools/index-tools.js.map +1 -1
- package/dist/tools/insights-tools.d.ts +137 -0
- package/dist/tools/insights-tools.d.ts.map +1 -0
- package/dist/tools/insights-tools.js +438 -0
- package/dist/tools/insights-tools.js.map +1 -0
- package/dist/tools/pattern-tools.d.ts +7 -0
- package/dist/tools/pattern-tools.d.ts.map +1 -1
- package/dist/tools/pattern-tools.js +287 -15
- package/dist/tools/pattern-tools.js.map +1 -1
- package/dist/tools/php-tools.d.ts +78 -4
- package/dist/tools/php-tools.d.ts.map +1 -1
- package/dist/tools/php-tools.js +824 -42
- package/dist/tools/php-tools.js.map +1 -1
- package/dist/tools/php8-compat-tools.d.ts +62 -0
- package/dist/tools/php8-compat-tools.d.ts.map +1 -0
- package/dist/tools/php8-compat-tools.js +287 -0
- package/dist/tools/php8-compat-tools.js.map +1 -0
- package/dist/tools/php8-migration-candidates-tools.d.ts +68 -0
- package/dist/tools/php8-migration-candidates-tools.d.ts.map +1 -0
- package/dist/tools/php8-migration-candidates-tools.js +476 -0
- package/dist/tools/php8-migration-candidates-tools.js.map +1 -0
- package/dist/tools/phpstan-baseline-tools.d.ts +62 -0
- package/dist/tools/phpstan-baseline-tools.d.ts.map +1 -0
- package/dist/tools/phpstan-baseline-tools.js +263 -0
- package/dist/tools/phpstan-baseline-tools.js.map +1 -0
- package/dist/tools/project-tools.d.ts +4 -2
- package/dist/tools/project-tools.d.ts.map +1 -1
- package/dist/tools/project-tools.js +19 -6
- package/dist/tools/project-tools.js.map +1 -1
- package/dist/tools/react-tools.d.ts +24 -0
- package/dist/tools/react-tools.d.ts.map +1 -1
- package/dist/tools/react-tools.js +292 -3
- package/dist/tools/react-tools.js.map +1 -1
- package/dist/tools/search-tools.d.ts.map +1 -1
- package/dist/tools/search-tools.js +35 -5
- package/dist/tools/search-tools.js.map +1 -1
- package/dist/tools/symbol-tools.d.ts.map +1 -1
- package/dist/tools/symbol-tools.js +4 -1
- package/dist/tools/symbol-tools.js.map +1 -1
- package/dist/tools/yii-console-tools.d.ts +69 -0
- package/dist/tools/yii-console-tools.d.ts.map +1 -0
- package/dist/tools/yii-console-tools.js +256 -0
- package/dist/tools/yii-console-tools.js.map +1 -0
- package/dist/tools/yii-migrations-tools.d.ts +79 -0
- package/dist/tools/yii-migrations-tools.d.ts.map +1 -0
- package/dist/tools/yii-migrations-tools.js +543 -0
- package/dist/tools/yii-migrations-tools.js.map +1 -0
- package/dist/tools/yii-modules-tools.d.ts +63 -0
- package/dist/tools/yii-modules-tools.d.ts.map +1 -0
- package/dist/tools/yii-modules-tools.js +201 -0
- package/dist/tools/yii-modules-tools.js.map +1 -0
- package/dist/tools/yii-rbac-tools.d.ts +89 -0
- package/dist/tools/yii-rbac-tools.d.ts.map +1 -0
- package/dist/tools/yii-rbac-tools.js +238 -0
- package/dist/tools/yii-rbac-tools.js.map +1 -0
- package/dist/tools/yii3-attribute-candidates-tools.d.ts +72 -0
- package/dist/tools/yii3-attribute-candidates-tools.d.ts.map +1 -0
- package/dist/tools/yii3-attribute-candidates-tools.js +301 -0
- package/dist/tools/yii3-attribute-candidates-tools.js.map +1 -0
- package/dist/tools/yii3-migration-tools.d.ts +74 -0
- package/dist/tools/yii3-migration-tools.d.ts.map +1 -0
- package/dist/tools/yii3-migration-tools.js +440 -0
- package/dist/tools/yii3-migration-tools.js.map +1 -0
- package/dist/types.d.ts +5 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/constant-file-pattern.d.ts +3 -1
- package/dist/utils/constant-file-pattern.d.ts.map +1 -1
- package/dist/utils/constant-file-pattern.js +6 -4
- package/dist/utils/constant-file-pattern.js.map +1 -1
- package/dist/utils/heritage-edges.d.ts +16 -0
- package/dist/utils/heritage-edges.d.ts.map +1 -1
- package/dist/utils/heritage-edges.js +31 -10
- package/dist/utils/heritage-edges.js.map +1 -1
- package/dist/utils/source-stripper.d.ts +23 -0
- package/dist/utils/source-stripper.d.ts.map +1 -0
- package/dist/utils/source-stripper.js +239 -0
- package/dist/utils/source-stripper.js.map +1 -0
- package/dist/utils/tsconfig-paths.d.ts +2 -2
- package/dist/utils/tsconfig-paths.d.ts.map +1 -1
- package/dist/utils/tsconfig-paths.js +10 -4
- package/dist/utils/tsconfig-paths.js.map +1 -1
- package/dist/utils/wall-clock.d.ts +9 -0
- package/dist/utils/wall-clock.d.ts.map +1 -0
- package/dist/utils/wall-clock.js +19 -0
- package/dist/utils/wall-clock.js.map +1 -0
- package/package.json +1 -1
- package/rules/codesift.md +10 -3
- package/rules/codesift.mdc +10 -3
- package/rules/codex.md +10 -3
- package/rules/gemini.md +10 -3
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP 8 modernization candidate finder (M1).
|
|
3
|
+
*
|
|
4
|
+
* Companion to M3 (php8_compat_check). Where M3 is the gating tool — "will
|
|
5
|
+
* this PHP 8 merge break anything" — M1 is the post-merge modernization
|
|
6
|
+
* tool. After PHP 8 lands, run M1 to surface places where the legacy
|
|
7
|
+
* 7.2-style idiom can be tightened up using new language features.
|
|
8
|
+
*
|
|
9
|
+
* Sub-checks (each is a regex pattern over file content):
|
|
10
|
+
*
|
|
11
|
+
* promotable-ctor ctor with N parameters whose body only does
|
|
12
|
+
* $this->x = $x assignments — collapse to
|
|
13
|
+
* promoted constructor (PHP 8.0+).
|
|
14
|
+
* docblock-to-typed-property /** @var T *\/ above an untyped public/private
|
|
15
|
+
* property — convert to inline `public T $x`
|
|
16
|
+
* (PHP 7.4+).
|
|
17
|
+
* nullable-flag-to-syntax /** @var T|null *\/ — same conversion but
|
|
18
|
+
* produces `public ?T $x`.
|
|
19
|
+
* readonly-candidate property only assigned in __construct — add
|
|
20
|
+
* `readonly` modifier (PHP 8.1+).
|
|
21
|
+
* enum-from-class-consts class with N const NAME = 'value' entries +
|
|
22
|
+
* a getValues()/getOptions() method — convert
|
|
23
|
+
* to a backed enum (PHP 8.1+).
|
|
24
|
+
* match-from-switch switch ($x) { case A: return ...; ...}
|
|
25
|
+
* without fall-through — convert to match.
|
|
26
|
+
*
|
|
27
|
+
* Each finding includes:
|
|
28
|
+
* - file, line, snippet
|
|
29
|
+
* - rule_id, severity (always "modernize" — informational, never blocking)
|
|
30
|
+
* - suggested_replacement: rough sketch of the new form (string, NOT
|
|
31
|
+
* auto-applied)
|
|
32
|
+
* - confidence: "high" | "medium" | "low"
|
|
33
|
+
*
|
|
34
|
+
* The tool is intentionally lossy: many candidates will be rejected after
|
|
35
|
+
* human review (e.g., a property "only assigned in ctor" might still be
|
|
36
|
+
* mutated via reflection for testing). The point is to triage thousands
|
|
37
|
+
* of files into a small reviewable list, not to auto-fix.
|
|
38
|
+
*/
|
|
39
|
+
import { readFile } from "node:fs/promises";
|
|
40
|
+
import { join } from "node:path";
|
|
41
|
+
import { getCodeIndex } from "./index-tools.js";
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Implementation
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
const VENDOR_RE = /(^|\/)(?:vendor|node_modules|runtime|tests\/_data)(\/|$)/;
|
|
46
|
+
const SAMPLE_LIMIT_PER_RULE = 5;
|
|
47
|
+
export async function findPhp8MigrationCandidates(repo, options) {
|
|
48
|
+
const index = await getCodeIndex(repo);
|
|
49
|
+
if (!index)
|
|
50
|
+
throw new Error(`Repository "${repo}" not found.`);
|
|
51
|
+
const sampleLimit = options?.max_samples_per_rule ?? SAMPLE_LIMIT_PER_RULE;
|
|
52
|
+
const includeVendor = options?.include_vendor ?? false;
|
|
53
|
+
const filePattern = options?.file_pattern;
|
|
54
|
+
const ruleFilter = options?.rules ? new Set(options.rules) : null;
|
|
55
|
+
const phpFiles = index.files.filter((f) => {
|
|
56
|
+
if (!f.path.endsWith(".php"))
|
|
57
|
+
return false;
|
|
58
|
+
if (!includeVendor && VENDOR_RE.test(f.path))
|
|
59
|
+
return false;
|
|
60
|
+
if (filePattern && !f.path.includes(filePattern))
|
|
61
|
+
return false;
|
|
62
|
+
return true;
|
|
63
|
+
});
|
|
64
|
+
const candidates = [];
|
|
65
|
+
// Symbol-level rules use the index directly (faster, no second file read).
|
|
66
|
+
if (!ruleFilter || ruleFilter.has("docblock-to-typed-property")) {
|
|
67
|
+
findDocblockToTypedProperty(index, candidates);
|
|
68
|
+
}
|
|
69
|
+
if (!ruleFilter || ruleFilter.has("nullable-flag-to-syntax")) {
|
|
70
|
+
findNullableFlagToSyntax(index, candidates);
|
|
71
|
+
}
|
|
72
|
+
if (!ruleFilter || ruleFilter.has("readonly-candidate")) {
|
|
73
|
+
findReadonlyCandidates(index, candidates);
|
|
74
|
+
}
|
|
75
|
+
if (!ruleFilter || ruleFilter.has("enum-from-class-consts")) {
|
|
76
|
+
findEnumFromClassConsts(index, candidates);
|
|
77
|
+
}
|
|
78
|
+
if (!ruleFilter || ruleFilter.has("promotable-ctor")) {
|
|
79
|
+
findPromotableCtor(index, candidates);
|
|
80
|
+
}
|
|
81
|
+
// File-level rule (match-from-switch) needs the raw source — switch/match
|
|
82
|
+
// can span across functions, so a per-symbol scan would miss cross-method
|
|
83
|
+
// patterns. Scoped to the file set we already filtered.
|
|
84
|
+
if (!ruleFilter || ruleFilter.has("match-from-switch")) {
|
|
85
|
+
await Promise.all(phpFiles.map(async (f) => {
|
|
86
|
+
let content;
|
|
87
|
+
try {
|
|
88
|
+
content = await readFile(join(index.root, f.path), "utf-8");
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
findMatchFromSwitch(content, f.path, candidates);
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
// Group by rule with sample cap.
|
|
97
|
+
const byRuleMap = new Map();
|
|
98
|
+
for (const c of candidates) {
|
|
99
|
+
if (!byRuleMap.has(c.rule_id))
|
|
100
|
+
byRuleMap.set(c.rule_id, []);
|
|
101
|
+
byRuleMap.get(c.rule_id).push(c);
|
|
102
|
+
}
|
|
103
|
+
const byRule = [...byRuleMap.entries()].map(([rule_id, list]) => ({
|
|
104
|
+
rule_id,
|
|
105
|
+
count: list.length,
|
|
106
|
+
description: RULE_DESCRIPTIONS[rule_id],
|
|
107
|
+
samples: list.slice(0, sampleLimit),
|
|
108
|
+
}));
|
|
109
|
+
byRule.sort((a, b) => b.count - a.count);
|
|
110
|
+
return {
|
|
111
|
+
repo,
|
|
112
|
+
scanned_files: phpFiles.length,
|
|
113
|
+
total_candidates: candidates.length,
|
|
114
|
+
by_rule: byRule,
|
|
115
|
+
candidates,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Rule descriptions (used in output for clarity)
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
const RULE_DESCRIPTIONS = {
|
|
122
|
+
"promotable-ctor": "__construct that only assigns parameters to same-named properties — collapse to PHP 8.0 promoted constructor.",
|
|
123
|
+
"docblock-to-typed-property": "/** @var T */ above an untyped property — convert to PHP 7.4 inline typed property `public T $x;`.",
|
|
124
|
+
"nullable-flag-to-syntax": "/** @var T|null */ above a property — convert to PHP 7.4 nullable typed property `public ?T $x;`.",
|
|
125
|
+
"readonly-candidate": "Property only assigned in __construct, no setter, no unset — add `readonly` modifier (PHP 8.1+).",
|
|
126
|
+
"enum-from-class-consts": "Pre-enum idiom: class of `const FOO = 'foo'` literals + getValues()/getOptions() — convert to PHP 8.1 backed enum.",
|
|
127
|
+
"match-from-switch": "switch with no fall-through where every case returns a value — convert to PHP 8.0 match expression.",
|
|
128
|
+
};
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// Rule implementations
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
/**
|
|
133
|
+
* docblock-to-typed-property: inline type would replace @var. Uses the v2.0.0
|
|
134
|
+
* extractor's `meta.type_source: "phpdoc"` flag — that's exactly the cohort
|
|
135
|
+
* we want (property has type info in the docblock but not inline).
|
|
136
|
+
*/
|
|
137
|
+
function findDocblockToTypedProperty(index, out) {
|
|
138
|
+
for (const sym of index.symbols) {
|
|
139
|
+
if (sym.kind !== "field")
|
|
140
|
+
continue;
|
|
141
|
+
if (!sym.file.endsWith(".php"))
|
|
142
|
+
continue;
|
|
143
|
+
if (sym.meta?.from_constructor)
|
|
144
|
+
continue; // skip promoted-ctor synth fields
|
|
145
|
+
const ts = sym.meta?.type_source;
|
|
146
|
+
if (ts !== "phpdoc")
|
|
147
|
+
continue;
|
|
148
|
+
const t = sym.meta?.type;
|
|
149
|
+
if (!t)
|
|
150
|
+
continue;
|
|
151
|
+
// Skip rule 2 patterns (nullable union) — they belong to nullable-flag-to-syntax
|
|
152
|
+
if (/\|null\b|\bnull\|/.test(t))
|
|
153
|
+
continue;
|
|
154
|
+
const visibility = sym.meta?.visibility ?? "public";
|
|
155
|
+
const propName = sym.name.replace(/^\$/, "");
|
|
156
|
+
out.push({
|
|
157
|
+
rule_id: "docblock-to-typed-property",
|
|
158
|
+
file: sym.file,
|
|
159
|
+
line: sym.start_line,
|
|
160
|
+
snippet: `/** @var ${t} */ ${visibility} ${sym.name}`,
|
|
161
|
+
description: RULE_DESCRIPTIONS["docblock-to-typed-property"],
|
|
162
|
+
suggested_replacement: `${visibility} ${normalizeDocblockType(t)} \$${propName};`,
|
|
163
|
+
confidence: rateTypeConfidence(t),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* nullable-flag-to-syntax: `@var T|null` → `?T`. Carved out from
|
|
169
|
+
* docblock-to-typed-property so callers can decide they want only the
|
|
170
|
+
* nullable conversion (which is the safer of the two — it never loses
|
|
171
|
+
* information).
|
|
172
|
+
*/
|
|
173
|
+
function findNullableFlagToSyntax(index, out) {
|
|
174
|
+
for (const sym of index.symbols) {
|
|
175
|
+
if (sym.kind !== "field")
|
|
176
|
+
continue;
|
|
177
|
+
if (!sym.file.endsWith(".php"))
|
|
178
|
+
continue;
|
|
179
|
+
if (sym.meta?.from_constructor)
|
|
180
|
+
continue;
|
|
181
|
+
if (sym.meta?.type_source !== "phpdoc")
|
|
182
|
+
continue;
|
|
183
|
+
const t = sym.meta?.type;
|
|
184
|
+
if (!t)
|
|
185
|
+
continue;
|
|
186
|
+
if (!/\|null\b|\bnull\|/.test(t))
|
|
187
|
+
continue;
|
|
188
|
+
const baseType = t.replace(/\|null$|^null\|/, "");
|
|
189
|
+
if (!baseType || baseType.includes("|"))
|
|
190
|
+
continue; // Multi-type union — not a simple ?T
|
|
191
|
+
const visibility = sym.meta?.visibility ?? "public";
|
|
192
|
+
const propName = sym.name.replace(/^\$/, "");
|
|
193
|
+
out.push({
|
|
194
|
+
rule_id: "nullable-flag-to-syntax",
|
|
195
|
+
file: sym.file,
|
|
196
|
+
line: sym.start_line,
|
|
197
|
+
snippet: `/** @var ${t} */ ${visibility} ${sym.name}`,
|
|
198
|
+
description: RULE_DESCRIPTIONS["nullable-flag-to-syntax"],
|
|
199
|
+
suggested_replacement: `${visibility} ?${normalizeDocblockType(baseType)} \$${propName};`,
|
|
200
|
+
confidence: rateTypeConfidence(baseType),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* readonly-candidate: property assigned only in __construct. We approximate
|
|
206
|
+
* by walking the parent class's source for `$this->propName = ` patterns
|
|
207
|
+
* and checking that all of them appear inside the __construct body (or
|
|
208
|
+
* inside a method we know is the ctor). Conservative — false positives
|
|
209
|
+
* acceptable for a discovery tool.
|
|
210
|
+
*/
|
|
211
|
+
function findReadonlyCandidates(index, out) {
|
|
212
|
+
// Group fields by parent class id so we can scan each class once.
|
|
213
|
+
const fieldsByClass = new Map();
|
|
214
|
+
for (const sym of index.symbols) {
|
|
215
|
+
if (sym.kind !== "field")
|
|
216
|
+
continue;
|
|
217
|
+
if (!sym.parent)
|
|
218
|
+
continue;
|
|
219
|
+
if (sym.meta?.is_readonly)
|
|
220
|
+
continue; // already readonly
|
|
221
|
+
if (sym.meta?.is_static)
|
|
222
|
+
continue;
|
|
223
|
+
if (!fieldsByClass.has(sym.parent))
|
|
224
|
+
fieldsByClass.set(sym.parent, []);
|
|
225
|
+
fieldsByClass.get(sym.parent).push(sym);
|
|
226
|
+
}
|
|
227
|
+
for (const [classId, fields] of fieldsByClass.entries()) {
|
|
228
|
+
const cls = index.symbols.find((s) => s.id === classId);
|
|
229
|
+
if (!cls || !cls.source)
|
|
230
|
+
continue;
|
|
231
|
+
// Find the constructor method by name (could be __construct).
|
|
232
|
+
const ctor = index.symbols.find((s) => s.parent === classId && s.kind === "method" && s.name === "__construct");
|
|
233
|
+
const ctorSource = ctor?.source ?? "";
|
|
234
|
+
for (const f of fields) {
|
|
235
|
+
const propName = f.name.replace(/^\$/, "");
|
|
236
|
+
// All assignment sites for $this->propName in the class body.
|
|
237
|
+
const assignRe = new RegExp(`\\$this->${escapeRegex(propName)}\\s*=`, "g");
|
|
238
|
+
const allAssigns = (cls.source.match(assignRe) ?? []).length;
|
|
239
|
+
if (allAssigns === 0)
|
|
240
|
+
continue;
|
|
241
|
+
// How many of those assignments are inside the ctor body?
|
|
242
|
+
const ctorAssigns = (ctorSource.match(assignRe) ?? []).length;
|
|
243
|
+
if (ctorAssigns !== allAssigns)
|
|
244
|
+
continue;
|
|
245
|
+
// Skip if there is an explicit setter that mutates this property.
|
|
246
|
+
const setterRe = new RegExp(`function\\s+set${propName.charAt(0).toUpperCase()}${propName.slice(1)}\\s*\\(`, "i");
|
|
247
|
+
if (setterRe.test(cls.source))
|
|
248
|
+
continue;
|
|
249
|
+
const visibility = f.meta?.visibility ?? "public";
|
|
250
|
+
const inlineType = f.meta?.type ?? "mixed";
|
|
251
|
+
out.push({
|
|
252
|
+
rule_id: "readonly-candidate",
|
|
253
|
+
file: f.file,
|
|
254
|
+
line: f.start_line,
|
|
255
|
+
snippet: `${visibility} ${inlineType} \$${propName}`,
|
|
256
|
+
description: RULE_DESCRIPTIONS["readonly-candidate"],
|
|
257
|
+
suggested_replacement: `${visibility} readonly ${inlineType} \$${propName};`,
|
|
258
|
+
confidence: f.meta?.type_source === "inline" ? "high" : "medium",
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* enum-from-class-consts: classes that look like a pre-enum bag-of-constants.
|
|
265
|
+
* Heuristic: a class with >=3 `constant` symbols whose values are all
|
|
266
|
+
* string literals AND a static method named getValues / getOptions /
|
|
267
|
+
* getList / cases (which devs commonly add to enumerate the constants).
|
|
268
|
+
*/
|
|
269
|
+
function findEnumFromClassConsts(index, out) {
|
|
270
|
+
const constsByClass = new Map();
|
|
271
|
+
for (const sym of index.symbols) {
|
|
272
|
+
if (sym.kind !== "constant")
|
|
273
|
+
continue;
|
|
274
|
+
if (!sym.parent)
|
|
275
|
+
continue;
|
|
276
|
+
if (!sym.file.endsWith(".php"))
|
|
277
|
+
continue;
|
|
278
|
+
if (!constsByClass.has(sym.parent))
|
|
279
|
+
constsByClass.set(sym.parent, []);
|
|
280
|
+
constsByClass.get(sym.parent).push(sym);
|
|
281
|
+
}
|
|
282
|
+
const ENUM_HELPER_NAMES = new Set([
|
|
283
|
+
"getValues",
|
|
284
|
+
"getOptions",
|
|
285
|
+
"getList",
|
|
286
|
+
"all",
|
|
287
|
+
"labels",
|
|
288
|
+
"names",
|
|
289
|
+
"values",
|
|
290
|
+
]);
|
|
291
|
+
for (const [classId, consts] of constsByClass.entries()) {
|
|
292
|
+
if (consts.length < 3)
|
|
293
|
+
continue;
|
|
294
|
+
const cls = index.symbols.find((s) => s.id === classId);
|
|
295
|
+
if (!cls || cls.kind !== "class")
|
|
296
|
+
continue;
|
|
297
|
+
// All constants must have string-literal values for this to be a true
|
|
298
|
+
// pre-enum. Mixed types or method calls are a sign of a config class.
|
|
299
|
+
let allStrings = true;
|
|
300
|
+
for (const c of consts) {
|
|
301
|
+
if (!c.source) {
|
|
302
|
+
allStrings = false;
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
// const_element source is just `NAME = 'value'` (no `const` keyword,
|
|
306
|
+
// no trailing `;` — those belong to the enclosing const_declaration).
|
|
307
|
+
// Match a string literal anywhere after the `=`.
|
|
308
|
+
if (!/=\s*['"][^'"]*['"]/.test(c.source)) {
|
|
309
|
+
allStrings = false;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (!allStrings)
|
|
314
|
+
continue;
|
|
315
|
+
// At least one helper method name must be present (or class name ends
|
|
316
|
+
// in "Enum" / "Status" / "Type" — common pre-enum suffixes).
|
|
317
|
+
const helperPresent = index.symbols.some((s) => s.parent === classId &&
|
|
318
|
+
s.kind === "method" &&
|
|
319
|
+
ENUM_HELPER_NAMES.has(s.name));
|
|
320
|
+
const naming = /(?:Enum|Status|Type|Kind|Code)$/.test(cls.name);
|
|
321
|
+
if (!helperPresent && !naming)
|
|
322
|
+
continue;
|
|
323
|
+
out.push({
|
|
324
|
+
rule_id: "enum-from-class-consts",
|
|
325
|
+
file: cls.file,
|
|
326
|
+
line: cls.start_line,
|
|
327
|
+
snippet: `class ${cls.name} { ${consts.length} consts }`,
|
|
328
|
+
description: RULE_DESCRIPTIONS["enum-from-class-consts"],
|
|
329
|
+
suggested_replacement: `enum ${cls.name}: string { case Foo = 'foo'; /* … convert each const */ }`,
|
|
330
|
+
confidence: helperPresent ? "high" : "medium",
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* promotable-ctor: __construct(T $x, U $y) { $this->x = $x; $this->y = $y; }
|
|
336
|
+
* is mechanically promotable to __construct(public T $x, public U $y) {}.
|
|
337
|
+
*
|
|
338
|
+
* Heuristic: extract the constructor body, count assignment statements,
|
|
339
|
+
* count formal parameters. If every parameter $X has exactly one matching
|
|
340
|
+
* `$this->X = $X;` in the body and there are no other statements (modulo
|
|
341
|
+
* whitespace), the constructor is promotable.
|
|
342
|
+
*/
|
|
343
|
+
function findPromotableCtor(index, out) {
|
|
344
|
+
for (const sym of index.symbols) {
|
|
345
|
+
if (sym.kind !== "method" || sym.name !== "__construct")
|
|
346
|
+
continue;
|
|
347
|
+
if (!sym.source)
|
|
348
|
+
continue;
|
|
349
|
+
// Skip if already using promoted ctor (visibility on parameters).
|
|
350
|
+
if (/\b(?:public|private|protected)\s+(?:readonly\s+)?[\w\\?|&]+\s+\$\w+/.test(sym.source)) {
|
|
351
|
+
// This is a heuristic — promoted params have visibility BEFORE the
|
|
352
|
+
// type. Already-promoted ctors have nothing to modernize.
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
// Pull formal parameter names from the signature
|
|
356
|
+
const sigMatch = /__construct\s*\(([^)]*)\)/.exec(sym.source);
|
|
357
|
+
if (!sigMatch)
|
|
358
|
+
continue;
|
|
359
|
+
const sig = sigMatch[1];
|
|
360
|
+
if (!sig.trim())
|
|
361
|
+
continue;
|
|
362
|
+
const paramNames = [];
|
|
363
|
+
for (const part of sig.split(",")) {
|
|
364
|
+
const pm = /\$(\w+)/.exec(part);
|
|
365
|
+
if (pm)
|
|
366
|
+
paramNames.push(pm[1]);
|
|
367
|
+
}
|
|
368
|
+
if (paramNames.length === 0)
|
|
369
|
+
continue;
|
|
370
|
+
// Pull body { … }
|
|
371
|
+
const bodyStart = sym.source.indexOf("{");
|
|
372
|
+
const bodyEnd = sym.source.lastIndexOf("}");
|
|
373
|
+
if (bodyStart === -1 || bodyEnd <= bodyStart)
|
|
374
|
+
continue;
|
|
375
|
+
const body = sym.source.slice(bodyStart + 1, bodyEnd).trim();
|
|
376
|
+
// Count $this->NAME = $NAME; statements with names matching params.
|
|
377
|
+
let matched = 0;
|
|
378
|
+
let extras = 0;
|
|
379
|
+
const statements = body
|
|
380
|
+
.split(/;\s*(?:\n|$)/)
|
|
381
|
+
.map((s) => s.trim())
|
|
382
|
+
.filter(Boolean);
|
|
383
|
+
for (const stmt of statements) {
|
|
384
|
+
const am = /^\$this->(\w+)\s*=\s*\$(\w+)$/.exec(stmt);
|
|
385
|
+
if (am && am[1] === am[2] && paramNames.includes(am[1])) {
|
|
386
|
+
matched++;
|
|
387
|
+
}
|
|
388
|
+
else if (stmt && !/^\/\/|^#/.test(stmt)) {
|
|
389
|
+
extras++;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (matched !== paramNames.length || extras > 0)
|
|
393
|
+
continue;
|
|
394
|
+
out.push({
|
|
395
|
+
rule_id: "promotable-ctor",
|
|
396
|
+
file: sym.file,
|
|
397
|
+
line: sym.start_line,
|
|
398
|
+
snippet: sym.source.slice(0, Math.min(160, sym.source.length)).replace(/\s+/g, " "),
|
|
399
|
+
description: RULE_DESCRIPTIONS["promotable-ctor"],
|
|
400
|
+
suggested_replacement: `public function __construct(${paramNames
|
|
401
|
+
.map((n) => `public \$${n}`)
|
|
402
|
+
.join(", ")}) {}`,
|
|
403
|
+
confidence: "high",
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* match-from-switch: every case returns a value, no fall-through. Pattern
|
|
409
|
+
* is regex-based — over-approximates by including switches that already
|
|
410
|
+
* have break statements. The auditor reviews each finding.
|
|
411
|
+
*/
|
|
412
|
+
function findMatchFromSwitch(content, file, out) {
|
|
413
|
+
// Bounded regex: switch with at least 2 case-return blocks and no
|
|
414
|
+
// visible break / fall-through within a 2000-char window after the
|
|
415
|
+
// switch keyword.
|
|
416
|
+
const switchRe = /switch\s*\(\s*(\$\w+(?:->\w+)?|\w+\s*\([^)]*\))\s*\)\s*\{/g;
|
|
417
|
+
let m;
|
|
418
|
+
while ((m = switchRe.exec(content)) !== null) {
|
|
419
|
+
const body = content.slice(m.index, m.index + 2000);
|
|
420
|
+
// Each case must contain a return; no `break` between cases means
|
|
421
|
+
// every branch terminates the switch.
|
|
422
|
+
const caseReturns = (body.match(/case\s+[^:]+:\s*[^\n]*return/g) ?? []).length;
|
|
423
|
+
const breaks = (body.match(/\bbreak\s*;/g) ?? []).length;
|
|
424
|
+
if (caseReturns >= 2 && breaks === 0) {
|
|
425
|
+
out.push({
|
|
426
|
+
rule_id: "match-from-switch",
|
|
427
|
+
file,
|
|
428
|
+
line: countLines(content, m.index),
|
|
429
|
+
snippet: extractLine(content, m.index),
|
|
430
|
+
description: RULE_DESCRIPTIONS["match-from-switch"],
|
|
431
|
+
suggested_replacement: "return match($expr) { … };",
|
|
432
|
+
confidence: caseReturns >= 4 ? "high" : "medium",
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// ---------------------------------------------------------------------------
|
|
438
|
+
// Helpers
|
|
439
|
+
// ---------------------------------------------------------------------------
|
|
440
|
+
function rateTypeConfidence(type) {
|
|
441
|
+
// Plain primitives = high confidence; class types = medium (might need
|
|
442
|
+
// alias resolution); union/intersection = low.
|
|
443
|
+
if (/^(?:string|int|integer|float|bool|boolean|array|mixed|void|object|iterable|callable)$/i.test(type)) {
|
|
444
|
+
return "high";
|
|
445
|
+
}
|
|
446
|
+
if (/[|&]/.test(type))
|
|
447
|
+
return "low";
|
|
448
|
+
return "medium";
|
|
449
|
+
}
|
|
450
|
+
function normalizeDocblockType(type) {
|
|
451
|
+
// Map common docblock spellings to PHP keyword forms.
|
|
452
|
+
const map = {
|
|
453
|
+
integer: "int",
|
|
454
|
+
boolean: "bool",
|
|
455
|
+
double: "float",
|
|
456
|
+
};
|
|
457
|
+
return map[type.toLowerCase()] ?? type;
|
|
458
|
+
}
|
|
459
|
+
function escapeRegex(s) {
|
|
460
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
461
|
+
}
|
|
462
|
+
function countLines(source, idx) {
|
|
463
|
+
let line = 1;
|
|
464
|
+
for (let i = 0; i < idx; i++) {
|
|
465
|
+
if (source.charCodeAt(i) === 10)
|
|
466
|
+
line++;
|
|
467
|
+
}
|
|
468
|
+
return line;
|
|
469
|
+
}
|
|
470
|
+
function extractLine(source, idx) {
|
|
471
|
+
const start = source.lastIndexOf("\n", idx) + 1;
|
|
472
|
+
const end = source.indexOf("\n", idx);
|
|
473
|
+
const line = source.slice(start, end === -1 ? source.length : end);
|
|
474
|
+
return line.trim().slice(0, 200);
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=php8-migration-candidates-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"php8-migration-candidates-tools.js","sourceRoot":"","sources":["../../src/tools/php8-migration-candidates-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHPStan baseline analyzer (N6).
|
|
3
|
+
*
|
|
4
|
+
* Mature PHP codebases adopt PHPStan incrementally — they raise the level
|
|
5
|
+
* to e.g. 6, generate a baseline file containing every existing error,
|
|
6
|
+
* and treat the baseline as a debt ledger. The Yii2 panel in this gap
|
|
7
|
+
* analysis (tgm-panel) ships an 18 011-line phpstan-baseline.neon — that's
|
|
8
|
+
* roughly 1 800 ignored errors. The team knows the debt is there but has
|
|
9
|
+
* no per-path triage data.
|
|
10
|
+
*
|
|
11
|
+
* This tool parses phpstan-baseline.neon and surfaces:
|
|
12
|
+
* - by_path: files ranked by error count
|
|
13
|
+
* - by_category: error types (no-return-type, undefined-property,
|
|
14
|
+
* iterable-no-value-type, ...) ranked by frequency
|
|
15
|
+
* - quick_wins: files with 1-3 errors — easy refactor targets
|
|
16
|
+
* - aggregate counts (total_ignored, by-severity if hints present)
|
|
17
|
+
*
|
|
18
|
+
* The tool is universal — works on any PHP repo with PHPStan, not only
|
|
19
|
+
* Yii2. Auto-loads on composer.json detection.
|
|
20
|
+
*
|
|
21
|
+
* NEON parsing: NEON is a YAML superset with PHP-specific bracket forms.
|
|
22
|
+
* Rather than pull in a NEON parser dependency we hand-roll a minimal
|
|
23
|
+
* reader — the baseline format is mechanical (parameters: → ignoreErrors:
|
|
24
|
+
* → array of {message, count, path}). Edge cases like nested includes are
|
|
25
|
+
* out of scope; the tool would surface a file_unparseable note rather
|
|
26
|
+
* than crash.
|
|
27
|
+
*/
|
|
28
|
+
export interface PhpStanBaselineEntry {
|
|
29
|
+
message: string;
|
|
30
|
+
count: number;
|
|
31
|
+
path: string;
|
|
32
|
+
/** Best-effort category derived from the message text. */
|
|
33
|
+
category: string;
|
|
34
|
+
}
|
|
35
|
+
export interface PhpStanBaselineAudit {
|
|
36
|
+
repo: string;
|
|
37
|
+
baseline_file: string | null;
|
|
38
|
+
/** Total ignored errors (sum of count fields). */
|
|
39
|
+
total_ignored: number;
|
|
40
|
+
/** Files containing at least one ignored error. */
|
|
41
|
+
total_files: number;
|
|
42
|
+
by_path: Array<{
|
|
43
|
+
path: string;
|
|
44
|
+
count: number;
|
|
45
|
+
}>;
|
|
46
|
+
by_category: Record<string, number>;
|
|
47
|
+
/** Files with 1-3 ignored errors — quickest to clear. */
|
|
48
|
+
quick_wins: Array<{
|
|
49
|
+
path: string;
|
|
50
|
+
count: number;
|
|
51
|
+
categories: string[];
|
|
52
|
+
}>;
|
|
53
|
+
/** Raw entries (full list, sorted by count descending). */
|
|
54
|
+
entries: PhpStanBaselineEntry[];
|
|
55
|
+
/** Diagnostic when the baseline couldn't be parsed cleanly. */
|
|
56
|
+
parse_warnings: string[];
|
|
57
|
+
}
|
|
58
|
+
export declare function analyzePhpStanBaseline(repo: string, options?: {
|
|
59
|
+
baseline_path?: string;
|
|
60
|
+
max_paths?: number;
|
|
61
|
+
}): Promise<PhpStanBaselineAudit>;
|
|
62
|
+
//# sourceMappingURL=phpstan-baseline-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phpstan-baseline-tools.d.ts","sourceRoot":"","sources":["../../src/tools/phpstan-baseline-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAUH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,yDAAyD;IACzD,UAAU,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACzE,2DAA2D;IAC3D,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAChC,+DAA+D;IAC/D,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAQD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,oBAAoB,CAAC,CAuF/B"}
|