mirror of
https://github.com/danog/psalm-not-empty.git
synced 2024-11-26 20:04:54 +01:00
first commit
This commit is contained in:
parent
84d4f2d352
commit
6013ab1fda
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
|
||||
[*.{yaml,yml}]
|
||||
indent_size = 2
|
32
composer.json
Normal file
32
composer.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "orklah/psalm-no-empty",
|
||||
"description": "Automatically change empty() into a more explicit expression",
|
||||
"type": "psalm-plugin",
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "orklah"
|
||||
}
|
||||
],
|
||||
"extra": {
|
||||
"psalm" : {
|
||||
"pluginClass": "Orklah\\NotEmpty\\Plugin"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.3",
|
||||
"vimeo/psalm": "master"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Orklah\\NotEmpty\\": ["./src"]
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^4.0",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psalm/plugin-phpunit": "^0.15.0"
|
||||
}
|
||||
}
|
75
src/Hooks/NotEmptyHooks.php
Normal file
75
src/Hooks/NotEmptyHooks.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Orklah\NotEmpty\Hooks;
|
||||
|
||||
use PhpParser\Node\Expr\Empty_;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use Psalm\FileManipulation;
|
||||
use Psalm\Plugin\EventHandler\AfterExpressionAnalysisInterface;
|
||||
use Psalm\Plugin\EventHandler\Event\AfterExpressionAnalysisEvent;
|
||||
use Psalm\Type\Atomic;
|
||||
use function get_class;
|
||||
|
||||
|
||||
class NotEmptyHooks implements AfterExpressionAnalysisInterface
|
||||
{
|
||||
public static function afterExpressionAnalysis(AfterExpressionAnalysisEvent $event): ?bool
|
||||
{
|
||||
if (!$event->getCodebase()->alter_code) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$expr = $event->getExpr();
|
||||
$node_provider = $event->getStatementsSource()->getNodeTypeProvider();
|
||||
|
||||
if (!$expr instanceof Empty_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($expr->expr instanceof Variable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$type = $node_provider->getType($expr->expr);
|
||||
if ($type === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($type->from_docblock) {
|
||||
//TODO: maybe add an issue in non alter mode
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$type->isSingle()) {
|
||||
// TODO: add functionnality with isSingleAndMaybeNullable and add || EXPR !== null
|
||||
return true;
|
||||
}
|
||||
|
||||
$startPos = $expr->getStartFilePos() + 1;
|
||||
$endPos = $expr->getEndFilePos();
|
||||
|
||||
$atomic_types = $type->getAtomicTypes();
|
||||
$atomic_type = array_shift($atomic_types);
|
||||
$display_expr = (string)$expr->expr;
|
||||
if ($atomic_type instanceof Atomic\TInt) {
|
||||
$file_manipulation = new FileManipulation($startPos, $endPos, $display_expr . " === 0");
|
||||
$event->setFileReplacements([$file_manipulation]);
|
||||
} elseif ($atomic_type instanceof Atomic\TFloat) {
|
||||
$file_manipulation = new FileManipulation($startPos, $endPos, $display_expr . " === 0.0");
|
||||
$event->setFileReplacements([$file_manipulation]);
|
||||
} elseif ($atomic_type instanceof Atomic\TString) {
|
||||
$file_manipulation = new FileManipulation($startPos, $endPos, "(" . $display_expr . " === '' || " . $display_expr . " === '0')");
|
||||
$event->setFileReplacements([$file_manipulation]);
|
||||
} elseif ($atomic_type instanceof Atomic\TArray) {
|
||||
$file_manipulation = new FileManipulation($startPos, $endPos, $display_expr . " === []");
|
||||
$event->setFileReplacements([$file_manipulation]);
|
||||
} elseif ($atomic_type instanceof Atomic\TBool) {
|
||||
$file_manipulation = new FileManipulation($startPos, $endPos, $display_expr . " === false");
|
||||
$event->setFileReplacements([$file_manipulation]);
|
||||
} else {
|
||||
var_dump(get_class($atomic_type));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
17
src/Plugin.php
Normal file
17
src/Plugin.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace Orklah\NotEmpty;
|
||||
|
||||
use Orklah\NotEmpty\Hooks\NotEmptyHooks;
|
||||
use SimpleXMLElement;
|
||||
use Psalm\Plugin\PluginEntryPointInterface;
|
||||
use Psalm\Plugin\RegistrationInterface;
|
||||
|
||||
class Plugin implements PluginEntryPointInterface
|
||||
{
|
||||
public function __invoke(RegistrationInterface $registration, ?SimpleXMLElement $config = null): void
|
||||
{
|
||||
if(class_exists(NotEmptyHooks::class)){
|
||||
$registration->registerHooksFromClass(NotEmptyHooks::class);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user