Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Psalm Plugin Api Laravel Package

psalm/psalm-plugin-api

Psalm plugin API providing interfaces and helpers to build and integrate custom plugins with the Psalm static analysis tool, enabling extensions such as new checks, type providers, and project-specific analysis behavior.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package to your project via Composer:

    composer require psalm/psalm-plugin-api
    

    Ensure your composer.json includes "psalm/psalm-plugin-api": "^x.y.z" under require-dev if using Psalm as a dev dependency.

  2. First Use Case Create a basic plugin skeleton:

    // src/Plugin/MyPlugin.php
    namespace MyPlugin;
    
    use Psalm\Plugin\PluginEntryPointInterface;
    use Psalm\Plugin\RegistrationInterface;
    
    class MyPlugin implements PluginEntryPointInterface
    {
        public function __invoke(RegistrationInterface $registration, ?string $tempDir = null): void
        {
            // Register hooks here
        }
    }
    
  3. Psalm Configuration Update psalm.xml to include your plugin:

    <plugin_class>MyPlugin\MyPlugin</plugin_class>
    
  4. Verify Run Psalm with --init to generate stubs, then analyze:

    vendor/bin/psalm --init
    vendor/bin/psalm
    

Implementation Patterns

Core Workflows

  1. Hook Registration Use RegistrationInterface to attach to Psalm’s lifecycle:

    $registration->registerHook(Hook::AFTER_ANALYSIS, [$this, 'postAnalysis']);
    
  2. Custom Analysis Extend Psalm\CodeLocation and Psalm\Type for type inference:

    $registration->registerHook(Hook::AFTER_METHOD_ANALYSIS, function (AfterMethodAnalysisInterface $event) {
        $method = $event->getMethod();
        if ($method->getDeclaringClass()->getName() === 'MyClass') {
            $event->getType()->addPossibleType(new \Psalm\Type\Atomic\TString());
        }
    });
    
  3. Stub Generation Implement StubGeneratorInterface for custom stubs:

    $registration->registerStubGenerator(new class implements StubGeneratorInterface {
        public function generateStubFile(string $file_path, string $contents): string {
            return str_replace('// STUB', '// CUSTOM_STUB', $contents);
        }
    });
    

Integration Tips

  • Dependency Injection: Use Psalm\Plugin\PluginEntryPointInterface to access Psalm’s container.
  • Async Hooks: For performance, prefer Hook::AFTER_ANALYSIS over Hook::BEFORE_ANALYSIS.
  • Configuration: Pass plugin-specific config via PluginEntryPointInterface::__invoke()’s $tempDir or environment variables.

Gotchas and Tips

Pitfalls

  1. Type Safety Psalm plugins must adhere to Psalm’s type system. Misusing Psalm\Type classes (e.g., TArray vs TArrayLike) can cause false positives/negatives. Fix: Use Psalm\Type\Union for ambiguous cases.

  2. Hook Order Hooks fire in registration order. Override another plugin’s behavior by registering later. Tip: Log hook execution order with Psalm\LoggerInterface.

  3. Stub Conflicts Custom stubs may override Psalm’s built-in stubs. Test with --no-cache to avoid stale stubs. Workaround: Use StubGeneratorInterface’s $contents to merge stubs.

  4. Performance Heavy analysis in Hook::BEFORE_ANALYSIS can slow Psalm. Offload work to Hook::AFTER_ANALYSIS or use caching.

Debugging

  • Logging: Inject Psalm\LoggerInterface via the container:
    $logger = $registration->getContainer()->getByType(LoggerInterface::class);
    $logger->info('Plugin executed');
    
  • Validation: Use Psalm\Internal\ProjectFilesAnalysis to inspect parsed files during AFTER_ANALYSIS.

Extension Points

  1. Custom Rules Extend Psalm\Plugin\Rule\RuleInterface for static analysis rules:

    $registration->registerRule(new class implements RuleInterface {
        public function getPropertyName(): string { return 'my_rule'; }
        public function run(CodeLocation $location, Callable $callback): void { /* ... */ }
    });
    
  2. Template Analysis Hook into Hook::AFTER_TEMPLATE_ANALYSIS to modify template logic (e.g., Blade).

  3. Configuration Use Psalm\Config to read plugin-specific settings from psalm.xml:

    <plugin_config>
        <my_plugin>
            <option>value</option>
        </my_plugin>
    </plugin_config>
    

    Access via:

    $config = $registration->getContainer()->getByType(Config::class);
    $value = $config->getPluginConfig('my_plugin', 'option');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests