Skip to content

Commit

Permalink
Merge pull request #329 from tighten/adc/fix-namespace-slash
Browse files Browse the repository at this point in the history
Fix namespace leading slash
  • Loading branch information
driftingly authored Jan 12, 2023
2 parents 7dcc5d4 + 73709be commit be2a686
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 169 deletions.
2 changes: 1 addition & 1 deletion bin/tlint
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env php
<?php

const TLINT_VERSION = 'v7.0.0';
const TLINT_VERSION = 'v8.0.2';

foreach (
[
Expand Down
55 changes: 2 additions & 53 deletions src/Formatters/RemoveLeadingSlashNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Illuminate\Support\Str;
use PhpParser\Lexer;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\CloningVisitor;
use PhpParser\NodeVisitorAbstract;
Expand All @@ -31,17 +30,13 @@ public function format(Parser $parser, Lexer $lexer): string
$newStmts = $traverser->traverse($oldStmts);

$useStatementsVisitor = $this->useStatementVisitor($this->getCodeLines());
$classVisitor = $this->classVisitor($this->getCodeLines());

$traverser = new NodeTraverser();
$traverser->addVisitor($useStatementsVisitor);
$traverser->addVisitor($classVisitor);

$newStmts = $traverser->traverse($newStmts);
$traverser->traverse($newStmts);

$replacements = $useStatementsVisitor->getReplacements() + $classVisitor->getReplacements();

collect($replacements)->each(function ($replacement, $line) {
collect($useStatementsVisitor->getReplacements())->each(function ($replacement, $line) {
$this->code = $this->replaceCodeLine($line, $replacement);
});

Expand Down Expand Up @@ -84,50 +79,4 @@ public function enterNode(Node $node): Node|int|null
}
};
}

private function classVisitor($codeLines): NodeVisitorAbstract
{
return new class($codeLines) extends NodeVisitorAbstract
{
public $replaceLines = [];

private $codeLines = [];

public function __construct($codeLines)
{
$this->codeLines = $codeLines;
}

public function getReplacements()
{
return $this->replaceLines;
}

public function enterNode(Node $node): Node|int|null
{
if (! $node instanceof Node\Expr\New_
&& ! $node instanceof StaticCall
&& ! $node instanceof Node\Expr\ClassConstFetch
) {
return null;
}

if (! $node->class instanceof Node\Name) {
return null;
}

if (Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->class->toString() . '::class')
&& ! Str::contains($this->codeLines[$node->getLine() - 1], 'factory')
) {
return null;
}

if (Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->class->toString())) {
$this->replaceLines[$node->getLine()] = Str::replace('\\' . $node->class->toString(), $node->class->toString(), $this->codeLines[$node->getLine() - 1]);
}

return $node;
}
};
}
}
40 changes: 28 additions & 12 deletions src/Linters/RemoveLeadingSlashNamespaces.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,37 @@ public function lint(Parser $parser)
$traverser = new NodeTraverser();

$classVisitor = new FindingVisitor(function (Node $node) {
return (
$node instanceof Node\Expr\New_
|| $node instanceof Node\Expr\StaticCall
|| $node instanceof Node\Expr\ClassConstFetch
)
&& $node->class instanceof Node\Name
&& Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->class->toString())
&& (! Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->class->toString() . '::class')
|| Str::contains($this->codeLines[$node->getLine() - 1], 'factory'));
if (! $node instanceof Node\Expr\New_
&& ! $node instanceof Node\Expr\StaticCall
&& ! $node instanceof Node\Expr\ClassConstFetch
) {
return false;
}

if (! $node->class instanceof Node\Name) {
return false;
}

if (Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->class->toString() . '::class')
&& ! Str::contains($this->codeLines[$node->getLine() - 1], 'factory')
) {
return false;
}

return Str::matchAll('/(' . preg_quote('\\' . $node->class->toString()) . ')[(:@]{1}/', $this->codeLines[$node->getLine() - 1])
->isNotEmpty();
});

