Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ jobs:
8.1,
8.2,
8.3,
8.4
8.4,
8.5
]
composer: [basic]
# Test against both supported nikic/php-parser major versions.
Expand Down
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ We will use:

### Supported PHP Features

Runtime support for this library is PHP 8.1+, while the parser test suite validates analyzable source syntax from PHP 5.3 through PHP 8.5.

#### Legacy source syntax that can still be analyzed

| Source Syntax Generation | Representative coverage |
|---|---|
| PHP 5.3 | namespaces, closures with `use`, `array()` syntax |
| PHP 5.4 | traits, `callable`, short arrays |
| PHP 5.5 | generators / `yield`, `finally` |
| PHP 5.6 | variadics, argument unpacking-ready syntax, constant arrays |
| PHP 7.0 | scalar parameter types, return types, anonymous classes |
| PHP 7.1 | nullable types, `iterable`, `void` |
| PHP 7.2 | `object` type |
| PHP 7.3 | trailing commas in calls |
| PHP 7.4 | typed properties, arrow functions |

#### Modern source syntax coverage

| Feature | PHP Version | Supported |
|---|---|---|
| Attributes (class, method, property, parameter, constant) | 8.0+ | ✅ |
Expand All @@ -54,6 +72,7 @@ We will use:
| Trait constants | 8.2+ | ✅ |
| Typed class constants | 8.3+ | ✅ |
| `#[\Override]` attribute detection | 8.3+ | ✅ |
| Property hooks / asymmetric visibility | 8.4+ | ✅ |

### Install via "composer require"

Expand Down Expand Up @@ -123,6 +142,24 @@ $phpClasses = $phpCode->getClasses();
var_dump($phpClasses[Dummy::class]); // "PHPClass"-object
````

Unified metadata API:
```php
$phpCode = \voku\SimplePhpParser\Parsers\PhpCodeParser::getPhpFiles(__DIR__ . '/src');

$phpClasses = $phpCode->getClasses();
$phpInterfaces = $phpCode->getInterfaces();
$phpTraits = $phpCode->getTraits();
$phpEnums = $phpCode->getEnums();
$phpFunctions = $phpCode->getFunctions();
$phpConstants = $phpCode->getConstants();

$functionInfo = $phpCode->getFunctionsInfo();
$methodInfo = $phpClasses[MyService::class]->getMethodsInfo();
$propertyInfo = $phpClasses[MyService::class]->getPropertiesInfo();
```

The library is meant to be the simple integration layer that other tools can call instead of wiring together `nikic/php-parser`, `phpstan/phpdoc-parser`, `phpDocumentor`, and native reflection themselves. The test suite validates analyzable PHP source from PHP 5.3 through PHP 8.5, including legacy syntax generations and modern type declarations / metadata such as attributes, enums, readonly constructs, typed constants, and property hooks.

Access enums:
```php
$phpCode = \voku\SimplePhpParser\Parsers\PhpCodeParser::getPhpFiles(__DIR__ . '/src');
Expand Down
5 changes: 4 additions & 1 deletion src/voku/SimplePhpParser/Model/PHPClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,10 @@ private function mergePromotedPropertyData(
$existingProperty->access_set = $promotedProperty->access_set;
}

if ($existingProperty->hooks === [] && $promotedProperty->hooks !== []) {
// AST is the ground truth for promoted-property hooks; always prefer it
// when the param node carries hook data. Only fall back to whatever
// reflection already populated when the AST node has nothing.
if ($promotedProperty->hooks !== []) {
$existingProperty->hooks = $promotedProperty->hooks;
}

Expand Down
85 changes: 85 additions & 0 deletions tests/DummyCombinedSources.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace voku\tests;

use Attribute;
use DateTimeImmutable;

#[Attribute(Attribute::TARGET_CLASS)]
class DummyCombinedClassAttribute
{
public function __construct(
public string $label = ''
) {
}
}

#[Attribute(Attribute::TARGET_PROPERTY)]
class DummyCombinedPropertyAttribute
{
public function __construct(
public string $source = ''
) {
}
}

#[Attribute(Attribute::TARGET_METHOD)]
class DummyCombinedMethodAttribute
{
public function __construct(
public string $label = ''
) {
}
}

#[Attribute(Attribute::TARGET_PARAMETER)]
class DummyCombinedParameterAttribute
{
public function __construct(
public string $label = ''
) {
}
}

final class DummyCombinedDependency
{
}

#[DummyCombinedClassAttribute(label: 'combined')]
final class DummyCombinedSources
{
/**
* @var class-string<DummyCombinedDependency>
*/
#[DummyCombinedPropertyAttribute(source: 'reflection')]
public string $dependencyClass = DummyCombinedDependency::class;

/**
* Build a payload snapshot.
*
* Collects native types, advanced phpDoc types and reflection metadata together.
*
* @param array{status: string, retries: int|float} $payload
* @param callable(string): string $formatter
*
* @return array{status: string, retries: int|float}
*/
#[DummyCombinedMethodAttribute(label: 'method')]
public function buildSnapshot(
#[DummyCombinedParameterAttribute(label: 'payload')] array $payload,
#[DummyCombinedParameterAttribute(label: 'formatter')] callable $formatter,
bool $withMeta = true

Check warning on line 73 in tests/DummyCombinedSources.php

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "$withMeta".

See more on https://sonarcloud.io/project/issues?id=voku_Simple-PHP-Code-Parser&issues=AZ1-ERZvSTzC4JOHQHaJ&open=AZ1-ERZvSTzC4JOHQHaJ&pullRequest=86
): array {
return [
'status' => $formatter($payload['status']),
'retries' => $payload['retries'],
];
}

public function freeze(DateTimeImmutable $at): DateTimeImmutable
{
return $at;
}
}
Loading