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
21 changes: 7 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- 'master'
- '3.next-cake5'
- '4.next-cake5'
pull_request:
branches:
- '*'
Expand All @@ -19,18 +19,11 @@ jobs:
strategy:
fail-fast: false
matrix:
php-version: ['8.1', '8.4']
dependencies: ['highest']
include:
- php-version: '8.1'
dependencies: 'lowest'
- php-version: '8.2'
dependencies: 'highest'
- php-version: '8.3'
dependencies: 'highest'
php-version: ['8.5']
dependencies: ['highest', 'lowest']

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -47,19 +40,19 @@ jobs:
composer-options: ${{ matrix.composer-options }}

- name: Run PHPUnit
run: vendor/bin/phpunit
run: composer test

cs-stan:
name: Coding Standard & Static Analysis
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.5'
extensions: mbstring, intl
coverage: none
tools: phive, cs2pr
Expand Down
43 changes: 0 additions & 43 deletions .travis.yml

This file was deleted.

10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# CakePHP extension for PHPStan
# CakePHP 6 extension for PHPStan

![Build Status](https://github.com/CakeDC/cakephp-phpstan/actions/workflows/ci.yml/badge.svg)
[![Downloads](https://poser.pugx.org/CakeDC/cakephp-phpstan/d/total.svg)](https://packagist.org/packages/CakeDC/cakephp-phpstan)
Expand All @@ -13,6 +13,10 @@ and multiple rules.

# Installation

Requires PHP 8.5+, CakePHP 6, and PHPStan 2.1.26+. CakePHP 6 is currently in development; configure `"minimum-stability": "dev"` and `"prefer-stable": true` in the root Composer project to allow its dependencies.

When upgrading, move custom console helpers to `Console/Helper`. Commands implement `execute(): ?int` and access arguments and console IO through properties.

To use this extension, require it through [Composer](https://getcomposer.org/):

```
Expand All @@ -39,11 +43,11 @@ Features included:
1. Provide correct return type for `Cake\ORM\Locator\LocatorInterface::get()`
1. Provide correct return type for `Cake\Controller\Controller::loadComponent()`
1. Provide correct return type for `Cake\Controller\Controller::fetchTable()`
1. Provide correct return type for `Cake\Controller\Component::fetchTable()`
1. Provide correct return type for `fetchTable()` on components using `Cake\ORM\Locator\LocatorAwareTrait`
1. Provide correct return type for `Cake\Command\Command::fetchTable()`
1. Provide correct return type for `Cake\Mailer\Mailer::fetchTable()`
1. Provide correct return type for `Cake\View\Cell::fetchTable()`
1. Provide correct return type for `Cake\Console\ConsoleIo::helper()`
1. Provide correct return type for `Cake\Console\ConsoleIo::helper()` and `Cake\Console\ConsoleIoInterface::helper()`

# Table class return type extensions
### SelectQueryFindListReturnTypeExtension
Expand Down
21 changes: 13 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cakedc/cakephp-phpstan",
"description": "CakePHP plugin extension for PHPStan.",
"description": "CakePHP 6 plugin extension for PHPStan.",
"type": "phpstan-extension",
"license": "MIT",
"authors": [
Expand All @@ -11,14 +11,14 @@
}
],
"require": {
"php": ">=8.1.0",
"php": ">=8.5",
"phpstan/phpstan": "^2.1.26",
"cakephp/cakephp": "^5.0"
"cakephp/cakephp": "^6.0"
},
"require-dev": {
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^10.5 || ^11.5 || ^12.1",
"cakephp/cakephp-codesniffer": "^5.0",
"phpunit/phpunit": "^13.0",
"cakephp/cakephp-codesniffer": "6.x-dev",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0"
},
Expand All @@ -39,12 +39,15 @@
"CakeDC\\PHPStan\\Test\\": "tests/",
"CakeDC\\MyPlugin\\": "tests/test_plugin",
"App\\": "tests/test_app"
}
},
"classmap": [
"tests/data/StaticOnlyTable.php"
]
},
"scripts": {
"cs-check": "phpcs -p",
"cs-fix": "phpcbf -p",
"test": "phpunit --stderr",
"test": "@php -d memory_limit=1G vendor/bin/phpunit --stderr",
"stan-integration": [
"phpstan analyse --debug -c phpstan-test-app.neon",
"phpstan analyse --debug -c phpstan-test-plugin.neon"
Expand All @@ -61,5 +64,7 @@
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
2 changes: 0 additions & 2 deletions phpstan-test-app.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,3 @@ parameters:
ignoreErrors:
-
identifier: missingType.generics
-
identifier: method.deprecated
26 changes: 9 additions & 17 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="./vendor/autoload.php"
backupGlobals="false"
colors="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd"
cacheDirectory=".phpunit.cache">

<testsuite name="CakeDCPhpStan">
<directory>./tests</directory>
</testsuite>

<source>
<include>
<directory suffix=".php">./src</directory>
</include>
</source>
<phpunit bootstrap="vendor/autoload.php" colors="true" cacheDirectory="tmp/phpunit">
<testsuites>
<testsuite name="CakeDCPhpStan">
<directory>tests/TestCase</directory>
</testsuite>
</testsuites>
<source>
<include><directory suffix=".php">src</directory></include>
</source>
</phpunit>
3 changes: 2 additions & 1 deletion src/Rule/Controller/ControllerMethodMustBeUsedRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Cake\Controller\Controller;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\Expression;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
Expand Down Expand Up @@ -62,7 +63,7 @@ public function processNode(Node $node, Scope $scope): array
$methodCall = $node->expr;

// Check if the method name is one we care about
if (!$methodCall->name instanceof Node\Identifier) {
if (!$methodCall->name instanceof Identifier) {
return [];
}

Expand Down
3 changes: 2 additions & 1 deletion src/Rule/Debug/DisallowDebugFuncCallRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use PhpParser\Node;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
Expand Down Expand Up @@ -44,7 +45,7 @@ public function getNodeType(): string
public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof FuncCall);
if (!$node->name instanceof Node\Name) {
if (!$node->name instanceof Name) {
return [];
}
$usedName = $node->name->name;
Expand Down
9 changes: 6 additions & 3 deletions src/Rule/LoadObjectExistsCakeClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
use CakeDC\PHPStan\Rule\Traits\ParseClassNameFromArgTrait;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\ArrayItem;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
Expand Down Expand Up @@ -49,7 +52,7 @@ public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof MethodCall);
$args = $node->getArgs();
if (!$node->name instanceof Node\Identifier) {
if (!$node->name instanceof Identifier) {
return [];
}
$reference = $scope->getType($node->var)->getReferencedClasses()[0] ?? null;
Expand Down Expand Up @@ -100,13 +103,13 @@ protected function getInputClassName(String_ $nameArg, ?Arg $options): ?string
$className = $nameArg->value;
if (
$options === null
|| !$options->value instanceof Node\Expr\Array_
|| !$options->value instanceof Array_
) {
return $className;
}
foreach ($options->value->items as $item) {
if (
!$item instanceof Node\Expr\ArrayItem
!$item instanceof ArrayItem
|| !$item->key instanceof String_
|| $item->key->value !== 'className'
) {
Expand Down
3 changes: 2 additions & 1 deletion src/Rule/Mailer/GetMailerExistsClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
Expand Down Expand Up @@ -56,7 +57,7 @@ public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof MethodCall);
if (
!$node->name instanceof Node\Identifier
!$node->name instanceof Identifier
|| $node->name->name !== 'getMailer'
) {
return [];
Expand Down
8 changes: 5 additions & 3 deletions src/Rule/Model/AddAssociationMatchOptionsTypesRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\ArrayItem;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
Expand Down Expand Up @@ -65,7 +67,7 @@ public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof MethodCall);
$args = $node->getArgs();
if (!$node->name instanceof Node\Identifier) {
if (!$node->name instanceof Identifier) {
return [];
}
$reference = $scope->getType($node->var)->getReferencedClasses()[0] ?? null;
Expand All @@ -78,7 +80,7 @@ public function processNode(Node $node, Scope $scope): array
}
if (
$details['options'] === null
|| !$details['options']->value instanceof Node\Expr\Array_
|| !$details['options']->value instanceof Array_
) {
return [];
}
Expand Down Expand Up @@ -170,7 +172,7 @@ protected function processPropertyTypeCheck(
$classReflection = $object->getClassReflection();
assert($classReflection instanceof ClassReflection);
$propertyType = $classReflection
->getInstanceProperty('_' . $property, $scope)
->getInstanceProperty($property, $scope)
->getWritableType();
$assignedValueType = $scope->getType($item->value);
$accepts = $this->ruleLevelHelper->accepts($propertyType, $assignedValueType, true);
Expand Down
8 changes: 5 additions & 3 deletions src/Rule/Model/OrmSelectQueryFindMatchOptionsTypesRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
use CakeDC\PHPStan\Rule\Traits\ParseClassNameFromArgTrait;
use InvalidArgumentException;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ExtendedMethodReflection;
Expand Down Expand Up @@ -99,7 +101,7 @@ public function processNode(Node $node, Scope $scope): array
{
assert($node instanceof MethodCall);
$args = $node->getArgs();
if (!$node->name instanceof Node\Identifier || !in_array($node->name->name, $this->targetMethods, true)) {
if (!$node->name instanceof Identifier || !in_array($node->name->name, $this->targetMethods, true)) {
return [];
}
$referenceClasses = $scope->getType($node->var)->getReferencedClasses();
Expand Down Expand Up @@ -238,7 +240,7 @@ protected function getTargetMethod(Scope $scope, string $targetMethod): ?Extende
* @param array<\PhpParser\Node\Expr> $options
* @return array<\PhpParser\Node\Expr>
*/
protected function extractOptionsUnpackedArray(Node\Arg $arg, array $options): array
protected function extractOptionsUnpackedArray(Arg $arg, array $options): array
{
if ($arg->value instanceof Array_ && $arg->unpack) {
$options = $this->getOptionsFromArray($arg->value, $options);
Expand Down Expand Up @@ -299,7 +301,7 @@ protected function getOptionsFromArray(Array_ $source, array $options): array
*/
protected function getParamNamesIgnore(Scope $scope, MethodCall $node): array
{
assert($node->name instanceof Node\Identifier);
assert($node->name instanceof Identifier);
$methodReflection = $scope->getMethodReflection($scope->getType($node->var), $node->name->toString());
if ($methodReflection === null) {
return [];
Expand Down
Loading
Loading