|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance for AI assistants working with the phpstan/phpstan-phpunit repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a PHPStan extension that provides advanced static analysis support for PHPUnit test suites. It offers: |
| 8 | + |
| 9 | +- **Type extensions**: Correct return types for `createMock()`, `getMockForAbstractClass()`, `getMockFromWsdl()`, `MockBuilder::getMock()`, etc., returning intersection types (e.g., `MockObject&Foo`) so both mock and original class methods are available. |
| 10 | +- **PHPDoc interpretation**: Converts `Foo|MockObject` union types in phpDocs to intersection types. |
| 11 | +- **Assert type narrowing**: Specifies types of expressions passed to `assertInstanceOf`, `assertTrue`, `assertInternalType`, etc. |
| 12 | +- **Early terminating methods**: Defines `fail()`, `markTestIncomplete()`, `markTestSkipped()` as early terminating to prevent false positive undefined variable errors. |
| 13 | +- **Strict rules** (in `rules.neon`): Checks for better assertion usage (e.g., prefer `assertTrue()` over `assertSame(true, ...)`), `@covers` validation, data provider declaration checks, and more. |
| 14 | + |
| 15 | +## PHP Version Requirements |
| 16 | + |
| 17 | +This repository supports **PHP 7.4+**. Do not use language features unavailable in PHP 7.4 (e.g., enums, fibers, readonly properties, intersection types in code — though they appear in stubs/phpDocs). |
| 18 | + |
| 19 | +## PHPUnit Compatibility |
| 20 | + |
| 21 | +The extension supports multiple PHPUnit versions: **^9.5, ^10.5, ^11.5, ^12.0**. Code must be compatible across all these versions. The CI matrix tests all combinations. |
| 22 | + |
| 23 | +## Common Commands |
| 24 | + |
| 25 | +```bash |
| 26 | +# Install dependencies |
| 27 | +composer install |
| 28 | + |
| 29 | +# Run all checks (lint, coding standard, tests, PHPStan) |
| 30 | +make check |
| 31 | + |
| 32 | +# Run tests only |
| 33 | +make tests |
| 34 | + |
| 35 | +# Run PHPStan analysis |
| 36 | +make phpstan |
| 37 | + |
| 38 | +# Run linting |
| 39 | +make lint |
| 40 | + |
| 41 | +# Install coding standard tool (first time only) |
| 42 | +make cs-install |
| 43 | + |
| 44 | +# Run coding standard checks |
| 45 | +make cs |
| 46 | + |
| 47 | +# Fix coding standard issues |
| 48 | +make cs-fix |
| 49 | + |
| 50 | +# Generate PHPStan baseline |
| 51 | +make phpstan-generate-baseline |
| 52 | +``` |
| 53 | + |
| 54 | +## Project Structure |
| 55 | + |
| 56 | +``` |
| 57 | +src/ |
| 58 | +├── PhpDoc/PHPUnit/ # PHPDoc type resolution extensions |
| 59 | +├── Rules/PHPUnit/ # Static analysis rules for PHPUnit |
| 60 | +└── Type/PHPUnit/ # Type-specifying and dynamic return type extensions |
| 61 | + └── Assert/ # Assert method type narrowing |
| 62 | +
|
| 63 | +tests/ |
| 64 | +├── Rules/PHPUnit/ # Rule tests and test data (data/ subdirectory) |
| 65 | +├── Rules/Methods/ # Method call rule tests |
| 66 | +├── Type/PHPUnit/ # Type extension tests and test data (data/ subdirectory) |
| 67 | +└── bootstrap.php # Test bootstrap (loads Composer autoloader) |
| 68 | +
|
| 69 | +stubs/ # PHPUnit stub files for type definitions |
| 70 | +``` |
| 71 | + |
| 72 | +## Configuration Files |
| 73 | + |
| 74 | +- **`extension.neon`** — Main extension configuration registered via phpstan/extension-installer. Defines parameters, services (type extensions, helpers), and stub files. |
| 75 | +- **`rules.neon`** — Strict PHPUnit-specific rules. Loaded separately; users opt in by including this file. |
| 76 | +- **`phpstan.neon`** — Self-analysis configuration (level 8, with strict rules and deprecation rules). |
| 77 | +- **`phpstan-baseline.neon`** — Baseline for known PHPStan errors in the project itself. |
| 78 | +- **`phpunit.xml`** — PHPUnit configuration for running the test suite. |
| 79 | + |
| 80 | +## Architecture |
| 81 | + |
| 82 | +### Type Extensions (`src/Type/PHPUnit/`) |
| 83 | + |
| 84 | +These implement PHPStan interfaces to provide correct types: |
| 85 | + |
| 86 | +- `MockBuilderDynamicReturnTypeExtension` — Preserves `MockBuilder<T>` generic type through chained method calls. |
| 87 | +- `MockForIntersectionDynamicReturnTypeExtension` — Returns `MockObject&T` intersection types for mock creation methods. |
| 88 | +- `Assert/AssertMethodTypeSpecifyingExtension` (and function/static variants) — Narrows types after assert calls (e.g., after `assertInstanceOf(Foo::class, $x)`, `$x` is known to be `Foo`). |
| 89 | + |
| 90 | +### Rules (`src/Rules/PHPUnit/`) |
| 91 | + |
| 92 | +These implement `PHPStan\Rules\Rule<T>` to report errors: |
| 93 | + |
| 94 | +- `AssertSameBooleanExpectedRule`, `AssertSameNullExpectedRule` — Suggest specific assertions over generic `assertSame`. |
| 95 | +- `AssertSameWithCountRule` — Suggest `assertCount()` over `assertSame(count(...), ...)`. |
| 96 | +- `ClassCoversExistsRule`, `ClassMethodCoversExistsRule` — Validate `@covers` annotations reference existing code. |
| 97 | +- `DataProviderDeclarationRule`, `DataProviderDataRule` — Validate data provider declarations and data. |
| 98 | +- `MockMethodCallRule` — Check mock method calls are valid. |
| 99 | +- `ShouldCallParentMethodsRule` — Verify `setUp()`/`tearDown()` call parent methods. |
| 100 | + |
| 101 | +### Stubs (`stubs/`) |
| 102 | + |
| 103 | +PHPStan stub files that provide generic type information for PHPUnit classes (e.g., `TestCase::createMock<T>()` returns `MockObject&T`). |
| 104 | + |
| 105 | +## Writing Tests |
| 106 | + |
| 107 | +- **Rule tests** extend `PHPStan\Testing\RuleTestCase<T>`. They implement `getRule()` and call `$this->analyse()` with a test data file path and expected errors array. Test data files live in `tests/Rules/PHPUnit/data/`. |
| 108 | +- **Type tests** extend `PHPStan\Testing\TypeInferenceTestCase`. They use `@dataProvider` with `self::gatherAssertTypes()` or `self::dataFileAsserts()` and call `$this->assertFileAsserts()`. Test data files live in `tests/Type/PHPUnit/data/`. |
| 109 | +- Both types override `getAdditionalConfigFiles()` to return the path to `extension.neon` (and sometimes `rules.neon`). |
| 110 | + |
| 111 | +## Coding Standards |
| 112 | + |
| 113 | +- Uses tabs for indentation (PHP, XML, NEON files). |
| 114 | +- Uses spaces for YAML files (indent size 2). |
| 115 | +- Coding standard is enforced via [phpstan/build-cs](https://github.com/phpstan/build-cs) (PHPCS with a custom standard). |
| 116 | +- Run `make cs` to check, `make cs-fix` to auto-fix. |
| 117 | + |
| 118 | +## CI Pipeline |
| 119 | + |
| 120 | +The GitHub Actions workflow (`.github/workflows/build.yml`) runs on the `2.0.x` branch and pull requests: |
| 121 | + |
| 122 | +1. **Lint** — PHP syntax check across PHP 7.4–8.5. |
| 123 | +2. **Coding Standard** — PHPCS checks using build-cs. |
| 124 | +3. **Tests** — PHPUnit across PHP 7.4–8.5 × lowest/highest dependencies × PHPUnit 9.5/10.5/11.5/12.0 (with version-appropriate exclusions). |
| 125 | +4. **Static Analysis** — PHPStan self-analysis with the same matrix. |
| 126 | +5. **Mutation Testing** — Infection framework on PHP 8.2–8.5, requires 100% MSI on changed lines. |
| 127 | + |
| 128 | +## Development Branch |
| 129 | + |
| 130 | +The main development branch is `2.0.x`. |
0 commit comments