{"owner":"vimeo","repo":"psalm","hasSkills":true,"totalSkillsCount":3,"totalTokensCount":5444,"categories":["anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["docs/running_psalm/plugins/using_plugins.md","docs/running_psalm/plugins/plugins_type_system.md","docs/running_psalm/plugins/authoring_plugins.md"],"skills":{"docs/running_psalm/plugins/using_plugins.md":"# Using Plugins\n\nPsalm can be extended through plugins to find and fix domain-specific issues.\n\n## Using Composer-based plugins\n\nPsalm plugins are distributed as composer packages.\n\n### Discovering plugins\n\nYou can find a list of plugins on [Psalm’s own website](https://psalm.dev/plugins), and [also on Packagist](https://packagist.org/?type=psalm-plugin). Alternatively you can get a list via the CLI by typing `composer search -t psalm-plugin '.'`\n\n### Installing plugins\n\n`composer require --dev <plugin-vendor/plugin-package>`\n\n### Managing known plugins\n\nOnce installed, use the `psalm-plugin` tool to enable, disable and show available and enabled plugins.\n\nTo enable a plugin, run `vendor/bin/psalm-plugin enable plugin-vendor/plugin-package`.\n\nTo disable a plugin, run `vendor/bin/psalm-plugin disable plugin-vendor/plugin-package`.\n\n`vendor/bin/psalm-plugin show` will show you a list of all local plugins (enabled and disabled).\n\n## Using your own plugins\n\nIs there no plugin for your favourite framework / library yet? Create it! It's as easy as forking a repository, tweaking some docblocks and publishing the package to Packagist.\n\nConsult [Authoring Plugins](authoring_plugins.md) chapter to get started.\n","docs/running_psalm/plugins/plugins_type_system.md":"# Plugins: type system internals\n\nPsalm's type system represents the types of variables within a program using different classes. Plugins both receive, and can update this type information.\n\n## Union types\n\nAll type information you are likely to use will be wrapped in a [Union Type](../../annotating_code/type_syntax/union_types.md).\n\nThe `Union` class constructor takes an array of `Atomic` types, and can represent one or more of these types at a time. They correspond to a vertical bar in a doc comment.\n\n``` php\nnew Union([new TNamedObject('Foo\\\\Bar\\\\SomeClass')]); // equivalent to Foo\\Bar\\SomeClass in docblock\nnew Union([new TString(), new TInt()]); // equivalent to string|int in docblock\n```\n\n## Atomic types\n\nPrimitive types like floats, integers and strings, plus arrays, and classes. You can find all of these in [`src/Psalm/Types/Atomic`](https://github.com/vimeo/psalm/tree/master/src/Psalm/Type/Atomic).\n\nNote that all non-abstract classes in this folder are valid types. They are all prefixed by 'T'.\n\nThe classes are as follows:\n\n### Misc\n\n`TVoid` - denotes the `void` type, normally just used to annotate a function/method that returns nothing\n\n`TNull` - denotes the `null` type\n\n`TNever` - denotes the `no-return`/`never-return` type for functions that never return, either throwing an exception or terminating (like the builtin `exit()`). Also used for union types that can have no possible types (impossible intersections for example).  Empty arrays `[]` have the type `array<never, never>`.\n\n`TMixed` - denotes the `mixed` type, used when you don’t know the type of an expression.\n\n`TNonEmptyMixed `- as above, but not empty. Generated for `$x` inside the `if` statement `if ($x) {...}` when `$x` is `mixed` outside.\n\n`TEmptyMixed` - as above, but empty. Generated for `$x` inside the `if` statement `if (!$x) {...}` when `$x` is `mixed` outside.\n\n`TIterable` - denotes the [`iterable` type](https://www.php.net/manual/en/language.types.iterable.php) (which can also result from an `is_iterable` check).\n\n`TResource` - denotes the `resource` type (e.g. a file handle).\n\n`TClosedResource` - denotes the `resource` type that has been closed (e.g. a file handle through `fclose()`).\n\n`TAssertionFalsy` - Represents any value reduced to false when computed in boolean context. This is used for assertions\n\n`TConditional` - Internal representation of a conditional return type in phpdoc. For example ($param1 is int ? int : string)\n\n`TIntMask` - Represents the type that is the result of a bitmask combination of its parameters. `int-mask<1, 2, 4>` corresponds to `1|2|3|4|5|6|7`\n\n`TIntMaskOf` - as above, but used with a reference to constants in code `int-mask-of<MyClass::CLASS_CONSTANT_*>` will corresponds to `1|2|3|4|5|6|7` if there are three constant 1, 2 and 4\n\n`TKeyOf` - Represents an offset of an array (e.g. `key-of<MyClass::CLASS_CONSTANT>`).\n\n`TValueOf` - Represents a value of an array or enum (e.g. `value-of<MyClass::CLASS_CONSTANT>`).\n\n`TTemplateIndexedAccess` - To be documented\n\n`TTemplateKeyOf` - Represents the type used when using TKeyOf when the type of the array is a template\n\n`TTemplateValueOf` - Represents the type used when using TValueOf when the type of the array or enum is a template\n\n`TPropertiesOf` - Represents properties and their types of a class as a keyed array (e.g. `properties-of<MyClass>`)\n\n`TTemplatePropertiesOf` - Represents the type used when using TPropertiesOf when type of the class is a template\n\n`TTypeAlias` - To be documented\n\n### Scalar supertype\n\n`TScalar` - denotes the `scalar` super type (which can also result from an `is_scalar` check). This type encompasses `float`, `int`, `bool` and `string`.\n\n`TEmptyScalar` - denotes a `scalar` type that is also empty.\n\n`TNonEmptyScalar` - denotes a `scalar` type that is also non-empty.\n\n### Numeric supertype\n\n`TNumeric` - denotes the `numeric` type (which can also result from an `is_numeric` check).\n\n`TEmptyNumeric` - denotes the `numeric` type that's also empty (which can also result from an `is_numeric` and `empty` check).\n\n### Scalar types\n\nAll scalar types have literal versions e.g. `int` vs `int(5)`.\n\n#### Ints\n\n`TInt` - denotes the `int` type, where the exact value is unknown.\n\n`TLiteralInt` - is used to represent an integer value where the exact numeric value is known.\n\n`TIntRange` - allows to describe an int with bounded values (ie. `int<1, 5>`).\n\n#### Floats\n\n`TFloat` - denotes the `float` type, where the exact value is unknown.\n\n`TLiteralFloat` - is used to represent a floating point value where the exact numeric value is known.\n\n#### Bools\n\n`TBool`, `TFalse`, `TTrue`\n\n`TBool` - denotes the `bool` type where the exact value is unknown.\n\n`TFalse` - denotes the `false` value type\n\n`TTrue` - denotes the `true` value type\n\n``` php\n/** @return string|false    false when string is empty, first char of the parameter otherwise */\nfunction firstChar(string $s) { return empty($s) ? false : $s[0]; }\n```\n\nHere, the function may never return true, but if you had to replace false with bool, Psalm would have to consider true as a possible return value. With narrower type it's able to report meaningless code like this (https://psalm.dev/r/037291351d):\n\n``` php\n$first = firstChar(\"sdf\");\nif (true === $first) {\n  echo \"This is actually dead code\";\n}\n```\n\n#### Strings\n\n`TString` - denotes the `string` type, where the exact value is unknown.\n\n`TNonEmptyString` - denotes a string, that is also non-empty\n\n`TNumericString` - denotes a string that's also a numeric value e.g. `\"5\"`. It can result from `is_string($s) && is_numeric($s)`.\n\n`TLiteralString` - is used to represent a string whose value is known.\n\n`TClassString` - denotes the `class-string` type, used to describe a string representing a valid PHP class. The parent type from which the classes descend may or may not be specified in the constructor.\n\n`TLiteralClassString` - denotes a specific class string, generated by expressions like `A::class`.\n\n`TTraitString` - denotes the `trait-string` type, used to describe a string representing a valid PHP trait.\n\n`TDependentGetClass` - Represents a string whose value is a fully-qualified class found by get_class($var)\n\n`TDependentGetDebugType` - Represents a string whose value is that of a type found by get_debug_type($var)\n\n`TDependentGetType` - Represents a string whose value is that of a type found by gettype($var)\n\n`TCallableString` - denotes the `callable-string` type, used to represent an unknown string that is also `callable`.\n\n`TSqlSelectString` - this is a special type, specifically for consumption by plugins.\n\n`TLowercaseString` - denotes a string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TNonEmptyLowercaseString` - denotes a non-empty-string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TSingleLetter` - denotes a string that has a length of 1\n\n#### Scalar class constants\n\n`TScalarClassConstant` - denotes a class constant whose value might not yet be known.\n\n#### Array key supertype\n\n`TArrayKey` - denotes the `array-key` type, used for something that could be the offset of an `array`.\n\n### Arrays\n\n`TArray` - denotes a simple array of the form `array<TKey, TValue>`. It expects an array with two elements, both union types.\n\n`TNonEmptyArray` - as above, but denotes an array known to be non-empty.\n\n`TKeyedArray` represents an 'object-like array' - an array with known keys.\n\n``` php\n$x = [\"a\" => 1, \"b\" => 2]; // is TKeyedArray, array{a: int, b: int}\n$y = rand(0, 1) ? [\"a\" => null] : [\"a\" => 1, \"b\" => \"b\"]; // is TKeyedArray with optional keys/values, array{a: ?int, b?: string}\n```\n\nThis type is also used to represent lists (instead of the now-deprecated `TList` type).  \n\nNote that not all associative arrays are considered object-like. If the keys are not known, the array is treated as a mapping between two types.\n\n``` php\n$a = [];\nforeach (range(1,1) as $_) $a[(string)rand(0,1)] = rand(0,1); // array<string,int>\n```\n\n`TCallableKeyedArray` - denotes an object-like array that is _also_ `callable`.\n\n`TClassStringMap` - Represents an array where the type of each value is a function of its string key value\n\n### Callables & closures\n\n`TCallable` - denotes the `callable` type. Can result from an `is_callable` check.\n`TClosure` - denotes a `Closure` type.\n\n`TCallable` and `TClosure` can optionally be defined with parameters and return types, too\n\n### Object supertypes\n\n`TObject` - denotes the `object` type\n\n`TObjectWithProperties` - an object with specified member variables e.g. `object{foo:int, bar:string}`.\n\n### Object types\n\n`TNamedObject` - denotes an object type where the type of the object is known e.g. `Exception`, `Throwable`, `Foo\\Bar`\n\n`TGenericObject` - denotes an object type that has generic parameters e.g. `ArrayObject<string, Foo\\Bar>`\n\n`TCallableObject` - denotes an object that is also `callable` (i.e. it has `__invoke` defined).\n\n`TAnonymousClassInstance` - Denotes an anonymous class (i.e. `new class{}`) with potential methods\n\n### Template\n\n`TTemplateParam` - denotes a template parameter that has been previously specified in a `@template` tag.\n\n`TTemplateParamClass` - denotes a `class-string` corresponding to a template parameter previously specified in a `@template` tag.\n\n## Creating type object instances\n\nThere are two ways of creating the object instances which describe a given type. They can be created directly using new, or created declaratively from a doc string. Normally, you'd want to use the second option. However, understanding the structure of this data will help you understand types passed into a plugin.\n\nNote that these classes do sometimes change, so `Type::parseString` is always going to be the more robust option.\n\n### Creating type object instances directly\n\nThe following example constructs types representing a string, a floating-point number, and a class called 'Foo\\Bar\\SomeClass'.\n\n``` php\nnew TLiteralString('A text string')\nnew TLiteralFloat(3.142)\nnew TNamedObject('Foo\\Bar\\SomeClass')\n```\n\nTypes within Psalm are always wrapped in a union as a convenience feature. Almost anywhere you may expect a type, you can get a union as well (property types, return types, argument types, etc). So wrapping a single atomic type (like TInt) in a union container allows to uniformly handle that type elsewhere, without repetitive checks like this:\n\n``` php\nif ($type instanceof Union)\n   foreach ($types->getTypes() as $atomic)\n      handleAtomic($atomic);\nelse handleAtomic($type);\n\n// with union container it becomes\nforeach ($types->getTypes() as $atomic)\n   handleAtomic($atomic);\n```\n\nAlso, union trees are always shallow, because Psalm will flatten union of unions into a single-level union `((A|B)|(C|D) => A|B|C|D)`.\n\nMore complex types can be constructed as follows. The following represents an associative array with 3 keys. Psalm calls these 'object-like arrays', and represents them with the 'TKeyedArray' class.\n\n\n``` php\n        new Union([\n            TKeyedArray::make([\n                'key_1' => new Union([new TString()]),\n                'key_2' => new Union([new TInt()]),\n                'key_3' => new Union([new TBool()])])]);\n```\n\nThe Type object includes some static helper methods, which automatically wrap the type in a Union. Thus this can be written more tersely:\n\n``` php\nnew Union([\n    new Type\\Atomic\\TKeyedArray([\n        'first' => Type::getInt(),\n        'second' => Type::getString()])]);\n```\n\nYou can also use `Type::getInt(5)` to generate a union type corresponding to the literal int value 5.\n\n\n### Creating type object instances from doc string types\n\nAnother way of creating these instances is to use the class `Psalm\\Type` which includes a static method `parseString`. You may pass any doc string type description to this, and it will return the corresponding object representation.\n\n``` php\n\\Psalm\\Type::parseString('int|null');\n```\n\nYou can find how Psalm would represent a given type as objects, by specifying the type as an input to this function, and calling `var_dump` on the result.\n","docs/running_psalm/plugins/authoring_plugins.md":"# Authoring Plugins\n\n## Quick start\n\n### Using a template repository\n\nHead over to [plugin template repository](https://github.com/psalm/psalm-plugin-skeleton) on GitHub, login and click `Use this template` button.\n\n### Using skeleton project\n\nRun `composer create-project psalm/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.\n\n## Psalm plugin API\n\nBackwards compatibility for the plugin API is now covered by a separate metapackage, [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\nThis is a separate, empty metapackage: its major version will be bumped every time a breaking change occurs within Psalm's plugin API; minors will also be bumped when adding new features to Psalm's plugin API.  \n\nPlugins, starting from the first stable release of v7, need to explicitly require a caret range (i.e. ^1, NOT 1.0.0) that package in order to avoid breaking changes during Psalm upgrades.  \n\nPlugins that support v7 betas can already require `0.x` versions of the package.  \n\nAll plugin API versions with a list of contained breaking changes will be listed in the readme of [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\n## Stub files\n\nStub files provide a way to override third-party type information when you cannot add Psalm's extended docblocks to the upstream source files directly.\nBy convention, stub files have `.phpstub` extension to avoid IDEs treating them as actual php code.\n\n## Generating stubs\n\nDev-require the library you want to tweak types for, e.g.\n```\ncomposer require --dev cakephp/chronos\n```\nThen generate the stubs\n```\nvendor/bin/psalm --generate-stubs=stubs/chronos.phpstub\n```\nOpen the generated file and remove everything not related to the library you're stubbing. Tweak the docblocks to provide more accurate types.\n\n## Registering stub files\n\nSkeleton/template project includes the code to register all `.phpstub` files from the `stubs` directory.\n\nTo register a stub file manually use `Psalm\\Plugin\\RegistrationInterface::addStubFile()`.\n\n## Registering custom scanners and analyzers\n\nIn addition to XML configuration node `<fileExtensions>` plugins can register their own custom scanner\nand analyzer implementations for particular file extensions, e.g.\n\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeScanner('html', CustomFileScanner::class)`\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeAnalyzer('html', CustomFileAnalyzer::class)`\n\n## Publishing your plugin on Packagist\n\nFollow instructions on packagist.org under 'Publishing Packages' section.\n\n## Advanced topics\n\n### Starting from scratch\n\nComposer-based plugin is a composer package which conforms to these requirements:\n\n1. Its `type` field is set to `psalm-plugin`\n2. 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.\n3. Entry-point class implements `Psalm\\Plugin\\PluginEntryPointInterface`\n\n### Psalm API\n\nPlugins may implement one of (or more than one of) `Psalm\\Plugin\\EventHandler\\*` interface(s).\n\n```php\n<?php\nclass SomePlugin implements \\Psalm\\Plugin\\EventHandler\\AfterStatementAnalysisInterface\n{\n}\n```\n\n`Psalm\\Plugin\\EventHandler\\*` offers the following interfaces that you can implement:\n\n- `AfterAnalysisInterface` - called after Psalm has completed its analysis. Use this hook if you want to do something with the analysis results.\n- `AfterClassLikeAnalysisInterface` - called after Psalm has completed its analysis of a given class.\n- `AfterClassLikeExistenceCheckInterface` - called after Psalm analyzes a reference to a class, interface or trait.\n- `AfterClassLikeVisitInterface` - 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`/`--no-reflection-cache`. Use this if you want to collect or modify information about a class before Psalm begins its analysis.\n- `AfterCodebasePopulatedInterface` - called after Psalm has scanned necessary files and populated codebase data.\n- `AfterEveryFunctionCallAnalysisInterface` - called after Psalm evaluates any function call. Cannot influence the call further.\n- `AfterExpressionAnalysisInterface` - called after Psalm evaluates an expression.\n- `AfterFileAnalysisInterface` - called after Psalm analyzes a file.\n- `AfterFunctionCallAnalysisInterface` - called after Psalm evaluates a function call to any function defined within the project itself. Can alter the return type or perform modifications of the call.\n- `AfterFunctionLikeAnalysisInterface` - called after Psalm has completed its analysis of a given function-like.\n- `AfterMethodCallAnalysisInterface` - called after Psalm analyzes a method call.\n- `BeforeStatementAnalysisInterface` - called before Psalm evaluates a statement.\n- `AfterStatementAnalysisInterface` - called after Psalm evaluates a statement.\n- `BeforeAddIssueInterface` - called before Psalm adds an item to it's internal `IssueBuffer`, allows handling code issues individually\n- `BeforeFileAnalysisInterface` - called before Psalm analyzes a file.\n- `ClassFilePathProviderInterface.php` - can be used to determine the file path a of a class not autoloadable using composer, but autoloadable through a custom autoloader, to avoid actually invoking the autoloader and executing the class\n- `FunctionExistenceProviderInterface` - can be used to override Psalm's builtin function existence checks for one or more functions.\n- `FunctionParamsProviderInterface.php` - can be used to override Psalm's builtin function parameter lookup for one or more functions.\n- `FunctionReturnTypeProviderInterface` - can be used to override Psalm's builtin function return type lookup for one or more functions.\n- `MethodCapabilitiesProviderInterface` - can be used to give the capabilities (purity) a call of a method of one or more classes requires, e.g. from its arguments.\n- `MethodExistenceProviderInterface` - can be used to override Psalm's builtin method existence checks for one or more classes.\n- `MethodParamsProviderInterface` - can be used to override Psalm's builtin method parameter lookup for one or more classes.\n- `MethodReturnTypeProviderInterface` - can be used to override Psalm's builtin method return type lookup for one or more classes.\n- `MethodVisibilityProviderInterface` - can be used to override Psalm's builtin method visibility checks for one or more classes.\n- `PropertyExistenceProviderInterface` - can be used to override Psalm's builtin property existence checks for one or more classes.\n- `PropertyTypeProviderInterface` - can be used to override Psalm's builtin property type lookup for one or more classes.\n- `PropertyVisibilityProviderInterface` - can be used to override Psalm's builtin property visibility checks for one or more classes.\n- `DynamicFunctionStorageProviderInterface` - can be used to override signature for one or more functions. It means you can define variadic param list. Infer return type by input args. Define function templates. Also check out `Psalm\\Plugin\\DynamicFunctionStorage` to find out what api it brings for you to change function's definition.\n\nHere are a couple of example plugins:\n - [StringChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/StringChecker.php) - checks class references in strings\n - [PreventFloatAssignmentChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/PreventFloatAssignmentChecker.php) - prevents assignment to floats\n - [FunctionCasingChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/FunctionCasingChecker.php) - checks that your functions and methods are correctly-cased\n\nTo ensure your plugin runs when Psalm does, add it to your [config](../configuration.md) (not needed for composer-based plugins):\n```xml\n    <plugins>\n        <plugin filename=\"src/plugins/SomePlugin.php\" />\n    </plugins>\n```\n\nYou can also specify an absolute path to your plugin:\n```xml\n    <plugins>\n        <plugin filename=\"/path/to/SomePlugin.php\" />\n    </plugins>\n```\n\n### Using Xdebug\n\nAs 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:\n\n```console\n$ PSALM_ALLOW_XDEBUG=1 path/to/psalm\n```\n\n## Type system\n\nUnderstand how Psalm handles types by [reading this guide](plugins_type_system.md).\n\n## Handling custom plugin issues\n\nPlugins 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`.\n\nTo 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:\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\" errorLevel=\"suppress\" />\n```\n\nYou can also use more complex rules in the `<issueHandler />` element, as you can with any other issue type e.g.\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\">\n    <errorLevel type=\"suppress\">\n        <directory name=\"tests\" />\n    </errorLevel>\n</PluginIssue>\n```\n\n## Upgrading file-based plugin to composer-based version\n\nCreate new plugin project using skeleton, then pass the class name of you file-based plugin to `registerHooksFromClass()`\nmethod of the `Psalm\\Plugin\\RegistrationInterface` instance that was passed into your plugin entry point's `__invoke()`\nmethod. See the [conversion example](https://github.com/vimeo/psalm/tree/master/examples/plugins/composer-based/echo-checker/).\n"},"files":{"docs/running_psalm/plugins/using_plugins.md":"# Using Plugins\n\nPsalm can be extended through plugins to find and fix domain-specific issues.\n\n## Using Composer-based plugins\n\nPsalm plugins are distributed as composer packages.\n\n### Discovering plugins\n\nYou can find a list of plugins on [Psalm’s own website](https://psalm.dev/plugins), and [also on Packagist](https://packagist.org/?type=psalm-plugin). Alternatively you can get a list via the CLI by typing `composer search -t psalm-plugin '.'`\n\n### Installing plugins\n\n`composer require --dev <plugin-vendor/plugin-package>`\n\n### Managing known plugins\n\nOnce installed, use the `psalm-plugin` tool to enable, disable and show available and enabled plugins.\n\nTo enable a plugin, run `vendor/bin/psalm-plugin enable plugin-vendor/plugin-package`.\n\nTo disable a plugin, run `vendor/bin/psalm-plugin disable plugin-vendor/plugin-package`.\n\n`vendor/bin/psalm-plugin show` will show you a list of all local plugins (enabled and disabled).\n\n## Using your own plugins\n\nIs there no plugin for your favourite framework / library yet? Create it! It's as easy as forking a repository, tweaking some docblocks and publishing the package to Packagist.\n\nConsult [Authoring Plugins](authoring_plugins.md) chapter to get started.\n","docs/running_psalm/plugins/plugins_type_system.md":"# Plugins: type system internals\n\nPsalm's type system represents the types of variables within a program using different classes. Plugins both receive, and can update this type information.\n\n## Union types\n\nAll type information you are likely to use will be wrapped in a [Union Type](../../annotating_code/type_syntax/union_types.md).\n\nThe `Union` class constructor takes an array of `Atomic` types, and can represent one or more of these types at a time. They correspond to a vertical bar in a doc comment.\n\n``` php\nnew Union([new TNamedObject('Foo\\\\Bar\\\\SomeClass')]); // equivalent to Foo\\Bar\\SomeClass in docblock\nnew Union([new TString(), new TInt()]); // equivalent to string|int in docblock\n```\n\n## Atomic types\n\nPrimitive types like floats, integers and strings, plus arrays, and classes. You can find all of these in [`src/Psalm/Types/Atomic`](https://github.com/vimeo/psalm/tree/master/src/Psalm/Type/Atomic).\n\nNote that all non-abstract classes in this folder are valid types. They are all prefixed by 'T'.\n\nThe classes are as follows:\n\n### Misc\n\n`TVoid` - denotes the `void` type, normally just used to annotate a function/method that returns nothing\n\n`TNull` - denotes the `null` type\n\n`TNever` - denotes the `no-return`/`never-return` type for functions that never return, either throwing an exception or terminating (like the builtin `exit()`). Also used for union types that can have no possible types (impossible intersections for example).  Empty arrays `[]` have the type `array<never, never>`.\n\n`TMixed` - denotes the `mixed` type, used when you don’t know the type of an expression.\n\n`TNonEmptyMixed `- as above, but not empty. Generated for `$x` inside the `if` statement `if ($x) {...}` when `$x` is `mixed` outside.\n\n`TEmptyMixed` - as above, but empty. Generated for `$x` inside the `if` statement `if (!$x) {...}` when `$x` is `mixed` outside.\n\n`TIterable` - denotes the [`iterable` type](https://www.php.net/manual/en/language.types.iterable.php) (which can also result from an `is_iterable` check).\n\n`TResource` - denotes the `resource` type (e.g. a file handle).\n\n`TClosedResource` - denotes the `resource` type that has been closed (e.g. a file handle through `fclose()`).\n\n`TAssertionFalsy` - Represents any value reduced to false when computed in boolean context. This is used for assertions\n\n`TConditional` - Internal representation of a conditional return type in phpdoc. For example ($param1 is int ? int : string)\n\n`TIntMask` - Represents the type that is the result of a bitmask combination of its parameters. `int-mask<1, 2, 4>` corresponds to `1|2|3|4|5|6|7`\n\n`TIntMaskOf` - as above, but used with a reference to constants in code `int-mask-of<MyClass::CLASS_CONSTANT_*>` will corresponds to `1|2|3|4|5|6|7` if there are three constant 1, 2 and 4\n\n`TKeyOf` - Represents an offset of an array (e.g. `key-of<MyClass::CLASS_CONSTANT>`).\n\n`TValueOf` - Represents a value of an array or enum (e.g. `value-of<MyClass::CLASS_CONSTANT>`).\n\n`TTemplateIndexedAccess` - To be documented\n\n`TTemplateKeyOf` - Represents the type used when using TKeyOf when the type of the array is a template\n\n`TTemplateValueOf` - Represents the type used when using TValueOf when the type of the array or enum is a template\n\n`TPropertiesOf` - Represents properties and their types of a class as a keyed array (e.g. `properties-of<MyClass>`)\n\n`TTemplatePropertiesOf` - Represents the type used when using TPropertiesOf when type of the class is a template\n\n`TTypeAlias` - To be documented\n\n### Scalar supertype\n\n`TScalar` - denotes the `scalar` super type (which can also result from an `is_scalar` check). This type encompasses `float`, `int`, `bool` and `string`.\n\n`TEmptyScalar` - denotes a `scalar` type that is also empty.\n\n`TNonEmptyScalar` - denotes a `scalar` type that is also non-empty.\n\n### Numeric supertype\n\n`TNumeric` - denotes the `numeric` type (which can also result from an `is_numeric` check).\n\n`TEmptyNumeric` - denotes the `numeric` type that's also empty (which can also result from an `is_numeric` and `empty` check).\n\n### Scalar types\n\nAll scalar types have literal versions e.g. `int` vs `int(5)`.\n\n#### Ints\n\n`TInt` - denotes the `int` type, where the exact value is unknown.\n\n`TLiteralInt` - is used to represent an integer value where the exact numeric value is known.\n\n`TIntRange` - allows to describe an int with bounded values (ie. `int<1, 5>`).\n\n#### Floats\n\n`TFloat` - denotes the `float` type, where the exact value is unknown.\n\n`TLiteralFloat` - is used to represent a floating point value where the exact numeric value is known.\n\n#### Bools\n\n`TBool`, `TFalse`, `TTrue`\n\n`TBool` - denotes the `bool` type where the exact value is unknown.\n\n`TFalse` - denotes the `false` value type\n\n`TTrue` - denotes the `true` value type\n\n``` php\n/** @return string|false    false when string is empty, first char of the parameter otherwise */\nfunction firstChar(string $s) { return empty($s) ? false : $s[0]; }\n```\n\nHere, the function may never return true, but if you had to replace false with bool, Psalm would have to consider true as a possible return value. With narrower type it's able to report meaningless code like this (https://psalm.dev/r/037291351d):\n\n``` php\n$first = firstChar(\"sdf\");\nif (true === $first) {\n  echo \"This is actually dead code\";\n}\n```\n\n#### Strings\n\n`TString` - denotes the `string` type, where the exact value is unknown.\n\n`TNonEmptyString` - denotes a string, that is also non-empty\n\n`TNumericString` - denotes a string that's also a numeric value e.g. `\"5\"`. It can result from `is_string($s) && is_numeric($s)`.\n\n`TLiteralString` - is used to represent a string whose value is known.\n\n`TClassString` - denotes the `class-string` type, used to describe a string representing a valid PHP class. The parent type from which the classes descend may or may not be specified in the constructor.\n\n`TLiteralClassString` - denotes a specific class string, generated by expressions like `A::class`.\n\n`TTraitString` - denotes the `trait-string` type, used to describe a string representing a valid PHP trait.\n\n`TDependentGetClass` - Represents a string whose value is a fully-qualified class found by get_class($var)\n\n`TDependentGetDebugType` - Represents a string whose value is that of a type found by get_debug_type($var)\n\n`TDependentGetType` - Represents a string whose value is that of a type found by gettype($var)\n\n`TCallableString` - denotes the `callable-string` type, used to represent an unknown string that is also `callable`.\n\n`TSqlSelectString` - this is a special type, specifically for consumption by plugins.\n\n`TLowercaseString` - denotes a string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TNonEmptyLowercaseString` - denotes a non-empty-string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TSingleLetter` - denotes a string that has a length of 1\n\n#### Scalar class constants\n\n`TScalarClassConstant` - denotes a class constant whose value might not yet be known.\n\n#### Array key supertype\n\n`TArrayKey` - denotes the `array-key` type, used for something that could be the offset of an `array`.\n\n### Arrays\n\n`TArray` - denotes a simple array of the form `array<TKey, TValue>`. It expects an array with two elements, both union types.\n\n`TNonEmptyArray` - as above, but denotes an array known to be non-empty.\n\n`TKeyedArray` represents an 'object-like array' - an array with known keys.\n\n``` php\n$x = [\"a\" => 1, \"b\" => 2]; // is TKeyedArray, array{a: int, b: int}\n$y = rand(0, 1) ? [\"a\" => null] : [\"a\" => 1, \"b\" => \"b\"]; // is TKeyedArray with optional keys/values, array{a: ?int, b?: string}\n```\n\nThis type is also used to represent lists (instead of the now-deprecated `TList` type).  \n\nNote that not all associative arrays are considered object-like. If the keys are not known, the array is treated as a mapping between two types.\n\n``` php\n$a = [];\nforeach (range(1,1) as $_) $a[(string)rand(0,1)] = rand(0,1); // array<string,int>\n```\n\n`TCallableKeyedArray` - denotes an object-like array that is _also_ `callable`.\n\n`TClassStringMap` - Represents an array where the type of each value is a function of its string key value\n\n### Callables & closures\n\n`TCallable` - denotes the `callable` type. Can result from an `is_callable` check.\n`TClosure` - denotes a `Closure` type.\n\n`TCallable` and `TClosure` can optionally be defined with parameters and return types, too\n\n### Object supertypes\n\n`TObject` - denotes the `object` type\n\n`TObjectWithProperties` - an object with specified member variables e.g. `object{foo:int, bar:string}`.\n\n### Object types\n\n`TNamedObject` - denotes an object type where the type of the object is known e.g. `Exception`, `Throwable`, `Foo\\Bar`\n\n`TGenericObject` - denotes an object type that has generic parameters e.g. `ArrayObject<string, Foo\\Bar>`\n\n`TCallableObject` - denotes an object that is also `callable` (i.e. it has `__invoke` defined).\n\n`TAnonymousClassInstance` - Denotes an anonymous class (i.e. `new class{}`) with potential methods\n\n### Template\n\n`TTemplateParam` - denotes a template parameter that has been previously specified in a `@template` tag.\n\n`TTemplateParamClass` - denotes a `class-string` corresponding to a template parameter previously specified in a `@template` tag.\n\n## Creating type object instances\n\nThere are two ways of creating the object instances which describe a given type. They can be created directly using new, or created declaratively from a doc string. Normally, you'd want to use the second option. However, understanding the structure of this data will help you understand types passed into a plugin.\n\nNote that these classes do sometimes change, so `Type::parseString` is always going to be the more robust option.\n\n### Creating type object instances directly\n\nThe following example constructs types representing a string, a floating-point number, and a class called 'Foo\\Bar\\SomeClass'.\n\n``` php\nnew TLiteralString('A text string')\nnew TLiteralFloat(3.142)\nnew TNamedObject('Foo\\Bar\\SomeClass')\n```\n\nTypes within Psalm are always wrapped in a union as a convenience feature. Almost anywhere you may expect a type, you can get a union as well (property types, return types, argument types, etc). So wrapping a single atomic type (like TInt) in a union container allows to uniformly handle that type elsewhere, without repetitive checks like this:\n\n``` php\nif ($type instanceof Union)\n   foreach ($types->getTypes() as $atomic)\n      handleAtomic($atomic);\nelse handleAtomic($type);\n\n// with union container it becomes\nforeach ($types->getTypes() as $atomic)\n   handleAtomic($atomic);\n```\n\nAlso, union trees are always shallow, because Psalm will flatten union of unions into a single-level union `((A|B)|(C|D) => A|B|C|D)`.\n\nMore complex types can be constructed as follows. The following represents an associative array with 3 keys. Psalm calls these 'object-like arrays', and represents them with the 'TKeyedArray' class.\n\n\n``` php\n        new Union([\n            TKeyedArray::make([\n                'key_1' => new Union([new TString()]),\n                'key_2' => new Union([new TInt()]),\n                'key_3' => new Union([new TBool()])])]);\n```\n\nThe Type object includes some static helper methods, which automatically wrap the type in a Union. Thus this can be written more tersely:\n\n``` php\nnew Union([\n    new Type\\Atomic\\TKeyedArray([\n        'first' => Type::getInt(),\n        'second' => Type::getString()])]);\n```\n\nYou can also use `Type::getInt(5)` to generate a union type corresponding to the literal int value 5.\n\n\n### Creating type object instances from doc string types\n\nAnother way of creating these instances is to use the class `Psalm\\Type` which includes a static method `parseString`. You may pass any doc string type description to this, and it will return the corresponding object representation.\n\n``` php\n\\Psalm\\Type::parseString('int|null');\n```\n\nYou can find how Psalm would represent a given type as objects, by specifying the type as an input to this function, and calling `var_dump` on the result.\n","docs/running_psalm/plugins/authoring_plugins.md":"# Authoring Plugins\n\n## Quick start\n\n### Using a template repository\n\nHead over to [plugin template repository](https://github.com/psalm/psalm-plugin-skeleton) on GitHub, login and click `Use this template` button.\n\n### Using skeleton project\n\nRun `composer create-project psalm/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.\n\n## Psalm plugin API\n\nBackwards compatibility for the plugin API is now covered by a separate metapackage, [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\nThis is a separate, empty metapackage: its major version will be bumped every time a breaking change occurs within Psalm's plugin API; minors will also be bumped when adding new features to Psalm's plugin API.  \n\nPlugins, starting from the first stable release of v7, need to explicitly require a caret range (i.e. ^1, NOT 1.0.0) that package in order to avoid breaking changes during Psalm upgrades.  \n\nPlugins that support v7 betas can already require `0.x` versions of the package.  \n\nAll plugin API versions with a list of contained breaking changes will be listed in the readme of [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\n## Stub files\n\nStub files provide a way to override third-party type information when you cannot add Psalm's extended docblocks to the upstream source files directly.\nBy convention, stub files have `.phpstub` extension to avoid IDEs treating them as actual php code.\n\n## Generating stubs\n\nDev-require the library you want to tweak types for, e.g.\n```\ncomposer require --dev cakephp/chronos\n```\nThen generate the stubs\n```\nvendor/bin/psalm --generate-stubs=stubs/chronos.phpstub\n```\nOpen the generated file and remove everything not related to the library you're stubbing. Tweak the docblocks to provide more accurate types.\n\n## Registering stub files\n\nSkeleton/template project includes the code to register all `.phpstub` files from the `stubs` directory.\n\nTo register a stub file manually use `Psalm\\Plugin\\RegistrationInterface::addStubFile()`.\n\n## Registering custom scanners and analyzers\n\nIn addition to XML configuration node `<fileExtensions>` plugins can register their own custom scanner\nand analyzer implementations for particular file extensions, e.g.\n\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeScanner('html', CustomFileScanner::class)`\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeAnalyzer('html', CustomFileAnalyzer::class)`\n\n## Publishing your plugin on Packagist\n\nFollow instructions on packagist.org under 'Publishing Packages' section.\n\n## Advanced topics\n\n### Starting from scratch\n\nComposer-based plugin is a composer package which conforms to these requirements:\n\n1. Its `type` field is set to `psalm-plugin`\n2. 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.\n3. Entry-point class implements `Psalm\\Plugin\\PluginEntryPointInterface`\n\n### Psalm API\n\nPlugins may implement one of (or more than one of) `Psalm\\Plugin\\EventHandler\\*` interface(s).\n\n```php\n<?php\nclass SomePlugin implements \\Psalm\\Plugin\\EventHandler\\AfterStatementAnalysisInterface\n{\n}\n```\n\n`Psalm\\Plugin\\EventHandler\\*` offers the following interfaces that you can implement:\n\n- `AfterAnalysisInterface` - called after Psalm has completed its analysis. Use this hook if you want to do something with the analysis results.\n- `AfterClassLikeAnalysisInterface` - called after Psalm has completed its analysis of a given class.\n- `AfterClassLikeExistenceCheckInterface` - called after Psalm analyzes a reference to a class, interface or trait.\n- `AfterClassLikeVisitInterface` - 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`/`--no-reflection-cache`. Use this if you want to collect or modify information about a class before Psalm begins its analysis.\n- `AfterCodebasePopulatedInterface` - called after Psalm has scanned necessary files and populated codebase data.\n- `AfterEveryFunctionCallAnalysisInterface` - called after Psalm evaluates any function call. Cannot influence the call further.\n- `AfterExpressionAnalysisInterface` - called after Psalm evaluates an expression.\n- `AfterFileAnalysisInterface` - called after Psalm analyzes a file.\n- `AfterFunctionCallAnalysisInterface` - called after Psalm evaluates a function call to any function defined within the project itself. Can alter the return type or perform modifications of the call.\n- `AfterFunctionLikeAnalysisInterface` - called after Psalm has completed its analysis of a given function-like.\n- `AfterMethodCallAnalysisInterface` - called after Psalm analyzes a method call.\n- `BeforeStatementAnalysisInterface` - called before Psalm evaluates a statement.\n- `AfterStatementAnalysisInterface` - called after Psalm evaluates a statement.\n- `BeforeAddIssueInterface` - called before Psalm adds an item to it's internal `IssueBuffer`, allows handling code issues individually\n- `BeforeFileAnalysisInterface` - called before Psalm analyzes a file.\n- `ClassFilePathProviderInterface.php` - can be used to determine the file path a of a class not autoloadable using composer, but autoloadable through a custom autoloader, to avoid actually invoking the autoloader and executing the class\n- `FunctionExistenceProviderInterface` - can be used to override Psalm's builtin function existence checks for one or more functions.\n- `FunctionParamsProviderInterface.php` - can be used to override Psalm's builtin function parameter lookup for one or more functions.\n- `FunctionReturnTypeProviderInterface` - can be used to override Psalm's builtin function return type lookup for one or more functions.\n- `MethodCapabilitiesProviderInterface` - can be used to give the capabilities (purity) a call of a method of one or more classes requires, e.g. from its arguments.\n- `MethodExistenceProviderInterface` - can be used to override Psalm's builtin method existence checks for one or more classes.\n- `MethodParamsProviderInterface` - can be used to override Psalm's builtin method parameter lookup for one or more classes.\n- `MethodReturnTypeProviderInterface` - can be used to override Psalm's builtin method return type lookup for one or more classes.\n- `MethodVisibilityProviderInterface` - can be used to override Psalm's builtin method visibility checks for one or more classes.\n- `PropertyExistenceProviderInterface` - can be used to override Psalm's builtin property existence checks for one or more classes.\n- `PropertyTypeProviderInterface` - can be used to override Psalm's builtin property type lookup for one or more classes.\n- `PropertyVisibilityProviderInterface` - can be used to override Psalm's builtin property visibility checks for one or more classes.\n- `DynamicFunctionStorageProviderInterface` - can be used to override signature for one or more functions. It means you can define variadic param list. Infer return type by input args. Define function templates. Also check out `Psalm\\Plugin\\DynamicFunctionStorage` to find out what api it brings for you to change function's definition.\n\nHere are a couple of example plugins:\n - [StringChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/StringChecker.php) - checks class references in strings\n - [PreventFloatAssignmentChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/PreventFloatAssignmentChecker.php) - prevents assignment to floats\n - [FunctionCasingChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/FunctionCasingChecker.php) - checks that your functions and methods are correctly-cased\n\nTo ensure your plugin runs when Psalm does, add it to your [config](../configuration.md) (not needed for composer-based plugins):\n```xml\n    <plugins>\n        <plugin filename=\"src/plugins/SomePlugin.php\" />\n    </plugins>\n```\n\nYou can also specify an absolute path to your plugin:\n```xml\n    <plugins>\n        <plugin filename=\"/path/to/SomePlugin.php\" />\n    </plugins>\n```\n\n### Using Xdebug\n\nAs 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:\n\n```console\n$ PSALM_ALLOW_XDEBUG=1 path/to/psalm\n```\n\n## Type system\n\nUnderstand how Psalm handles types by [reading this guide](plugins_type_system.md).\n\n## Handling custom plugin issues\n\nPlugins 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`.\n\nTo 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:\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\" errorLevel=\"suppress\" />\n```\n\nYou can also use more complex rules in the `<issueHandler />` element, as you can with any other issue type e.g.\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\">\n    <errorLevel type=\"suppress\">\n        <directory name=\"tests\" />\n    </errorLevel>\n</PluginIssue>\n```\n\n## Upgrading file-based plugin to composer-based version\n\nCreate new plugin project using skeleton, then pass the class name of you file-based plugin to `registerHooksFromClass()`\nmethod of the `Psalm\\Plugin\\RegistrationInterface` instance that was passed into your plugin entry point's `__invoke()`\nmethod. See the [conversion example](https://github.com/vimeo/psalm/tree/master/examples/plugins/composer-based/echo-checker/).\n"},"items":[{"name":"authoring_plugins.md","path":"docs/running_psalm/plugins/authoring_plugins.md","rawUrl":"https://raw.githubusercontent.com/vimeo/psalm/HEAD/docs/running_psalm/plugins/authoring_plugins.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Authoring Plugins\n\n## Quick start\n\n### Using a template repository\n\nHead over to [plugin template repository](https://github.com/psalm/psalm-plugin-skeleton) on GitHub, login and click `Use this template` button.\n\n### Using skeleton project\n\nRun `composer create-project psalm/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.\n\n## Psalm plugin API\n\nBackwards compatibility for the plugin API is now covered by a separate metapackage, [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\nThis is a separate, empty metapackage: its major version will be bumped every time a breaking change occurs within Psalm's plugin API; minors will also be bumped when adding new features to Psalm's plugin API.  \n\nPlugins, starting from the first stable release of v7, need to explicitly require a caret range (i.e. ^1, NOT 1.0.0) that package in order to avoid breaking changes during Psalm upgrades.  \n\nPlugins that support v7 betas can already require `0.x` versions of the package.  \n\nAll plugin API versions with a list of contained breaking changes will be listed in the readme of [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\n## Stub files\n\nStub files provide a way to override third-party type information when you cannot add Psalm's extended docblocks to the upstream source files directly.\nBy convention, stub files have `.phpstub` extension to avoid IDEs treating them as actual php code.\n\n## Generating stubs\n\nDev-require the library you want to tweak types for, e.g.\n```\ncomposer require --dev cakephp/chronos\n```\nThen generate the stubs\n```\nvendor/bin/psalm --generate-stubs=stubs/chronos.phpstub\n```\nOpen the generated file and remove everything not related to the library you're stubbing. Tweak the docblocks to provide more accurate types.\n\n## Registering stub files\n\nSkeleton/template project includes the code to register all `.phpstub` files from the `stubs` directory.\n\nTo register a stub file manually use `Psalm\\Plugin\\RegistrationInterface::addStubFile()`.\n\n## Registering custom scanners and analyzers\n\nIn addition to XML configuration node `<fileExtensions>` plugins can register their own custom scanner\nand analyzer implementations for particular file extensions, e.g.\n\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeScanner('html', CustomFileScanner::class)`\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeAnalyzer('html', CustomFileAnalyzer::class)`\n\n## Publishing your plugin on Packagist\n\nFollow instructions on packagist.org under 'Publishing Packages' section.\n\n## Advanced topics\n\n### Starting from scratch\n\nComposer-based plugin is a composer package which conforms to these requirements:\n\n1. Its `type` field is set to `psalm-plugin`\n2. 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.\n3. Entry-point class implements `Psalm\\Plugin\\PluginEntryPointInterface`\n\n### Psalm API\n\nPlugins may implement one of (or more than one of) `Psalm\\Plugin\\EventHandler\\*` interface(s).\n\n```php\n<?php\nclass SomePlugin implements \\Psalm\\Plugin\\EventHandler\\AfterStatementAnalysisInterface\n{\n}\n```\n\n`Psalm\\Plugin\\EventHandler\\*` offers the following interfaces that you can implement:\n\n- `AfterAnalysisInterface` - called after Psalm has completed its analysis. Use this hook if you want to do something with the analysis results.\n- `AfterClassLikeAnalysisInterface` - called after Psalm has completed its analysis of a given class.\n- `AfterClassLikeExistenceCheckInterface` - called after Psalm analyzes a reference to a class, interface or trait.\n- `AfterClassLikeVisitInterface` - 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`/`--no-reflection-cache`. Use this if you want to collect or modify information about a class before Psalm begins its analysis.\n- `AfterCodebasePopulatedInterface` - called after Psalm has scanned necessary files and populated codebase data.\n- `AfterEveryFunctionCallAnalysisInterface` - called after Psalm evaluates any function call. Cannot influence the call further.\n- `AfterExpressionAnalysisInterface` - called after Psalm evaluates an expression.\n- `AfterFileAnalysisInterface` - called after Psalm analyzes a file.\n- `AfterFunctionCallAnalysisInterface` - called after Psalm evaluates a function call to any function defined within the project itself. Can alter the return type or perform modifications of the call.\n- `AfterFunctionLikeAnalysisInterface` - called after Psalm has completed its analysis of a given function-like.\n- `AfterMethodCallAnalysisInterface` - called after Psalm analyzes a method call.\n- `BeforeStatementAnalysisInterface` - called before Psalm evaluates a statement.\n- `AfterStatementAnalysisInterface` - called after Psalm evaluates a statement.\n- `BeforeAddIssueInterface` - called before Psalm adds an item to it's internal `IssueBuffer`, allows handling code issues individually\n- `BeforeFileAnalysisInterface` - called before Psalm analyzes a file.\n- `ClassFilePathProviderInterface.php` - can be used to determine the file path a of a class not autoloadable using composer, but autoloadable through a custom autoloader, to avoid actually invoking the autoloader and executing the class\n- `FunctionExistenceProviderInterface` - can be used to override Psalm's builtin function existence checks for one or more functions.\n- `FunctionParamsProviderInterface.php` - can be used to override Psalm's builtin function parameter lookup for one or more functions.\n- `FunctionReturnTypeProviderInterface` - can be used to override Psalm's builtin function return type lookup for one or more functions.\n- `MethodCapabilitiesProviderInterface` - can be used to give the capabilities (purity) a call of a method of one or more classes requires, e.g. from its arguments.\n- `MethodExistenceProviderInterface` - can be used to override Psalm's builtin method existence checks for one or more classes.\n- `MethodParamsProviderInterface` - can be used to override Psalm's builtin method parameter lookup for one or more classes.\n- `MethodReturnTypeProviderInterface` - can be used to override Psalm's builtin method return type lookup for one or more classes.\n- `MethodVisibilityProviderInterface` - can be used to override Psalm's builtin method visibility checks for one or more classes.\n- `PropertyExistenceProviderInterface` - can be used to override Psalm's builtin property existence checks for one or more classes.\n- `PropertyTypeProviderInterface` - can be used to override Psalm's builtin property type lookup for one or more classes.\n- `PropertyVisibilityProviderInterface` - can be used to override Psalm's builtin property visibility checks for one or more classes.\n- `DynamicFunctionStorageProviderInterface` - can be used to override signature for one or more functions. It means you can define variadic param list. Infer return type by input args. Define function templates. Also check out `Psalm\\Plugin\\DynamicFunctionStorage` to find out what api it brings for you to change function's definition.\n\nHere are a couple of example plugins:\n - [StringChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/StringChecker.php) - checks class references in strings\n - [PreventFloatAssignmentChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/PreventFloatAssignmentChecker.php) - prevents assignment to floats\n - [FunctionCasingChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/FunctionCasingChecker.php) - checks that your functions and methods are correctly-cased\n\nTo ensure your plugin runs when Psalm does, add it to your [config](../configuration.md) (not needed for composer-based plugins):\n```xml\n    <plugins>\n        <plugin filename=\"src/plugins/SomePlugin.php\" />\n    </plugins>\n```\n\nYou can also specify an absolute path to your plugin:\n```xml\n    <plugins>\n        <plugin filename=\"/path/to/SomePlugin.php\" />\n    </plugins>\n```\n\n### Using Xdebug\n\nAs 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:\n\n```console\n$ PSALM_ALLOW_XDEBUG=1 path/to/psalm\n```\n\n## Type system\n\nUnderstand how Psalm handles types by [reading this guide](plugins_type_system.md).\n\n## Handling custom plugin issues\n\nPlugins 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`.\n\nTo 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:\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\" errorLevel=\"suppress\" />\n```\n\nYou can also use more complex rules in the `<issueHandler />` element, as you can with any other issue type e.g.\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\">\n    <errorLevel type=\"suppress\">\n        <directory name=\"tests\" />\n    </errorLevel>\n</PluginIssue>\n```\n\n## Upgrading file-based plugin to composer-based version\n\nCreate new plugin project using skeleton, then pass the class name of you file-based plugin to `registerHooksFromClass()`\nmethod of the `Psalm\\Plugin\\RegistrationInterface` instance that was passed into your plugin entry point's `__invoke()`\nmethod. See the [conversion example](https://github.com/vimeo/psalm/tree/master/examples/plugins/composer-based/echo-checker/).\n","isInternal":false,"tokens":2158,"sizeBytes":9935},{"name":"plugins_type_system.md","path":"docs/running_psalm/plugins/plugins_type_system.md","rawUrl":"https://raw.githubusercontent.com/vimeo/psalm/HEAD/docs/running_psalm/plugins/plugins_type_system.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Plugins: type system internals\n\nPsalm's type system represents the types of variables within a program using different classes. Plugins both receive, and can update this type information.\n\n## Union types\n\nAll type information you are likely to use will be wrapped in a [Union Type](../../annotating_code/type_syntax/union_types.md).\n\nThe `Union` class constructor takes an array of `Atomic` types, and can represent one or more of these types at a time. They correspond to a vertical bar in a doc comment.\n\n``` php\nnew Union([new TNamedObject('Foo\\\\Bar\\\\SomeClass')]); // equivalent to Foo\\Bar\\SomeClass in docblock\nnew Union([new TString(), new TInt()]); // equivalent to string|int in docblock\n```\n\n## Atomic types\n\nPrimitive types like floats, integers and strings, plus arrays, and classes. You can find all of these in [`src/Psalm/Types/Atomic`](https://github.com/vimeo/psalm/tree/master/src/Psalm/Type/Atomic).\n\nNote that all non-abstract classes in this folder are valid types. They are all prefixed by 'T'.\n\nThe classes are as follows:\n\n### Misc\n\n`TVoid` - denotes the `void` type, normally just used to annotate a function/method that returns nothing\n\n`TNull` - denotes the `null` type\n\n`TNever` - denotes the `no-return`/`never-return` type for functions that never return, either throwing an exception or terminating (like the builtin `exit()`). Also used for union types that can have no possible types (impossible intersections for example).  Empty arrays `[]` have the type `array<never, never>`.\n\n`TMixed` - denotes the `mixed` type, used when you don’t know the type of an expression.\n\n`TNonEmptyMixed `- as above, but not empty. Generated for `$x` inside the `if` statement `if ($x) {...}` when `$x` is `mixed` outside.\n\n`TEmptyMixed` - as above, but empty. Generated for `$x` inside the `if` statement `if (!$x) {...}` when `$x` is `mixed` outside.\n\n`TIterable` - denotes the [`iterable` type](https://www.php.net/manual/en/language.types.iterable.php) (which can also result from an `is_iterable` check).\n\n`TResource` - denotes the `resource` type (e.g. a file handle).\n\n`TClosedResource` - denotes the `resource` type that has been closed (e.g. a file handle through `fclose()`).\n\n`TAssertionFalsy` - Represents any value reduced to false when computed in boolean context. This is used for assertions\n\n`TConditional` - Internal representation of a conditional return type in phpdoc. For example ($param1 is int ? int : string)\n\n`TIntMask` - Represents the type that is the result of a bitmask combination of its parameters. `int-mask<1, 2, 4>` corresponds to `1|2|3|4|5|6|7`\n\n`TIntMaskOf` - as above, but used with a reference to constants in code `int-mask-of<MyClass::CLASS_CONSTANT_*>` will corresponds to `1|2|3|4|5|6|7` if there are three constant 1, 2 and 4\n\n`TKeyOf` - Represents an offset of an array (e.g. `key-of<MyClass::CLASS_CONSTANT>`).\n\n`TValueOf` - Represents a value of an array or enum (e.g. `value-of<MyClass::CLASS_CONSTANT>`).\n\n`TTemplateIndexedAccess` - To be documented\n\n`TTemplateKeyOf` - Represents the type used when using TKeyOf when the type of the array is a template\n\n`TTemplateValueOf` - Represents the type used when using TValueOf when the type of the array or enum is a template\n\n`TPropertiesOf` - Represents properties and their types of a class as a keyed array (e.g. `properties-of<MyClass>`)\n\n`TTemplatePropertiesOf` - Represents the type used when using TPropertiesOf when type of the class is a template\n\n`TTypeAlias` - To be documented\n\n### Scalar supertype\n\n`TScalar` - denotes the `scalar` super type (which can also result from an `is_scalar` check). This type encompasses `float`, `int`, `bool` and `string`.\n\n`TEmptyScalar` - denotes a `scalar` type that is also empty.\n\n`TNonEmptyScalar` - denotes a `scalar` type that is also non-empty.\n\n### Numeric supertype\n\n`TNumeric` - denotes the `numeric` type (which can also result from an `is_numeric` check).\n\n`TEmptyNumeric` - denotes the `numeric` type that's also empty (which can also result from an `is_numeric` and `empty` check).\n\n### Scalar types\n\nAll scalar types have literal versions e.g. `int` vs `int(5)`.\n\n#### Ints\n\n`TInt` - denotes the `int` type, where the exact value is unknown.\n\n`TLiteralInt` - is used to represent an integer value where the exact numeric value is known.\n\n`TIntRange` - allows to describe an int with bounded values (ie. `int<1, 5>`).\n\n#### Floats\n\n`TFloat` - denotes the `float` type, where the exact value is unknown.\n\n`TLiteralFloat` - is used to represent a floating point value where the exact numeric value is known.\n\n#### Bools\n\n`TBool`, `TFalse`, `TTrue`\n\n`TBool` - denotes the `bool` type where the exact value is unknown.\n\n`TFalse` - denotes the `false` value type\n\n`TTrue` - denotes the `true` value type\n\n``` php\n/** @return string|false    false when string is empty, first char of the parameter otherwise */\nfunction firstChar(string $s) { return empty($s) ? false : $s[0]; }\n```\n\nHere, the function may never return true, but if you had to replace false with bool, Psalm would have to consider true as a possible return value. With narrower type it's able to report meaningless code like this (https://psalm.dev/r/037291351d):\n\n``` php\n$first = firstChar(\"sdf\");\nif (true === $first) {\n  echo \"This is actually dead code\";\n}\n```\n\n#### Strings\n\n`TString` - denotes the `string` type, where the exact value is unknown.\n\n`TNonEmptyString` - denotes a string, that is also non-empty\n\n`TNumericString` - denotes a string that's also a numeric value e.g. `\"5\"`. It can result from `is_string($s) && is_numeric($s)`.\n\n`TLiteralString` - is used to represent a string whose value is known.\n\n`TClassString` - denotes the `class-string` type, used to describe a string representing a valid PHP class. The parent type from which the classes descend may or may not be specified in the constructor.\n\n`TLiteralClassString` - denotes a specific class string, generated by expressions like `A::class`.\n\n`TTraitString` - denotes the `trait-string` type, used to describe a string representing a valid PHP trait.\n\n`TDependentGetClass` - Represents a string whose value is a fully-qualified class found by get_class($var)\n\n`TDependentGetDebugType` - Represents a string whose value is that of a type found by get_debug_type($var)\n\n`TDependentGetType` - Represents a string whose value is that of a type found by gettype($var)\n\n`TCallableString` - denotes the `callable-string` type, used to represent an unknown string that is also `callable`.\n\n`TSqlSelectString` - this is a special type, specifically for consumption by plugins.\n\n`TLowercaseString` - denotes a string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TNonEmptyLowercaseString` - denotes a non-empty-string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TSingleLetter` - denotes a string that has a length of 1\n\n#### Scalar class constants\n\n`TScalarClassConstant` - denotes a class constant whose value might not yet be known.\n\n#### Array key supertype\n\n`TArrayKey` - denotes the `array-key` type, used for something that could be the offset of an `array`.\n\n### Arrays\n\n`TArray` - denotes a simple array of the form `array<TKey, TValue>`. It expects an array with two elements, both union types.\n\n`TNonEmptyArray` - as above, but denotes an array known to be non-empty.\n\n`TKeyedArray` represents an 'object-like array' - an array with known keys.\n\n``` php\n$x = [\"a\" => 1, \"b\" => 2]; // is TKeyedArray, array{a: int, b: int}\n$y = rand(0, 1) ? [\"a\" => null] : [\"a\" => 1, \"b\" => \"b\"]; // is TKeyedArray with optional keys/values, array{a: ?int, b?: string}\n```\n\nThis type is also used to represent lists (instead of the now-deprecated `TList` type).  \n\nNote that not all associative arrays are considered object-like. If the keys are not known, the array is treated as a mapping between two types.\n\n``` php\n$a = [];\nforeach (range(1,1) as $_) $a[(string)rand(0,1)] = rand(0,1); // array<string,int>\n```\n\n`TCallableKeyedArray` - denotes an object-like array that is _also_ `callable`.\n\n`TClassStringMap` - Represents an array where the type of each value is a function of its string key value\n\n### Callables & closures\n\n`TCallable` - denotes the `callable` type. Can result from an `is_callable` check.\n`TClosure` - denotes a `Closure` type.\n\n`TCallable` and `TClosure` can optionally be defined with parameters and return types, too\n\n### Object supertypes\n\n`TObject` - denotes the `object` type\n\n`TObjectWithProperties` - an object with specified member variables e.g. `object{foo:int, bar:string}`.\n\n### Object types\n\n`TNamedObject` - denotes an object type where the type of the object is known e.g. `Exception`, `Throwable`, `Foo\\Bar`\n\n`TGenericObject` - denotes an object type that has generic parameters e.g. `ArrayObject<string, Foo\\Bar>`\n\n`TCallableObject` - denotes an object that is also `callable` (i.e. it has `__invoke` defined).\n\n`TAnonymousClassInstance` - Denotes an anonymous class (i.e. `new class{}`) with potential methods\n\n### Template\n\n`TTemplateParam` - denotes a template parameter that has been previously specified in a `@template` tag.\n\n`TTemplateParamClass` - denotes a `class-string` corresponding to a template parameter previously specified in a `@template` tag.\n\n## Creating type object instances\n\nThere are two ways of creating the object instances which describe a given type. They can be created directly using new, or created declaratively from a doc string. Normally, you'd want to use the second option. However, understanding the structure of this data will help you understand types passed into a plugin.\n\nNote that these classes do sometimes change, so `Type::parseString` is always going to be the more robust option.\n\n### Creating type object instances directly\n\nThe following example constructs types representing a string, a floating-point number, and a class called 'Foo\\Bar\\SomeClass'.\n\n``` php\nnew TLiteralString('A text string')\nnew TLiteralFloat(3.142)\nnew TNamedObject('Foo\\Bar\\SomeClass')\n```\n\nTypes within Psalm are always wrapped in a union as a convenience feature. Almost anywhere you may expect a type, you can get a union as well (property types, return types, argument types, etc). So wrapping a single atomic type (like TInt) in a union container allows to uniformly handle that type elsewhere, without repetitive checks like this:\n\n``` php\nif ($type instanceof Union)\n   foreach ($types->getTypes() as $atomic)\n      handleAtomic($atomic);\nelse handleAtomic($type);\n\n// with union container it becomes\nforeach ($types->getTypes() as $atomic)\n   handleAtomic($atomic);\n```\n\nAlso, union trees are always shallow, because Psalm will flatten union of unions into a single-level union `((A|B)|(C|D) => A|B|C|D)`.\n\nMore complex types can be constructed as follows. The following represents an associative array with 3 keys. Psalm calls these 'object-like arrays', and represents them with the 'TKeyedArray' class.\n\n\n``` php\n        new Union([\n            TKeyedArray::make([\n                'key_1' => new Union([new TString()]),\n                'key_2' => new Union([new TInt()]),\n                'key_3' => new Union([new TBool()])])]);\n```\n\nThe Type object includes some static helper methods, which automatically wrap the type in a Union. Thus this can be written more tersely:\n\n``` php\nnew Union([\n    new Type\\Atomic\\TKeyedArray([\n        'first' => Type::getInt(),\n        'second' => Type::getString()])]);\n```\n\nYou can also use `Type::getInt(5)` to generate a union type corresponding to the literal int value 5.\n\n\n### Creating type object instances from doc string types\n\nAnother way of creating these instances is to use the class `Psalm\\Type` which includes a static method `parseString`. You may pass any doc string type description to this, and it will return the corresponding object representation.\n\n``` php\n\\Psalm\\Type::parseString('int|null');\n```\n\nYou can find how Psalm would represent a given type as objects, by specifying the type as an input to this function, and calling `var_dump` on the result.\n","isInternal":false,"tokens":3016,"sizeBytes":12074},{"name":"using_plugins.md","path":"docs/running_psalm/plugins/using_plugins.md","rawUrl":"https://raw.githubusercontent.com/vimeo/psalm/HEAD/docs/running_psalm/plugins/using_plugins.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"# Using Plugins\n\nPsalm can be extended through plugins to find and fix domain-specific issues.\n\n## Using Composer-based plugins\n\nPsalm plugins are distributed as composer packages.\n\n### Discovering plugins\n\nYou can find a list of plugins on [Psalm’s own website](https://psalm.dev/plugins), and [also on Packagist](https://packagist.org/?type=psalm-plugin). Alternatively you can get a list via the CLI by typing `composer search -t psalm-plugin '.'`\n\n### Installing plugins\n\n`composer require --dev <plugin-vendor/plugin-package>`\n\n### Managing known plugins\n\nOnce installed, use the `psalm-plugin` tool to enable, disable and show available and enabled plugins.\n\nTo enable a plugin, run `vendor/bin/psalm-plugin enable plugin-vendor/plugin-package`.\n\nTo disable a plugin, run `vendor/bin/psalm-plugin disable plugin-vendor/plugin-package`.\n\n`vendor/bin/psalm-plugin show` will show you a list of all local plugins (enabled and disabled).\n\n## Using your own plugins\n\nIs there no plugin for your favourite framework / library yet? Create it! It's as easy as forking a repository, tweaking some docblocks and publishing the package to Packagist.\n\nConsult [Authoring Plugins](authoring_plugins.md) chapter to get started.\n","isInternal":false,"tokens":270,"sizeBytes":1222}],"systemPromptSnippet":"<yakaai_skills repo=\"vimeo/psalm\">\n<!-- File: docs/running_psalm/plugins/authoring_plugins.md (Tokens: ~2158 | Category: anthropic-skill) -->\n# Authoring Plugins\n\n## Quick start\n\n### Using a template repository\n\nHead over to [plugin template repository](https://github.com/psalm/psalm-plugin-skeleton) on GitHub, login and click `Use this template` button.\n\n### Using skeleton project\n\nRun `composer create-project psalm/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.\n\n## Psalm plugin API\n\nBackwards compatibility for the plugin API is now covered by a separate metapackage, [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\nThis is a separate, empty metapackage: its major version will be bumped every time a breaking change occurs within Psalm's plugin API; minors will also be bumped when adding new features to Psalm's plugin API.  \n\nPlugins, starting from the first stable release of v7, need to explicitly require a caret range (i.e. ^1, NOT 1.0.0) that package in order to avoid breaking changes during Psalm upgrades.  \n\nPlugins that support v7 betas can already require `0.x` versions of the package.  \n\nAll plugin API versions with a list of contained breaking changes will be listed in the readme of [psalm/psalm-plugin-api](https://packagist.org/packages/psalm/psalm-plugin-api).  \n\n## Stub files\n\nStub files provide a way to override third-party type information when you cannot add Psalm's extended docblocks to the upstream source files directly.\nBy convention, stub files have `.phpstub` extension to avoid IDEs treating them as actual php code.\n\n## Generating stubs\n\nDev-require the library you want to tweak types for, e.g.\n```\ncomposer require --dev cakephp/chronos\n```\nThen generate the stubs\n```\nvendor/bin/psalm --generate-stubs=stubs/chronos.phpstub\n```\nOpen the generated file and remove everything not related to the library you're stubbing. Tweak the docblocks to provide more accurate types.\n\n## Registering stub files\n\nSkeleton/template project includes the code to register all `.phpstub` files from the `stubs` directory.\n\nTo register a stub file manually use `Psalm\\Plugin\\RegistrationInterface::addStubFile()`.\n\n## Registering custom scanners and analyzers\n\nIn addition to XML configuration node `<fileExtensions>` plugins can register their own custom scanner\nand analyzer implementations for particular file extensions, e.g.\n\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeScanner('html', CustomFileScanner::class)`\n* `Psalm\\Plugin\\FileExtensionsInterface::addFileTypeAnalyzer('html', CustomFileAnalyzer::class)`\n\n## Publishing your plugin on Packagist\n\nFollow instructions on packagist.org under 'Publishing Packages' section.\n\n## Advanced topics\n\n### Starting from scratch\n\nComposer-based plugin is a composer package which conforms to these requirements:\n\n1. Its `type` field is set to `psalm-plugin`\n2. 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.\n3. Entry-point class implements `Psalm\\Plugin\\PluginEntryPointInterface`\n\n### Psalm API\n\nPlugins may implement one of (or more than one of) `Psalm\\Plugin\\EventHandler\\*` interface(s).\n\n```php\n<?php\nclass SomePlugin implements \\Psalm\\Plugin\\EventHandler\\AfterStatementAnalysisInterface\n{\n}\n```\n\n`Psalm\\Plugin\\EventHandler\\*` offers the following interfaces that you can implement:\n\n- `AfterAnalysisInterface` - called after Psalm has completed its analysis. Use this hook if you want to do something with the analysis results.\n- `AfterClassLikeAnalysisInterface` - called after Psalm has completed its analysis of a given class.\n- `AfterClassLikeExistenceCheckInterface` - called after Psalm analyzes a reference to a class, interface or trait.\n- `AfterClassLikeVisitInterface` - 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`/`--no-reflection-cache`. Use this if you want to collect or modify information about a class before Psalm begins its analysis.\n- `AfterCodebasePopulatedInterface` - called after Psalm has scanned necessary files and populated codebase data.\n- `AfterEveryFunctionCallAnalysisInterface` - called after Psalm evaluates any function call. Cannot influence the call further.\n- `AfterExpressionAnalysisInterface` - called after Psalm evaluates an expression.\n- `AfterFileAnalysisInterface` - called after Psalm analyzes a file.\n- `AfterFunctionCallAnalysisInterface` - called after Psalm evaluates a function call to any function defined within the project itself. Can alter the return type or perform modifications of the call.\n- `AfterFunctionLikeAnalysisInterface` - called after Psalm has completed its analysis of a given function-like.\n- `AfterMethodCallAnalysisInterface` - called after Psalm analyzes a method call.\n- `BeforeStatementAnalysisInterface` - called before Psalm evaluates a statement.\n- `AfterStatementAnalysisInterface` - called after Psalm evaluates a statement.\n- `BeforeAddIssueInterface` - called before Psalm adds an item to it's internal `IssueBuffer`, allows handling code issues individually\n- `BeforeFileAnalysisInterface` - called before Psalm analyzes a file.\n- `ClassFilePathProviderInterface.php` - can be used to determine the file path a of a class not autoloadable using composer, but autoloadable through a custom autoloader, to avoid actually invoking the autoloader and executing the class\n- `FunctionExistenceProviderInterface` - can be used to override Psalm's builtin function existence checks for one or more functions.\n- `FunctionParamsProviderInterface.php` - can be used to override Psalm's builtin function parameter lookup for one or more functions.\n- `FunctionReturnTypeProviderInterface` - can be used to override Psalm's builtin function return type lookup for one or more functions.\n- `MethodCapabilitiesProviderInterface` - can be used to give the capabilities (purity) a call of a method of one or more classes requires, e.g. from its arguments.\n- `MethodExistenceProviderInterface` - can be used to override Psalm's builtin method existence checks for one or more classes.\n- `MethodParamsProviderInterface` - can be used to override Psalm's builtin method parameter lookup for one or more classes.\n- `MethodReturnTypeProviderInterface` - can be used to override Psalm's builtin method return type lookup for one or more classes.\n- `MethodVisibilityProviderInterface` - can be used to override Psalm's builtin method visibility checks for one or more classes.\n- `PropertyExistenceProviderInterface` - can be used to override Psalm's builtin property existence checks for one or more classes.\n- `PropertyTypeProviderInterface` - can be used to override Psalm's builtin property type lookup for one or more classes.\n- `PropertyVisibilityProviderInterface` - can be used to override Psalm's builtin property visibility checks for one or more classes.\n- `DynamicFunctionStorageProviderInterface` - can be used to override signature for one or more functions. It means you can define variadic param list. Infer return type by input args. Define function templates. Also check out `Psalm\\Plugin\\DynamicFunctionStorage` to find out what api it brings for you to change function's definition.\n\nHere are a couple of example plugins:\n - [StringChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/StringChecker.php) - checks class references in strings\n - [PreventFloatAssignmentChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/PreventFloatAssignmentChecker.php) - prevents assignment to floats\n - [FunctionCasingChecker](https://github.com/vimeo/psalm/blob/master/examples/plugins/FunctionCasingChecker.php) - checks that your functions and methods are correctly-cased\n\nTo ensure your plugin runs when Psalm does, add it to your [config](../configuration.md) (not needed for composer-based plugins):\n```xml\n    <plugins>\n        <plugin filename=\"src/plugins/SomePlugin.php\" />\n    </plugins>\n```\n\nYou can also specify an absolute path to your plugin:\n```xml\n    <plugins>\n        <plugin filename=\"/path/to/SomePlugin.php\" />\n    </plugins>\n```\n\n### Using Xdebug\n\nAs 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:\n\n```console\n$ PSALM_ALLOW_XDEBUG=1 path/to/psalm\n```\n\n## Type system\n\nUnderstand how Psalm handles types by [reading this guide](plugins_type_system.md).\n\n## Handling custom plugin issues\n\nPlugins 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`.\n\nTo 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:\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\" errorLevel=\"suppress\" />\n```\n\nYou can also use more complex rules in the `<issueHandler />` element, as you can with any other issue type e.g.\n\n```xml\n<PluginIssue name=\"NoFloatAssignment\">\n    <errorLevel type=\"suppress\">\n        <directory name=\"tests\" />\n    </errorLevel>\n</PluginIssue>\n```\n\n## Upgrading file-based plugin to composer-based version\n\nCreate new plugin project using skeleton, then pass the class name of you file-based plugin to `registerHooksFromClass()`\nmethod of the `Psalm\\Plugin\\RegistrationInterface` instance that was passed into your plugin entry point's `__invoke()`\nmethod. See the [conversion example](https://github.com/vimeo/psalm/tree/master/examples/plugins/composer-based/echo-checker/).\n\n<!-- File: docs/running_psalm/plugins/plugins_type_system.md (Tokens: ~3016 | Category: anthropic-skill) -->\n# Plugins: type system internals\n\nPsalm's type system represents the types of variables within a program using different classes. Plugins both receive, and can update this type information.\n\n## Union types\n\nAll type information you are likely to use will be wrapped in a [Union Type](../../annotating_code/type_syntax/union_types.md).\n\nThe `Union` class constructor takes an array of `Atomic` types, and can represent one or more of these types at a time. They correspond to a vertical bar in a doc comment.\n\n``` php\nnew Union([new TNamedObject('Foo\\\\Bar\\\\SomeClass')]); // equivalent to Foo\\Bar\\SomeClass in docblock\nnew Union([new TString(), new TInt()]); // equivalent to string|int in docblock\n```\n\n## Atomic types\n\nPrimitive types like floats, integers and strings, plus arrays, and classes. You can find all of these in [`src/Psalm/Types/Atomic`](https://github.com/vimeo/psalm/tree/master/src/Psalm/Type/Atomic).\n\nNote that all non-abstract classes in this folder are valid types. They are all prefixed by 'T'.\n\nThe classes are as follows:\n\n### Misc\n\n`TVoid` - denotes the `void` type, normally just used to annotate a function/method that returns nothing\n\n`TNull` - denotes the `null` type\n\n`TNever` - denotes the `no-return`/`never-return` type for functions that never return, either throwing an exception or terminating (like the builtin `exit()`). Also used for union types that can have no possible types (impossible intersections for example).  Empty arrays `[]` have the type `array<never, never>`.\n\n`TMixed` - denotes the `mixed` type, used when you don’t know the type of an expression.\n\n`TNonEmptyMixed `- as above, but not empty. Generated for `$x` inside the `if` statement `if ($x) {...}` when `$x` is `mixed` outside.\n\n`TEmptyMixed` - as above, but empty. Generated for `$x` inside the `if` statement `if (!$x) {...}` when `$x` is `mixed` outside.\n\n`TIterable` - denotes the [`iterable` type](https://www.php.net/manual/en/language.types.iterable.php) (which can also result from an `is_iterable` check).\n\n`TResource` - denotes the `resource` type (e.g. a file handle).\n\n`TClosedResource` - denotes the `resource` type that has been closed (e.g. a file handle through `fclose()`).\n\n`TAssertionFalsy` - Represents any value reduced to false when computed in boolean context. This is used for assertions\n\n`TConditional` - Internal representation of a conditional return type in phpdoc. For example ($param1 is int ? int : string)\n\n`TIntMask` - Represents the type that is the result of a bitmask combination of its parameters. `int-mask<1, 2, 4>` corresponds to `1|2|3|4|5|6|7`\n\n`TIntMaskOf` - as above, but used with a reference to constants in code `int-mask-of<MyClass::CLASS_CONSTANT_*>` will corresponds to `1|2|3|4|5|6|7` if there are three constant 1, 2 and 4\n\n`TKeyOf` - Represents an offset of an array (e.g. `key-of<MyClass::CLASS_CONSTANT>`).\n\n`TValueOf` - Represents a value of an array or enum (e.g. `value-of<MyClass::CLASS_CONSTANT>`).\n\n`TTemplateIndexedAccess` - To be documented\n\n`TTemplateKeyOf` - Represents the type used when using TKeyOf when the type of the array is a template\n\n`TTemplateValueOf` - Represents the type used when using TValueOf when the type of the array or enum is a template\n\n`TPropertiesOf` - Represents properties and their types of a class as a keyed array (e.g. `properties-of<MyClass>`)\n\n`TTemplatePropertiesOf` - Represents the type used when using TPropertiesOf when type of the class is a template\n\n`TTypeAlias` - To be documented\n\n### Scalar supertype\n\n`TScalar` - denotes the `scalar` super type (which can also result from an `is_scalar` check). This type encompasses `float`, `int`, `bool` and `string`.\n\n`TEmptyScalar` - denotes a `scalar` type that is also empty.\n\n`TNonEmptyScalar` - denotes a `scalar` type that is also non-empty.\n\n### Numeric supertype\n\n`TNumeric` - denotes the `numeric` type (which can also result from an `is_numeric` check).\n\n`TEmptyNumeric` - denotes the `numeric` type that's also empty (which can also result from an `is_numeric` and `empty` check).\n\n### Scalar types\n\nAll scalar types have literal versions e.g. `int` vs `int(5)`.\n\n#### Ints\n\n`TInt` - denotes the `int` type, where the exact value is unknown.\n\n`TLiteralInt` - is used to represent an integer value where the exact numeric value is known.\n\n`TIntRange` - allows to describe an int with bounded values (ie. `int<1, 5>`).\n\n#### Floats\n\n`TFloat` - denotes the `float` type, where the exact value is unknown.\n\n`TLiteralFloat` - is used to represent a floating point value where the exact numeric value is known.\n\n#### Bools\n\n`TBool`, `TFalse`, `TTrue`\n\n`TBool` - denotes the `bool` type where the exact value is unknown.\n\n`TFalse` - denotes the `false` value type\n\n`TTrue` - denotes the `true` value type\n\n``` php\n/** @return string|false    false when string is empty, first char of the parameter otherwise */\nfunction firstChar(string $s) { return empty($s) ? false : $s[0]; }\n```\n\nHere, the function may never return true, but if you had to replace false with bool, Psalm would have to consider true as a possible return value. With narrower type it's able to report meaningless code like this (https://psalm.dev/r/037291351d):\n\n``` php\n$first = firstChar(\"sdf\");\nif (true === $first) {\n  echo \"This is actually dead code\";\n}\n```\n\n#### Strings\n\n`TString` - denotes the `string` type, where the exact value is unknown.\n\n`TNonEmptyString` - denotes a string, that is also non-empty\n\n`TNumericString` - denotes a string that's also a numeric value e.g. `\"5\"`. It can result from `is_string($s) && is_numeric($s)`.\n\n`TLiteralString` - is used to represent a string whose value is known.\n\n`TClassString` - denotes the `class-string` type, used to describe a string representing a valid PHP class. The parent type from which the classes descend may or may not be specified in the constructor.\n\n`TLiteralClassString` - denotes a specific class string, generated by expressions like `A::class`.\n\n`TTraitString` - denotes the `trait-string` type, used to describe a string representing a valid PHP trait.\n\n`TDependentGetClass` - Represents a string whose value is a fully-qualified class found by get_class($var)\n\n`TDependentGetDebugType` - Represents a string whose value is that of a type found by get_debug_type($var)\n\n`TDependentGetType` - Represents a string whose value is that of a type found by gettype($var)\n\n`TCallableString` - denotes the `callable-string` type, used to represent an unknown string that is also `callable`.\n\n`TSqlSelectString` - this is a special type, specifically for consumption by plugins.\n\n`TLowercaseString` - denotes a string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TNonEmptyLowercaseString` - denotes a non-empty-string where every character is lowercased. (which can also result from a `strtolower` call).\n\n`TSingleLetter` - denotes a string that has a length of 1\n\n#### Scalar class constants\n\n`TScalarClassConstant` - denotes a class constant whose value might not yet be known.\n\n#### Array key supertype\n\n`TArrayKey` - denotes the `array-key` type, used for something that could be the offset of an `array`.\n\n### Arrays\n\n`TArray` - denotes a simple array of the form `array<TKey, TValue>`. It expects an array with two elements, both union types.\n\n`TNonEmptyArray` - as above, but denotes an array known to be non-empty.\n\n`TKeyedArray` represents an 'object-like array' - an array with known keys.\n\n``` php\n$x = [\"a\" => 1, \"b\" => 2]; // is TKeyedArray, array{a: int, b: int}\n$y = rand(0, 1) ? [\"a\" => null] : [\"a\" => 1, \"b\" => \"b\"]; // is TKeyedArray with optional keys/values, array{a: ?int, b?: string}\n```\n\nThis type is also used to represent lists (instead of the now-deprecated `TList` type).  \n\nNote that not all associative arrays are considered object-like. If the keys are not known, the array is treated as a mapping between two types.\n\n``` php\n$a = [];\nforeach (range(1,1) as $_) $a[(string)rand(0,1)] = rand(0,1); // array<string,int>\n```\n\n`TCallableKeyedArray` - denotes an object-like array that is _also_ `callable`.\n\n`TClassStringMap` - Represents an array where the type of each value is a function of its string key value\n\n### Callables & closures\n\n`TCallable` - denotes the `callable` type. Can result from an `is_callable` check.\n`TClosure` - denotes a `Closure` type.\n\n`TCallable` and `TClosure` can optionally be defined with parameters and return types, too\n\n### Object supertypes\n\n`TObject` - denotes the `object` type\n\n`TObjectWithProperties` - an object with specified member variables e.g. `object{foo:int, bar:string}`.\n\n### Object types\n\n`TNamedObject` - denotes an object type where the type of the object is known e.g. `Exception`, `Throwable`, `Foo\\Bar`\n\n`TGenericObject` - denotes an object type that has generic parameters e.g. `ArrayObject<string, Foo\\Bar>`\n\n`TCallableObject` - denotes an object that is also `callable` (i.e. it has `__invoke` defined).\n\n`TAnonymousClassInstance` - Denotes an anonymous class (i.e. `new class{}`) with potential methods\n\n### Template\n\n`TTemplateParam` - denotes a template parameter that has been previously specified in a `@template` tag.\n\n`TTemplateParamClass` - denotes a `class-string` corresponding to a template parameter previously specified in a `@template` tag.\n\n## Creating type object instances\n\nThere are two ways of creating the object instances which describe a given type. They can be created directly using new, or created declaratively from a doc string. Normally, you'd want to use the second option. However, understanding the structure of this data will help you understand types passed into a plugin.\n\nNote that these classes do sometimes change, so `Type::parseString` is always going to be the more robust option.\n\n### Creating type object instances directly\n\nThe following example constructs types representing a string, a floating-point number, and a class called 'Foo\\Bar\\SomeClass'.\n\n``` php\nnew TLiteralString('A text string')\nnew TLiteralFloat(3.142)\nnew TNamedObject('Foo\\Bar\\SomeClass')\n```\n\nTypes within Psalm are always wrapped in a union as a convenience feature. Almost anywhere you may expect a type, you can get a union as well (property types, return types, argument types, etc). So wrapping a single atomic type (like TInt) in a union container allows to uniformly handle that type elsewhere, without repetitive checks like this:\n\n``` php\nif ($type instanceof Union)\n   foreach ($types->getTypes() as $atomic)\n      handleAtomic($atomic);\nelse handleAtomic($type);\n\n// with union container it becomes\nforeach ($types->getTypes() as $atomic)\n   handleAtomic($atomic);\n```\n\nAlso, union trees are always shallow, because Psalm will flatten union of unions into a single-level union `((A|B)|(C|D) => A|B|C|D)`.\n\nMore complex types can be constructed as follows. The following represents an associative array with 3 keys. Psalm calls these 'object-like arrays', and represents them with the 'TKeyedArray' class.\n\n\n``` php\n        new Union([\n            TKeyedArray::make([\n                'key_1' => new Union([new TString()]),\n                'key_2' => new Union([new TInt()]),\n                'key_3' => new Union([new TBool()])])]);\n```\n\nThe Type object includes some static helper methods, which automatically wrap the type in a Union. Thus this can be written more tersely:\n\n``` php\nnew Union([\n    new Type\\Atomic\\TKeyedArray([\n        'first' => Type::getInt(),\n        'second' => Type::getString()])]);\n```\n\nYou can also use `Type::getInt(5)` to generate a union type corresponding to the literal int value 5.\n\n\n### Creating type object instances from doc string types\n\nAnother way of creating these instances is to use the class `Psalm\\Type` which includes a static method `parseString`. You may pass any doc string type description to this, and it will return the corresponding object representation.\n\n``` php\n\\Psalm\\Type::parseString('int|null');\n```\n\nYou can find how Psalm would represent a given type as objects, by specifying the type as an input to this function, and calling `var_dump` on the result.\n\n<!-- File: docs/running_psalm/plugins/using_plugins.md (Tokens: ~270 | Category: anthropic-skill) -->\n# Using Plugins\n\nPsalm can be extended through plugins to find and fix domain-specific issues.\n\n## Using Composer-based plugins\n\nPsalm plugins are distributed as composer packages.\n\n### Discovering plugins\n\nYou can find a list of plugins on [Psalm’s own website](https://psalm.dev/plugins), and [also on Packagist](https://packagist.org/?type=psalm-plugin). Alternatively you can get a list via the CLI by typing `composer search -t psalm-plugin '.'`\n\n### Installing plugins\n\n`composer require --dev <plugin-vendor/plugin-package>`\n\n### Managing known plugins\n\nOnce installed, use the `psalm-plugin` tool to enable, disable and show available and enabled plugins.\n\nTo enable a plugin, run `vendor/bin/psalm-plugin enable plugin-vendor/plugin-package`.\n\nTo disable a plugin, run `vendor/bin/psalm-plugin disable plugin-vendor/plugin-package`.\n\n`vendor/bin/psalm-plugin show` will show you a list of all local plugins (enabled and disabled).\n\n## Using your own plugins\n\nIs there no plugin for your favourite framework / library yet? Create it! It's as easy as forking a repository, tweaking some docblocks and publishing the package to Packagist.\n\nConsult [Authoring Plugins](authoring_plugins.md) chapter to get started.\n</yakaai_skills>"}