Skip to content

Commit

Permalink
fix: add support for builder types
Browse files Browse the repository at this point in the history
  • Loading branch information
owenvoke committed Oct 17, 2024
1 parent bc4f5fa commit 1846907
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 25 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
"require-dev": {
"composer/composer": "^2.7",
"friendsofphp/php-cs-fixer": "^3.53",
"orchestra/testbench": "^9.5",
"pestphp/pest": "^2.34",
"spatie/invade": "^1.1.1",
"spatie/invade": "^1.0",
"squizlabs/php_codesniffer": "^3.8"
},
"autoload": {
Expand Down
36 changes: 25 additions & 11 deletions src/PHPStan/Laravel/Migrations/WithoutTimestampsVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Worksome\CodingStyle\PHPStan\Laravel\Migrations;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
Expand Down Expand Up @@ -107,27 +108,40 @@ private function isModelCall(Node $node): bool
return false;
}

if ($node instanceof MethodCall) {
$varType = $this->scope->getType($node->var);
if ($node instanceof StaticCall) {
if (! $node->class instanceof Node\Name) {
return false;
}

$className = $this->scope->resolveName($node->class);

if (! $className) {
return false;
}

$modelType = new ObjectType(Model::class);
$classType = new ObjectType($className);

return $varType->isSuperTypeOf($modelType)->yes();
return $modelType->isSuperTypeOf($classType)->yes();
}

if (! $node instanceof StaticCall || ! $node->class instanceof Node\Name) {
return false;
}
$classType = $this->scope->getType($node->var);

$className = $this->scope->resolveName($node->class);
$modelType = new ObjectType(Model::class);
$builderType = new ObjectType(Builder::class);

if ($modelType->isSuperTypeOf($classType)->yes()) {
return true;
}

if (! $className) {
if (! $builderType->isSuperTypeOf($classType)->yes()) {
return false;
}

$modelType = new ObjectType(Model::class);
$classType = new ObjectType($className);
if (! isset($classType->getTypes()[0])) {
return false;
}

return $classType->isSubclassOf($modelType)->yes();
return $modelType->isSuperTypeOf($classType->getTypes()[0])->yes();
}
}
1 change: 1 addition & 0 deletions tests/PHPStan/BaseRuleTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static function getAdditionalConfigFiles(): array
{
return array_merge(parent::getAdditionalConfigFiles(), [
__DIR__ . '/../../phpstan-rich-parser.neon',
__DIR__ . '/phpstan.neon',
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace Worksome\CodingStyle\Tests\PHPStan\Laravel\Migrations\RequireWithoutTimestampRule\Fixture\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class TestUser extends Model
{
use SoftDeletes;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ return new class extends Migration
'test' => 'test',
]);

$testUser = TestUser::make(['test' => 'test']);
$testUser->save();
TestUser::make(['test' => 'test'])->save();

$testUser2 = TestUser::make(['test' => 'test']);
$testUser2->saveQuietly();
TestUser::make(['test' => 'test'])->saveQuietly();

TestUser::where('test', 'test')
->delete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ return new class extends Migration
->nullable();
});

TestClient::withTrashed()->update([
TestClient::update([
'test' => 'test',
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@
24,
],
[
"Line 29: The 'save()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
29,
"Line 28: The 'save()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
28,
],
[
"Line 32: The 'saveQuietly()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
32,
"Line 30: The 'saveQuietly()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
30,
],
[
"Line 34: The 'delete()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
34,
"Line 32: The 'delete()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
32,
],
[
"Line 37: The 'restore()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
37,
"Line 35: The 'restore()' method call should be within 'withoutTimestamps()' context to prevent unintended timestamp updates.",
35,
],
],
'invalid migration with multiple models' => [
Expand Down
13 changes: 13 additions & 0 deletions tests/PHPStan/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
services:
- class: Larastan\Larastan\Methods\MacroMethodsClassReflectionExtension
tags:
- phpstan.broker.methodsClassReflectionExtension
- class: Larastan\Larastan\Methods\BuilderHelper
arguments:
checkProperties: false
- class: Larastan\Larastan\Methods\EloquentBuilderForwardsCallsExtension
tags:
- phpstan.broker.methodsClassReflectionExtension
- class: Larastan\Larastan\Methods\ModelForwardsCallsExtension
tags:
- phpstan.broker.methodsClassReflectionExtension

0 comments on commit 1846907

Please sign in to comment.