Skip to content

Commit

Permalink
split legacy plugin registration into a wrapper class
Browse files Browse the repository at this point in the history
also added `PluginApi` namespace and `RegistrationInterface`
  • Loading branch information
weirdan committed Jul 9, 2018
1 parent 8fd45d9 commit 98b3c97
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 33 deletions.
1 change: 1 addition & 0 deletions psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
<PossiblyUnusedMethod>
<errorLevel type="suppress">
<directory name="tests" />
<directory name="src/Psalm/PluginApi" />
<file name="src/Psalm/Plugin.php" />
<referencedMethod name="Psalm\Codebase::getParentInterfaces" />
<referencedMethod name="Psalm\Codebase::getMethodParams" />
Expand Down
35 changes: 6 additions & 29 deletions src/Psalm/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -750,8 +750,6 @@ public function initializePlugins(ProjectChecker $project_checker)
}
}

$codebase = $project_checker->codebase;

foreach ($this->filetype_scanner_paths as $extension => $path) {
$fq_class_name = $this->getPluginClassForPath($project_checker, $path, 'Psalm\\Scanner\\FileScanner');

Expand All @@ -771,33 +769,12 @@ public function initializePlugins(ProjectChecker $project_checker)
}

foreach ($this->plugin_paths as $path) {
$fq_class_name = $this->getPluginClassForPath($project_checker, $path, 'Psalm\\Plugin');

/** @psalm-suppress UnresolvableInclude */
require_once($path);

if ($codebase->methods->methodExists($fq_class_name . '::afterMethodCallCheck')) {
$this->after_method_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterFunctionCallCheck')) {
$this->after_function_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterExpressionCheck')) {
$this->after_expression_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterStatementCheck')) {
$this->after_statement_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterClassLikeExistsCheck')) {
$this->after_classlike_exists_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterVisitClassLike')) {
$this->after_visit_classlikes[$fq_class_name] = $fq_class_name;
try {
$plugin_object = new LegacyPlugin($path, $this, $project_checker);
$plugin_object($facade);
} catch (\Throwable $e) {
// todo: ???
throw $e;
}
}
}
Expand Down
99 changes: 99 additions & 0 deletions src/Psalm/LegacyPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
namespace Psalm;

use Psalm\Checker\ClassLikeChecker;
use Psalm\Checker\ProjectChecker;
use Psalm\Scanner\FileScanner;

class LegacyPlugin
{
/** @var string */
private $path;

/** @var ProjectChecker */
private $project_checker;

/** @var Config */
private $config;

public function __construct(string $path, Config $config, ProjectChecker $project_checker)
{
$this->path = $path;
$this->config = $config;
$this->project_checker = $project_checker;
}

public function __invoke(PluginApi\RegistrationInterface $api): void
{
$codebase = $this->project_checker->codebase;
$fq_class_name = $this->getPluginClassForPath($this->path, Plugin::class);

/** @psalm-suppress UnresolvableInclude */
require_once($this->path);

if ($codebase->methods->methodExists($fq_class_name . '::afterMethodCallCheck')) {
$this->config->after_method_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterFunctionCallCheck')) {
$this->config->after_function_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterExpressionCheck')) {
$this->config->after_expression_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterStatementCheck')) {
$this->config->after_statement_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterClassLikeExistsCheck')) {
$this->config->after_classlike_exists_checks[$fq_class_name] = $fq_class_name;
}

if ($codebase->methods->methodExists($fq_class_name . '::afterVisitClassLike')) {
$this->config->after_visit_classlikes[$fq_class_name] = $fq_class_name;
}
}

/**
* @param string $path
* @param string $must_extend
*
* @return string
*/
private function getPluginClassForPath(string $path, string $must_extend)
{
$codebase = $this->project_checker->codebase;

$file_storage = $codebase->createFileStorageForPath($path);
$file_to_scan = new FileScanner($path, $this->config->shortenFileName($path), true);
$file_to_scan->scan(
$codebase,
$file_storage
);

$declared_classes = ClassLikeChecker::getClassesForFile($this->project_checker, $path);

if (count($declared_classes) !== 1) {
throw new \InvalidArgumentException(
'Plugins must have exactly one class in the file - ' . $path . ' has ' .
count($declared_classes)
);
}

$fq_class_name = reset($declared_classes);

if (!$codebase->classExtends(
$fq_class_name,
$must_extend
)
) {
throw new \InvalidArgumentException(
'This plugin must extend ' . $must_extend . ' - ' . $path . ' does not'
);
}

return $fq_class_name;
}
}
7 changes: 7 additions & 0 deletions src/Psalm/PluginApi/RegistrationInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php
namespace Psalm\PluginApi;

interface RegistrationInterface
{
public function addStubFile(string $file_name): void;
}
6 changes: 2 additions & 4 deletions src/Psalm/PluginFacade.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?php
namespace Psalm;
use Psalm\PluginApi\RegistrationInterface;

/**
* Represents the API available to plugins
*/
class PluginFacade
class PluginFacade implements RegistrationInterface
{
/**
* @var Config
Expand Down

0 comments on commit 98b3c97

Please sign in to comment.