-
Notifications
You must be signed in to change notification settings - Fork 0
Php parser adapter #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4c9f2e8
d1d03a5
4aee07b
ca6315c
e8157e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| # AGENTS.md | ||
|
|
||
| This file provides guidance for agentic coding assistants operating in this repository. | ||
| Follow these instructions when reading, modifying, or adding code. | ||
|
|
||
| --- | ||
|
|
||
| ## Project Overview | ||
|
|
||
| - PHP 8.2+ CLI application built with **Laravel Zero** | ||
| - Purpose: analyze PHP class dependencies, coupling, instability, and cycles | ||
| - Architecture: layered (Application / Domain / Infrastructure) | ||
| - Testing: **Pest** (on top of PHPUnit) | ||
| - Formatting: **Laravel Pint** | ||
|
|
||
| --- | ||
|
|
||
| ## Environment & Prerequisites | ||
|
|
||
| - PHP >= 8.2 | ||
| - Composer | ||
| - Xdebug (optional, for coverage) | ||
|
|
||
| Install dependencies: | ||
|
|
||
| - `composer install` | ||
|
|
||
| --- | ||
|
|
||
| ## Build, Lint, and Test Commands | ||
|
|
||
| ### Running the Application | ||
|
|
||
| - Main binary: `class-dependencies-analyzer` | ||
| - Example: | ||
| - `php class-dependencies-analyzer analyze:class app` | ||
|
|
||
| ### Tests (Pest) | ||
|
|
||
| - Run full test suite: | ||
| - `composer test` | ||
| - `vendor/bin/pest -p` | ||
|
|
||
| - Run a single test file: | ||
| - `vendor/bin/pest tests/Unit/FooTest.php` | ||
|
|
||
| - Run a single test by name: | ||
| - `vendor/bin/pest --filter="it does something"` | ||
|
|
||
| - Run a specific testsuite: | ||
| - `vendor/bin/pest --testsuite=Unit` | ||
|
|
||
| - Parallel execution is enabled by default via `-p` | ||
|
|
||
| ### Coverage | ||
|
|
||
| - Run tests with coverage: | ||
| - `composer coverage` | ||
|
|
||
| ### Linting / Formatting | ||
|
|
||
| - Format code using Pint: | ||
| - `vendor/bin/pint` | ||
|
|
||
| - Check formatting without writing: | ||
| - `vendor/bin/pint --test` | ||
|
|
||
| ### Healthcheck Scripts | ||
|
|
||
| Defined in `composer.json`: | ||
|
|
||
| - `composer healthcheck` | ||
| - Includes multiple analyzer self-checks and a test run | ||
|
|
||
| --- | ||
|
|
||
| ## Code Style Guidelines | ||
|
|
||
| ### General | ||
|
|
||
| - Follow **PSR-12** and Laravel conventions | ||
| - Prefer clarity over cleverness | ||
| - Keep classes small and single-purpose | ||
|
|
||
| ### Imports | ||
|
|
||
| - Use fully-qualified imports (`use ...`) at top of file | ||
| - One import per line | ||
| - Remove unused imports | ||
| - Group imports logically (PHP, App, Vendor) | ||
|
|
||
| ### Formatting | ||
|
|
||
| - Enforced by **Laravel Pint** | ||
| - 4 spaces indentation | ||
| - One class per file | ||
| - Trailing commas in multiline argument lists | ||
|
|
||
| ### Naming Conventions | ||
|
|
||
| - Classes: `StudlyCase` | ||
| - Methods: `camelCase` | ||
| - Variables: `camelCase` | ||
| - Constants: `SCREAMING_SNAKE_CASE` | ||
| - Interfaces: descriptive nouns (no `Interface` suffix preferred) | ||
|
|
||
| ### Types & Signatures | ||
|
|
||
| - Always use scalar and object type hints | ||
| - Always declare return types | ||
| - Prefer `readonly` and promoted constructor properties where applicable | ||
| - Avoid mixed types unless strictly necessary | ||
|
|
||
| ### Error Handling | ||
|
|
||
| - Use exceptions for exceptional states | ||
| - Catch `Throwable` only at application boundaries | ||
| - Domain logic should not swallow exceptions | ||
| - Present errors via presenters or CLI output, not `echo` | ||
|
|
||
| ### Null & Defensive Code | ||
|
|
||
| - Prefer explicit null checks | ||
| - Avoid deeply nested conditionals | ||
| - Fail fast when input is invalid | ||
|
|
||
| --- | ||
|
|
||
| ## Architecture Rules | ||
|
|
||
| ### Application Layer | ||
|
|
||
| - Orchestrates use cases | ||
| - Depends on Domain abstractions (ports) | ||
| - No infrastructure details | ||
|
|
||
| ### Domain Layer | ||
|
|
||
| - Contains core business logic | ||
| - Framework-agnostic | ||
| - No IO, no framework dependencies | ||
|
|
||
| ### Infrastructure Layer | ||
|
|
||
| - Implements ports (filesystem, CLI, adapters) | ||
| - Can depend on frameworks and vendor libraries | ||
|
|
||
| ### Dependency Direction | ||
|
|
||
| - Infrastructure → Application → Domain | ||
| - Never the reverse | ||
|
|
||
| --- | ||
|
|
||
| ## Testing Guidelines | ||
|
|
||
| - Prefer **Unit tests** for domain logic | ||
| - Use **Feature tests** for CLI commands and integration | ||
| - Tests should be deterministic and isolated | ||
| - Use Mockery for mocking ports | ||
|
|
||
| --- | ||
|
|
||
| ## Filesystem & Safety Rules | ||
|
|
||
| - Do not modify files in `vendor/` | ||
| - Do not commit generated reports or artifacts | ||
| - Avoid touching unrelated files | ||
|
|
||
| --- | ||
|
|
||
| ## Git & Commits | ||
|
|
||
| - Do not commit unless explicitly requested | ||
| - Follow existing commit message style | ||
| - Never rewrite history without permission | ||
|
|
||
| --- | ||
|
|
||
| ## Agent Behavior Expectations | ||
|
|
||
| - Respect this file for all edits in this repository | ||
| - Keep changes minimal and focused | ||
| - Ask before making large refactors | ||
| - Do not introduce new tools or dependencies without approval | ||
|
|
||
| --- | ||
|
|
||
| End of AGENTS.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| <?php | ||
|
|
||
| namespace App\Infrastructure\Analyze\Adapters\PhpParser; | ||
|
|
||
| use App\Infrastructure\Analyze\Ports\ClassAnalysis; | ||
|
|
||
| final class AstClassAnalysis implements ClassAnalysis | ||
| { | ||
| public function __construct( | ||
| private readonly string $fqcn, | ||
| private readonly array $dependencies, | ||
| private readonly bool $isInterface = false, | ||
| private readonly bool $isAbstract = false, | ||
| ) {} | ||
|
|
||
| public function fqcn(): string | ||
| { | ||
| return $this->fqcn; | ||
| } | ||
|
|
||
| public function dependencies(): array | ||
| { | ||
| return $this->dependencies; | ||
| } | ||
|
|
||
| public function isInterface(): bool | ||
| { | ||
| return $this->isInterface; | ||
| } | ||
|
|
||
| public function isAbstract(): bool | ||
| { | ||
| return $this->isAbstract; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| <?php | ||
|
|
||
| namespace App\Infrastructure\Analyze\Adapters\PhpParser; | ||
|
|
||
| use PhpParser\Node; | ||
| use PhpParser\NodeVisitorAbstract; | ||
| use PhpParser\Node\Stmt\Class_; | ||
| use PhpParser\Node\Stmt\Interface_; | ||
| use PhpParser\Node\Stmt\Enum_; | ||
|
|
||
| final class DependencyCollectorVisitor extends NodeVisitorAbstract | ||
| { | ||
| private array $dependencies = []; | ||
| private ?string $fqcn = null; | ||
| private bool $isInterface = false; | ||
| private bool $isAbstract = false; | ||
|
|
||
| public function enterNode(Node $node): void | ||
| { | ||
| if ($node instanceof Class_) { | ||
| $this->fqcn = $node->namespacedName?->toString(); | ||
| $this->isAbstract = $node->isAbstract(); | ||
| $this->isInterface = false; | ||
| } | ||
|
|
||
| if ($node instanceof Interface_ && $this->fqcn === null) { | ||
| $this->fqcn = $node->namespacedName?->toString(); | ||
| $this->isInterface = true; | ||
| } | ||
|
|
||
| if ($node instanceof Enum_) { | ||
| $this->fqcn = $node->namespacedName?->toString(); | ||
| } | ||
|
|
||
| if ($node instanceof Node\Name) { | ||
| $name = $node->toString(); | ||
| if (! $this->isBuiltinType($name)) { | ||
| $this->dependencies[] = $name; | ||
| } | ||
| } | ||
|
|
||
| if ($node instanceof Node\Attribute) { | ||
| $this->dependencies[] = $node->name->toString(); | ||
| } | ||
| } | ||
|
|
||
| public function analysis(): AstClassAnalysis | ||
| { | ||
| return new AstClassAnalysis( | ||
| fqcn: $this->fqcn ?? '', | ||
| dependencies: array_values(array_unique($this->dependencies)), | ||
| isInterface: $this->isInterface, | ||
| isAbstract: $this->isAbstract, | ||
| ); | ||
| } | ||
|
|
||
| private function isBuiltinType(string $name): bool | ||
| { | ||
| return in_array(strtolower($name), [ | ||
| 'string', 'int', 'float', 'bool', 'array', 'callable', | ||
| 'iterable', 'object', 'mixed', 'null', 'false', 'true', | ||
| 'never', 'void', 'self', 'parent', 'static', | ||
| ], true); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,29 @@ | ||||||||||||||||||||||||||||||||||||||||||
| <?php | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| namespace App\Infrastructure\Analyze\Adapters\PhpParser; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| use PhpParser\ParserFactory; | ||||||||||||||||||||||||||||||||||||||||||
| use PhpParser\NodeTraverser; | ||||||||||||||||||||||||||||||||||||||||||
| use PhpParser\NodeVisitor\NameResolver; | ||||||||||||||||||||||||||||||||||||||||||
| use App\Infrastructure\Analyze\Ports\ClassDependenciesParser; | ||||||||||||||||||||||||||||||||||||||||||
| use App\Infrastructure\Analyze\Ports\ClassAnalysis; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| final class PhpAstClassDependenciesParser implements ClassDependenciesParser | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| public function parse(string $file): ClassAnalysis | ||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||
| $code = file_get_contents($file); | ||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gestion d'erreur manquante pour la lecture de fichier
🔎 Solution proposée avec gestion d'erreur+$code = @file_get_contents($file);
+
+if ($code === false) {
+ throw new \RuntimeException("Impossible de lire le fichier : {$file}");
+}
-$code = file_get_contents($file);Alternative sans opérateur @ : +if (!file_exists($file)) {
+ throw new \RuntimeException("Fichier introuvable : {$file}");
+}
+
+if (!is_readable($file)) {
+ throw new \RuntimeException("Fichier non lisible : {$file}");
+}
+
$code = file_get_contents($file);
+
+if ($code === false) {
+ throw new \RuntimeException("Erreur lors de la lecture du fichier : {$file}");
+}📝 Committable suggestion
Suggested change
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| $parser = (new ParserFactory())->createForNewestSupportedVersion(); | ||||||||||||||||||||||||||||||||||||||||||
| $ast = $parser->parse($code); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| $collector = new DependencyCollectorVisitor(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| $traverser = new NodeTraverser(); | ||||||||||||||||||||||||||||||||||||||||||
| $traverser->addVisitor(new NameResolver()); | ||||||||||||||||||||||||||||||||||||||||||
| $traverser->addVisitor($collector); | ||||||||||||||||||||||||||||||||||||||||||
| $traverser->traverse($ast); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return $collector->analysis(); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||||||||||||||||
| <?php | ||||||||||||||||||||
|
|
||||||||||||||||||||
| namespace Tests\Fixtures\Php85; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| use Attribute; | ||||||||||||||||||||
| use DateTimeInterface; | ||||||||||||||||||||
| use IteratorAggregate; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| #[Attribute] | ||||||||||||||||||||
| class CustomAttribute {} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| interface Contract {} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| abstract class AbstractBase {} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| enum Status: string { | ||||||||||||||||||||
| case Active = 'active'; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| final class ModernClass extends AbstractBase implements Contract, IteratorAggregate | ||||||||||||||||||||
| { | ||||||||||||||||||||
| public function __construct( | ||||||||||||||||||||
| private readonly DateTimeInterface $clock, | ||||||||||||||||||||
| ) {} | ||||||||||||||||||||
|
|
||||||||||||||||||||
| #[CustomAttribute] | ||||||||||||||||||||
| public function handle(Status|Contract|null $value): ?DateTimeInterface | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return $this->clock; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
Comment on lines
+27
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Paramètre inutilisé dans la méthode handle(). Le paramètre 🔎 Correction proposéeSi le paramètre est nécessaire uniquement pour tester la détection des types union, considère soit :
#[CustomAttribute]
- public function handle(Status|Contract|null $value): ?DateTimeInterface
+ public function handle(): ?DateTimeInterface
{
return $this->clock;
}Ou si tu veux démontrer la gestion des types union : #[CustomAttribute]
public function handle(Status|Contract|null $value): ?DateTimeInterface
{
+ // Utilisation du paramètre pour démonstration
+ if ($value instanceof Status) {
+ return $this->clock;
+ }
return $this->clock;
}📝 Committable suggestion
Suggested change
🧰 Tools🪛 PHPMD (2.15.0)27-27: Avoid unused parameters such as '$value'. (undefined) (UnusedFormalParameter) 🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| public function getIterator(): \Traversable | ||||||||||||||||||||
| { | ||||||||||||||||||||
| return new \ArrayIterator([]); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?php | ||
|
|
||
| use App\Infrastructure\Analyze\Adapters\PhpParser\PhpAstClassDependenciesParser; | ||
|
|
||
| it('detects dependencies from modern PHP syntax (8.1+) ', function () { | ||
| $parser = app(PhpAstClassDependenciesParser::class); | ||
|
|
||
| $analysis = $parser->parse(__DIR__ . '/../../../Fixtures/Php85/ModernClass.php'); | ||
|
|
||
| expect($analysis->fqcn())->toBe('Tests\\Fixtures\\Php85\\ModernClass'); | ||
|
|
||
| expect($analysis->dependencies())->toContain( | ||
| 'Tests\\Fixtures\\Php85\\AbstractBase', | ||
| 'Tests\\Fixtures\\Php85\\Contract', | ||
| 'IteratorAggregate', | ||
| 'DateTimeInterface', | ||
| 'Tests\\Fixtures\\Php85\\Status', | ||
| 'Tests\\Fixtures\\Php85\\CustomAttribute', | ||
| 'ArrayIterator', | ||
| 'Traversable', | ||
| ); | ||
| }); | ||
|
|
||
| it('marks interface and abstract correctly', function () { | ||
| $parser = app(PhpAstClassDependenciesParser::class); | ||
|
|
||
| $analysis = $parser->parse(__DIR__ . '/../../../Fixtures/Php85/ModernClass.php'); | ||
|
|
||
| expect($analysis->isAbstract())->toBeFalse(); | ||
| expect($analysis->isInterface())->toBeFalse(); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1993
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 167
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 375
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 495
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 953
🏁 Script executed:
# Check the PhpAstClassDependenciesParser to understand context cat -n app/Infrastructure/Analyze/Adapters/PhpParser/PhpAstClassDependenciesParser.phpRepository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1147
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 3949
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 583
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1771
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1352
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 2365
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1013
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 256
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 127
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 130
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 332
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 127
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1280
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 434
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 452
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1121
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 210
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 3314
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1603
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 752
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 297
🏁 Script executed:
# Look for any additional test fixtures or edge cases ls -la tests/Fixtures/Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 253
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
# Check the Jerowork adapter which seems to have more sophisticated filtering cat -n app/Infrastructure/Analyze/Adapters/Jerowork/NativeDecliner.phpRepository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1709
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 154
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1455
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1494
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 495
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 4743
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 73
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1641
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 364
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 747
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 811
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 303
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 565
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1141
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 935
🏁 Script executed:
Repository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 177
🏁 Script executed:
# Final verification - check the complete test to see if it verifies exact dependencies cat tests/Unit/Infrastructure/Analyze/PhpAstClassDependenciesParserTest.phpRepository: DeGraciaMathieu/php-class-dependencies-analyzer
Length of output: 1135
Collecter sélectivement selon le contexte du nœud parent
La capture de tous les
Node\Namesans filtrage entraîne la collecte de noms non pertinents. Le codebase contient une alternative (adapter Jerowork) qui filtre explicitement les types primitifs (null,string,int,bool, etc.) et les classes/fonctions natives PHP, confirmant que ce risque est réel.Actuellement,
array_unique()ne déduplique que ; il n'élimine pas les faux positifs sémantiques. Le test utilisetoContain()plutôt quetoBe(), ce qui permet des dépendances supplémentaires non détectées.Considérez un filtrage par contexte parent pour capturer uniquement les dépendances de classe valides : extends, implements, type hints, new, instanceof, catch, attributes.
🤖 Prompt for AI Agents