phpstan-mcp-mx 0.21.1 → 0.23.0
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/CHANGELOG.md +20 -1
- package/README.md +128 -79
- package/dist/baseline.d.ts +1 -1
- package/dist/baseline.js +27 -15
- package/dist/baseline.js.map +1 -1
- package/dist/changed.d.ts +5 -5
- package/dist/changed.js +68 -35
- package/dist/changed.js.map +1 -1
- package/dist/compare.d.ts +3 -3
- package/dist/compare.js +14 -8
- package/dist/compare.js.map +1 -1
- package/dist/composer.d.ts +2 -2
- package/dist/composer.js +49 -27
- package/dist/composer.js.map +1 -1
- package/dist/config.d.ts +4 -3
- package/dist/config.js +11 -7
- package/dist/config.js.map +1 -1
- package/dist/defaults.d.ts +1 -1
- package/dist/defaults.js +3 -2
- package/dist/defaults.js.map +1 -1
- package/dist/dumptype.d.ts +1 -1
- package/dist/dumptype.js +20 -12
- package/dist/dumptype.js.map +1 -1
- package/dist/failure.d.ts +2 -2
- package/dist/failure.js.map +1 -1
- package/dist/index.js +27 -4
- package/dist/index.js.map +1 -1
- package/dist/php.d.ts +46 -0
- package/dist/php.js +100 -0
- package/dist/php.js.map +1 -0
- package/dist/phpstan/error.js.map +1 -1
- package/dist/phpstan/output.d.ts +2 -2
- package/dist/phpstan/output.js +16 -10
- package/dist/phpstan/output.js.map +1 -1
- package/dist/phpstan/parameters.d.ts +2 -2
- package/dist/phpstan/parameters.js +1 -1
- package/dist/phpstan/parameters.js.map +1 -1
- package/dist/phpstan/process.d.ts +16 -5
- package/dist/phpstan/process.js +48 -19
- package/dist/phpstan/process.js.map +1 -1
- package/dist/phpstan/queue.d.ts +1 -1
- package/dist/phpstan/queue.js +6 -4
- package/dist/phpstan/queue.js.map +1 -1
- package/dist/phpstan.d.ts +6 -6
- package/dist/phpstan.js +51 -31
- package/dist/phpstan.js.map +1 -1
- package/dist/project.d.ts +7 -3
- package/dist/project.js +60 -21
- package/dist/project.js.map +1 -1
- package/dist/report.d.ts +5 -5
- package/dist/report.js +47 -28
- package/dist/report.js.map +1 -1
- package/dist/root-source.d.ts +43 -0
- package/dist/root-source.js +124 -0
- package/dist/root-source.js.map +1 -0
- package/dist/roots.d.ts +13 -1
- package/dist/roots.js +24 -7
- package/dist/roots.js.map +1 -1
- package/dist/runner.d.ts +3 -3
- package/dist/runner.js +17 -10
- package/dist/runner.js.map +1 -1
- package/dist/runs.d.ts +3 -3
- package/dist/runs.js +9 -6
- package/dist/runs.js.map +1 -1
- package/dist/schema-dialect.d.ts +2 -2
- package/dist/schema-dialect.js +8 -5
- package/dist/schema-dialect.js.map +1 -1
- package/dist/server.d.ts +3 -2
- package/dist/server.js +10 -6
- package/dist/server.js.map +1 -1
- package/dist/tmpdir.d.ts +3 -3
- package/dist/tmpdir.js +10 -7
- package/dist/tmpdir.js.map +1 -1
- package/dist/tools/analysis.d.ts +4 -4
- package/dist/tools/analysis.js +7 -5
- package/dist/tools/analysis.js.map +1 -1
- package/dist/tools/inspect.d.ts +7 -7
- package/dist/tools/inspect.js +111 -45
- package/dist/tools/inspect.js.map +1 -1
- package/dist/tools/prompts.d.ts +5 -5
- package/dist/tools/prompts.js +15 -15
- package/dist/tools/prompts.js.map +1 -1
- package/dist/tools/shared.d.ts +4 -4
- package/dist/tools/shared.js +13 -11
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/writes.d.ts +3 -3
- package/dist/tools/writes.js +4 -4
- package/dist/tools/writes.js.map +1 -1
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +2 -1
- package/dist/tools.js.map +1 -1
- package/dist/unmatched.d.ts +3 -3
- package/dist/unmatched.js +35 -20
- package/dist/unmatched.js.map +1 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/dist/phpstan/process.js
CHANGED
|
@@ -7,9 +7,9 @@ const KILL_GRACE_MS = 5_000;
|
|
|
7
7
|
* output af op maxBuffer (1 MB), en de JSON van een groot project gaat daar
|
|
8
8
|
* ruim overheen.
|
|
9
9
|
*
|
|
10
|
-
* `detached
|
|
10
|
+
* Op POSIX maakt `detached` het proces leider van een eigen procesgroep, zodat een
|
|
11
11
|
* timeout de héle groep kan doden. Zonder dat blijven PHPStans parallelle workers
|
|
12
|
-
* na een timeout gewoon doorrekenen.
|
|
12
|
+
* na een timeout gewoon doorrekenen. Op Windows niet: zie `startsOwnGroup`.
|
|
13
13
|
*/
|
|
14
14
|
export function execute(binary, args, cwd, timeoutMs, signal) {
|
|
15
15
|
return new Promise((resolve) => {
|
|
@@ -17,13 +17,15 @@ export function execute(binary, args, cwd, timeoutMs, signal) {
|
|
|
17
17
|
const child = spawn(binary, args, {
|
|
18
18
|
cwd,
|
|
19
19
|
shell: false,
|
|
20
|
-
detached:
|
|
20
|
+
detached: startsOwnGroup(),
|
|
21
|
+
// Zonder console-venster op Windows; op POSIX doet de optie niets.
|
|
22
|
+
windowsHide: true,
|
|
21
23
|
// PAO_DISABLE hoort bij --no-progress en --no-ansi: allemaal om PHPStans
|
|
22
24
|
// eigen, machineleesbare uitvoer te krijgen. laravel/pao hangt zich via
|
|
23
25
|
// autoload.files in de autoloader van het project, ziet aan variabelen als
|
|
24
26
|
// CLAUDECODE dat er een agent draait, en vervangt de uitvoer dan door zijn
|
|
25
27
|
// eigen formaat ({"tool":"phpstan","result":"passed"}). Dat parseert hier
|
|
26
|
-
// niet, dus zonder deze regel is zo'n project onanalyseerbaar
|
|
28
|
+
// niet, dus zonder deze regel is zo'n project onanalyseerbaar en de server
|
|
27
29
|
// erft die agent-variabelen juist altijd, want de client start hem.
|
|
28
30
|
//
|
|
29
31
|
// De tmpdir-variabelen komen uit de projectroot (die is hier de cwd), zodat
|
|
@@ -39,7 +41,9 @@ export function execute(binary, args, cwd, timeoutMs, signal) {
|
|
|
39
41
|
spawnError = error;
|
|
40
42
|
});
|
|
41
43
|
const timers = [];
|
|
42
|
-
const stopTimers = () => timers.forEach((timer) => {
|
|
44
|
+
const stopTimers = () => timers.forEach((timer) => {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
});
|
|
43
47
|
let reason = null;
|
|
44
48
|
// Timeout en annulering ruimen op dezelfde manier op; alleen de reden verschilt,
|
|
45
49
|
// en die bepaalt straks welke uitleg het model krijgt.
|
|
@@ -47,15 +51,22 @@ export function execute(binary, args, cwd, timeoutMs, signal) {
|
|
|
47
51
|
reason ??= why;
|
|
48
52
|
killGroup(child.pid, 'SIGTERM');
|
|
49
53
|
// Wie op SIGTERM niet reageert, krijgt alsnog SIGKILL.
|
|
50
|
-
timers.push(setTimeout(() => {
|
|
54
|
+
timers.push(setTimeout(() => {
|
|
55
|
+
killGroup(child.pid, 'SIGKILL');
|
|
56
|
+
}, KILL_GRACE_MS));
|
|
57
|
+
};
|
|
58
|
+
timers.push(setTimeout(() => {
|
|
59
|
+
stop('timeout');
|
|
60
|
+
}, timeoutMs));
|
|
61
|
+
const onAbort = () => {
|
|
62
|
+
stop('geannuleerd');
|
|
51
63
|
};
|
|
52
|
-
timers.push(setTimeout(() => { stop('timeout'); }, timeoutMs));
|
|
53
|
-
const onAbort = () => { stop('geannuleerd'); };
|
|
54
64
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
55
65
|
let settled = false;
|
|
56
66
|
const finish = (code, stopSignal) => {
|
|
57
|
-
if (settled)
|
|
67
|
+
if (settled) {
|
|
58
68
|
return;
|
|
69
|
+
}
|
|
59
70
|
settled = true;
|
|
60
71
|
stopTimers();
|
|
61
72
|
// Listener opruimen: het signaal van een verzoek kan langer leven dan deze
|
|
@@ -73,20 +84,34 @@ export function execute(binary, args, cwd, timeoutMs, signal) {
|
|
|
73
84
|
// Normaal wachten we op 'close': dan is alle output binnen.
|
|
74
85
|
child.on('close', finish);
|
|
75
86
|
// Maar bij een timeout wordt alleen het proces zelf gedood, terwijl zijn
|
|
76
|
-
// kleinkinderen
|
|
87
|
+
// kleinkinderen PHPStan draait parallelle workers de pipes openhouden.
|
|
77
88
|
// 'close' komt dan pas als die klaar zijn, en dan is de timeout geen timeout
|
|
78
89
|
// meer. Zodra het proces zelf door een signaal is gestopt, heeft wachten op
|
|
79
90
|
// meer output geen zin.
|
|
80
91
|
child.on('exit', (code, exitSignal) => {
|
|
81
|
-
if (exitSignal !== null)
|
|
92
|
+
if (exitSignal !== null) {
|
|
82
93
|
finish(code, exitSignal);
|
|
94
|
+
}
|
|
83
95
|
});
|
|
84
96
|
});
|
|
85
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Of PHPStan in een eigen procesgroep start, met `detached`.
|
|
100
|
+
*
|
|
101
|
+
* Op Windows niet. Daar betekent `detached` DETACHED_PROCESS: php.exe krijgt géén
|
|
102
|
+
* console, en dan krijgt elk console-programma dat het zelf start een nieuw, zichtbaar
|
|
103
|
+
* venster de xdebug-restart en elke parallelle worker. `windowsHide` gaat niet over op
|
|
104
|
+
* die kleinkinderen. Nagemeten met een kleinkind via `proc_open`: detached gaf een
|
|
105
|
+
* zichtbaar venster, zonder detached geen enkel. Een eigen groep is daar ook niet nodig:
|
|
106
|
+
* `taskkill /T` ruimt de boom op via het pid (zie `planKill`).
|
|
107
|
+
*/
|
|
108
|
+
export function startsOwnGroup(platform = process.platform) {
|
|
109
|
+
return platform !== 'win32';
|
|
110
|
+
}
|
|
86
111
|
/**
|
|
87
112
|
* Bepaalt hoe de procesgroep van `pid` gedood wordt. Als plan teruggegeven en niet
|
|
88
113
|
* meteen uitgevoerd, want anders is de Windows-tak niet te testen op een machine
|
|
89
|
-
* waar je hem niet kunt uitvoeren
|
|
114
|
+
* waar je hem niet kunt uitvoeren en juist die tak was stuk.
|
|
90
115
|
*/
|
|
91
116
|
export function planKill(pid, signal, platform = process.platform) {
|
|
92
117
|
// Een negatieve pid als groeps-id is POSIX; op Windows bestaat dat niet en
|
|
@@ -105,20 +130,23 @@ export function planKill(pid, signal, platform = process.platform) {
|
|
|
105
130
|
const TASKKILL_NOT_FOUND = 128;
|
|
106
131
|
/** Doodt de hele procesgroep van `pid`, op de manier die dit platform kent. */
|
|
107
132
|
function killGroup(pid, signal) {
|
|
108
|
-
if (pid === undefined)
|
|
133
|
+
if (pid === undefined) {
|
|
109
134
|
return;
|
|
135
|
+
}
|
|
110
136
|
carryOutKill(pid, planKill(pid, signal));
|
|
111
137
|
}
|
|
112
138
|
/**
|
|
113
139
|
* Voert een plan uit `planKill` uit. Los daarvan, zodat ook het *uitvoeren* van de
|
|
114
140
|
* Windows-tak te testen is: met een commando dat niet bestaat, een dat faalt, en een
|
|
115
|
-
* dat met 128 eindigt
|
|
141
|
+
* dat met 128 eindigt de exit code van taskkill voor een proces dat al weg is.
|
|
116
142
|
*/
|
|
117
143
|
export function carryOutKill(pid, plan) {
|
|
118
144
|
if (plan.kind === 'commando') {
|
|
119
145
|
// Fire-and-forget: dit loopt in een timer en mag de event loop niet blokkeren.
|
|
120
|
-
const killer = spawn(plan.command, [...plan.args], { shell: false, stdio: 'ignore' });
|
|
121
|
-
killer.on('error', (error) => {
|
|
146
|
+
const killer = spawn(plan.command, [...plan.args], { shell: false, stdio: 'ignore', windowsHide: true });
|
|
147
|
+
killer.on('error', (error) => {
|
|
148
|
+
reportKillFailure(pid, error);
|
|
149
|
+
});
|
|
122
150
|
killer.on('exit', (code) => {
|
|
123
151
|
if (code !== 0 && code !== TASKKILL_NOT_FOUND) {
|
|
124
152
|
reportKillFailure(pid, new Error(`${plan.command} exited with code ${String(code)}`));
|
|
@@ -130,13 +158,14 @@ export function carryOutKill(pid, plan) {
|
|
|
130
158
|
process.kill(plan.target, plan.signal);
|
|
131
159
|
}
|
|
132
160
|
catch (error) {
|
|
133
|
-
if (isReportableKillError(error))
|
|
161
|
+
if (isReportableKillError(error)) {
|
|
134
162
|
reportKillFailure(pid, error);
|
|
163
|
+
}
|
|
135
164
|
}
|
|
136
165
|
}
|
|
137
166
|
/**
|
|
138
167
|
* Of een mislukte kill het melden waard is. `ESRCH` betekent dat de groep al weg
|
|
139
|
-
* is
|
|
168
|
+
* is de race tussen de timer en deze aanroep, en precies de gewenste uitkomst.
|
|
140
169
|
* Alles anders wél melden: de vorige versie slikte élke fout en verborg daarmee dat
|
|
141
170
|
* een negatieve pid op Windows niet eens bestaat.
|
|
142
171
|
*/
|
|
@@ -145,7 +174,7 @@ export function isReportableKillError(error) {
|
|
|
145
174
|
}
|
|
146
175
|
/**
|
|
147
176
|
* Meldt dat het opruimen niet gelukt is. Naar stderr, want bij stdio-transport is
|
|
148
|
-
* stdout het protocol
|
|
177
|
+
* stdout het protocol en niet gooien: dit loopt in een timer, waar een exception
|
|
149
178
|
* de hele server omhaalt.
|
|
150
179
|
*/
|
|
151
180
|
function reportKillFailure(pid, error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/phpstan/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAezC,4EAA4E;AAC5E,MAAM,aAAa,GAAG,KAAK,CAAC;AAE5B;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CACrB,MAAc,EACd,IAAuB,EACvB,GAAW,EACX,SAAiB,EACjB,MAA+B;
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/phpstan/process.ts"],"names":[],"mappings":"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"}
|
package/dist/phpstan/queue.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export declare const MAX_PARALLEL_ENV_VAR = "PHPSTAN_MCP_MAX_PARALLEL";
|
|
3
3
|
/**
|
|
4
4
|
* Leest hoeveel analyses tegelijk mogen draaien. Een onbruikbare waarde wordt
|
|
5
|
-
* geweigerd en niet stil vervangen door de standaard
|
|
5
|
+
* geweigerd en niet stil vervangen door de standaard net als bij de
|
|
6
6
|
* geheugenlimiet: wie dit zet, heeft er iets mee bedoeld.
|
|
7
7
|
*/
|
|
8
8
|
export declare function loadMaxParallel(env?: NodeJS.ProcessEnv): number;
|
package/dist/phpstan/queue.js
CHANGED
|
@@ -6,18 +6,19 @@ export const MAX_PARALLEL_ENV_VAR = 'PHPSTAN_MCP_MAX_PARALLEL';
|
|
|
6
6
|
* Twee tegelijk. De queue per project bestond al voor de resultcache, maar over
|
|
7
7
|
* projecten heen begrensde niets: een model dat na list_projects tien projecten
|
|
8
8
|
* aanroept, start tien PHPStan-processen die elk hun eigen parallelle workers
|
|
9
|
-
* opzetten
|
|
9
|
+
* opzetten en met een geheugenlimiet van 2G is dat tien keer dat plafond.
|
|
10
10
|
*/
|
|
11
11
|
const DEFAULT_MAX_PARALLEL = 2;
|
|
12
12
|
/**
|
|
13
13
|
* Leest hoeveel analyses tegelijk mogen draaien. Een onbruikbare waarde wordt
|
|
14
|
-
* geweigerd en niet stil vervangen door de standaard
|
|
14
|
+
* geweigerd en niet stil vervangen door de standaard net als bij de
|
|
15
15
|
* geheugenlimiet: wie dit zet, heeft er iets mee bedoeld.
|
|
16
16
|
*/
|
|
17
17
|
export function loadMaxParallel(env = process.env) {
|
|
18
18
|
const configured = (env[MAX_PARALLEL_ENV_VAR] ?? fromConfig('maxParallel', env))?.trim();
|
|
19
|
-
if (configured === undefined || configured === '')
|
|
19
|
+
if (configured === undefined || configured === '') {
|
|
20
20
|
return DEFAULT_MAX_PARALLEL;
|
|
21
|
+
}
|
|
21
22
|
const parsed = Number(configured);
|
|
22
23
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
23
24
|
throw new PhpstanError(`${MAX_PARALLEL_ENV_VAR} is set to "${configured}", and that is not a whole number of 1 or more. ` +
|
|
@@ -69,8 +70,9 @@ export function enqueue(key, task) {
|
|
|
69
70
|
queues.set(key, tail);
|
|
70
71
|
void tail.then(() => {
|
|
71
72
|
// Alleen opruimen als er ondertussen niets nieuws achteraan is gezet.
|
|
72
|
-
if (queues.get(key) === tail)
|
|
73
|
+
if (queues.get(key) === tail) {
|
|
73
74
|
queues.delete(key);
|
|
75
|
+
}
|
|
74
76
|
});
|
|
75
77
|
return result;
|
|
76
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/phpstan/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/phpstan/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAElE,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,UAAU,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAEzF,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QAClD,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IAElC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,YAAY,CACpB,GAAG,oBAAoB,eAAe,UAAU,kDAAkD;YAChG,iCAAiC,MAAM,CAAC,oBAAoB,CAAC,IAAI,CACpE,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qEAAqE;AACrE,IAAI,OAAO,GAAG,CAAC,CAAC;AAEhB,MAAM,OAAO,GAAmB,EAAE,CAAC;AAEnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,IAAsB;IAEtD,gFAAgF;IAChF,yDAAyD;IACzD,OAAO,OAAO,IAAI,eAAe,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,IAAI,CAAC,CAAC;IAEb,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,OAAO,IAAI,CAAC,CAAC;QACb,uEAAuE;QACvE,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC;IACtB,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAA+B;IAE7E,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,YAAY,CAAC,mBAAmB,OAAO,2DAA2D,CAAC,CAAC;IAChH,CAAC;AACH,CAAC;AAED,qFAAqF;AACrF,MAAM,MAAM,GAAG,IAAI,GAAG,EAA4B,CAAC;AAEnD;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAI,GAAW,EAAE,IAAsB;IAE5D,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACtD,iFAAiF;IACjF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAE3C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtB,KAAK,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;QAClB,sEAAsE;QACtE,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/phpstan.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ export interface BaselineGenerated {
|
|
|
69
69
|
* Laat PHPStan een baseline schrijven: alle huidige fouten worden erin gezet, zodat
|
|
70
70
|
* een volgende analyse alleen meldt wat er nieuw bij komt.
|
|
71
71
|
*
|
|
72
|
-
* Dit schrijft een bestand in het project
|
|
72
|
+
* Dit schrijft een bestand in het project de enige tool die dat doet, en daarom
|
|
73
73
|
* alleen bereikbaar als de server met schrijfrechten gestart is.
|
|
74
74
|
*/
|
|
75
75
|
export declare function generateBaseline(project: ResolvedProject, options: GenerateBaselineOptions): Promise<BaselineGenerated>;
|
|
@@ -78,7 +78,7 @@ export declare function generateBaseline(project: ResolvedProject, options: Gene
|
|
|
78
78
|
* draait, en geeft het pad dáár terug.
|
|
79
79
|
*
|
|
80
80
|
* Nodig voor `unmatched_ignores` (een tijdelijke config) en `inspect_type` (een kopie
|
|
81
|
-
* van het bestand): een bestand op de host ziet een container niet
|
|
81
|
+
* van het bestand): een bestand op de host ziet een container niet alleen de
|
|
82
82
|
* projectmap is gemount. Het ín het project
|
|
83
83
|
* zetten zou wel werken, maar dan schrijft een read-only tool in de repository. Gemeten
|
|
84
84
|
* in een echte container: PHPStan leest geen config van stdin (`/dev/stdin` en
|
|
@@ -90,7 +90,7 @@ export declare function writeInRunner(project: ResolvedProject, name: string, co
|
|
|
90
90
|
/**
|
|
91
91
|
* Draait `phpstan diagnose` in één project: PHP- en PHPStan-versie, de configs die
|
|
92
92
|
* Composer-pakketten meebrengen, en of de turbo-extensie aanstaat. Geen analyse, dus
|
|
93
|
-
* geen bevindingen
|
|
93
|
+
* geen bevindingen dit is wat je wil weten als een project zich vreemd gedraagt.
|
|
94
94
|
*
|
|
95
95
|
* Wel door de semafoor en niet door de queue per project: dit is een PHPStan-proces
|
|
96
96
|
* dat de machine belast, maar het schrijft geen resultcache waar een analyse
|
|
@@ -116,7 +116,7 @@ export interface EditedFile {
|
|
|
116
116
|
/**
|
|
117
117
|
* Het hele project analyseren (de `paths` uit de config) in plaats van alleen dit bestand.
|
|
118
118
|
* Voor het "vóór" van `analyse_changed`: de aanroepers staan in andere bestanden. Dan moet
|
|
119
|
-
* het bestand wel binnen die `paths` vallen
|
|
119
|
+
* het bestand wel binnen die `paths` vallen anders weigert PHPStan het (nagemeten).
|
|
120
120
|
*/
|
|
121
121
|
readonly wholeProject?: boolean;
|
|
122
122
|
}
|
|
@@ -139,7 +139,7 @@ export declare function tmpCopyName(project: string, kind: string): string;
|
|
|
139
139
|
* resultcache niet weg; hij gaat toch door de queue, want hij leest hem wel.
|
|
140
140
|
*
|
|
141
141
|
* De kopie komt in de tijdelijke map van het project, met een runner in die van díe
|
|
142
|
-
* omgeving
|
|
142
|
+
* omgeving dezelfde weg als de config van `unmatched_ignores`. Op de host wordt hij na
|
|
143
143
|
* afloop weggegooid; in een runner blijft hij staan en overschrijft de volgende aanroep
|
|
144
144
|
* hem, zodat er per project en proces hoogstens één blijft liggen.
|
|
145
145
|
*/
|
|
@@ -148,7 +148,7 @@ export declare function analyseEdited(project: ResolvedProject, edited: EditedFi
|
|
|
148
148
|
* Leest de standaard geheugenlimiet uit de omgeving. Een onbruikbare waarde wordt
|
|
149
149
|
* hier al geweigerd en niet aan PHPStan doorgegeven: die zou er per analyse op
|
|
150
150
|
* klappen met een melding die "memory limit" bevat, waarna describeFailure het
|
|
151
|
-
* model aanraadt een limiet mee te geven
|
|
151
|
+
* model aanraadt een limiet mee te geven precies het verkeerde advies, want de
|
|
152
152
|
* fout zit in de serverconfiguratie en niet in de aanroep.
|
|
153
153
|
*/
|
|
154
154
|
export declare function loadDefaultMemoryLimit(env?: NodeJS.ProcessEnv): string | undefined;
|
package/dist/phpstan.js
CHANGED
|
@@ -5,6 +5,7 @@ import { fromConfig } from './config.js';
|
|
|
5
5
|
import { PROJECTS_ENV_VAR, ProjectDefaultsError, defaultsFor, isValidMemoryLimit } from './defaults.js';
|
|
6
6
|
import { ProjectError, resolveWithin } from './project.js';
|
|
7
7
|
import { PhpstanError } from './phpstan/error.js';
|
|
8
|
+
import { hostPhp, planHostStart } from './php.js';
|
|
8
9
|
import { RUNNERS_ENV_VAR, naarHost, naarOmgeving, phpstanIn, runnerFor } from './runner.js';
|
|
9
10
|
import { collectWarnings, condenseDetails, toResult, tryParse } from './phpstan/output.js';
|
|
10
11
|
import { execute } from './phpstan/process.js';
|
|
@@ -38,8 +39,9 @@ export async function clearResultCache(project, options = {}) {
|
|
|
38
39
|
// de verkeerde map.
|
|
39
40
|
const args = ['clear-result-cache', '--no-ansi'];
|
|
40
41
|
const config = options.config ?? defaultConfig(project);
|
|
41
|
-
if (config !== undefined)
|
|
42
|
+
if (config !== undefined) {
|
|
42
43
|
args.push(`--configuration=${config}`);
|
|
44
|
+
}
|
|
43
45
|
const execution = await runPhpstan(project, args, timeoutFor(project, options), options.signal);
|
|
44
46
|
const output = execution.stdout.trim();
|
|
45
47
|
if (execution.code !== 0 || output === '') {
|
|
@@ -53,7 +55,7 @@ export async function clearResultCache(project, options = {}) {
|
|
|
53
55
|
* Laat PHPStan een baseline schrijven: alle huidige fouten worden erin gezet, zodat
|
|
54
56
|
* een volgende analyse alleen meldt wat er nieuw bij komt.
|
|
55
57
|
*
|
|
56
|
-
* Dit schrijft een bestand in het project
|
|
58
|
+
* Dit schrijft een bestand in het project de enige tool die dat doet, en daarom
|
|
57
59
|
* alleen bereikbaar als de server met schrijfrechten gestart is.
|
|
58
60
|
*/
|
|
59
61
|
export async function generateBaseline(project, options) {
|
|
@@ -77,14 +79,16 @@ export async function generateBaseline(project, options) {
|
|
|
77
79
|
/**
|
|
78
80
|
* Wat er gestart wordt en waar PHPStan dan staat.
|
|
79
81
|
*
|
|
80
|
-
* Zonder runner is dat
|
|
81
|
-
* commando van de gebruiker ervóór en staat
|
|
82
|
-
* dan is de host-check ook niet meer zinnig,
|
|
82
|
+
* Zonder runner is dat `vendor/bin/phpstan` op de host, op Windows via php.exe (zie
|
|
83
|
+
* `planHostStart`). Met runner draait het commando van de gebruiker ervóór en staat
|
|
84
|
+
* PHPStan op het pad binnen díe omgeving dan is de host-check ook niet meer zinnig,
|
|
85
|
+
* want daar hoeft geen vendor/ te staan.
|
|
83
86
|
*/
|
|
84
87
|
function planUitvoering(project) {
|
|
85
88
|
const runner = runnerFor(project.path);
|
|
86
89
|
if (runner === null) {
|
|
87
|
-
|
|
90
|
+
const { file, prefix } = planHostStart(requireBinary(project), hostPhp());
|
|
91
|
+
return { file, prefix, phpstan: '', runner: null };
|
|
88
92
|
}
|
|
89
93
|
const [file, ...prefix] = runner.command;
|
|
90
94
|
return { file: file, prefix, phpstan: phpstanIn(runner), runner };
|
|
@@ -94,23 +98,29 @@ function planUitvoering(project) {
|
|
|
94
98
|
*
|
|
95
99
|
* Eén plek voor elk subcommando. Eerder liep alleen `analyse` via de runner, en
|
|
96
100
|
* startten `diagnose`, `clear-result-cache` en `--generate-baseline` altijd op de host:
|
|
97
|
-
* de diagnose beschreef dan de host in plaats van de container
|
|
101
|
+
* de diagnose beschreef dan de host in plaats van de container terwijl juist die tool
|
|
98
102
|
* is waar een mislukte bootstrap naar verwijst.
|
|
99
103
|
*/
|
|
100
104
|
function runPhpstan(project, ruweArgs, timeoutMs, signal) {
|
|
101
105
|
const plan = planUitvoering(project);
|
|
102
106
|
const args = plan.runner === null
|
|
103
|
-
? [...ruweArgs]
|
|
107
|
+
? [...plan.prefix, ...ruweArgs]
|
|
104
108
|
: [...plan.prefix, plan.phpstan, ...vertaalArgs(ruweArgs, project.path, plan.runner)];
|
|
105
109
|
return execute(plan.file, args, project.path, timeoutMs, signal);
|
|
106
110
|
}
|
|
107
111
|
/**
|
|
108
112
|
* Weigert vóór de queue een project waar PHPStan niet kan draaien: geen binary op de
|
|
109
113
|
* host en geen runner. Met een runner zegt de host-check niets.
|
|
114
|
+
*
|
|
115
|
+
* Een ontbrekende php.exe op Windows hoort hier bewust níet: dat is een fout in de
|
|
116
|
+
* serverconfiguratie, en die volgt bij het starten zelf (`planUitvoering`). Hier
|
|
117
|
+
* controleren zou hem vóór de fouten in de aanroep zetten (een ontbrekende config, een
|
|
118
|
+
* al geannuleerd verzoek), en die zeggen de aanroeper meer.
|
|
110
119
|
*/
|
|
111
120
|
function requireRunnable(project) {
|
|
112
|
-
if (runnerFor(project.path) === null)
|
|
121
|
+
if (runnerFor(project.path) === null) {
|
|
113
122
|
requireBinary(project);
|
|
123
|
+
}
|
|
114
124
|
}
|
|
115
125
|
/** Zet de argumenten die paden bevatten om naar de omgeving van de runner. */
|
|
116
126
|
function vertaalArgs(args, project, runner) {
|
|
@@ -161,7 +171,7 @@ const WRITE_IN_RUNNER = 'd="${TMPDIR:-/tmp}"; f="$d/$2"; printf "%s" "$1" > "$f.
|
|
|
161
171
|
* draait, en geeft het pad dáár terug.
|
|
162
172
|
*
|
|
163
173
|
* Nodig voor `unmatched_ignores` (een tijdelijke config) en `inspect_type` (een kopie
|
|
164
|
-
* van het bestand): een bestand op de host ziet een container niet
|
|
174
|
+
* van het bestand): een bestand op de host ziet een container niet alleen de
|
|
165
175
|
* projectmap is gemount. Het ín het project
|
|
166
176
|
* zetten zou wel werken, maar dan schrijft een read-only tool in de repository. Gemeten
|
|
167
177
|
* in een echte container: PHPStan leest geen config van stdin (`/dev/stdin` en
|
|
@@ -171,8 +181,9 @@ const WRITE_IN_RUNNER = 'd="${TMPDIR:-/tmp}"; f="$d/$2"; printf "%s" "$1" > "$f.
|
|
|
171
181
|
*/
|
|
172
182
|
export async function writeInRunner(project, name, content, options = {}) {
|
|
173
183
|
const runner = runnerFor(project.path);
|
|
174
|
-
if (runner === null)
|
|
184
|
+
if (runner === null) {
|
|
175
185
|
throw new Error('writeInRunner is only for a project with a runner');
|
|
186
|
+
}
|
|
176
187
|
const [file, ...prefix] = runner.command;
|
|
177
188
|
const execution = await execute(file, [...prefix, 'sh', '-c', WRITE_IN_RUNNER, 'sh', content, name], project.path, timeoutFor(project, options), options.signal);
|
|
178
189
|
const pad = execution.stdout.trim();
|
|
@@ -186,7 +197,7 @@ export async function writeInRunner(project, name, content, options = {}) {
|
|
|
186
197
|
/**
|
|
187
198
|
* Draait `phpstan diagnose` in één project: PHP- en PHPStan-versie, de configs die
|
|
188
199
|
* Composer-pakketten meebrengen, en of de turbo-extensie aanstaat. Geen analyse, dus
|
|
189
|
-
* geen bevindingen
|
|
200
|
+
* geen bevindingen dit is wat je wil weten als een project zich vreemd gedraagt.
|
|
190
201
|
*
|
|
191
202
|
* Wel door de semafoor en niet door de queue per project: dit is een PHPStan-proces
|
|
192
203
|
* dat de machine belast, maar het schrijft geen resultcache waar een analyse
|
|
@@ -216,7 +227,7 @@ export async function diagnose(project, options = {}) {
|
|
|
216
227
|
if (output === '') {
|
|
217
228
|
// Ook diagnose start de applicatie, en faalt dus op dezelfde bootstrap als een
|
|
218
229
|
// analyse. Dan dezelfde reden: zonder viel dit terug op phpstan_failed, terwijl de
|
|
219
|
-
// tekst letterlijk "bootstrap failed" zei
|
|
230
|
+
// tekst letterlijk "bootstrap failed" zei gezien op een project zonder ext-redis.
|
|
220
231
|
const details = condenseDetails(execution.stderr.trim());
|
|
221
232
|
const bootstrap = /bootstrap failed|unable to bootstrap/i.test(details);
|
|
222
233
|
throw new PhpstanError(`PHPStan returned no diagnosis in ${project.path} (exit code ${execution.code ?? '?'}).\n\n` +
|
|
@@ -234,7 +245,7 @@ export async function diagnose(project, options = {}) {
|
|
|
234
245
|
/**
|
|
235
246
|
* De uiteindelijke configuratie via `dump-parameters`. Een aanvulling op de diagnose en
|
|
236
247
|
* geen voorwaarde: dit laadt de bootstrap, en bij een project waar die niet start (zoals
|
|
237
|
-
* een Laravel-app zonder ext-redis op de host) faalt het
|
|
248
|
+
* een Laravel-app zonder ext-redis op de host) faalt het dan is PHPStans eigen diagnose
|
|
238
249
|
* juist wat je nodig hebt, dus die komt er gewoon, met de reden waarom dit ontbreekt.
|
|
239
250
|
*/
|
|
240
251
|
async function effectiveParameters(project, timeoutMs, signal) {
|
|
@@ -252,7 +263,7 @@ async function effectiveParameters(project, timeoutMs, signal) {
|
|
|
252
263
|
};
|
|
253
264
|
}
|
|
254
265
|
// Een pad uit de omgeving van een runner eerst terug naar de host, dan relatief aan het
|
|
255
|
-
// project
|
|
266
|
+
// project hetzelfde als bij de bevindingen.
|
|
256
267
|
const display = (path) => displayPath(project.path, runner === null ? path : naarHost(runner, project.path, path));
|
|
257
268
|
try {
|
|
258
269
|
return { parameters: summariseParameters(execution.stdout, display), parametersProblem: null };
|
|
@@ -299,7 +310,7 @@ export function tmpCopyName(project, kind) {
|
|
|
299
310
|
* resultcache niet weg; hij gaat toch door de queue, want hij leest hem wel.
|
|
300
311
|
*
|
|
301
312
|
* De kopie komt in de tijdelijke map van het project, met een runner in die van díe
|
|
302
|
-
* omgeving
|
|
313
|
+
* omgeving dezelfde weg als de config van `unmatched_ignores`. Op de host wordt hij na
|
|
303
314
|
* afloop weggegooid; in een runner blijft hij staan en overschrijft de volgende aanroep
|
|
304
315
|
* hem, zodat er per project en proces hoogstens één blijft liggen.
|
|
305
316
|
*/
|
|
@@ -319,8 +330,9 @@ export async function analyseEdited(project, edited, options = {}) {
|
|
|
319
330
|
]);
|
|
320
331
|
}
|
|
321
332
|
finally {
|
|
322
|
-
if (runner === null)
|
|
333
|
+
if (runner === null) {
|
|
323
334
|
rmSync(tmpFile, { force: true });
|
|
335
|
+
}
|
|
324
336
|
}
|
|
325
337
|
}));
|
|
326
338
|
}
|
|
@@ -372,13 +384,14 @@ async function run(project, options, editor = []) {
|
|
|
372
384
|
* Leest de standaard geheugenlimiet uit de omgeving. Een onbruikbare waarde wordt
|
|
373
385
|
* hier al geweigerd en niet aan PHPStan doorgegeven: die zou er per analyse op
|
|
374
386
|
* klappen met een melding die "memory limit" bevat, waarna describeFailure het
|
|
375
|
-
* model aanraadt een limiet mee te geven
|
|
387
|
+
* model aanraadt een limiet mee te geven precies het verkeerde advies, want de
|
|
376
388
|
* fout zit in de serverconfiguratie en niet in de aanroep.
|
|
377
389
|
*/
|
|
378
390
|
export function loadDefaultMemoryLimit(env = process.env) {
|
|
379
391
|
const configured = (env[MEMORY_LIMIT_ENV_VAR] ?? fromConfig('memoryLimit', env))?.trim();
|
|
380
|
-
if (configured === undefined || configured === '')
|
|
392
|
+
if (configured === undefined || configured === '') {
|
|
381
393
|
return undefined;
|
|
394
|
+
}
|
|
382
395
|
if (!isValidMemoryLimit(configured)) {
|
|
383
396
|
throw new PhpstanError(`${MEMORY_LIMIT_ENV_VAR} is set to "${configured}", and PHPStan does not accept that format. ` +
|
|
384
397
|
'Use a number with an optional K, M or G (e.g. "1G"), or -1 for no limit.');
|
|
@@ -400,8 +413,9 @@ function buildArgs(project, options, editor = []) {
|
|
|
400
413
|
* die van de server. Dezelfde volgorde als bij de geheugenlimiet.
|
|
401
414
|
*/
|
|
402
415
|
function timeoutFor(project, options) {
|
|
403
|
-
if (options.timeoutMs !== undefined)
|
|
416
|
+
if (options.timeoutMs !== undefined) {
|
|
404
417
|
return options.timeoutMs;
|
|
418
|
+
}
|
|
405
419
|
const seconds = defaultsFor(project.path).timeoutSeconds;
|
|
406
420
|
return seconds === undefined ? DEFAULT_TIMEOUT_MS : seconds * 1000;
|
|
407
421
|
}
|
|
@@ -411,19 +425,21 @@ function timeoutFor(project, options) {
|
|
|
411
425
|
* Door resolveWithin, ook al komt hij uit de serverconfiguratie en niet uit een
|
|
412
426
|
* aanroep: een neon kan PHP-code laten uitvoeren, en de whitelist gaat over wat er
|
|
413
427
|
* gestart wordt, niet alleen over wat er geanalyseerd wordt. Een fout hier is een
|
|
414
|
-
* fout in de serverconfiguratie en wordt ook zo genoemd
|
|
428
|
+
* fout in de serverconfiguratie en wordt ook zo genoemd anders lijkt het alsof de
|
|
415
429
|
* aanroeper een verkeerd pad meegaf.
|
|
416
430
|
*/
|
|
417
431
|
function defaultConfig(project) {
|
|
418
432
|
const config = defaultsFor(project.path).config;
|
|
419
|
-
if (config === undefined)
|
|
433
|
+
if (config === undefined) {
|
|
420
434
|
return undefined;
|
|
435
|
+
}
|
|
421
436
|
try {
|
|
422
437
|
return resolveWithin(project, config);
|
|
423
438
|
}
|
|
424
439
|
catch (error) {
|
|
425
|
-
if (!(error instanceof ProjectError))
|
|
440
|
+
if (!(error instanceof ProjectError)) {
|
|
426
441
|
throw error;
|
|
442
|
+
}
|
|
427
443
|
throw new ProjectDefaultsError(`${PROJECTS_ENV_VAR}: the config "${config}" for ${project.path} cannot be used. ${error.message}`);
|
|
428
444
|
}
|
|
429
445
|
}
|
|
@@ -472,13 +488,16 @@ function flags(project, options) {
|
|
|
472
488
|
// Vóór de rest, zoals PHPStan het zelf ook documenteert: de config bepaalt wat de
|
|
473
489
|
// overige vlaggen overrulen.
|
|
474
490
|
const config = options.config ?? defaultConfig(project);
|
|
475
|
-
if (config !== undefined)
|
|
491
|
+
if (config !== undefined) {
|
|
476
492
|
args.push(`--configuration=${config}`);
|
|
477
|
-
|
|
493
|
+
}
|
|
494
|
+
if (options.level !== undefined) {
|
|
478
495
|
args.push(`--level=${options.level}`);
|
|
496
|
+
}
|
|
479
497
|
const memoryLimit = options.memoryLimit ?? defaults.memoryLimit ?? loadDefaultMemoryLimit();
|
|
480
|
-
if (memoryLimit !== undefined)
|
|
498
|
+
if (memoryLimit !== undefined) {
|
|
481
499
|
args.push(`--memory-limit=${memoryLimit}`);
|
|
500
|
+
}
|
|
482
501
|
return args;
|
|
483
502
|
}
|
|
484
503
|
/** De paden die geanalyseerd worden, met de controle die PHPStan zelf niet uitlegt. */
|
|
@@ -503,7 +522,7 @@ function describeFailure(project, execution) {
|
|
|
503
522
|
const gemeen = { exitCode: execution.code, ...oorzaakUit(details) };
|
|
504
523
|
// Nagemeten: een bestand onder `excludePaths` dat expliciet als pad meegaat, geeft
|
|
505
524
|
// deze tekst met exit 0 en zonder JSON. Zonder eigen tak viel het in unusable_output,
|
|
506
|
-
// met als advies de cache te legen
|
|
525
|
+
// met als advies de cache te legen terwijl het bestand gewoon niet meedoet.
|
|
507
526
|
if (/no files found to analyse/i.test(details)) {
|
|
508
527
|
const hint = 'Check `paths` and `excludePaths` in the config (diagnose_project shows them), or pass another path.';
|
|
509
528
|
return {
|
|
@@ -515,7 +534,7 @@ function describeFailure(project, execution) {
|
|
|
515
534
|
}
|
|
516
535
|
// De server bouwt de vlaggen zelf en een pad kan geen vlag zijn (resolveWithin), dus
|
|
517
536
|
// een onbekende optie betekent een PHPStan die ouder is dan wat deze tool nodig
|
|
518
|
-
// heeft
|
|
537
|
+
// heeft zoals `--tmp-file` voor inspect_type.
|
|
519
538
|
if (/option does not exist/i.test(details)) {
|
|
520
539
|
const hint = 'Update phpstan/phpstan in this project.';
|
|
521
540
|
return {
|
|
@@ -547,7 +566,7 @@ function describeFailure(project, execution) {
|
|
|
547
566
|
};
|
|
548
567
|
}
|
|
549
568
|
// Bij een mislukte bootstrap is diagnose_project de tool die het antwoord wél
|
|
550
|
-
// compleet oplevert
|
|
569
|
+
// compleet oplevert dezelfde uitvoer, maar in één proces en niet afgekapt.
|
|
551
570
|
// Zonder deze verwijzing is de betere tool onvindbaar op het moment dat je hem
|
|
552
571
|
// nodig hebt.
|
|
553
572
|
//
|
|
@@ -574,14 +593,15 @@ function describeFailure(project, execution) {
|
|
|
574
593
|
}
|
|
575
594
|
/**
|
|
576
595
|
* Haalt de oorzaakregel en het eerste stackframe uit de uitvoer. Die twee zeggen
|
|
577
|
-
* samen wát er misging en wáár het vandaan kwam
|
|
596
|
+
* samen wát er misging en wáár het vandaan kwam precies wat je anders zelf uit
|
|
578
597
|
* de blob moet vissen.
|
|
579
598
|
*/
|
|
580
599
|
function oorzaakUit(details) {
|
|
581
600
|
const regels = details.split('\n');
|
|
582
601
|
const oorzaak = regels.find((regel) => /^\s*(Error|Fatal error|PHP Fatal error):/i.test(regel));
|
|
583
|
-
if (oorzaak === undefined)
|
|
602
|
+
if (oorzaak === undefined) {
|
|
584
603
|
return {};
|
|
604
|
+
}
|
|
585
605
|
const frame = regels.find((regel) => /^#0\s/.test(regel.trim()));
|
|
586
606
|
const cause = oorzaak.replace(/^\s*(Error|Fatal error|PHP Fatal error):\s*/i, '').trim();
|
|
587
607
|
return {
|