-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
443 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"excludePaths": ["tests/Rule/data/DeadMethodRule/removing"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace ShipMonk\PHPStan\DeadCode\Formatter; | ||
|
||
use PHPStan\Command\AnalysisResult; | ||
use PHPStan\Command\ErrorFormatter\ErrorFormatter; | ||
use PHPStan\Command\Output; | ||
use ShipMonk\PHPStan\DeadCode\Rule\DeadMethodRule; | ||
use ShipMonk\PHPStan\DeadCode\Transformer\FileSystem; | ||
use ShipMonk\PHPStan\DeadCode\Transformer\RemoveMethodCodeTransformer; | ||
use function count; | ||
|
||
class RemoveDeadCodeFormatter implements ErrorFormatter | ||
{ | ||
|
||
private FileSystem $fileSystem; | ||
|
||
public function __construct(FileSystem $fileSystem) | ||
{ | ||
$this->fileSystem = $fileSystem; | ||
} | ||
|
||
public function formatErrors( | ||
AnalysisResult $analysisResult, | ||
Output $output | ||
): int | ||
{ | ||
$internalErrors = $analysisResult->getInternalErrorObjects(); | ||
|
||
foreach ($internalErrors as $internalError) { | ||
$output->writeLineFormatted('<error>' . $internalError->getMessage() . '</error>'); | ||
} | ||
|
||
if (count($internalErrors) > 0) { | ||
$output->writeLineFormatted(''); | ||
$output->writeLineFormatted('Fix listed internal errors first.'); | ||
return 1; | ||
} | ||
|
||
$deadMethodKeysByFiles = []; | ||
|
||
foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) { | ||
if ($fileSpecificError->getIdentifier() !== DeadMethodRule::ERROR_IDENTIFIER) { | ||
continue; | ||
} | ||
|
||
/** @var array<string, array{file: string, line: string}> $metadata */ | ||
$metadata = $fileSpecificError->getMetadata(); | ||
|
||
foreach ($metadata as $key => $data) { | ||
$deadMethodKeysByFiles[$data['file']][] = $key; | ||
} | ||
} | ||
|
||
$count = 0; | ||
|
||
foreach ($deadMethodKeysByFiles as $file => $blackMethodKeys) { | ||
$count += count($blackMethodKeys); | ||
|
||
$transformer = new RemoveMethodCodeTransformer($blackMethodKeys); | ||
$oldCode = $this->fileSystem->read($file); | ||
$newCode = $transformer->transformCode($oldCode); | ||
$this->fileSystem->write($file, $newCode); | ||
} | ||
|
||
$output->writeLineFormatted('Removed ' . $count . ' dead methods in ' . count($deadMethodKeysByFiles) . ' files.'); | ||
|
||
return 0; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace ShipMonk\PHPStan\DeadCode\Transformer; | ||
|
||
use LogicException; | ||
use function file_get_contents; | ||
use function file_put_contents; | ||
|
||
class FileSystem | ||
{ | ||
|
||
public function read(string $path): string | ||
{ | ||
$contents = file_get_contents($path); | ||
|
||
if ($contents === false) { | ||
throw new LogicException('Could not read file: ' . $path); | ||
} | ||
|
||
return $contents; | ||
} | ||
|
||
public function write(string $path, string $content): void | ||
{ | ||
$success = file_put_contents($path, $content); | ||
|
||
if ($success === false) { | ||
throw new LogicException('Could not write to file: ' . $path); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace ShipMonk\PHPStan\DeadCode\Transformer; | ||
|
||
use LogicException; | ||
use PhpParser\Lexer; | ||
use PhpParser\NodeTraverser as PhpTraverser; | ||
use PhpParser\NodeVisitor\CloningVisitor; | ||
use PhpParser\Parser; | ||
use PhpParser\Parser\Php7; | ||
use PhpParser\PrettyPrinter\Standard as PhpPrinter; | ||
|
||
class RemoveMethodCodeTransformer | ||
{ | ||
|
||
private Lexer $phpLexer; | ||
|
||
private Parser $phpParser; | ||
|
||
private PhpTraverser $cloningTraverser; | ||
|
||
private PhpTraverser $removingTraverser; | ||
|
||
private PhpPrinter $phpPrinter; | ||
|
||
/** | ||
* @param list<string> $deadMethodKeys | ||
*/ | ||
public function __construct(array $deadMethodKeys) | ||
{ | ||
$this->phpLexer = new Lexer([ | ||
'usedAttributes' => [ | ||
'comments', | ||
'startLine', | ||
'endLine', | ||
'startTokenPos', | ||
'endTokenPos', | ||
], | ||
]); | ||
$this->phpParser = new Php7($this->phpLexer); | ||
|
||
$this->cloningTraverser = new PhpTraverser(); | ||
$this->cloningTraverser->addVisitor(new CloningVisitor()); | ||
|
||
$this->removingTraverser = new PhpTraverser(); | ||
$this->removingTraverser->addVisitor(new RemoveMethodVisitor($deadMethodKeys)); | ||
|
||
$this->phpPrinter = new PhpPrinter(); | ||
} | ||
|
||
public function transformCode(string $oldCode): string | ||
{ | ||
$oldAst = $this->phpParser->parse($oldCode); | ||
|
||
if ($oldAst === null) { | ||
throw new LogicException('Failed to parse the code'); | ||
} | ||
|
||
$oldTokens = $this->phpLexer->getTokens(); | ||
$newAst = $this->removingTraverser->traverse($this->cloningTraverser->traverse($oldAst)); | ||
return $this->phpPrinter->printFormatPreserving($newAst, $oldAst, $oldTokens); | ||
} | ||
|
||
} |
Oops, something went wrong.