Skip to content

Commit f02dc0e

Browse files
phpstan-botclaude
authored andcommitted
Add CLAUDE.md with project guidelines for AI agents
Provides comprehensive documentation covering project overview, repository structure, PHP 7.4+ version requirements, multi-version Doctrine support, development commands, testing, coding standards, CI pipeline, and architecture notes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 734ef36 commit f02dc0e

1 file changed

Lines changed: 172 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance for AI agents working on the phpstan/phpstan-doctrine repository.
4+
5+
## Project Overview
6+
7+
phpstan-doctrine is a PHPStan extension that provides static analysis capabilities for Doctrine ORM, DBAL, and ODM. It adds type inference, DQL validation, QueryBuilder analysis, and custom rules that detect Doctrine-specific bugs at analysis time without running the application.
8+
9+
Key features:
10+
- DQL query validation (parse errors, unknown entities, unknown fields)
11+
- QueryBuilder type inference and validation
12+
- Magic repository method recognition (`findBy*`, `findOneBy*`, `countBy*`)
13+
- Entity column/relation type checking against property types
14+
- Return type inference for `EntityManager::getRepository()`, `find()`, `getReference()`
15+
- Query result type inference for `getResult()`, `getSingleResult()`, etc.
16+
- Doctrine ODM support
17+
- Database driver-aware type resolution for expressions like `SUM()`, `AVG()`
18+
19+
## Repository Structure
20+
21+
```
22+
src/ # Extension source code (PSR-4: PHPStan\)
23+
├── Classes/ # Forbidden class name extensions (proxy detection)
24+
├── Doctrine/ # Core Doctrine integration (driver detection, metadata loading)
25+
├── PhpDoc/ # PHPDoc type node resolver extensions
26+
├── Reflection/ # Class reflection extensions (repository methods, selectable)
27+
├── Rules/ # Custom PHPStan rules (entity validation, DQL checks)
28+
│ ├── Doctrine/ORM/ # ORM-specific rules
29+
│ └── Gedmo/ # Gedmo doctrine-extensions support
30+
├── Stubs/ # Stub file loader
31+
└── Type/ # Type inference extensions
32+
└── Doctrine/
33+
├── Collection/ # Collection type narrowing
34+
├── DBAL/ # DBAL QueryBuilder and Result types
35+
├── Descriptors/# Doctrine type → PHPStan type mappings (28 descriptors)
36+
├── Query/ # DQL Query result type walker and inference
37+
└── QueryBuilder/ # ORM QueryBuilder type tracking
38+
tests/ # Test suite
39+
├── DoctrineIntegration/# Integration tests (ORM, ODM, Persistence)
40+
├── Platform/ # Database platform tests (MySQL, PostgreSQL, SQLite)
41+
├── Reflection/ # Reflection extension tests
42+
├── Rules/ # Rule tests (entity validation, dead code, properties)
43+
└── Type/ # Type inference tests
44+
stubs/ # PHPStan stub files for Doctrine classes
45+
├── Collections/ # Collection and Selectable stubs
46+
├── DBAL/ # DBAL types, cache, exception stubs
47+
├── ORM/ # ORM Query, QueryBuilder, Mapping stubs
48+
├── Persistence/ # Persistence layer stubs
49+
└── runtime/Enum/ # PHP 8.1 enum polyfill stubs
50+
compatibility/ # Compatibility layer for multiple Doctrine versions
51+
├── patches/ # Composer patches for ORM v3 attribute support
52+
├── AnnotationDriver.php # ORM v2 fallback
53+
├── ArrayType.php # DBAL v3 fallback
54+
└── orm-3-baseline.php # Dynamic baseline selection by ORM version
55+
```
56+
57+
## PHP Version Support
58+
59+
This repository supports **PHP 7.4+**. All source code in `src/` and `tests/` must be compatible with PHP 7.4. Do not use language features from PHP 8.0+ (named arguments, union types in signatures, match expressions, etc.) in the main source code.
60+
61+
Some test data files under `tests/*/data-php-*` and `tests/*/data-attributes` target specific PHP versions and are excluded from lint/analysis on older versions.
62+
63+
## Multi-Version Doctrine Support
64+
65+
The extension supports multiple major versions of Doctrine libraries simultaneously:
66+
- **Doctrine ORM**: 2.x and 3.x
67+
- **Doctrine DBAL**: 3.x and 4.x
68+
- **Doctrine ODM**: 2.4+
69+
- **Doctrine Persistence**: 2.x and 3.x
70+
71+
This is achieved through:
72+
- The `compatibility/` directory providing fallback classes for missing APIs
73+
- Composer patches in `compatibility/patches/` for ORM v3 attribute support
74+
- Version-specific PHPStan baselines (`phpstan-baseline-orm-2.neon`, `phpstan-baseline-orm-3.neon`, `phpstan-baseline-dbal-3.neon`, `phpstan-baseline-dbal-4.neon`)
75+
- Dynamic baseline selection in `compatibility/orm-3-baseline.php`
76+
- `method_exists()` checks in source code for version-dependent API calls
77+
- CI matrix testing across version combinations
78+
79+
## Configuration Files
80+
81+
- **`extension.neon`** — Main extension services: type descriptors, dynamic return type extensions, reflection extensions, PHPDoc resolvers. Loaded automatically via phpstan/extension-installer.
82+
- **`rules.neon`** — Custom validation rules (DQL, entity columns, relations, mapping). Optionally included by users who provide an `objectManagerLoader`.
83+
- **`phpstan.neon`** — Self-analysis configuration (level 8, includes all baselines and strict rules).
84+
- **`phpunit.xml`** — Test configuration. The `platform` test group is excluded by default and runs separately in CI.
85+
86+
## Development Commands
87+
88+
All commands are defined in the `Makefile`:
89+
90+
```bash
91+
make check # Run all checks (lint, cs, tests, phpstan)
92+
make tests # Run PHPUnit tests
93+
make lint # Run parallel-lint on src/ and tests/
94+
make cs # Run coding standard checks (requires make cs-install first)
95+
make cs-fix # Auto-fix coding standard violations
96+
make cs-install # Clone phpstan/build-cs repository
97+
make phpstan # Run PHPStan self-analysis
98+
make phpstan-generate-baseline # Regenerate the PHPStan baseline
99+
```
100+
101+
## Running Tests
102+
103+
```bash
104+
composer install
105+
make tests # Runs: php vendor/bin/phpunit
106+
```
107+
108+
Platform tests (requiring database containers) are in the `platform` group and excluded by default. They run in CI via `.github/workflows/platform-test.yml` with MySQL and PostgreSQL services.
109+
110+
## Coding Standards
111+
112+
The project uses the [phpstan/build-cs](https://github.com/phpstan/build-cs) coding standard (branch `2.x`):
113+
114+
```bash
115+
make cs-install # Clone the build-cs repo
116+
make cs # Check coding standards
117+
make cs-fix # Auto-fix violations
118+
```
119+
120+
Key style rules:
121+
- Tab indentation for PHP, XML, and NEON files
122+
- Space indentation (2 spaces) for YAML files
123+
- LF line endings, UTF-8 encoding
124+
- Trailing whitespace trimmed, final newline required
125+
126+
## CI Pipeline
127+
128+
The CI runs on every pull request and push to `2.0.x`:
129+
130+
1. **Lint**`parallel-lint` on PHP 7.4–8.4
131+
2. **Coding Standard** — phpcs with build-cs rules
132+
3. **Tests** — PHPUnit on PHP 7.4–8.4, both lowest and highest dependencies, plus a special matrix entry with ORM 3.x + DBAL 4.x
133+
4. **Static Analysis** — PHPStan at level 8 on PHP 7.4–8.4, plus ORM 3.x + DBAL 4.x variant
134+
5. **Mutation Testing** — Infection on PHP 8.2–8.4, requires 100% MSI on changed lines
135+
6. **Platform Tests** — PHPUnit `platform` group against real MySQL and PostgreSQL databases
136+
137+
## Architecture Notes
138+
139+
### Type Descriptors
140+
141+
Type descriptors (`src/Type/Doctrine/Descriptors/`) map Doctrine DBAL column types to PHPStan types. Each descriptor implements `DoctrineTypeDescriptor` with:
142+
- `getType()` — Returns the Doctrine type class name
143+
- `getWritableToPropertyType()` — The PHP type Doctrine writes to entity properties
144+
- `getWritableToDatabaseType()` — The PHP type that can be written to the database
145+
146+
Descriptors are registered as services tagged with `phpstan.doctrine.typeDescriptor` in `extension.neon`.
147+
148+
### Query Result Type Walker
149+
150+
`QueryResultTypeWalker` (`src/Type/Doctrine/Query/`) walks the DQL AST to infer result types. It handles SELECT expressions, JOINs, aggregations, NEW expressions, and INDEX BY. It is driver-aware — result types for expressions like `SUM()` or `AVG()` depend on the database driver (MySQL vs PostgreSQL vs SQLite).
151+
152+
### QueryBuilder Type Tracking
153+
154+
The extension tracks QueryBuilder method calls through `QueryBuilderType`, carrying DQL parts as PHPStan type metadata. When `getQuery()` is called, it reconstructs the DQL and runs it through the type walker.
155+
156+
### Custom Rules
157+
158+
Rules in `src/Rules/Doctrine/ORM/` validate entity mappings at analysis time:
159+
- `EntityColumnRule` — Column types match property types
160+
- `EntityRelationRule` — Relation configurations are valid
161+
- `EntityNotFinalRule` — Entities aren't `final` (breaks proxy generation)
162+
- `DqlRule` / `QueryBuilderDqlRule` — DQL syntax and semantic validation
163+
- `EntityMappingExceptionRule` — Catches mapping configuration errors
164+
165+
### Stubs
166+
167+
Stub files in `stubs/` provide PHPStan with type information for Doctrine classes, adding generics (`@template T of object`) and narrowed return types that the original Doctrine source doesn't express. These are loaded via `StubFilesExtensionLoader`.
168+
169+
## Branching
170+
171+
- **`2.0.x`** — Development branch (default for PRs)
172+
- **`main`** — Main/release branch

0 commit comments

Comments
 (0)