Skip to content

Commit

Permalink
feat: add collector to collect used views from other views
Browse files Browse the repository at this point in the history
  • Loading branch information
canvural committed Nov 1, 2022
1 parent ae6fd19 commit 45997d5
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 5 deletions.
6 changes: 4 additions & 2 deletions extension.neon
Expand Up @@ -5,8 +5,6 @@ parameters:
earlyTerminatingFunctionCalls:
- abort
- dd
excludePaths:
- *.blade.php
mixinExcludeClasses:
- Eloquent
bootstrapFiles:
Expand Down Expand Up @@ -452,6 +450,10 @@ services:
class: NunoMaduro\Larastan\Collectors\UsedEmailViewCollector
tags:
- phpstan.collector
-
class: NunoMaduro\Larastan\Collectors\UsedViewInAnotherViewCollector
tags:
- phpstan.collector
rules:
- NunoMaduro\Larastan\Rules\RelationExistenceRule
- NunoMaduro\Larastan\Rules\UselessConstructs\NoUselessWithFunctionCallsRule
Expand Down
43 changes: 43 additions & 0 deletions src/Collectors/UsedViewInAnotherViewCollector.php
@@ -0,0 +1,43 @@
<?php

namespace NunoMaduro\Larastan\Collectors;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Collectors\Collector;
use PHPStan\Node\FileNode;

/** @implements Collector<FileNode, string[]> */
class UsedViewInAnotherViewCollector implements Collector
{
/** @see https://regex101.com/r/8gosof/1 */
private const VIEW_NAME_REGEX = '/@(extends|include(If|Unless|When|First)?)(\(.*?\'(.*?)\'(\)|,))/m';

public function getNodeType(): string
{
return FileNode::class;
}

public function processNode(Node $node, Scope $scope): ?array
{
$nodes = array_filter($node->getNodes(), function (Node $node) {
return $node instanceof Node\Stmt\InlineHTML;
});

if (count($nodes) === 0) {
return null;
}

$usedViews = [];

foreach ($nodes as $node) {
preg_match_all(self::VIEW_NAME_REGEX, $node->value, $matches, PREG_SET_ORDER, 0);

$usedViews = array_merge($usedViews, array_map(function ($match) {
return $match[4];
}, $matches));
}

return $usedViews;
}
}
10 changes: 8 additions & 2 deletions src/Rules/UnusedViewsRule.php
Expand Up @@ -4,10 +4,12 @@

namespace NunoMaduro\Larastan\Rules;

use function collect;
use Illuminate\Support\Facades\File;
use Illuminate\View\Factory;
use NunoMaduro\Larastan\Collectors\UsedEmailViewCollector;
use NunoMaduro\Larastan\Collectors\UsedViewFunctionCollector;
use NunoMaduro\Larastan\Collectors\UsedViewInAnotherViewCollector;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Node\CollectedDataNode;
Expand All @@ -25,12 +27,16 @@ public function getNodeType(): string

public function processNode(Node $node, Scope $scope): array
{
$usedViews = array_unique(array_merge(...array_values($node->get(UsedViewFunctionCollector::class)), ...array_values($node->get(UsedEmailViewCollector::class))));
$usedViews = collect([
$node->get(UsedViewFunctionCollector::class),
$node->get(UsedEmailViewCollector::class),
$node->get(UsedViewInAnotherViewCollector::class),
])->flatten()->unique()->toArray();

$allViews = array_map(function (SplFileInfo $file) {
return $file->getPathname();
}, array_filter(File::allFiles(resource_path('views')), function (SplFileInfo $file) {
return ! str_contains($file->getPathname(), 'views/vendor') && $file->getExtension() === 'php' && str_ends_with($file->getFilename(), '.blade.php');
return ! str_contains($file->getPathname(), 'views/vendor') && str_ends_with($file->getFilename(), '.blade.php');
}));

$existingViews = [];
Expand Down
3 changes: 3 additions & 0 deletions tests/Application/resources/views/base.blade.php
@@ -0,0 +1,3 @@
<h1>Base view</h1>

@include('users.index')
9 changes: 9 additions & 0 deletions tests/Application/resources/views/index.blade.php
@@ -0,0 +1,9 @@
<?php
// ignore here
?>

@extends('base')

Lorem ipsum

@include('home')
5 changes: 5 additions & 0 deletions tests/Rules/Data/FooController.php
Expand Up @@ -7,6 +7,11 @@

class FooController
{
public function index()
{
return view('index');
}

public function existing(): View
{
return view('users.index');
Expand Down
4 changes: 3 additions & 1 deletion tests/Rules/UnusedViewsRuleTest.php
Expand Up @@ -4,6 +4,7 @@

use NunoMaduro\Larastan\Collectors\UsedEmailViewCollector;
use NunoMaduro\Larastan\Collectors\UsedViewFunctionCollector;
use NunoMaduro\Larastan\Collectors\UsedViewInAnotherViewCollector;
use NunoMaduro\Larastan\Rules\UnusedViewsRule;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
Expand All @@ -21,12 +22,13 @@ protected function getCollectors(): array
return [
new UsedViewFunctionCollector,
new UsedEmailViewCollector,
new UsedViewInAnotherViewCollector,
];
}

public function testRule(): void
{
$this->analyse([__DIR__.'/Data/FooController.php'], [
$this->analyse([__DIR__.'/Data/FooController.php', __DIR__.'/../Application/resources/views/index.blade.php', __DIR__.'/../Application/resources/views/base.blade.php'], [
[
'This view is not used in the project.',
00,
Expand Down

0 comments on commit 45997d5

Please sign in to comment.