Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .phpstan-dba-mysqli.cache

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .phpstan-dba-pdo-mysql.cache

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
"doctrine/dbal": "^3.2",
"friendsofphp/php-cs-fixer": "3.4.0",
"php-parallel-lint/php-parallel-lint": "^1.3",
"phpstan/extension-installer": "^1.2",
"phpstan/phpstan-php-parser": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"phpunit/phpunit": "^9",
"tomasvotruba/unused-public": "^0.0.26",
"vlucas/phpdotenv": "^5.4"
},
"conflicts": {
Expand Down Expand Up @@ -86,7 +88,8 @@
"config": {
"sort-packages": true,
"allow-plugins": {
"composer/package-versions-deprecated": true
"composer/package-versions-deprecated": true,
"phpstan/extension-installer": true
}
},
"extra": {
Expand Down
51 changes: 51 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
parameters:
ignoreErrors:
-
message: '#^Instanceof between mysqli_result\<array\<string, int\|string\|null\>\> and mysqli_result will always evaluate to true\.$#'
count: 1
path: src/DbSchema/SchemaHasherMysql.php

-
message: "#^Instanceof between mysqli_result\\<array\\<string, int\\<\\-128, 127\\>\\|string\\|null\\>\\> and mysqli_result will always evaluate to true\\.$#"
count: 1
path: src/DbSchema/SchemaHasherMysql.php

-
message: "#^Strict comparison using \\!\\=\\= between null and PHPStan\\\\Type\\\\Type will always evaluate to true\\.$#"
count: 1
path: src/Extensions/PdoStatementFetchDynamicReturnTypeExtension.php

-
message: "#^Strict comparison using \\=\\=\\= between 'dibi' and 'dibi' will always evaluate to true\\.$#"
count: 1
path: src/QueryReflection/DbaApi.php

-
message: "#^Return type \\(array\\<int, array\\{name\\: string, table\\?\\: string, native_type\\: string, len\\: int, flags\\: array\\<int, string\\>\\}\\>\\|PDOException\\|null\\) of method staabm\\\\PHPStanDba\\\\QueryReflection\\\\PdoPgSqlQueryReflector\\:\\:simulateQuery\\(\\) should be covariant with return type \\(array\\<int, array\\{name\\: string, table\\: string, native_type\\: string, len\\: int, flags\\: array\\<int, string\\>, precision\\: int\\<0, max\\>, pdo_type\\: 0\\|1\\|2\\|3\\|4\\|5\\|6\\|536870912\\|1073741824\\|2147483648\\}\\>\\|PDOException\\|null\\) of method staabm\\\\PHPStanDba\\\\QueryReflection\\\\BasePdoQueryReflector\\:\\:simulateQuery\\(\\)$#"
count: 1
path: src/QueryReflection/PdoPgSqlQueryReflector.php

-
message: "#^Casting to \\*NEVER\\* something that's already \\*NEVER\\*\\.$#"
count: 1
path: src/QueryReflection/QueryReflection.php

-
message: "#^Instanceof between PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType and PHPStan\\\\Type\\\\Constant\\\\ConstantIntegerType will always evaluate to true\\.$#"
count: 1
path: src/QueryReflection/QueryReflection.php

-
message: "#^Strict comparison using \\=\\=\\= between null and null will always evaluate to true\\.$#"
count: 1
path: src/QueryReflection/QueryReflection.php

-
message: "#^Call to function is_string\\(\\) with string will always evaluate to true\\.$#"
count: 2
path: src/TypeMapping/MysqliTypeMapper.php

-
message: "#^Only booleans are allowed in an if condition, int given\\.$#"
count: 1
path: src/TypeMapping/MysqliTypeMapper.php
6 changes: 6 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
includes:
- config/stubFiles.neon
- config/extensions.neon
- phpstan-baseline.neon

parameters:
level: max

paths:
- src/

unused_public:
methods: true
properties: true
constants: true

bootstrapFiles:
- bootstrap.php

Expand Down
3 changes: 3 additions & 0 deletions src/Analyzer/QueryPlanAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

namespace staabm\PHPStanDba\Analyzer;

/**
* @api
*/
final class QueryPlanAnalyzer
{
/**
Expand Down
6 changes: 6 additions & 0 deletions src/Analyzer/QueryPlanAnalyzerMysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
final class QueryPlanAnalyzerMysql
{
/**
* @api
*
* @deprecated use QueryPlanAnalyzer::DEFAULT_UNINDEXED_READS_THRESHOLD instead
*/
public const DEFAULT_UNINDEXED_READS_THRESHOLD = QueryPlanAnalyzer::DEFAULT_UNINDEXED_READS_THRESHOLD;
/**
* @api
*
* @deprecated use QueryPlanAnalyzer::TABLES_WITHOUT_DATA instead
*/
public const TABLES_WITHOUT_DATA = QueryPlanAnalyzer::TABLES_WITHOUT_DATA;
/**
* @api
*
* @deprecated use QueryPlanAnalyzer::DEFAULT_SMALL_TABLE_THRESHOLD instead
*/
public const DEFAULT_SMALL_TABLE_THRESHOLD = QueryPlanAnalyzer::DEFAULT_SMALL_TABLE_THRESHOLD;
Expand Down
2 changes: 2 additions & 0 deletions src/Ast/ExpressionFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public function __construct()
}

/**
* @api
*
* @param Variable|MethodCall $expr
*
* @deprecated use findAssignmentExpression() instead
Expand Down
4 changes: 2 additions & 2 deletions src/Ast/PreviousConnectingVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class PreviousConnectingVisitor extends NodeVisitorAbstract
public const ATTRIBUTE_PREVIOUS = 'dba-previous';

/**
* @var Node[]
* @var list<Node>
*/
private $stack = [];

Expand All @@ -33,7 +33,7 @@ public function beforeTraverse(array $nodes)

public function enterNode(Node $node)
{
if (!empty($this->stack)) {
if ([] !== $this->stack) {
$node->setAttribute(self::ATTRIBUTE_PARENT, $this->stack[\count($this->stack) - 1]);
}

Expand Down
2 changes: 2 additions & 0 deletions src/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use staabm\PHPStanDba\QueryReflection\QuerySimulation;

/**
* @api
*
* @phpstan-type ErrorCodes value-of<MysqliQueryReflector::MYSQL_ERROR_CODES>|value-of<BasePdoQueryReflector::PDO_ERROR_CODES>
*/
final class Error
Expand Down
2 changes: 1 addition & 1 deletion src/PdoReflection/PdoStatementReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public function createGenericStatement(iterable $queryStrings, int $reflectionFe
foreach ($queryStrings as $queryString) {
$bothType = $queryReflection->getResultType($queryString, QueryReflector::FETCH_TYPE_BOTH);

if ($bothType) {
if (null !== $bothType) {
$genericObjects[] = new PdoStatementObjectType($bothType, $reflectionFetchType);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/PhpDoc/PhpDocUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static function matchTaintEscape($callLike, Scope $scope): ?string
// atm no resolved phpdoc for methods
// see https://github.com/phpstan/phpstan/discussions/7657
$phpDocString = $methodReflection->getDocComment();
if (null !== $phpDocString && preg_match('/@psalm-taint-escape\s+(\S+).*$/m', $phpDocString, $matches)) {
if (null !== $phpDocString && 1 === preg_match('/@psalm-taint-escape\s+(\S+).*$/m', $phpDocString, $matches)) {
return $matches[1];
}
}
Expand Down Expand Up @@ -91,7 +91,7 @@ private static function matchStringAnnotation(string $annotation, $callLike, Sco
// atm no resolved phpdoc for methods
// see https://github.com/phpstan/phpstan/discussions/7657
$phpDocString = $methodReflection->getDocComment();
if (null !== $phpDocString && preg_match('/'.$annotation.'\s+(\S+).*$/m', $phpDocString, $matches)) {
if (null !== $phpDocString && 1 === preg_match('/'.$annotation.'\s+(\S+).*$/m', $phpDocString, $matches)) {
$placeholder = $matches[1];

if (\in_array($placeholder[0], ['"', "'"], true)) {
Expand Down
4 changes: 2 additions & 2 deletions src/QueryReflection/ChainedReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function validateQueryString(string $queryString): ?Error
$reflectorError = $reflector->validateQueryString($queryString);

// on "not found" error, we try the next reflector.
if ($reflectorError) {
if (null !== $reflectorError) {
if (!\in_array($reflectorError->getCode(), [MysqliQueryReflector::MYSQL_UNKNOWN_TABLE], true)) {
return $reflectorError;
}
Expand All @@ -54,7 +54,7 @@ public function getResultType(string $queryString, int $fetchType): ?Type
foreach ($this->reflectors as $reflector) {
$reflectorResult = $reflector->getResultType($queryString, $fetchType);

if ($reflectorResult) {
if (null !== $reflectorResult) {
return $reflectorResult;
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/QueryReflection/MysqliQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ final class MysqliQueryReflector implements QueryReflector, RecordingReflector
private const MYSQL_SYNTAX_ERROR_CODE = 1064;
private const MYSQL_UNKNOWN_COLUMN_IN_FIELDLIST = 1054;
public const MYSQL_UNKNOWN_TABLE = 1146;
public const MYSQL_INCORRECT_TABLE = 1103;

public const MYSQL_HOST_NOT_FOUND = 2002;
private const MYSQL_INCORRECT_TABLE = 1103;

/**
* @api
*/
public const NAME = 'mysqli';

private const MYSQL_ERROR_CODES = [
Expand Down
3 changes: 3 additions & 0 deletions src/QueryReflection/Parameter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use PHPStan\Type\Type;

/**
* @api
*/
final class Parameter
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/QueryReflection/PdoMysqlQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
*/
class PdoMysqlQueryReflector extends BasePdoQueryReflector
{
/**
* @api
*/
public const NAME = 'pdo-mysql';

public function __construct(PDO $pdo)
Expand Down
3 changes: 3 additions & 0 deletions src/QueryReflection/PdoPgSqlQueryReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
*/
final class PdoPgSqlQueryReflector extends BasePdoQueryReflector
{
/**
* @api
*/
public const NAME = 'pdo-pgsql';

public function __construct(PDO $pdo)
Expand Down
11 changes: 8 additions & 3 deletions src/QueryReflection/QueryReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public function __construct(?DbaApi $dbaApi = null)
self::reflector()->setupDbaApi($dbaApi);
}

/**
* @api
*/
public static function setupReflector(QueryReflector $reflector, RuntimeConfiguration $runtimeConfiguration): void
{
self::$reflector = $reflector;
Expand All @@ -56,7 +59,7 @@ public static function setupReflector(QueryReflector $reflector, RuntimeConfigur

public function validateQueryString(string $queryString): ?Error
{
if ('SELECT' !== $this->getQueryType($queryString)) {
if ('SELECT' !== self::getQueryType($queryString)) {
return null;
}

Expand All @@ -73,7 +76,7 @@ public function validateQueryString(string $queryString): ?Error
*/
public function getResultType(string $queryString, int $fetchType): ?Type
{
if ('SELECT' !== $this->getQueryType($queryString)) {
if ('SELECT' !== self::getQueryType($queryString)) {
return null;
}

Expand Down Expand Up @@ -111,6 +114,8 @@ public function resolvePreparedQueryStrings(Expr $queryExpr, Type $parameterType
}

/**
* @api
*
* @deprecated use resolvePreparedQueryStrings() instead
*
* @throws UnresolvableQueryException
Expand Down Expand Up @@ -257,7 +262,7 @@ public static function getQueryType(string $query): ?string
{
$query = ltrim($query);

if (preg_match('/^\s*\(?\s*(SELECT|SHOW|UPDATE|INSERT|DELETE|REPLACE|CREATE|CALL|OPTIMIZE)/i', $query, $matches)) {
if (1 === preg_match('/^\s*\(?\s*(SELECT|SHOW|UPDATE|INSERT|DELETE|REPLACE|CREATE|CALL|OPTIMIZE)/i', $query, $matches)) {
return strtoupper($matches[1]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/QueryReflection/QuerySimulation.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*/
final class QuerySimulation
{
public const DATE_FORMAT = 'Y-m-d';
private const DATE_FORMAT = 'Y-m-d';

/**
* @throws UnresolvableQueryException
Expand Down
11 changes: 10 additions & 1 deletion src/QueryReflection/ReflectionCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

final class ReflectionCache
{
public const SCHEMA_VERSION = 'v11-phpstan1_9_3-update';
private const SCHEMA_VERSION = 'v11-phpstan1_9_3-update';

/**
* @var string
Expand Down Expand Up @@ -67,13 +67,22 @@ private function __construct(string $cacheFile)
}
}

/**
* @api
*
* @param non-empty-string $cacheFile
*
* @return static
*/
public static function create(string $cacheFile): self
{
return new self($cacheFile);
}

/**
* @deprecated use create() instead
*
* @api
*/
public static function load(string $cacheFile): self
{
Expand Down
3 changes: 3 additions & 0 deletions src/QueryReflection/RuntimeConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use PHPStan\Php\PhpVersion;
use staabm\PHPStanDba\Analyzer\QueryPlanAnalyzer;

/**
* @api
*/
final class RuntimeConfiguration
{
/**
Expand Down
4 changes: 2 additions & 2 deletions src/TypeMapping/MysqliTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public function __construct(?DbaApi $dbaApi)
// skip bool constants like MYSQLI_IS_MARIADB
continue;
}
if (preg_match('/^MYSQLI_TYPE_(.*)/', $c, $m)) {
if (1 === preg_match('/^MYSQLI_TYPE_(.*)/', $c, $m)) {
if (!\is_string($m[1])) {
throw new ShouldNotHappenException();
}
$this->nativeTypes[$n] = $m[1];
} elseif (preg_match('/MYSQLI_(.*)_FLAG$/', $c, $m)) {
} elseif (1 === preg_match('/MYSQLI_(.*)_FLAG$/', $c, $m)) {
if (!\is_string($m[1])) {
throw new ShouldNotHappenException();
}
Expand Down
Loading