4.1 KiB
Authoring Plugins
Plugins may implement one of (or more than one of) Psalm\Plugin\Hook\*
interface(s).
<?php
class SomePlugin implements \Psalm\Plugin\Hook\AfterStatementAnalysisInterface
{
}
Psalm\Plugin\Hook\*
offers six interfaces that you can implement:
AfterStatementAnalysisInterface
- called after Psalm evaluates each statementAfterExpressionAnalysisInterface
- called after Psalm evaluates each expressionAfterClassLikeVisitInterface
- called after Psalm crawls the parsed Abstract Syntax Tree for a class-like (class, interface, trait). Due to caching the AST is crawled the first time Psalm sees the file, and is only re-crawled if the file changes, the cache is cleared, or you're disabling cache with--no-cache
AfterClassLikeExistenceCheckInterface
- called after Psalm analyzes a reference to a class-likeAfterMethodCallAnalysisInterface
- called after Psalm analyzes a method callAfterFunctionCallAnalysisInterface
- called after Psalm analyzes a function call
Here are a couple of example plugins:
- StringChecker - checks class references in strings
- PreventFloatAssignmentChecker - prevents assignment to floats
- FunctionCasingChecker - checks that your functions and methods are correctly-cased
To ensure your plugin runs when Psalm does, add it to your config:
<plugins>
<plugin filename="src/plugins/SomePlugin.php" />
</plugins>
You can also specify an absolute path to your plugin:
<plugins>
<plugin filename="/path/to/SomePlugin.php" />
</plugins>
Type system
Understand how Psalm handles types by reading this guide.
Handling custom plugin issues
Plugins may sometimes need to emit their own issues (i.e. not emit one of the existing issues). If this is the case, they can emit an issue that extends Psalm\Issue\PluginIssue
.
To suppress a custom plugin issue in docblocks you can just use its issue name (e.g. /** @psalm-suppress NoFloatAssignment */
, but to suppress it in Psalm’s config you must use the pattern:
<PluginIssue name="NoFloatAssignment" errorLevel="suppress" />
You can also use more complex rules in the <issueHandler />
element, as you can with any other issue type e.g.
<PluginIssue name="NoFloatAssignment">
<errorLevel type="suppress">
<directory name="tests" />
</errorLevel>
</PluginIssue>
Authoring composer-based plugins
Requirements
Composer-based plugin is a composer package which conforms to these requirements:
- Its
type
field is set topsalm-plugin
- It has
extra.psalm.pluginClass
subkey in itscomposer.json
that reference an entry-point class that will be invoked to register the plugin into Psalm runtime. - Entry-point class implements
Psalm\Plugin\PluginEntryPointInterface
Using skeleton project
Run composer create-project weirdan/psalm-plugin-skeleton:dev-master your-plugin-name
to quickly bootstrap a new plugin project in your-plugin-name
folder. Make sure you adjust namespaces in composer.json
, Plugin.php
and tests
folder.
Upgrading file-based plugin to composer-based version
Create new plugin project using skeleton, then pass the class name of you file-based plugin to registerHooksFromClass()
method of the Psalm\Plugin\RegistrationInterface
instance that was passed into your plugin entry point's __invoke()
method. See the conversion example.
Registering stub files
Use Psalm\Plugin\RegistrationInterface::addStubFile()
. See the sample plugin.
Stub files provide a way to override third-party type information when you cannot add Psalm's extended docblocks to the upstream source files directly.