# Authoring Plugins ## Quick start ### Using a template repository Head over to [plugin template repository](https://github.com/weirdan/psalm-plugin-skeleton) on Github and click `Use this template` button. ### 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. ## Stub files 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. By convention, stub files have `.phpstub` extension to avoid IDEs treating them as actual php code. ## Generating stubs Dev-require the library you want to tweak types for, e.g. ``` composer require --dev cakephp/chronos ``` Then generate the stubs ``` vendor/bin/psalm --generate-stubs=stubs/chronos.phpstub ``` Open the generated file and remove everything not related to the library you're stubbing. Tweak the docblocks to provide more accurate types. ## Registering stub files Skeleton/template project includes the code to register all `.phpstub` files from the `stubs` directory. To register a stub file manually use `Psalm\Plugin\RegistrationInterface::addStubFile()`. ## Registering custom scanners and analyzers In addition to XML configuration node `` plugins can register their own custom scanner and analyzer implementations for particular file extensions, e.g. * `Psalm\Plugin\RegistrationInterface::addFileTypeScanner('html', CustomFileScanner::class)` * `Psalm\Plugin\RegistrationInterface::addFileTypeAnalyzer('html', CustomFileAnalyzer::class)` ## Publishing your plugin on Packagist Follow instructions on packagist.org under 'Publishing Packages' section. ## Advanced topics ### Starting from scratch Composer-based plugin is a composer package which conforms to these requirements: 1. Its `type` field is set to `psalm-plugin` 2. It has `extra.psalm.pluginClass` subkey in its `composer.json` that reference an entry-point class that will be invoked to register the plugin into Psalm runtime. 3. Entry-point class implements `Psalm\Plugin\PluginEntryPointInterface` ### Psalm API Plugins may implement one of (or more than one of) `Psalm\Plugin\Hook\*` interface(s). ```php ``` You can also specify an absolute path to your plugin: ```xml ``` ### Using Xdebug As Psalm disables _Xdebug_ at runtime, if you need to debug your code step-by-step when authoring a plugin, you can allow the extension by running Psalm as following: ```console $ PSALM_ALLOW_XDEBUG=1 path/to/psalm ``` ## Type system Understand how Psalm handles types by [reading this guide](plugins_type_system.md). ## Handling custom plugin issues Plugins may sometimes need to emit their own issues (i.e. not emit one of the [existing issues](../issues.md)). 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](../dealing_with_code_issues.md#config-suppression) you must use the pattern: ```xml ``` You can also use more complex rules in the `` element, as you can with any other issue type e.g. ```xml ``` ## 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](https://github.com/vimeo/psalm/tree/master/examples/plugins/composer-based/echo-checker/).