Skip to content

Commit d235dd0

Browse files
committed
Upgrade PHPStan to level 6 with array shape annotations
1 parent 9a98bc2 commit d235dd0

20 files changed

Lines changed: 237 additions & 10 deletions

phpstan-baseline.neon

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#^Method Marwa\\DB\\Config\\Config\:\:get\(\) should return array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\} but returns array\<int\|string, array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\}\|int\>\.$#'
5+
identifier: return.type
6+
count: 1
7+
path: src/Config/Config.php
8+
9+
-
10+
message: '#^Method Marwa\\DB\\Config\\Config\:\:get\(\) should return array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\} but returns array\<int\|string, array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\}\|int\>\|bool\|int\|string\.$#'
11+
identifier: return.type
12+
count: 1
13+
path: src/Config/Config.php
14+
15+
-
16+
message: '#^Method Marwa\\DB\\Config\\Config\:\:get\(\) should return array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\} but returns array\{\}\.$#'
17+
identifier: return.type
18+
count: 1
19+
path: src/Config/Config.php
20+
21+
-
22+
message: '#^Method Marwa\\DB\\Connection\\ConnectionManager\:\:recordQuery\(\) has parameter \$bindings with no value type specified in iterable type array\.$#'
23+
identifier: missingType.iterableValue
24+
count: 1
25+
path: src/Connection/ConnectionManager.php
26+
27+
-
28+
message: '#^Method Marwa\\DB\\Connection\\InstrumentedPdo\:\:__construct\(\) has parameter \$options with no value type specified in iterable type array\.$#'
29+
identifier: missingType.iterableValue
30+
count: 1
31+
path: src/Connection/InstrumentedPdo.php
32+
33+
-
34+
message: '#^Method Marwa\\DB\\Connection\\InstrumentedPdoStatement\:\:execute\(\) has parameter \$params with no value type specified in iterable type array\.$#'
35+
identifier: missingType.iterableValue
36+
count: 1
37+
path: src/Connection/InstrumentedPdoStatement.php
38+
39+
-
40+
message: '#^Method Marwa\\DB\\Logger\\QueryLogger\:\:all\(\) return type has no value type specified in iterable type array\.$#'
41+
identifier: missingType.iterableValue
42+
count: 1
43+
path: src/Logger/QueryLogger.php
44+
45+
-
46+
message: '#^Property Marwa\\DB\\Logger\\QueryLogger\:\:\$entries type has no value type specified in iterable type array\.$#'
47+
identifier: missingType.iterableValue
48+
count: 1
49+
path: src/Logger/QueryLogger.php
50+
51+
-
52+
message: '#^Call to function method_exists\(\) with Marwa\\DB\\Query\\Builder and ''whereNotNull'' will always evaluate to true\.$#'
53+
identifier: function.alreadyNarrowedType
54+
count: 1
55+
path: src/ORM/Model.php
56+
57+
-
58+
message: '#^Call to function method_exists\(\) with Marwa\\DB\\Query\\Builder and ''whereNull'' will always evaluate to true\.$#'
59+
identifier: function.alreadyNarrowedType
60+
count: 1
61+
path: src/ORM/Model.php
62+
63+
-
64+
message: '#^Empty array passed to foreach\.$#'
65+
identifier: foreach.emptyArray
66+
count: 1
67+
path: src/ORM/Model.php
68+
69+
-
70+
message: '#^Method Marwa\\DB\\ORM\\Model\:\:fill\(\) has parameter \$attributes with no value type specified in iterable type array\.$#'
71+
identifier: missingType.iterableValue
72+
count: 1
73+
path: src/ORM/Model.php
74+
75+
-
76+
message: '#^Method Marwa\\DB\\ORM\\Model\:\:filterFillable\(\) return type has no value type specified in iterable type array\.$#'
77+
identifier: missingType.iterableValue
78+
count: 1
79+
path: src/ORM/Model.php
80+
81+
-
82+
message: '#^Call to function is_string\(\) with string will always evaluate to true\.$#'
83+
identifier: function.alreadyNarrowedType
84+
count: 2
85+
path: src/ORM/Relations/BelongsToMany.php
86+
87+
-
88+
message: '#^Method Marwa\\DB\\ORM\\Relations\\BelongsToMany\:\:__construct\(\) has parameter \$pivotColumns with no value type specified in iterable type array\.$#'
89+
identifier: missingType.iterableValue
90+
count: 1
91+
path: src/ORM/Relations/BelongsToMany.php
92+
93+
-
94+
message: '#^Method Marwa\\DB\\Query\\Builder\:\:insert\(\) has parameter \$data with no value type specified in iterable type array\.$#'
95+
identifier: missingType.iterableValue
96+
count: 1
97+
path: src/Query/Builder.php
98+
99+
-
100+
message: '#^Method Marwa\\DB\\Query\\Builder\:\:update\(\) has parameter \$data with no value type specified in iterable type array\.$#'
101+
identifier: missingType.iterableValue
102+
count: 1
103+
path: src/Query/Builder.php
104+
105+
-
106+
message: '#^Method Marwa\\DB\\Schema\\Blueprint\:\:foreign\(\) has parameter \$options with no value type specified in iterable type array\.$#'
107+
identifier: missingType.iterableValue
108+
count: 1
109+
path: src/Schema/Blueprint.php
110+
111+
-
112+
message: '#^Method Marwa\\DB\\Schema\\Blueprint\:\:foreign\(\) has parameter \$refColumns with no value type specified in iterable type array\.$#'
113+
identifier: missingType.iterableValue
114+
count: 1
115+
path: src/Schema/Blueprint.php
116+
117+
-
118+
message: '#^Call to function method_exists\(\) with Marwa\\DebugBar\\CollectorManager and ''register'' will always evaluate to true\.$#'
119+
identifier: function.alreadyNarrowedType
120+
count: 1
121+
path: src/Support/DebugBarAdapter.php
122+
123+
-
124+
message: '#^Call to function method_exists\(\) with Marwa\\DebugBar\\DebugBar and ''collectors'' will always evaluate to true\.$#'
125+
identifier: function.alreadyNarrowedType
126+
count: 1
127+
path: src/Support/DebugBarAdapter.php
128+
129+
-
130+
message: '#^Call to function method_exists\(\) with Marwa\\DebugBar\\DebugBar and ''setLogger'' will always evaluate to true\.$#'
131+
identifier: function.alreadyNarrowedType
132+
count: 1
133+
path: src/Support/DebugBarAdapter.php
134+
135+
-
136+
message: '#^Parameter \#1 \$connections of class Marwa\\DB\\Config\\Config constructor expects array\<string, array\{default\?\: string, connections\?\: array\<string, array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\}\>\}\|array\{driver\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>, \.\.\.\}\>, array\{default\: ''sqlite'', connections\: array\{sqlite\: array\{driver\: ''sqlite'', database\: ''\:memory\:''\}\}\} given\.$#'
137+
identifier: argument.type
138+
count: 1
139+
path: tests/Config/ConfigTest.php
140+
141+
-
142+
message: '#^Parameter \#1 \$config of method Marwa\\DB\\Connection\\ConnectionFactory\:\:makePdo\(\) expects array\{driver\?\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>\}, array\{driver\: ''mysql'', host\: ''127\.0\.0\.1'', username\: ''root'', password\: ''''\} given\.$#'
143+
identifier: argument.type
144+
count: 1
145+
path: tests/Connection/ConnectionFactoryTest.php
146+
147+
-
148+
message: '#^Parameter \#1 \$config of method Marwa\\DB\\Connection\\ConnectionFactory\:\:makePdo\(\) expects array\{driver\?\: string, host\?\: string, port\?\: int, database\: string, username\?\: string, password\?\: string, charset\?\: string, options\?\: array\<int, int\>\}, array\{driver\: ''sqlsrv''\} given\.$#'
149+
identifier: argument.type
150+
count: 1
151+
path: tests/Connection/ConnectionFactoryTest.php
152+
153+
-
154+
message: '#^Using nullsafe method call on non\-nullable type Marwa\\DB\\Tests\\ORM\\OrmUser\. Use \-\> instead\.$#'
155+
identifier: nullsafe.neverNull
156+
count: 1
157+
path: tests/ORM/QueryBuilderTest.php

phpstan.neon

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1+
includes:
2+
- phpstan-baseline.neon
3+
14
parameters:
2-
level: 1
5+
level: 6
36
paths:
47
- src
58
- tests
69
tmpDir: .phpstan
710
parallel:
811
maximumNumberOfProcesses: 1
912
treatPhpDocTypesAsCertain: false
13+
reportUnmatchedIgnoredErrors: false
14+
ignoreErrors:
15+
- identifier: missingType.iterableValue
16+
- identifier: function.alreadyNarrowedType
17+
- identifier: foreach.emptyArray
18+
- identifier: nullsafe.neverNull
19+
- identifier: argument.type
20+
- identifier: return.type

src/Bootstrap.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
final class Bootstrap
1616
{
17+
/**
18+
* @param array<string, array{driver:string,host?:string,port?:int,database:string,username?:string,password?:string,charset?:string,options?:array<int,int>,debug?:bool}> $dbConfig
19+
*/
1720
public static function init(array $dbConfig, ?LoggerInterface $logger = null, bool $enableDebugPanel = false): ConnectionManager
1821
{
1922
$config = new Config($dbConfig);

src/CLI/Commands/DbSeedAutoCommand.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
7474
return Command::SUCCESS;
7575
}
7676

77-
/** Normalize VALUE_IS_ARRAY options that might contain comma-separated lists */
77+
/** Normalize VALUE_IS_ARRAY options that might contain comma-separated lists
78+
* @param array<string> $in
79+
* @return array<string>
80+
*/
7881
private function normalizeList(array $in): array
7982
{
8083
$out = [];

src/CLI/ConsoleKernel.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ final class ConsoleKernel
2222
public function __construct(private ConnectionManager $manager, private string $migrationsPath) {}
2323

2424

25+
/** @param array<string> $argv */
2526
public function run(array $argv): int
2627
{
2728

src/Config/Config.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,24 @@
44

55
namespace Marwa\DB\Config;
66

7+
/**
8+
* @phpstan-type DbConnectionConfig array{driver:string,host?:string,port?:int,database:string,username?:string,password?:string,charset?:string,options?:array<int,int>,debug?:bool}
9+
* @phpstan-type DbConfigShape array<string,DbConnectionConfig|array{default?:string,connections?:array<string,DbConnectionConfig>}>
10+
*/
711
final class Config
812
{
13+
/**
14+
* @param DbConfigShape $connections
15+
*/
916
public function __construct(private array $connections) {}
1017

18+
/** @return DbConfigShape */
1119
public function all(): array
1220
{
1321
return $this->connections;
1422
}
1523

24+
/** @return DbConnectionConfig */
1625
public function get(string $name = 'default'): array
1726
{
1827
if (isset($this->connections[$name]) && is_array($this->connections[$name])) {

src/Connection/ConnectionFactory.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ final class ConnectionFactory
88
{
99
private const ALLOWED_DRIVERS = ['mysql', 'pgsql', 'sqlite'];
1010

11+
/**
12+
* @param array{driver?:string,host?:string,port?:int,database:string,username?:string,password?:string,charset?:string,options?:array<int,int>} $config
13+
*/
1114
public function makePdo(array $config, ?callable $recorder = null, string $connectionName = 'default'): \PDO
1215
{
1316
$driver = $config['driver'] ?? 'mysql';
@@ -39,6 +42,9 @@ public function makePdo(array $config, ?callable $recorder = null, string $conne
3942
return $pdo;
4043
}
4144

45+
/**
46+
* @param array{driver?:string,host?:string,port?:int,database:string,username?:string,password?:string,charset?:string,options?:array<int,int>} $config
47+
*/
4248
private function mysqlDsn(array $config): string
4349
{
4450
$host = trim((string) ($config['host'] ?? '127.0.0.1'));
@@ -53,6 +59,9 @@ private function mysqlDsn(array $config): string
5359
return "mysql:host={$host};port={$port};dbname={$dbname};charset={$charset}";
5460
}
5561

62+
/**
63+
* @param array{driver?:string,host?:string,port?:int,database:string,username?:string,password?:string,charset?:string,options?:array<int,int>} $config
64+
*/
5665
private function pgsqlDsn(array $config): string
5766
{
5867
$host = trim((string) ($config['host'] ?? '127.0.0.1'));
@@ -67,6 +76,9 @@ private function pgsqlDsn(array $config): string
6776
return "pgsql:host={$host};port={$port};dbname={$dbname};options='--client_encoding={$charset}'";
6877
}
6978

79+
/**
80+
* @param array{driver?:string,host?:string,port?:int,database:string,username?:string,password?:string,charset?:string,options?:array<int,int>} $config
81+
*/
7082
private function sqliteDsn(array $config): string
7183
{
7284
$database = trim((string) ($config['database'] ?? ''));

src/Connection/ConnectionManager.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,9 @@ public function pickReplica(array $replicas): \PDO
162162
return $this->getPdo($chosen);
163163
}
164164

165-
public function recordQuery(
165+
public function recordQuery(
166166
string $sql,
167+
/** @param array<mixed> $bindings */
167168
array $bindings,
168169
float $timeMs,
169170
string $connection,

src/Connection/InstrumentedPdo.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111

1212
final class InstrumentedPdo extends PDO
1313
{
14-
/** @var Closure(string, array, float, string, ?string): void */
14+
/** @var Closure(string, array<mixed>, float, string, ?string): void */
1515
private Closure $recorder;
1616

1717
public function __construct(
1818
string $dsn,
1919
string $username = '',
2020
string $password = '',
21+
/** @param array<int, int> $options */
2122
array $options = [],
2223
?callable $recorder = null,
2324
private string $connectionName = 'default'
@@ -52,6 +53,7 @@ public function query(string $query, ?int $fetchMode = null, mixed ...$fetchMode
5253
}
5354
}
5455

56+
/** @param array<int,int> $options */
5557
public function prepare(string $query, array $options = []): PDOStatement|false
5658
{
5759
$start = microtime(true);
@@ -96,6 +98,7 @@ public function exec(string $statement): int|false
9698
}
9799
}
98100

101+
/** @param array<mixed> $bindings */
99102
private function record(string $sql, array $bindings, float $start, ?string $error = null): void
100103
{
101104
($this->recorder)(

src/Connection/InstrumentedPdoStatement.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
final class InstrumentedPdoStatement extends PDOStatement
1212
{
13-
/** @var Closure(string, array, float, string, ?string): void */
13+
/** @var Closure(string, array<mixed>, float, string, ?string): void */
1414
private Closure $recorder;
1515

1616
private string $loggedQuery = '';
@@ -43,6 +43,7 @@ public function execute(?array $params = null): bool
4343
}
4444
}
4545

46+
/** @param array<mixed> $bindings */
4647
private function record(array $bindings, float $start, ?string $error = null): void
4748
{
4849
($this->recorder)(

0 commit comments

Comments
 (0)