Skip to content
Open
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
70 changes: 70 additions & 0 deletions src/Ast/Type/ConditionalTypeForPropertyNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function sprintf;

class ConditionalTypeForPropertyNode implements TypeNode
{

use NodeAttributes;

public PropertyAccessNode $subject;

public TypeNode $targetType;

public TypeNode $if;

public TypeNode $else;

public bool $negated;

public function __construct(
PropertyAccessNode $subject,
TypeNode $targetType,
TypeNode $if,
TypeNode $else,
bool $negated
)
{
$this->subject = $subject;
$this->targetType = $targetType;
$this->if = $if;
$this->else = $else;
$this->negated = $negated;
}

public function __toString(): string
{
return sprintf(
'(%s %s %s ? %s : %s)',
$this->subject,
$this->negated ? 'is not' : 'is',
$this->targetType,
$this->if,
$this->else,
);
}

/**
* @param array<string, mixed> $properties
*/
public static function __set_state(array $properties): self
{
$instance = new self(
$properties['subject'],
$properties['targetType'],
$properties['if'],
$properties['else'],
$properties['negated'],
);
if (isset($properties['attributes'])) {
foreach ($properties['attributes'] as $key => $value) {
$instance->setAttribute($key, $value);
}
}
return $instance;
}

}
78 changes: 78 additions & 0 deletions src/Ast/Type/PropertyAccessNode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function array_map;
use function implode;

/**
* Represents a property access expression in conditional types.
*/
class PropertyAccessNode implements Node
{

use NodeAttributes;

public const HOLDER_SELF = 'self';
public const HOLDER_PARENT = 'parent';
public const HOLDER_STATIC = 'static';

public bool $isStatic;

/**
* For static access: 'self', 'parent', or 'static'
* For instance access: null (holder is implicitly $this)
*
* @var self::HOLDER_*|null
*/
public ?string $holder;

/** @var list<PropertyAccessPathItem> */
public array $path;

/**
* @param self::HOLDER_*|null $holder
* @param list<PropertyAccessPathItem> $path
*/
public function __construct(bool $isStatic, ?string $holder, array $path)
{
$this->isStatic = $isStatic;
$this->holder = $holder;
$this->path = $path;
}

public function __toString(): string
{
if ($this->isStatic) {
return $this->holder . '::$' . $this->path[0]->name;
}

$pathString = implode('->', array_map(
static fn (PropertyAccessPathItem $item): string => $item->name,
$this->path,
));

return '$this->' . $pathString;
}

/**
* @param array<string, mixed> $properties
*/
public static function __set_state(array $properties): self
{
$instance = new self(
$properties['isStatic'],
$properties['holder'],
$properties['path'],
);
if (isset($properties['attributes'])) {
foreach ($properties['attributes'] as $key => $value) {
$instance->setAttribute($key, $value);
}
}
return $instance;
}

}
46 changes: 46 additions & 0 deletions src/Ast/Type/PropertyAccessPathItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php declare(strict_types = 1);

namespace PHPStan\PhpDocParser\Ast\Type;

use PHPStan\PhpDocParser\Ast\Node;
use PHPStan\PhpDocParser\Ast\NodeAttributes;

/**
* Represents a single property in a property access path.
*
* Examples:
* - In `$this->config->database`, there are two items: 'config' and 'database'
* - In `self::$cache`, there is one item: 'cache'
*/
class PropertyAccessPathItem implements Node
{

use NodeAttributes;

public string $name;

public function __construct(string $name)
{
$this->name = $name;
}

public function __toString(): string
{
return $this->name;
}

/**
* @param array<string, mixed> $properties
*/
public static function __set_state(array $properties): self
{
$instance = new self($properties['name']);
if (isset($properties['attributes'])) {
foreach ($properties['attributes'] as $key => $value) {
$instance->setAttribute($key, $value);
}
}
return $instance;
}

}
2 changes: 1 addition & 1 deletion src/Lexer/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private function generateRegexp(): string
$patterns = [
self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++',

self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF-]*+)++',
self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x80-\\xFF](?:[0-9a-z_\\x80-\\xFF]|(?!->)-)*+)++',
self::TOKEN_THIS_VARIABLE => '\\$this(?![0-9a-z_\\x80-\\xFF])',
self::TOKEN_VARIABLE => '\\$[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF]*+',

Expand Down
Loading