Skip to content

Commit be2b185

Browse files
committed
use php-parser for deadcode
1 parent 9ece34b commit be2b185

File tree

8 files changed

+62
-25
lines changed

8 files changed

+62
-25
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"php": "^8.2",
2323
"deeplcom/deepl-php": "^1.7",
2424
"illuminate/contracts": "^10.0||^11.0",
25+
"nikic/php-parser": "^5.1",
2526
"openai-php/laravel": "^0.10.1",
2627
"spatie/laravel-package-tools": "^1.16",
2728
"spatie/regex": "^3.1",

config/translator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@
4141
],
4242

4343
'searchcode' => [
44-
'service' => 'regex',
44+
'service' => 'php-parser',
4545

4646
'services' => [
47-
'regex' => [
47+
'php-parser' => [
4848
'paths' => [
4949
app_path(),
5050
resource_path(),

src/Services/SearchCode/RegexService.php renamed to src/Services/SearchCode/PhpParserService.php

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22

33
namespace Elegantly\Translator\Services\SearchCode;
44

5-
use Spatie\Regex\MatchResult;
6-
use Spatie\Regex\Regex;
5+
use Illuminate\Support\Facades\Blade;
6+
use PhpParser\Node;
7+
use PhpParser\Node\Expr\FuncCall;
8+
use PhpParser\Node\Scalar\String_;
9+
use PhpParser\NodeFinder;
10+
use PhpParser\ParserFactory;
711
use Symfony\Component\Finder\Finder;
812
use Symfony\Component\Finder\SplFileInfo;
913

10-
class RegexService implements SearchCodeServiceInterface
14+
class PhpParserService implements SearchCodeServiceInterface
1115
{
12-
public static $patterns = [
13-
'/__\(["\'](?<key>[a-z0-9.\-_]+)["\']\)/i',
14-
];
15-
1616
public function __construct(
1717
public array $paths
1818
) {
@@ -38,22 +38,41 @@ public function finder(): Finder
3838
*/
3939
public static function scanCode(string $code): array
4040
{
41-
$chunks = collect(explode("\n", $code));
4241

43-
return $chunks
44-
->flatMap(function (string $code) {
45-
return collect(static::$patterns)
46-
->flatMap(fn (string $pattern) => Regex::matchAll($pattern, $code)->results())
47-
->map(fn (MatchResult $matchResult) => $matchResult->group('key'));
42+
$parser = (new ParserFactory)->createForNewestSupportedVersion();
43+
44+
$ast = $parser->parse($code);
45+
46+
$nodeFinder = new NodeFinder;
47+
48+
/** @var FuncCall[] $results */
49+
$results = $nodeFinder->find($ast, function (Node $node) {
50+
return $node instanceof FuncCall
51+
&& in_array($node->name->name, ['__', 'trans', 'trans_choice']);
52+
});
53+
54+
return collect($results)
55+
->map(function (FuncCall $funcCall) {
56+
$args = collect($funcCall->getArgs());
57+
$argKey = $args->firstWhere('name.name', 'key') ?? $args->first();
58+
$value = $argKey->value;
59+
60+
return $value instanceof String_ ? $value->value : null;
4861
})
62+
->values()
4963
->toArray();
5064
}
5165

5266
public function translationsByFiles(): array
5367
{
5468
return collect($this->finder())
55-
->keyBy(fn (SplFileInfo $file) => $file->getRealPath())
56-
->map(fn (SplFileInfo $file) => static::scanCode($file->getContents()))
69+
->map(function (SplFileInfo $file) {
70+
$content = str($file->getFilename())->endsWith('.blade.php')
71+
? Blade::compileString($file->getContents())
72+
: $file->getContents();
73+
74+
return static::scanCode($content);
75+
})
5776
->filter()
5877
->toArray();
5978
}

src/Services/SearchCode/SearchCodeServiceInterface.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
interface SearchCodeServiceInterface
66
{
7+
/**
8+
* @return array<string, string[]>
9+
*/
710
public function translationsByFiles(): array;
811

912
/**

src/TranslatorServiceProvider.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use Elegantly\Translator\Commands\TranslateTranslationsCommand;
99
use Elegantly\Translator\Services\Grammar\GrammarServiceInterface;
1010
use Elegantly\Translator\Services\Grammar\OpenAiService as GrammarOpenAiService;
11-
use Elegantly\Translator\Services\SearchCode\RegexService;
11+
use Elegantly\Translator\Services\SearchCode\PhpParserService;
1212
use Elegantly\Translator\Services\SearchCode\SearchCodeServiceInterface;
1313
use Elegantly\Translator\Services\Translate\DeepLService;
1414
use Elegantly\Translator\Services\Translate\OpenAiService;
@@ -88,7 +88,7 @@ public static function getSearchcodeServiceFromConfig(?string $serviceName = nul
8888
$service = $serviceName ?? config('translator.searchcode.service');
8989

9090
return match ($service) {
91-
'regex', RegexService::class => new RegexService(
91+
'php-parser', PhpParserService::class => new PhpParserService(
9292
config('translator.searchcode.services.regex.paths')
9393
),
9494
'', null => null,

tests/Feature/TranslatorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
use Elegantly\Translator\Services\SearchCode\RegexService;
3+
use Elegantly\Translator\Services\SearchCode\PhpParserService;
44
use Elegantly\Translator\Translator;
55

66
it('gets locales', function () {
@@ -88,7 +88,7 @@
8888
it('finds dead translations', function () {
8989
$translator = new Translator(
9090
storage: $this->getStorage(),
91-
searchcodeService: new RegexService([
91+
searchcodeService: new PhpParserService([
9292
$this->getAppPath(),
9393
$this->getResourcesPath(),
9494
])

tests/Unit/RegexServiceTest.php renamed to tests/Unit/PhpParserServiceTest.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
<?php
22

3-
use Elegantly\Translator\Services\SearchCode\RegexService;
3+
use Elegantly\Translator\Services\SearchCode\PhpParserService;
4+
5+
it('finds all occurences of __ in code', function (string $code) {
6+
$results = PhpParserService::scanCode($code);
7+
8+
expect($results)->toHaveLength(1);
9+
})->with([
10+
"<?php __('messages.dummy.class');",
11+
"<?php trans('messages.dummy.class');",
12+
"<?php trans_choice('messages.dummy.class', 1);",
13+
"<?php __('messages.dummy.class', []);",
14+
"<?php __('messages.dummy.class', [], 'en');",
15+
"<?php __(key: 'messages.dummy.class');",
16+
"<?php __(key: 'messages.dummy.class', replace: [], locale: 'en');",
17+
]);
418

519
it('gets all the translations keys grouped by files', function () {
620

721
$appPath = $this->getAppPath();
822
$resourcesPath = $this->getResourcesPath();
923

10-
$service = new RegexService(
24+
$service = new PhpParserService(
1125
paths: [
1226
$appPath,
1327
$resourcesPath,
@@ -34,7 +48,7 @@
3448
$appPath = $this->getAppPath();
3549
$resourcesPath = $this->getResourcesPath();
3650

37-
$service = new RegexService(
51+
$service = new PhpParserService(
3852
paths: [
3953
$appPath,
4054
$resourcesPath,

tests/src/app/DummyClass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ class DummyClass
66
{
77
public function getLabel()
88
{
9-
return __('messages.dummy.class');
9+
return __(key: 'messages.dummy.class');
1010
}
1111
}

0 commit comments

Comments
 (0)