-
Notifications
You must be signed in to change notification settings - Fork 664
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add ability to load plugins by class names - Plugins need to implement `__invoke(PluginFacade $psalm):void` method - Plugins are enabled by adding `<pluginClass class="Qualified\Class\Name"/>` - `PluginFacade` provides a single point of contact with Psalm, so that plugins cannot become coupled to Psalm internals * added `psalm-plugin` cli tool to manage plugins Available commands: `psalm-plugin list` - lists available and enabled plugins `psalm-plugin enable 'Plugin\Class\Name'` - enables plugin (modifies `psalm.xml`) `psalm-plugin disable 'Plugin\Class\Name'` - disables plugin (modifies `psalm.xml`) Plugin installation: `composer install plugin-vendor/plugin-package-name` Plugin authoring: Plugins are identified by package `type` field, which should contain `psalm-plugin` string. `extra.pluginClass` should refer to the name of the class implementing `__invoke(PluginFacade $psalm):void` function Todo: - better config file search - better output for `psalm-plugin` - better formatting for modified xml file - composer skeleton project for plugins - ability to refer to plugins by package name (cli only) - composer plugin to (optionally) enable plugin upon installation - documentation on plugin installation and authoring - interfaces for plugin dependencies - interface for plugin entry point - migration path for legacy plugins * documented previously undocumented plugin methods * split legacy plugin registration into a wrapper class also added `PluginApi` namespace and `RegistrationInterface` * reuse psalm's config search algorithm * enable/disable plugins by composer package name * allow specifying alternative config file name * whitelist PluginApi namespace three times, but well, it works now * interface for plugin entry points * psalm-plugin as a symfony console app * fixed errors found by psalm * suppressed false positive UnusedMethods * cs fix * better psalm-plugin output * don't leave empty `plugins` node to avoid old schema violation * removed junk file that shouldn't be there * cs fix * fixed phpunit failure (constant redefinition) * work around missing docblock in on symfony console * php 7.0 compatibility * allow `pluginClass` child elements as plugin configuration * decouple console commands from undelying implementation - introduce PluginListFactory - add `PluginList::enable(string $class)` and `PluginList::disable(string $class)` * PluginList tests * ComposerLock test * droppped debugging statement * added part of console command tests * added tests for EnableCommand * added DisableCommand tests * ignore unused args * ConfigFile test * disable travis cache in attempt to fix builds * nah, that didn't work * update for upstream changes * rebase fixes * namespaced `extra` entry for entry point * s/PluginFacade/PluginRegistrationSocket/g * Added $config parameter to PluginEntryPointInterface::__invoke() * cs fixes * entry point interface php7.0 compatibility * cleaned up old cruft - dropped todos I'm not going to pursues - locked entry point to be a class implementing entry point interface * fixed legacy plugins docs * Added RegistrationInterface::registerHooksFromClass() It mimics the way old plugins were registered in Psalm\Config, so handler classes extending Psalm\Plugin should be fully compatible with it. Since Psalm\Plugin-style plugin registration was moved to RegistrationSocket, LegacyPlugin now only load file-based plugins, so it was renamed to FileBasedPluginAdapter. * Converted EchoChecker plugin to composer-based format - Its subfolder is registered as a local composer package in the root composer.json, so it's directly installable with ``` composer require psalm/echo-checker-plugin ``` - Migration is trivial: drop the plugin into a separate folder, then add simple composer.json and the entry point class. * Updated docs * Don't reject hook handlers that inherit handling methods * strip void return type in stub file
- Loading branch information
Showing
31 changed files
with
1,877 additions
and
44 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
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,72 @@ | ||
<?php | ||
namespace Vimeo\CodeAnalysis\EchoChecker; | ||
|
||
use PhpParser; | ||
use Psalm\Checker; | ||
use Psalm\Checker\StatementsChecker; | ||
use Psalm\CodeLocation; | ||
use Psalm\Context; | ||
use Psalm\FileManipulation\FileManipulation; | ||
use Psalm\IssueBuffer; | ||
use Psalm\Issue\TypeCoercion; | ||
|
||
class EchoChecker extends \Psalm\Plugin | ||
{ | ||
/** | ||
* Called after an expression has been checked | ||
* | ||
* @param StatementsChecker $statements_checker | ||
* @param PhpParser\Node $stmt | ||
* @param Context $context | ||
* @param CodeLocation $code_location | ||
* @param string[] $suppressed_issues | ||
* @param FileManipulation[] $file_replacements | ||
* | ||
* @return null|false | ||
*/ | ||
public static function afterStatementCheck( | ||
StatementsChecker $statements_checker, | ||
PhpParser\Node $stmt, | ||
Context $context, | ||
CodeLocation $code_location, | ||
array $suppressed_issues, | ||
array &$file_replacements = [] | ||
) { | ||
if ($stmt instanceof PhpParser\Node\Stmt\Echo_) { | ||
foreach ($stmt->exprs as $expr) { | ||
if (!isset($expr->inferredType) || $expr->inferredType->isMixed()) { | ||
if (IssueBuffer::accepts( | ||
new TypeCoercion( | ||
'Echo requires an unescaped string, ' . $expr->inferredType . ' provided', | ||
new CodeLocation($statements_checker->getSource(), $expr) | ||
), | ||
$statements_checker->getSuppressedIssues() | ||
)) { | ||
// keep soldiering on | ||
} | ||
|
||
continue; | ||
} | ||
|
||
$types = $expr->inferredType->getTypes(); | ||
|
||
foreach ($types as $type) { | ||
if ($type instanceof \Psalm\Type\Atomic\TString | ||
&& !$type instanceof \Psalm\Type\Atomic\TLiteralString | ||
&& !$type instanceof \Psalm\Type\Atomic\THtmlEscapedString | ||
) { | ||
if (IssueBuffer::accepts( | ||
new TypeCoercion( | ||
'Echo requires an unescaped string, ' . $expr->inferredType . ' provided', | ||
new CodeLocation($statements_checker->getSource(), $expr) | ||
), | ||
$statements_checker->getSuppressedIssues() | ||
)) { | ||
// keep soldiering on | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
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,15 @@ | ||
<?php | ||
namespace Vimeo\CodeAnalysis\EchoChecker; | ||
|
||
use Psalm\PluginApi; | ||
use SimpleXMLElement; | ||
|
||
class PluginEntryPoint implements PluginApi\PluginEntryPointInterface | ||
{ | ||
/** @return void */ | ||
public function __invoke(PluginApi\RegistrationInterface $registration, ?SimpleXMLElement $config = null) | ||
{ | ||
require_once __DIR__ . '/EchoChecker.php'; | ||
$registration->registerHooksFromClass(EchoChecker::class); | ||
} | ||
} |
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,21 @@ | ||
{ | ||
"name": "psalm/echo-checker-plugin", | ||
"description": "Checks echo statements", | ||
"type": "psalm-plugin", | ||
"license": "MIT", | ||
"authors": [ | ||
{ | ||
"name": "Matthew Brown" | ||
} | ||
], | ||
"extra": { | ||
"psalm": { | ||
"pluginClass": "Vimeo\\CodeAnalysis\\EchoChecker\\PluginEntryPoint" | ||
} | ||
}, | ||
"autoload": { | ||
"psr-4": { | ||
"Vimeo\\CodeAnalysis\\EchoChecker\\": ["."] | ||
} | ||
} | ||
} |
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,2 @@ | ||
#!/usr/bin/env php | ||
<?php require_once __DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'psalm_plugin.php'; |
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
Oops, something went wrong.