$useStatementsVisitor = new FindingVisitor(function (Node $node) {
return $node instanceof Node\Stmt\UseUse
&& $node->name instanceof Node\Name
&& Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->name->toString());
if (! $node instanceof Node\Stmt\UseUse) {
return false;
}

if (! $node->name instanceof Node\Name) {
return false;
}

return Str::contains($this->codeLines[$node->getLine() - 1], '\\' . $node->name->toString());
});

$traverser->addVisitor($classVisitor);
Expand Down
132 changes: 29 additions & 103 deletions tests/Formatting/Formatters/RemoveLeadingSlashNamespacesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,63 +14,35 @@ public function catches_leading_slashes_in_use_statements()
$file = <<<file
<?php
namespace App;
use \Tighten\TLint;
use \PHPUnit\Framework\TestCase;
echo test;
class TestClass
{
public function test()
{
echo test;
}
}
file;

$correctlyFormatted = <<<'file'
<?php
namespace App;
use Tighten\TLint;
use PHPUnit\Framework\TestCase;
echo test;
file;

$formatted = (new TFormat())->format(
new RemoveLeadingSlashNamespaces($file, '.php')
);

$this->assertEquals($correctlyFormatted, $formatted);
}

/** @test */
public function catches_leading_slashes_in_static_calls()
class TestClass
{
public function test()
{
$file = <<<file
<?php
echo \Auth::user()->name;
file;

$correctlyFormatted = <<<'file'
<?php
echo Auth::user()->name;
file;

$formatted = (new TFormat())->format(
new RemoveLeadingSlashNamespaces($file, '.php')
);

$this->assertEquals($correctlyFormatted, $formatted);
echo test;
}

/** @test */
public function catches_leading_slashes_in_instantiations()
{
$file = <<<file
<?php
echo new \User();
file;

$correctlyFormatted = <<<'file'
<?php
echo new User();
}
file;

$formatted = (new TFormat())->format(
Expand All @@ -81,44 +53,30 @@ public function catches_leading_slashes_in_instantiations()
}

/** @test */
public function does_not_throw_on_variable_class_static_calls()
public function does_not_catch_leading_slash_in_code()
{
$file = <<<'file'
<?php
namespace App\Newsboard\Factory;
namespace App;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;
class Relationships
class AppServiceProvider extends ServiceProvider
{
static function randomOrCreate($className)
public function boot()
{
if ($className::all()->count() > 0) {
return $className::all()->random();
}
return factory($className)->create();
}
}
file;

$formatted = (new TFormat())->format(
new RemoveLeadingSlashNamespaces($file, '.php')
);
$name = \Illuminate\Support\Facades\Auth::user()->name;
$this->assertEquals($file, $formatted);
}
$zip = new \ZipArchive;
/** @test */
public function does_not_throw_when_calling_class_in_a_namespaced_file()
{
$file = <<<'file'
<?php
$class = new \stdClass;
namespace App\Nova;
$model = \App\User::class;
class User extends BaseResource
{
public static $model = \App\User::class;
Validator::extend('recaptcha', 'App\Validators\ReCaptchaValidator@validate');
}
}
file;

Expand All @@ -128,36 +86,4 @@ class User extends BaseResource

$this->assertEquals($file, $formatted);
}

/** @test */
public function catches_leading_slash_in_factories()
{
$file = <<<'file'
<?php
$factory->define(App\S::class, function (Faker\Generator $faker) {
return [
'user_id' => factory(App\User::class),
'version_id' => factory(\App\J\V::class),
];
});
file;

$correctlyFormatted = <<<'file'
<?php
$factory->define(App\S::class, function (Faker\Generator $faker) {
return [
'user_id' => factory(App\User::class),
'version_id' => factory(App\J\V::class),
];
});
file;

$formatted = (new TFormat())->format(
new RemoveLeadingSlashNamespaces($file, '.php')
);

$this->assertEquals($correctlyFormatted, $formatted);
}
}

0 comments on commit be2a686

Please sign in to comment.