### Install Dependencies Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/apigen/infra/CLAUDE.md Installs project dependencies. Run this after pulling changes. ```sh npm ci ``` -------------------------------- ### Install Zephir Extension Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Use the 'zephir install' command to deploy the compiled extension to the system's extension directory, with options for development or production. ```bash zephir install [--dev|--no-dev] ``` -------------------------------- ### Build Zephir Extension (Generate, Compile, Install) Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md The 'zephir build' command is a meta-command that executes generate, compile, and install sequentially. ```bash zephir build ``` -------------------------------- ### LevelsTestCase Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md This example shows how to set up a test class using LevelsTestCase to check rules across all PHPStan levels. ```php use PHPStan\Testing\LevelsTestCase; class LevelsTest extends LevelsTestCase { public function dataDirectory(): string { return __DIR__ . '/data'; } public function testLevels(): void { // Tests all .php files in data/ directory // across all rule levels 0-10 $this->checkLevels(); } } ``` -------------------------------- ### Install Zephir via Composer Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Installs Zephir using Composer, either for a specific project or globally. After installation, you can run `zephir help` to see available commands. ```bash # Project-level composer require phalcon/zephir composer exec zephir help # Global composer global require phalcon/zephir zephir help ``` -------------------------------- ### PHPStan Main Configuration Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/00-index.md This is an example of the main PHPStan configuration file (phpstan.neon). It demonstrates how to set the target PHP version, analysis level, paths to analyze, excluded paths, and error ignoring patterns. It also shows how to register custom rules and extensions. ```neon parameters: # Target PHP version phpVersion: 80200 # Rule level (0-10) level: 8 # Paths to analyze paths: - src - tests # Paths to exclude excludePaths: - src/Temp # Error ignoring ignoreErrors: - '#undefined method#' - file: src/Legacy.php message: '#.*#' services: # Register custom rule - class: App\MyRule tags: - phpstan.rules.rule # Register extension - class: App\MyExtension tags: - phpstan.typeSpecifier.functionTypeSpecifyingExtension ``` -------------------------------- ### Test Data File Format Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md This example shows the structure of a test data file, including comments for expected errors and type narrowing. ```php undefined_method(); // Type narrowing works if ($x instanceof Foo) { $x->method(); // OK, type is Foo } // Multiple errors $this->undefined_function(); // Error $undefined_var = 5; // Error ``` -------------------------------- ### Setup for RuleTestCase Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Implement the getRule() abstract method to return the Rule instance you want to test. ```php use PHPStan\Testing\RuleTestCase; use PHPStan\Rules\Rule; class MyRuleTest extends RuleTestCase { protected function getRule(): Rule { return new MyRule(); } } ``` -------------------------------- ### Install PHPStan Dependencies Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/README.md Run this command to install project dependencies using Composer. ```bash composer install ``` -------------------------------- ### Verify Zephir Installation Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Confirms that Zephir has been installed correctly and is accessible from your command line. ```bash zephir help ``` -------------------------------- ### MyFunctionRule Implementation Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/03-rules.md An example of a custom rule that checks for the usage of a forbidden function. ```php use PHPStan\Rules\Rule; use PHPStan\Analyser\Scope; use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; final class MyFunctionRule implements Rule { public function getNodeType(): string { return FuncCall::class; } public function processNode(Node $node, Scope $scope): array { // $node is guaranteed to be FuncCall $functionName = $node->name; if ($functionName instanceof Node\Name) { $name = $scope->resolveName($functionName); if ($name === 'dangerous_function') { return [ RuleErrorBuilder::message('Use of dangerous_function is forbidden') ->line($node->getStartLine()) ->build(), ]; } } return []; } } ``` -------------------------------- ### Multi-Level Test Data Examples Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Demonstrates various PHPStan analysis levels with examples of undefined functions, variables, wrong argument types, and missing type declarations. ```php undefined_function(); // Level 1+: undefined variable echo $undefined; // Level 5+: wrong argument type function foo(int $x) {} foo('not an int'); // Error at level 5+ // Level 6+: missing type declaration function bar($x) {} // Error at level 6+ ``` -------------------------------- ### Zephir Configuration Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md This is a sample configuration file for Zephir, specifying compiler settings and dependencies. It is used to configure the Zephir build process for the PHPStan Turbo extension. ```json { "name": "phpstanturbo", "version": "0.1.0", "build": { "force": false, "warnings": true, "debug": false }, "sources": [ "phpstanturbo/" ], "dependencies": { "php": ">=7.0.0" } } ``` -------------------------------- ### Configure Extension Lifecycle Hooks Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Manage extension setup and teardown phases using 'initializers' and 'destructors'. Hooks reference C header files and specify execution logic. ```json { "initializers": { "globals": [{"include": "header.h", "code": "init_globals();"}], "module": [{"include": "header.h", "code": "init_module();"}], "request": [{"include": "header.h", "code": "init_request();"}] }, "destructors": { "request": [{"include": "header.h", "code": "cleanup_request();"}], "post-request": [{"include": "header.h", "code": "cleanup_post_request();"}], "module": [{"include": "header.h", "code": "cleanup_module();"}], "globals": [{"include": "header.h", "code": "cleanup_globals();"}] } } ``` -------------------------------- ### Verify PHP Version Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Checks the installed PHP version. This is a prerequisite for Zephir development. ```bash php -v ``` -------------------------------- ### Example Test Class for Custom Rules Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md A complete example of a test class using RuleTestCase, demonstrating analysis of forbidden and allowed functions. ```php use PHPStan\Testing\RuleTestCase; use PHPStan\Rules\Rule; use App\Rules\MyCustomRule; class MyCustomRuleTest extends RuleTestCase { protected function getRule(): Rule { return new MyCustomRule( forbiddenFunctions: ['eval', 'assert'], ); } public function testForbiddenFunctions(): void { $this->analyse( [__DIR__ . '/data/forbidden-functions.php'], [ ['Call to forbidden function eval', 5], ['Call to forbidden function assert', 8], ] ); } public function testAllowedFunctions(): void { // This should pass with no expected errors $this->analyse( [__DIR__ . '/data/allowed-functions.php'], [] ); } } ``` -------------------------------- ### Install Zephir Dependencies on Ubuntu/Debian Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Installs necessary packages for Zephir compilation on Ubuntu or Debian-based systems. Ensure you have sudo privileges. ```bash sudo apt-get update sudo apt-get install git gcc make re2c php php-json php-dev libpcre3-dev build-essential ``` -------------------------------- ### Test Data: Allowed Functions Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md A sample PHP file demonstrating the use of functions that are permitted and should not trigger errors. ```php alert(1)'); ``` -------------------------------- ### Run PHPStan with Turbo Extension Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Example command to run PHPStan analysis with the Turbo extension enabled. ```bash bin/phpstan analyse ... ``` -------------------------------- ### Compile PHAR Archive Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/compiler/README.md Run these commands to install dependencies, prepare the build, and compile the PHAR. Remember to revert changes to composer.json and the vendor directory after compilation. ```bash composer install php bin/prepare cd build php ../box/vendor/bin/box compile --no-parallel ``` -------------------------------- ### Analysing PHP Files with Analyser Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/01-analyser.md Example of how to use the Analyser to analyze a list of PHP files and process the results. Requires obtaining the 'analyser' service from a DI container. ```php $analyser = $container->getService('analyser'); // from DI container $files = ['src/MyClass.php', 'tests/MyTest.php']; $result = $analyser->analyse($files); if (count($result->getErrors()) > 0) { foreach ($result->getErrors() as $error) { echo $error->getFile() . ':' . $error->getLine() . ' ' . $error->getMessage(); } } ``` -------------------------------- ### Example Rule Implementation in PHPStan Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/01-analyser.md Demonstrates how to implement a custom rule in PHPStan. Shows how to access node types, scope information, and check for specific contexts like traits or variable types. ```php class MyRule implements Rule { public function getNodeType(): string { return FuncCall::class; } public function processNode(Node $node, Scope $scope): array { // $node is a FuncCall $type = $scope->getType($node->name); // Type of function name if ($scope->isInTrait()) { $trait = $scope->getTraitReflection(); // Analyze trait context } if ($scope->hasVariableType('myVar')->yes()) { $varType = $scope->getVariableType('myVar'); } return []; // errors } } ``` -------------------------------- ### Helper Function assertType() Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Illustrates the usage of the assertType() helper function with various types and expressions. ```php ', 50); assertType('array', ['a' => 1, 'b' => 2]); ``` -------------------------------- ### Zephir Source Code Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md This is a Zephir source code file for the CombinationsHelper. It defines the native implementation of the combinations() method, which is intended to be faster than the pure PHP version. ```zephir namespace PHPStanTurbo; class CombinationsHelper { /** * @param array> $arrays * @return array> */ public static function combinations(array $arrays) { // Implementation details would go here // This is a placeholder for the native C code return []; } } ``` -------------------------------- ### Using ReflectionProvider to Check and Get Class/Function Info Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/04-reflection.md Demonstrates how to use the ReflectionProvider to check for the existence of classes and functions, and retrieve their reflection objects. This is useful for inspecting code structure without execution. ```php $provider = $container->getService(ReflectionProvider::class); if ($provider->hasClass('MyClass')) { $classReflection = $provider->getClass('MyClass'); echo $classReflection->getName(); // 'MyClass' } if ($provider->hasFunction('my_function')) { $funcReflection = $provider->getFunction('my_function'); echo $funcReflection->getName(); // 'my_function' ``` -------------------------------- ### RuleErrorBuilder Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/03-rules.md Demonstrates constructing a detailed error report using the fluent RuleErrorBuilder API. ```php return [ RuleErrorBuilder::message('Method does not exist') ->identifier('phpstan.rules.undefinedMethod') ->tip('Did you mean: methodExists()?') ->line(10) ->file('src/MyClass.php') ->metadata(['method' => 'nonExistentMethod']) ->build(), ]; ``` -------------------------------- ### Reflecting on a Class Method Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/04-reflection.md Demonstrates how to get a method's name, return type, visibility, and parameters from a ClassReflection object. ```php $classRef = $provider->getClass('MyClass'); $method = $classRef->getMethod('myMethod', $scope); echo $method->getName(); // 'myMethod' echo $method->getReturnType()->describe(...); // Return type description echo $method->isPublic() ? 'public' : 'not public'; foreach ($method->getParameters() as $param) { echo $param->getName(); } ``` -------------------------------- ### Compile PHPStan Turbo Extension with Zephir Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/README.md Navigate to the extension directory and use Zephir to generate and compile the extension. Ensure Zephir and its prerequisites are installed. ```bash cd turbo-ext vendor/bin/zephir generate && vendor/bin/zephir compile ``` -------------------------------- ### Defining Stub Files for Third-Party Code Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/05-phpdoc.md This example illustrates how to create a stub file (.phpstub) to override or provide type information for functions and classes from third-party libraries. It shows the syntax for documenting parameters and return types within stub files. ```php // my-stubs/vendor-lib/stubs.phpstub $items */ public function process($items): void {} } ``` -------------------------------- ### Instantiate PhpVersion Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/08-php-version.md Create a PhpVersion object by providing the version ID. For example, 80200 represents PHP 8.2.0. ```php public function __construct( int $versionId // e.g. 80200 for PHP 8.2.0 ) ``` -------------------------------- ### Analyse Method Example for RuleTestCase Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Use the analyse() method to run tests on files and assert expected errors. Expected errors are defined as an array of [message, line] pairs. ```php public function testRule(): void { $this->analyse( [__DIR__ . '/data/test.php'], [ ['Call to undefined method nonExistent', 5], ['Variable $undefined is undefined', 10], ] ); } ``` -------------------------------- ### Error Class getFile() Method Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/01-analyser.md Example of retrieving the file path where an error occurred. ```php echo $error->getFile() . ':' . $error->getLine() . ' ' . $error->getMessage(); ``` -------------------------------- ### Example Test Data File for Rule Analysis Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/03-rules.md This file contains sample PHP code used for testing a rule. It includes lines that are expected to trigger errors or be considered okay by the rule. ```php call_undefined_function(); // Line 3 — error if ($x instanceof Foo) { // Line 5 — okay, checks before using $x->someMethod(); } ``` -------------------------------- ### Reflecting on a Function Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/04-reflection.md Illustrates how to get a function's name and access its parameters, especially for overloaded functions. ```php $funcRef = $provider->getFunction('array_map'); echo $funcRef->getName(); // 'array_map' foreach ($funcRef->getParametersAcceptors() as $acceptor) { // For overloaded functions, there can be multiple signatures } ``` -------------------------------- ### Zephir Arithmetic Operators Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Provides examples of basic arithmetic operations supported in Zephir, including negation, addition, subtraction, multiplication, division, and modulus. ```zephir // Negation: -a // Addition: a + b // Subtraction: a - b // Multiplication: a * b // Division: a / b // Modulus: a % b ``` -------------------------------- ### Exploring ClassReflection Properties and Methods Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/04-reflection.md Shows how to use ClassReflection to get information about a class, including its name, file path, type (class, interface, trait, enum), inheritance, methods, and properties. Requires a scope object for property reflection. ```php $classRef = $provider->getClass('MyClass'); echo $classRef->getName(); // 'MyClass' echo $classRef->getFileName(); // '/path/to/MyClass.php' if ($classRef->isInterface()) { echo "It's an interface"; } foreach ($classRef->getMethods() as $method) { echo $method->getName(); } $prop = $classRef->getProperty('myProperty', $scope); echo $prop->getType(); // Type object ``` -------------------------------- ### Test Data: Forbidden Functions Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md A sample PHP file containing code that uses forbidden functions, demonstrating where errors are expected. ```php analyse( [__DIR__ . '/data/forbidden-functions.php'], [ ['Call to forbidden function eval()', 5], ['Call to forbidden function exec()', 8], ['Call to forbidden function system()', 11], ['Call to forbidden function passthru()', 14], ] ); } public function testAllowsSafeFunctions(): void { $this->analyse( [__DIR__ . '/data/allowed-functions.php'], [] ); } public function testHandlesVariableFunction(): void { $this->analyse( [__DIR__ . '/data/variable-functions.php'], [ // Detects forbidden functions even in variables ['Call to forbidden function eval()', 7], ] ); } } ``` -------------------------------- ### Initialize Zephir Extension Project Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Use the 'zephir init' command to create a new Zephir extension project, optionally specifying the backend. ```bash zephir init namespace [--backend=ZendEngine3] ``` -------------------------------- ### String Manipulation Methods in Zephir Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Provides examples of using built-in string methods for common operations like converting case and getting length. ```zephir string text = "hello world"; let text = text.upper(); // "HELLO WORLD" let len = text.length(); // 11 ``` -------------------------------- ### Generate API Documentation Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Use the 'zephir api' command to generate HTML API documentation for the extension, with options for path, output, URL, and other settings. ```bash zephir api [--path=PATH] [--output=OUTPUT] [--url=URL] [--options=OPTIONS] ``` -------------------------------- ### Local Development Commands Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/apigen/infra/README.md Commands for setting up dependencies, running checks, tests, synthesis, and diffing the CDK application locally. ```sh npm ci npm run check # tsc --noEmit npm test # vitest: 25 redirect-fn tests + 11 stack assertions npm run synth # cdk synth --all npm run diff # cdk diff --all (needs AWS creds for the target account) ``` -------------------------------- ### Create PHP IDE Stub Files Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Use the 'zephir stubs' command to generate PHP stub files for IDE integration, optionally specifying the backend. ```bash zephir stubs [--backend=ZendEngine3] ``` -------------------------------- ### Get Class Metadata Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/09-api-quick-reference.md Use the ReflectionProvider to get class metadata. Check if a class exists using hasClass() and retrieve class information, including methods and properties. ```php use PHPStan\Reflection\ReflectionProvider; $provider = $container->getService(ReflectionProvider::class); if ($provider->hasClass('MyClass')) { $class = $provider->getClass('MyClass'); echo $class->getName(); // 'MyClass' if ($class->hasMethod('myMethod')) { $method = $class->getMethod('myMethod', $scope); echo $method->getReturnType()->describe(...); } if ($class->hasProperty('myProperty')) { $prop = $class->getProperty('myProperty', $scope); echo $prop->getType()->describe(...); } } ``` -------------------------------- ### Custom Rule Configuration with Dependencies Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Illustrates how to configure a custom rule with specific dependencies or settings when extending `RuleTestCase`. ```php class MyRuleTest extends RuleTestCase { protected function getRule(): Rule { // Custom configuration return new MyRule( forbiddenFunctions: ['eval', 'assert'], allowedPatterns: ['/^test_/'], ); } } ``` -------------------------------- ### PHP 7.4 array_filter Signature Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/08-php-version.md Example of the built-in `array_filter` function signature for PHP 7.4. ```php function array_filter(array $array, ?callable $callback = null): array ``` -------------------------------- ### Throwing Basic Exceptions in Zephir Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Demonstrates the basic syntax for throwing a new exception instance with a message. ```zephir throw new \Exception("This is an exception"); ``` -------------------------------- ### Helper Function assertNativeType() Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Demonstrates assertNativeType() to assert the native type of an expression, ignoring PHPDoc annotations. ```php hasFunction('my_function')) { $func = $provider->getFunction('my_function'); foreach ($func->getParameters() as $param) { echo $param->getName(); echo $param->getType()->describe(...); } } ``` -------------------------------- ### IDE Documentation Stub Generation Configuration Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Sets up the generation of documentation stubs for IDE integration. Defines the output path and controls whether stub generation should run automatically after the main generation process. ```json { "stubs": { "path": "ide/%version%/%namespace%/", "stubs-run-after-generate": false } } ``` -------------------------------- ### Type Inference Test Data Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Demonstrates using assertType() in test data files to verify inferred types of variables and expressions. ```php getService('analyser'); $reflectionProvider = $container->getService(ReflectionProvider::class); ``` -------------------------------- ### API Documentation Generation Configuration Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Configures the generation of HTML API documentation. Specifies the output path, which can include version placeholders, and allows customization of the documentation theme and its options. ```json { "api": { "path": "doc/%version%", "theme": { "name": "zephir", "options": { "github": null, "analytics": null, "main_color": "#3E6496" } } } } ``` -------------------------------- ### Traverse and Transform Types with TypeTraverser Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/02-type-system.md Use TypeTraverser::map to recursively apply a transformation to all types within a type structure. This example transforms StringType to ConstantStringType. ```php $transformer = new class implements TypeTraverserCallable { public function __invoke(Type $type): Type { if ($type instanceof StringType) { return new ConstantStringType('transformed'); } return $type; } }; $type = TypeCombinator::union(new StringType(), new IntegerType()); $result = TypeTraverser::map($type, $transformer); // Result is 'transformed-string | int' ``` -------------------------------- ### Using CompositeRule for Multiple Rules Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/10-testing.md Demonstrates how to wrap multiple rules into a `CompositeRule` for simultaneous testing. ```php $rule1 = new Rule1(); $rule2 = new Rule2(); $composite = new CompositeRule([$rule1, $rule2]); $this->analyse( [__DIR__ . '/data/test.php'], [], // expected errors [$composite], // additional rules ); ``` -------------------------------- ### UnusedMethodRule Processing CollectedDataNode Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/06-virtual-nodes.md An example rule that listens for CollectedDataNode to process aggregated data from all files. It demonstrates accessing and utilizing data collected across the project. ```php final class UnusedMethodRule implements Rule { public function getNodeType(): string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope): array { $data = $node->getData(); $unusedMethods = $data['unused_methods'] ?? []; // Process aggregated data... return []; } } ``` -------------------------------- ### CDK App Entrypoint Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/apigen/infra/CLAUDE.md The CDK app entrypoint `bin/infra.ts` wires together the different stacks and defines constants for account, region, and repository. It reads the `productionAlias` context flag to determine the deployment configuration. ```typescript #!/usr/bin/env node import 'source-map-support/register'; import * as cdk from 'aws-cdk-lib'; import { InfraStack } from '../lib/apiref-stack'; import { OidcRolesStack } from '../lib/oidc-roles-stack'; const app = new cdk.App(); const account = process.env.CDK_DEFAULT_ACCOUNT; const region = process.env.CDK_DEFAULT_REGION; const repo = 'phpstan/apiref.phpstan.org'; const zone = 'phpstan.org'; const productionAlias = app.node.tryGetContext('productionAlias') ?? false; new OidcRolesStack(app, 'OidcRolesStack', { account, region, repo, }); new InfraStack(app, 'InfraStack', { account, region, repo, zone, productionAlias, }); ``` -------------------------------- ### CI Test Job Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/apigen/infra/CLAUDE.md The 'test' job in the CI workflow installs dependencies, checks TypeScript, runs tests, and synthesizes the CDK stack. It does not require AWS credentials. ```sh npm ci && npm run check && npm test && npx cdk synth --all ``` -------------------------------- ### Specifying Stub Files Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/07-dependency-injection.md Provide type information for third-party packages by listing stub files in the 'stubFiles' parameter. These files override reflection for type information. ```neon parameters: stubFiles: - vendor/external-lib/stubs.phpstub ``` -------------------------------- ### Get Class Names from Object Type Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/02-type-system.md Retrieve the class names directly represented by a type. For `ObjectType`, it returns the single class name; for unions of objects, it returns all. ```php $objectType = new ObjectType('MyClass'); $classNames = $objectType->getObjectClassNames(); // ['MyClass'] ``` -------------------------------- ### List All Zephir Commands Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Use the 'zephir list' command to display all available commands in the Zephir CLI. ```bash zephir list ``` -------------------------------- ### Zephir Method Modifiers: static, final, deprecated Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Shows examples of `static` methods for class-level operations, `final` methods to prevent overriding, and `deprecated` methods to mark them as obsolete. ```zephir public static function combinations(array arrays) -> array { // static method } ``` ```zephir final public function cannotOverride() -> void { } ``` ```zephir deprecated public function oldMethod() -> void { } ``` -------------------------------- ### Zephir Dynamic Function Invocation Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Demonstrates how to invoke functions stored in variables using the `{callback}(argument)` syntax. This is useful for passing functions as arguments or for dynamic dispatch. ```zephir public function process(var callback, string text) -> string { return {callback}(text); } ``` -------------------------------- ### Generate C Code from Zephir Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Use the 'zephir generate' command to convert Zephir code into C source files, optionally specifying the backend. ```bash zephir generate [--backend=ZendEngine3] ``` -------------------------------- ### Get Method/Property from Scope Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/09-api-quick-reference.md Retrieve method or property reflections directly from the current scope using $scope->getMethodReflection() or $scope->getInstancePropertyReflection(). This is useful when the class context is already established. ```php $classRef = $scope->getClassReflection(); if ($classRef !== null) { $method = $scope->getMethodReflection($type, 'myMethod'); $prop = $scope->getInstancePropertyReflection($type, 'myProp'); } ``` -------------------------------- ### Enable Zephir Extension in php.ini Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Instructions to add the compiled Zephir extension to the PHP configuration file. ```ini extension=/absolute/path/to/phpstan-src/turbo-ext/ext/modules/phpstanturbo.so ``` -------------------------------- ### Enable Turbo Extension if Loaded Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md This code snippet demonstrates the initialization flow for enabling the Turbo extension. It checks if the 'phpstanturbo' extension is loaded and, if so, uses class aliasing to replace the default PHP implementation with the native one. ```php bin/phpstan (line 21) ↓ TurboExtensionEnabler::enableIfLoaded() ↓ extension_loaded('phpstanturbo') → true? ↓ YES class_alias('PHPStanTurbo\CombinationsHelper', 'PHPStan\Internal\CombinationsHelper') ↓ All subsequent calls to CombinationsHelper::combinations() use native code ``` -------------------------------- ### Get Class String Type Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/02-type-system.md Obtain the `class-string` type for a given object type T. This is useful when you need to represent the type of a class name string that refers to a specific class. ```php $objectType = new ObjectType('MyClass'); $classStringType = $objectType->getClassStringType(); // Type is 'class-string' ``` -------------------------------- ### Ignoring Errors in Configuration Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/03-rules.md Shows how to ignore specific errors using patterns or file paths in the phpstan.neon configuration file. ```neon parameters: ignoreErrors: - '#Method does not exist#' - file: src/Legacy.php message: '#.*#' ``` -------------------------------- ### Get Return Type Directly from Reflection Object Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/UPGRADING.md When analyzing function or method bodies, retrieve the return type directly from the reflection object using getReturnType() instead of relying on ParametersAcceptorSelector::selectSingle(). ```php $function = $node->getFunctionReflection(); $returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType(); ``` ```php $returnType = $node->getFunctionReflection()->getReturnType(); ``` -------------------------------- ### Configure Optimizers in config.json Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Register custom optimizer directories and extra source files in the project's configuration file. ```json { "optimizer-dirs": ["optimizers"], "extra-sources": ["utils/pi.c"] } ``` -------------------------------- ### Type Narrowing Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/00-index.md Demonstrates type narrowing within a conditional block. Inside the `if ($x instanceof Foo)` block, the type of `$x` is narrowed to `Foo`. Extensions can provide custom narrowing logic. ```php if ($x instanceof Foo) { // Inside: $x is known to be Foo $scope->filterByTruthyValue($cond); } ``` -------------------------------- ### Run PHPStan Tests Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/README.md Execute this command to run the test suite for PHPStan. ```bash make tests ``` -------------------------------- ### Implementing a Custom PHPDoc Type Node Resolver Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/05-phpdoc.md This example demonstrates how to create a custom TypeNodeResolverExtension to support new PHPDoc type syntax. It shows how to resolve a custom type like 'positive-int' into a PHPStan Type object. ```php use PHPStan\PhpDoc\TypeNodeResolverExtension; use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode; final class CustomTypeNodeResolverExtension implements TypeNodeResolverExtension { public function resolve(TypeNode $typeNode, Scope $scope): ?Type { if ($typeNode instanceof IdentifierTypeNode && $typeNode->name === 'positive-int') { return new IntegerRangeType(1, null); // 1 to infinity } return null; } } ``` -------------------------------- ### Get Type of Expression in Scope Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/09-api-quick-reference.md Use $scope->getType($node) for PHPDoc-aware types or $scope->getNativeType($node) for native types. Check type properties like .yes(), .maybe(), or .no() to determine type certainty. ```php $type = $scope->getType($node); // PHPDoc-aware $nativeType = $scope->getNativeType($node); // Native types only // Check if type matches if ($type->isString()->yes()) { // Definitely a string } if ($type->isString()->maybe()) { // Possibly a string } if ($type->isString()->no()) { // Definitely not a string } ``` -------------------------------- ### Set Miscellaneous Extension Options Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/turbo-ext/CLAUDE.md Configure general extension behavior like output suppression ('silent') or detailed error messages ('verbose'). Custom directories for optimizers and prototypes can also be specified. ```json { "silent": false, "verbose": true, "optimizer-dirs": ["optimizers"], "prototype-dir": "prototypes" } ``` -------------------------------- ### Create Object Type Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/02-type-system.md Represents a specific PHP class. Provide the class name as a string. ```php new ObjectType('MyClass'); new ObjectType('stdClass'); ``` -------------------------------- ### Generic Types and Templates Example Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/00-index.md Shows how PHPStan supports generic types and template parameters using PHPDoc annotations. The `@template T` and `@param T[] $items` annotations define a generic type `T` for the function's parameter and return type. ```php /** * @template T * @param T[] $items * @return T */ function first(array $items): mixed {} ``` -------------------------------- ### Verbosity Levels for Type Description Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/02-type-system.md Demonstrates the different verbosity levels available for describing types using the VerbosityLevel class. ```php public static function value(): self public static function lines(): self public static function full(): self ``` -------------------------------- ### Create a Custom Rule Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/09-api-quick-reference.md Implement the Rule interface to define custom rules. Specify the node type to listen for and implement the processNode method to analyze the node and return errors. ```php use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Analyser\Scope; use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; final class MyRule implements Rule { public function getNodeType(): string { return FuncCall::class; // Listen for function calls } public function processNode(Node $node, Scope $scope): array { // $node is a FuncCall $functionName = $node->name; if ($functionName instanceof Node\Name) { $name = $scope->resolveName($functionName); if ($name === 'dangerous_function') { return [ RuleErrorBuilder::message('Forbidden function') ->identifier('app.rules.forbiddenFunction') ->line($node->getStartLine()) ->build(), ]; } } return []; } } ``` -------------------------------- ### Reflecting on a Class Property Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/04-reflection.md Shows how to access a property's name, type, and visibility using PropertyReflection. ```php $classRef = $provider->getClass('MyClass'); $prop = $classRef->getProperty('myProp', $scope); echo $prop->getName(); // 'myProp' echo $prop->getType()->describe(...); // Property type echo $prop->isPublic() ? 'public' : 'not public'; ``` -------------------------------- ### UnusedMethodRule Processing Collected Data Source: https://github.com/phpstan/phpstan-src/blob/2.2.x/_autodocs/03-rules.md Implements the `Rule` interface to process data aggregated by collectors. This rule listens for `CollectedDataNode` and accesses the collected data to identify unused methods. It serves as an example of how to consume data gathered by a collector like `UnusedMethodCollector`. ```php use PHPStan\Rules\Rule; use PHPStan\Node\CollectedDataNode; use PhpParser\Node; final class UnusedMethodRule implements Rule { public function getNodeType(): string { return CollectedDataNode::class; } public function processNode(Node $node, Scope $scope): array { // $node->getData() contains aggregated collector results $data = $node->getData(); $unusedMethods = $data['unused_methods'] ?? []; // Check which methods are actually used... // Report unused ones return []; } } ```