From 45ed09d5fae4c1c7866fb09361d84ef22b4049a9 Mon Sep 17 00:00:00 2001 From: Can Vural Date: Wed, 26 Oct 2022 08:48:28 +0200 Subject: [PATCH] feat: add collector to collect used views from other views --- extension.neon | 4 ++ .../UsedViewInAnotherViewCollector.php | 43 +++++++++++++++++++ src/Rules/UnusedViewsRule.php | 10 ++++- .../resources/views/base.blade.php | 3 ++ .../resources/views/index.blade.php | 9 ++++ tests/Rules/Data/FooController.php | 5 +++ tests/Rules/UnusedViewsRuleTest.php | 4 +- 7 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/Collectors/UsedViewInAnotherViewCollector.php create mode 100644 tests/Application/resources/views/base.blade.php create mode 100644 tests/Application/resources/views/index.blade.php diff --git a/extension.neon b/extension.neon index 4e0e06004b..ccad453355 100644 --- a/extension.neon +++ b/extension.neon @@ -452,6 +452,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 diff --git a/src/Collectors/UsedViewInAnotherViewCollector.php b/src/Collectors/UsedViewInAnotherViewCollector.php new file mode 100644 index 0000000000..4c78774354 --- /dev/null +++ b/src/Collectors/UsedViewInAnotherViewCollector.php @@ -0,0 +1,43 @@ + */ +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; + } +} diff --git a/src/Rules/UnusedViewsRule.php b/src/Rules/UnusedViewsRule.php index f477c43f6b..721098089c 100644 --- a/src/Rules/UnusedViewsRule.php +++ b/src/Rules/UnusedViewsRule.php @@ -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; @@ -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 = []; diff --git a/tests/Application/resources/views/base.blade.php b/tests/Application/resources/views/base.blade.php new file mode 100644 index 0000000000..871449b815 --- /dev/null +++ b/tests/Application/resources/views/base.blade.php @@ -0,0 +1,3 @@ +

Base view

+ +@include('users.index') diff --git a/tests/Application/resources/views/index.blade.php b/tests/Application/resources/views/index.blade.php new file mode 100644 index 0000000000..b750de39d9 --- /dev/null +++ b/tests/Application/resources/views/index.blade.php @@ -0,0 +1,9 @@ + + +@extends('base') + +Lorem ipsum + +@include('home') diff --git a/tests/Rules/Data/FooController.php b/tests/Rules/Data/FooController.php index d21e7d02bb..dff1914c04 100644 --- a/tests/Rules/Data/FooController.php +++ b/tests/Rules/Data/FooController.php @@ -7,6 +7,11 @@ class FooController { + public function index() + { + return view('index'); + } + public function existing(): View { return view('users.index'); diff --git a/tests/Rules/UnusedViewsRuleTest.php b/tests/Rules/UnusedViewsRuleTest.php index f80a3678a2..69d8532c4b 100644 --- a/tests/Rules/UnusedViewsRuleTest.php +++ b/tests/Rules/UnusedViewsRuleTest.php @@ -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; @@ -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,