Skip to content

Commit 3bceb9c

Browse files
authored
Merge pull request #10 from skylerkatz/feature/more-laralint-rules
special consideration for casts and booted method locations
2 parents e30ef97 + 620c651 commit 3bceb9c

6 files changed

Lines changed: 97 additions & 17 deletions

File tree

.github/workflows/phpunit.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Tests
22

3-
on: [push]
3+
on: [push, pull_request]
44

55
jobs:
66
phpunit:
@@ -41,14 +41,11 @@ jobs:
4141
run: "composer require --dev laravel/framework:^${{ matrix.laravel }}.0 orchestra/testbench:^${{ matrix.testbench }}.0 --update-with-all-dependencies --prefer-${{ matrix.dependency-version }} --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist"
4242

4343
- name: Execute tests
44-
run: vendor/bin/phpunit --coverage-clover ${{ github.workspace }}/clover.xml
44+
run: vendor/bin/phpunit --coverage-html "${{ github.workspace }}/code-coverage"
4545

4646
- name: Publish code coverage
47-
uses: paambaati/codeclimate-action@v2.4.0
48-
env:
49-
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
47+
if: matrix.laravel == 12 && matrix.dependency-version == 'stable'
48+
uses: actions/upload-artifact@v4
5049
with:
51-
coverageCommand: echo "ok"
52-
debug: true
53-
coverageLocations:
54-
"${{github.workspace}}/clover.xml:clover"
50+
name: code-coverage
51+
path: "${{github.workspace}}/code-coverage"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
/vendor/
33
composer.lock
44
.phpunit.result.cache
5+
/.phpunit.cache
6+
/code-coverage
57
.DS_Store

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# LaraLint
22

3-
[![GitHub Workflow Status](https://github.com/glhd/laralint/workflows/Tests/badge.svg)](https://github.com/glhd/laralint/actions?query=workflow%3ATests) [![Test Coverage](https://api.codeclimate.com/v1/badges/a2394b6b2d0b1e212fc1/test_coverage)](https://codeclimate.com/github/glhd/laralint/test_coverage)
3+
[![GitHub Workflow Status](https://github.com/glhd/laralint/workflows/Tests/badge.svg)](https://github.com/glhd/laralint/actions?query=workflow%3ATests)
44

55
This is a **very early** work-in-progress linter for Laravel projects.
66
It’s different from other PHP linters in that it focuses on building

phpunit.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" bootstrap="vendor/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
3-
<coverage processUncoveredFiles="true">
4-
<include>
5-
<directory suffix=".php">./src</directory>
6-
</include>
7-
</coverage>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
83
<testsuites>
94
<testsuite name="Tests">
105
<directory suffix="Test.php">./tests</directory>
@@ -18,4 +13,9 @@
1813
<env name="QUEUE_DRIVER" value="sync"/>
1914
<env name="MAIL_DRIVER" value="array"/>
2015
</php>
16+
<source>
17+
<include>
18+
<directory suffix=".php">./src</directory>
19+
</include>
20+
</source>
2121
</phpunit>

src/Linters/OrderClassMembers.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
use Glhd\LaraLint\Linters\Concerns\EvaluatesNodes;
66
use Glhd\LaraLint\Linters\Strategies\OrderingLinter;
77
use Illuminate\Support\Collection;
8+
use Illuminate\Support\Facades\Config;
89
use Illuminate\Support\Str;
910
use Microsoft\PhpParser\Node;
11+
use Microsoft\PhpParser\Node\ClassBaseClause;
1012
use Microsoft\PhpParser\Node\ClassConstDeclaration;
1113
use Microsoft\PhpParser\Node\MethodDeclaration;
1214
use Microsoft\PhpParser\Node\PropertyDeclaration;
1315
use Microsoft\PhpParser\Node\Statement\ClassDeclaration;
1416
use Microsoft\PhpParser\Node\TraitUseClause;
17+
use Microsoft\PhpParser\ResolvedName;
1518

1619
class OrderClassMembers extends OrderingLinter
1720
{
@@ -105,6 +108,41 @@ protected function matchers() : Collection
105108
return $this->isPrivate($node)
106109
&& false === $this->isStatic($node);
107110
}),
111+
112+
'the casts method' => $this->treeMatcher()
113+
->withChild(function(ClassDeclaration $node) {
114+
if (!$node->classBaseClause instanceof ClassBaseClause) {
115+
return false;
116+
}
117+
118+
$resolved = $node->classBaseClause->baseClass->getResolvedName();
119+
$extends = $resolved instanceof ResolvedName
120+
? $resolved->getFullyQualifiedNameText()
121+
: (string) $resolved;
122+
123+
return in_array($extends, Config::get('laralint.models', []));
124+
})
125+
->withChild(function(MethodDeclaration $node) {
126+
return 'casts' === $node->getName();
127+
}),
128+
129+
'the boot method' => $this->treeMatcher()
130+
->withChild(function(ClassDeclaration $node) {
131+
if (!$node->classBaseClause instanceof ClassBaseClause) {
132+
return false;
133+
}
134+
135+
$resolved = $node->classBaseClause->baseClass->getResolvedName();
136+
$extends = $resolved instanceof ResolvedName
137+
? $resolved->getFullyQualifiedNameText()
138+
: (string) $resolved;
139+
140+
return in_array($extends, Config::get('laralint.models', []));
141+
})
142+
->withChild(function(MethodDeclaration $node) {
143+
return in_array($node->getName(), ['booting', 'boot', 'booted'])
144+
&& $this->isStatic($node);
145+
}),
108146

109147
'an abstract method' => $this->treeMatcher()
110148
->withChild(function(MethodDeclaration $node) {

tests/Linters/OrderClassMembersTest.php

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,50 @@ public function publicFunctionAfterProtectedFunction()
112112
->lintSource($source)
113113
->assertNoLintingResults();
114114
}
115-
115+
116+
public function test_it_gives_special_consideration_to_casts_and_boot_methods_in_models() : void
117+
{
118+
$source = <<<'END_SOURCE'
119+
class Foo extends \App\Model
120+
{
121+
protected function casts(): array
122+
{
123+
return [];
124+
}
125+
126+
protected static function boot()
127+
{
128+
}
129+
130+
public function getFooAttribute()
131+
{
132+
}
133+
134+
public function setFooAttribute()
135+
{
136+
}
137+
138+
public function bar()
139+
{
140+
return $this->hasOne(Bar::class);
141+
}
142+
143+
public function scopeBar($query)
144+
{
145+
}
146+
147+
#[\Illuminate\Database\Eloquent\Attributes\Scope]
148+
public function baz($query)
149+
{
150+
}
151+
}
152+
END_SOURCE;
153+
154+
$this->withLinter(OrderClassMembers::class)
155+
->lintSource($source)
156+
->assertNoLintingResults();
157+
}
158+
116159
public function test_it_handles_anonymous_classes_with_their_own_ordering() : void
117160
{
118161
$source = <<<'END_SOURCE'

0 commit comments

Comments
 (0)