Skip to content

Instantly share code, notes, and snippets.

@asgrim
Last active May 1, 2020 15:31
Show Gist options
  • Save asgrim/9d19a2360feb338326520c5f8b4ea0f3 to your computer and use it in GitHub Desktop.
Save asgrim/9d19a2360feb338326520c5f8b4ea0f3 to your computer and use it in GitHub Desktop.
Simplified plugin for Psalm that does (part of) what I wanted in this Tweet: https://twitter.com/asgrim/status/1256181096938647555
<?php
declare(strict_types=1);
namespace StaticAnalysisPlugin;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use Psalm\Codebase;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\FileManipulation;
use Psalm\IssueBuffer;
use Psalm\Plugin\Hook\AfterMethodCallAnalysisInterface;
use Psalm\StatementsSource;
use Psalm\Type\Union;
class DisallowBlacklistedClassUsage implements AfterMethodCallAnalysisInterface
{
private static function noop() : void
{
}
public static function afterMethodCallAnalysis(
Expr $expr,
string $method_id,
string $appearing_method_id,
string $declaring_method_id,
Context $context,
StatementsSource $statements_source,
Codebase $codebase,
array &$file_replacements = [],
Union &$return_type_candidate = null) : void
{
if ($expr instanceof StaticCall) {
$className = $expr->class->getAttribute('resolvedName');
if (is_a($className, \Something\Blacklisted::class, true)) {
if (IssueBuffer::accepts(
new IllegalBlacklistedClassUsage(
'Illegal blacklisted class usage: ' . $className,
new CodeLocation($statements_source, $expr->name)
),
$statements_source->getSuppressedIssues()
)) {
self::noop();
}
}
}
}
}
class IllegalBlacklistedClassUsage extends \Psalm\Issue\PluginIssue {
}
@asgrim
Copy link
Author

asgrim commented May 1, 2020

Simplified plugin for Psalm that does (part of) what I wanted in this Tweet:

https://twitter.com/asgrim/status/1256181096938647555

https://psalm.dev/r/642d7a8565

A fuller implementation would check all this:

<?php

// class "A" is "blacklisted"

class A {
    public static string $staticProp = '';
    public string $prop = '';
    public static function foo() : void {}
    public function bar() : void {}
}
class B extends A {}
class C extends A {}

// All the following should be considered violations:
$b = new B();
new C();
B::foo();
A::foo();
$b->foo();
echo A::$staticProp;
echo $b->prop;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment