-
Notifications
You must be signed in to change notification settings - Fork 280
Expand file tree
/
Copy pathphpstan.neon
More file actions
119 lines (115 loc) · 6.16 KB
/
Copy pathphpstan.neon
File metadata and controls
119 lines (115 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Custom architectural rule: Bootstrap::getDatabase() may only be called from the
# composition-root entry points listed below; everything else must inject IDatabase.
# Rule class autoloaded via composer autoload-dev (Matecat\PhpStan\ -> dev-tools/phpstan).
services:
-
class: Matecat\PhpStan\Rules\NoDirectBootstrapGetDatabaseRule
tags:
- phpstan.rules.rule
arguments:
allowedFiles:
- lib/View/fileupload/index.php
- lib/Utils/TaskRunner/executor_worker.php
- internal_scripts/tasks/tasks.php
- lib/View/templates/_APIDoc.php
- router.php
-
class: Matecat\PhpStan\Rules\NoManualTransactionControlRule
tags:
- phpstan.rules.rule
arguments:
allowedFiles:
# The connection object that implements the scope. It is the only place the
# statements are the mechanism rather than a hand-rolled window, and this list is
# not expected to grow: everything else calls transaction(callable).
- lib/Model/DataAccess/Database.php
-
class: Matecat\PhpStan\Rules\NoDirectSessionSuperglobalRule
tags:
- phpstan.rules.rule
arguments:
allowedFiles:
# The adapter. This is the only entry that is meant to survive.
- lib/Utils/Session/PhpSessionStore.php
# The list is now empty of pending work: the adapter above is the single reader and
# writer of $_SESSION in every analysed path, which is the end state this rule was
# written to reach.
#
# plugins/aligner/lib/Features/Aligner.php used to be listed here and has been
# dropped as dead configuration, on two independent counts: `plugins/aligner` is in
# excludePaths below so the rule never analyses it, and the file no longer names the
# superglobal at all. The only $_SESSION left anywhere under plugins/aligner/lib is
# prose in a ConfigsController docblock, which is not a Variable node and so was
# never a violation.
-
class: Matecat\PhpStan\Rules\NoDirectSessionFunctionRule
tags:
- phpstan.rules.rule
arguments:
allowedFiles:
# The session runtime adapter: every session_* call and every session.* ini key in
# the analysed tree lives here. Unlike the list above this one is already at its end
# state and is not expected to grow — Bootstrap configures and closes the session
# through it, and controllers start one through it.
- lib/Utils/Session/PhpSession.php
parameters:
level: 8
paths:
- lib
- plugins
- internal_scripts/tasks
# Vendor type stubs — correct wrong/missing types in third-party libraries
# OpenAi::chat() declares $stream as null but accepts callable at runtime
stubFiles:
- phpstan-stubs/OpenAi.stub
- phpstan-stubs/KleinApp.stub
scanFiles:
- router.php
excludePaths:
- lib/View/APIDoc.php (?)
- vendor
- tests
# Plugin test suites are not analyzed (submodule-agnostic glob)
- plugins/*/tests/*
# internal_scripts task test suites are analyzed by the submodule's own phpstan.neon
# (bare level 8, no strict @throws checks). The root config's strict throw checks
# would flag every PHPUnit assertion, so exclude them here.
- internal_scripts/*/tests/* (?)
# Submodule vendor is gitignored (absent on CI); exclude so a local composer install
# inside the submodule doesn't flood the root scan with third-party errors.
- internal_scripts/*/vendor/* (?)
# Legacy plugin: cannot be economically cleaned; intentionally not analyzed.
# Its own phpstan-baseline.neon lives in the aligner submodule, unused by matecat.
- plugins/aligner (?)
universalObjectCratesClasses:
- Model\DataAccess\ShapelessConcreteStruct
# Flag @throws \Exception on public/protected methods when only
# a narrower exception (e.g. \InvalidArgumentException) is thrown
checkTooWideThrowTypesInProtectedAndPublicMethods: true
exceptions:
uncheckedExceptionClasses:
- 'Model\DataAccess\UnknownPropertyException'
- 'Controller\Exceptions\RenderTerminatedException'
- 'Controller\Exceptions\MissingDatabaseException'
# A stateless controller touching session state is a programming error, not a runtime
# condition, so it is deliberately an \Error. Declaring it checked would push a @throws
# onto every method that merely holds a SessionStore, which is the whole call graph —
# and callers must not be encouraged to catch it. Enforcement works by surfacing.
- 'Utils\Session\StatelessSessionViolation'
# Thrown by Database::commit() when a scope inside the transaction failed. Declaring it
# checked would push a @throws onto every method that writes anything, which is the whole
# call graph — and callers must not be encouraged to catch it: by the time it is thrown
# the transaction has already been rolled back and there is nothing left to salvage.
- 'Model\DataAccess\TransactionAbortedException'
# Thrown by Database::nextSequence() when it is reached inside a transaction it does not
# own. Like the above, catching it is never the right response: the allocation boundary
# is drawn in the wrong place and the fix belongs at the call site, not in a catch block.
- 'Model\DataAccess\SequenceAllocationInTransaction'
check:
# Report when code throws an exception that has no
# matching @throws tag in the method's PHPDoc
missingCheckedExceptionInThrows: true
# Report when @throws declares a broader type than
# what is actually thrown (applies to all methods)
tooWideThrowType: true
treatPhpDocTypesAsCertain: false