Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
56
src/Framework/Tokenizer/ValueObjects/DiscoveryState.php
Normal file
56
src/Framework/Tokenizer/ValueObjects/DiscoveryState.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Tokenizer\ValueObjects;
|
||||
|
||||
/**
|
||||
* State tracking for smart discovery tokenization
|
||||
* Tracks what we've found so far to enable early stopping
|
||||
*/
|
||||
final class DiscoveryState
|
||||
{
|
||||
public bool $namespaceFound = false;
|
||||
|
||||
public int $namespaceLineFound = 0;
|
||||
|
||||
public bool $classFound = false;
|
||||
|
||||
public int $classLineFound = 0;
|
||||
|
||||
public bool $classBodyStarted = false;
|
||||
|
||||
public int $useStatementsCount = 0;
|
||||
|
||||
public int $functionsCount = 0;
|
||||
|
||||
public int $attributesCount = 0;
|
||||
|
||||
public int $docCommentsCount = 0;
|
||||
|
||||
/**
|
||||
* Check if we have found significant structural content
|
||||
*/
|
||||
public function hasSignificantContent(): bool
|
||||
{
|
||||
return $this->namespaceFound ||
|
||||
$this->classFound ||
|
||||
$this->useStatementsCount > 0 ||
|
||||
$this->functionsCount > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a summary of what we've discovered
|
||||
*/
|
||||
public function getSummary(): array
|
||||
{
|
||||
return [
|
||||
'namespace' => $this->namespaceFound,
|
||||
'class' => $this->classFound,
|
||||
'uses' => $this->useStatementsCount,
|
||||
'functions' => $this->functionsCount,
|
||||
'attributes' => $this->attributesCount,
|
||||
'lines_processed' => max($this->namespaceLineFound, $this->classLineFound),
|
||||
];
|
||||
}
|
||||
}
|
||||
122
src/Framework/Tokenizer/ValueObjects/Token.php
Normal file
122
src/Framework/Tokenizer/ValueObjects/Token.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Tokenizer\ValueObjects;
|
||||
|
||||
/**
|
||||
* Represents a single token with full context
|
||||
*/
|
||||
final readonly class Token
|
||||
{
|
||||
public function __construct(
|
||||
public TokenType $type,
|
||||
public string $value,
|
||||
public int $line,
|
||||
public int $position,
|
||||
public int $id,
|
||||
public TokenContext $context
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is a specific PHP token type
|
||||
*/
|
||||
public function is(int|array $tokenId): bool
|
||||
{
|
||||
if (is_array($tokenId)) {
|
||||
return in_array($this->id, $tokenId, true);
|
||||
}
|
||||
|
||||
return $this->id === $tokenId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is structural (class, function, namespace, etc.)
|
||||
*/
|
||||
public function isStructural(): bool
|
||||
{
|
||||
return $this->is([
|
||||
T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM,
|
||||
T_FUNCTION, T_NAMESPACE, T_USE,
|
||||
T_EXTENDS, T_IMPLEMENTS,
|
||||
T_PUBLIC, T_PROTECTED, T_PRIVATE,
|
||||
T_STATIC, T_FINAL, T_ABSTRACT, T_READONLY,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is an attribute
|
||||
*/
|
||||
public function isAttribute(): bool
|
||||
{
|
||||
return $this->is(T_ATTRIBUTE) ||
|
||||
($this->context->isInAttribute && $this->is(T_STRING));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is a doc comment
|
||||
*/
|
||||
public function isDocComment(): bool
|
||||
{
|
||||
return $this->is(T_DOC_COMMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is a keyword
|
||||
*/
|
||||
public function isKeyword(): bool
|
||||
{
|
||||
return $this->type === TokenType::KEYWORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is an identifier (class name, function name, etc.)
|
||||
*/
|
||||
public function isIdentifier(): bool
|
||||
{
|
||||
return in_array($this->type, [
|
||||
TokenType::CLASS_NAME,
|
||||
TokenType::FUNCTION_NAME,
|
||||
TokenType::METHOD_NAME,
|
||||
TokenType::PROPERTY_NAME,
|
||||
TokenType::CONSTANT_NAME,
|
||||
], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get token length
|
||||
*/
|
||||
public function getLength(): int
|
||||
{
|
||||
return strlen($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get end position
|
||||
*/
|
||||
public function getEndPosition(): int
|
||||
{
|
||||
return $this->position + $this->getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this token contains a specific position
|
||||
*/
|
||||
public function containsPosition(int $position): bool
|
||||
{
|
||||
return $position >= $this->position && $position < $this->getEndPosition();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a clean version of the value (trimmed, no quotes, etc.)
|
||||
*/
|
||||
public function getCleanValue(): string
|
||||
{
|
||||
return match($this->type) {
|
||||
TokenType::STRING_LITERAL => trim($this->value, '"\''),
|
||||
TokenType::DOC_COMMENT => trim($this->value, '/*'),
|
||||
default => trim($this->value)
|
||||
};
|
||||
}
|
||||
}
|
||||
245
src/Framework/Tokenizer/ValueObjects/TokenCollection.php
Normal file
245
src/Framework/Tokenizer/ValueObjects/TokenCollection.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Tokenizer\ValueObjects;
|
||||
|
||||
use ArrayIterator;
|
||||
use Countable;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Collection of tokens with utility methods
|
||||
*/
|
||||
final readonly class TokenCollection implements IteratorAggregate, Countable
|
||||
{
|
||||
/**
|
||||
* @param array<Token> $tokens
|
||||
*/
|
||||
public function __construct(
|
||||
private array $tokens = []
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get iterator for the collection
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
{
|
||||
return new ArrayIterator($this->tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count tokens in collection
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all tokens as array
|
||||
* @return array<Token>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get token at index
|
||||
*/
|
||||
public function get(int $index): ?Token
|
||||
{
|
||||
return $this->tokens[$index] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter tokens by predicate
|
||||
*/
|
||||
public function filter(callable $predicate): self
|
||||
{
|
||||
return new self(array_values(array_filter($this->tokens, $predicate)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by token type
|
||||
*/
|
||||
public function filterByType(TokenType ...$types): self
|
||||
{
|
||||
return $this->filter(fn (Token $token) => in_array($token->type, $types, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter by PHP token ID
|
||||
*/
|
||||
public function filterById(int ...$ids): self
|
||||
{
|
||||
return $this->filter(fn (Token $token) => in_array($token->id, $ids, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only structural tokens
|
||||
*/
|
||||
public function getStructural(): self
|
||||
{
|
||||
return $this->filter(fn (Token $token) => $token->isStructural());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only identifiers
|
||||
*/
|
||||
public function getIdentifiers(): self
|
||||
{
|
||||
return $this->filter(fn (Token $token) => $token->isIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tokens in line range
|
||||
*/
|
||||
public function getInLineRange(int $startLine, int $endLine): self
|
||||
{
|
||||
return $this->filter(
|
||||
fn (Token $token) =>
|
||||
$token->line >= $startLine && $token->line <= $endLine
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tokens at specific line
|
||||
*/
|
||||
public function getAtLine(int $line): self
|
||||
{
|
||||
return $this->filter(fn (Token $token) => $token->line === $line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first token matching predicate
|
||||
*/
|
||||
public function findFirst(callable $predicate): ?Token
|
||||
{
|
||||
foreach ($this->tokens as $token) {
|
||||
if ($predicate($token)) {
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find first token of type
|
||||
*/
|
||||
public function findFirstOfType(TokenType $type): ?Token
|
||||
{
|
||||
return $this->findFirst(fn (Token $token) => $token->type === $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map tokens to another form
|
||||
*/
|
||||
public function map(callable $mapper): array
|
||||
{
|
||||
return array_map($mapper, $this->tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all values
|
||||
*/
|
||||
public function getValues(): array
|
||||
{
|
||||
return $this->map(fn (Token $token) => $token->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all clean values
|
||||
*/
|
||||
public function getCleanValues(): array
|
||||
{
|
||||
return $this->map(fn (Token $token) => $token->getCleanValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tokens grouped by type
|
||||
* @return array<string, array<Token>>
|
||||
*/
|
||||
public function groupByType(): array
|
||||
{
|
||||
$groups = [];
|
||||
foreach ($this->tokens as $token) {
|
||||
$type = $token->type->value;
|
||||
if (! isset($groups[$type])) {
|
||||
$groups[$type] = [];
|
||||
}
|
||||
$groups[$type][] = $token;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tokens grouped by line
|
||||
* @return array<int, array<Token>>
|
||||
*/
|
||||
public function groupByLine(): array
|
||||
{
|
||||
$groups = [];
|
||||
foreach ($this->tokens as $token) {
|
||||
if (! isset($groups[$token->line])) {
|
||||
$groups[$token->line] = [];
|
||||
}
|
||||
$groups[$token->line][] = $token;
|
||||
}
|
||||
|
||||
return $groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if collection is empty
|
||||
*/
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return empty($this->tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first token
|
||||
*/
|
||||
public function first(): ?Token
|
||||
{
|
||||
return $this->tokens[0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last token
|
||||
*/
|
||||
public function last(): ?Token
|
||||
{
|
||||
return empty($this->tokens) ? null : $this->tokens[count($this->tokens) - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Slice collection
|
||||
*/
|
||||
public function slice(int $offset, ?int $length = null): self
|
||||
{
|
||||
return new self(array_slice($this->tokens, $offset, $length));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge with another collection
|
||||
*/
|
||||
public function merge(self $other): self
|
||||
{
|
||||
return new self(array_merge($this->tokens, $other->tokens));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to string (concatenate all values)
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return implode('', $this->getValues());
|
||||
}
|
||||
}
|
||||
208
src/Framework/Tokenizer/ValueObjects/TokenContext.php
Normal file
208
src/Framework/Tokenizer/ValueObjects/TokenContext.php
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Tokenizer\ValueObjects;
|
||||
|
||||
/**
|
||||
* Context information for a token
|
||||
*/
|
||||
final class TokenContext
|
||||
{
|
||||
public function __construct(
|
||||
public readonly bool $isInClass = false,
|
||||
public readonly bool $isInFunction = false,
|
||||
public readonly bool $isInNamespace = false,
|
||||
public readonly bool $isInAttribute = false,
|
||||
public readonly bool $isInDocComment = false,
|
||||
public readonly ?string $currentClass = null,
|
||||
public readonly ?string $currentFunction = null,
|
||||
public readonly ?string $currentNamespace = null,
|
||||
public readonly array $scopeStack = [],
|
||||
public readonly int $nestingLevel = 0
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new context with updated values
|
||||
*/
|
||||
public function with(array $updates): self
|
||||
{
|
||||
return new self(
|
||||
isInClass: $updates['isInClass'] ?? $this->isInClass,
|
||||
isInFunction: $updates['isInFunction'] ?? $this->isInFunction,
|
||||
isInNamespace: $updates['isInNamespace'] ?? $this->isInNamespace,
|
||||
isInAttribute: $updates['isInAttribute'] ?? $this->isInAttribute,
|
||||
isInDocComment: $updates['isInDocComment'] ?? $this->isInDocComment,
|
||||
currentClass: $updates['currentClass'] ?? $this->currentClass,
|
||||
currentFunction: $updates['currentFunction'] ?? $this->currentFunction,
|
||||
currentNamespace: $updates['currentNamespace'] ?? $this->currentNamespace,
|
||||
scopeStack: $updates['scopeStack'] ?? $this->scopeStack,
|
||||
nestingLevel: $updates['nestingLevel'] ?? $this->nestingLevel
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter a new scope
|
||||
*/
|
||||
public function enterScope(string $type, ?string $name = null): self
|
||||
{
|
||||
$newStack = $this->scopeStack;
|
||||
$newStack[] = ['type' => $type, 'name' => $name];
|
||||
|
||||
$updates = [
|
||||
'scopeStack' => $newStack,
|
||||
'nestingLevel' => $this->nestingLevel + 1,
|
||||
];
|
||||
|
||||
// Use match for cleaner, type-safe scope handling
|
||||
$scopeUpdates = match($type) {
|
||||
'class', 'interface', 'trait', 'enum' => [
|
||||
'isInClass' => true,
|
||||
'currentClass' => $name,
|
||||
],
|
||||
'function', 'method' => [
|
||||
'isInFunction' => true,
|
||||
'currentFunction' => $name,
|
||||
],
|
||||
'namespace' => [
|
||||
'isInNamespace' => true,
|
||||
'currentNamespace' => $name,
|
||||
],
|
||||
'attribute' => [
|
||||
'isInAttribute' => true,
|
||||
],
|
||||
'doccomment' => [
|
||||
'isInDocComment' => true,
|
||||
],
|
||||
default => []
|
||||
};
|
||||
|
||||
return $this->with([...$updates, ...$scopeUpdates]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit current scope
|
||||
*/
|
||||
public function exitScope(): self
|
||||
{
|
||||
if (empty($this->scopeStack)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$newStack = $this->scopeStack;
|
||||
$exitedScope = array_pop($newStack);
|
||||
|
||||
$updates = [
|
||||
'scopeStack' => $newStack,
|
||||
'nestingLevel' => max(0, $this->nestingLevel - 1),
|
||||
];
|
||||
|
||||
// Update context based on remaining stack
|
||||
if (empty($newStack)) {
|
||||
$updates = [
|
||||
...$updates,
|
||||
'isInClass' => false,
|
||||
'isInFunction' => false,
|
||||
'isInAttribute' => false,
|
||||
'isInDocComment' => false,
|
||||
'currentClass' => null,
|
||||
'currentFunction' => null,
|
||||
];
|
||||
} else {
|
||||
// Check what scopes we're still in
|
||||
$stillInClass = false;
|
||||
$stillInFunction = false;
|
||||
$stillInAttribute = false;
|
||||
$stillInDocComment = false;
|
||||
$currentClass = null;
|
||||
$currentFunction = null;
|
||||
|
||||
foreach ($newStack as $scope) {
|
||||
$scopeType = $scope['type'];
|
||||
|
||||
match($scopeType) {
|
||||
'class', 'interface', 'trait', 'enum' => ($stillInClass = true) && ($currentClass = $scope['name']),
|
||||
'function', 'method' => ($stillInFunction = true) && ($currentFunction = $scope['name']),
|
||||
'attribute' => $stillInAttribute = true,
|
||||
'doccomment' => $stillInDocComment = true,
|
||||
default => null
|
||||
};
|
||||
}
|
||||
|
||||
$updates = [
|
||||
...$updates,
|
||||
'isInClass' => $stillInClass,
|
||||
'isInFunction' => $stillInFunction,
|
||||
'isInAttribute' => $stillInAttribute,
|
||||
'isInDocComment' => $stillInDocComment,
|
||||
'currentClass' => $currentClass,
|
||||
'currentFunction' => $currentFunction,
|
||||
];
|
||||
}
|
||||
|
||||
return $this->with($updates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current scope type
|
||||
*/
|
||||
public function getCurrentScopeType(): ?string
|
||||
{
|
||||
if (empty($this->scopeStack)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$currentScope = $this->scopeStack[array_key_last($this->scopeStack)];
|
||||
|
||||
return $currentScope['type'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're in a specific scope type
|
||||
*/
|
||||
public function isInScopeType(string $type): bool
|
||||
{
|
||||
return match($type) {
|
||||
'class' => $this->isInClass,
|
||||
'function' => $this->isInFunction,
|
||||
'namespace' => $this->isInNamespace,
|
||||
'attribute' => $this->isInAttribute,
|
||||
'doccomment' => $this->isInDocComment,
|
||||
default => false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fully qualified name for current context
|
||||
*/
|
||||
public function getFullyQualifiedName(?string $name = null): string
|
||||
{
|
||||
$parts = array_filter([
|
||||
$this->currentNamespace,
|
||||
$this->currentClass,
|
||||
$name,
|
||||
]);
|
||||
|
||||
return implode('\\', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the context
|
||||
*/
|
||||
public function clone(): self
|
||||
{
|
||||
return new self(
|
||||
isInClass: $this->isInClass,
|
||||
isInFunction: $this->isInFunction,
|
||||
isInNamespace: $this->isInNamespace,
|
||||
isInAttribute: $this->isInAttribute,
|
||||
isInDocComment: $this->isInDocComment,
|
||||
currentClass: $this->currentClass,
|
||||
currentFunction: $this->currentFunction,
|
||||
currentNamespace: $this->currentNamespace,
|
||||
scopeStack: $this->scopeStack,
|
||||
nestingLevel: $this->nestingLevel
|
||||
);
|
||||
}
|
||||
}
|
||||
132
src/Framework/Tokenizer/ValueObjects/TokenType.php
Normal file
132
src/Framework/Tokenizer/ValueObjects/TokenType.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Framework\Tokenizer\ValueObjects;
|
||||
|
||||
/**
|
||||
* Token type enumeration for semantic classification
|
||||
*/
|
||||
enum TokenType: string
|
||||
{
|
||||
// Structural
|
||||
case KEYWORD = 'keyword';
|
||||
case CLASS_NAME = 'class_name';
|
||||
case INTERFACE_NAME = 'interface_name';
|
||||
case TRAIT_NAME = 'trait_name';
|
||||
case ENUM_NAME = 'enum_name';
|
||||
case NAMESPACE_NAME = 'namespace_name';
|
||||
|
||||
// Identifiers
|
||||
case FUNCTION_NAME = 'function_name';
|
||||
case METHOD_NAME = 'method_name';
|
||||
case PROPERTY_NAME = 'property_name';
|
||||
case CONSTANT_NAME = 'constant_name';
|
||||
case VARIABLE = 'variable';
|
||||
case PARAMETER = 'parameter';
|
||||
|
||||
// Literals
|
||||
case STRING_LITERAL = 'string_literal';
|
||||
case NUMBER_LITERAL = 'number_literal';
|
||||
case BOOLEAN_LITERAL = 'boolean_literal';
|
||||
case NULL_LITERAL = 'null_literal';
|
||||
|
||||
// Comments
|
||||
case DOC_COMMENT = 'doc_comment';
|
||||
case DOC_TAG = 'doc_tag';
|
||||
case DOC_TYPE = 'doc_type';
|
||||
case DOC_VARIABLE = 'doc_variable';
|
||||
case DOC_TEXT = 'doc_text';
|
||||
case COMMENT = 'comment';
|
||||
|
||||
// Operators and syntax
|
||||
case OPERATOR = 'operator';
|
||||
case PUNCTUATION = 'punctuation';
|
||||
case BRACKET = 'bracket';
|
||||
case PARENTHESIS = 'parenthesis';
|
||||
case BRACE = 'brace';
|
||||
case SEMICOLON = 'semicolon';
|
||||
|
||||
// Attributes
|
||||
case ATTRIBUTE = 'attribute';
|
||||
case ATTRIBUTE_NAME = 'attribute_name';
|
||||
case ATTRIBUTE_ARGUMENT = 'attribute_argument';
|
||||
|
||||
// Types
|
||||
case TYPE_HINT = 'type_hint';
|
||||
case RETURN_TYPE = 'return_type';
|
||||
case UNION_TYPE = 'union_type';
|
||||
case INTERSECTION_TYPE = 'intersection_type';
|
||||
|
||||
// Special
|
||||
case WHITESPACE = 'whitespace';
|
||||
case PHP_TAG = 'php_tag';
|
||||
case HTML = 'html';
|
||||
case DEFAULT = 'default';
|
||||
case ERROR = 'error';
|
||||
|
||||
/**
|
||||
* Get CSS class for syntax highlighting
|
||||
*/
|
||||
public function getCssClass(): string
|
||||
{
|
||||
return 'token-' . str_replace('_', '-', $this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color for terminal output
|
||||
*/
|
||||
public function getTerminalColor(): string
|
||||
{
|
||||
return match($this) {
|
||||
self::KEYWORD => "\033[35m", // Magenta
|
||||
self::CLASS_NAME,
|
||||
self::INTERFACE_NAME,
|
||||
self::TRAIT_NAME,
|
||||
self::ENUM_NAME => "\033[36m", // Cyan
|
||||
self::FUNCTION_NAME,
|
||||
self::METHOD_NAME => "\033[33m", // Yellow
|
||||
self::VARIABLE,
|
||||
self::PARAMETER => "\033[37m", // White
|
||||
self::STRING_LITERAL => "\033[32m", // Green
|
||||
self::NUMBER_LITERAL => "\033[34m", // Blue
|
||||
self::COMMENT,
|
||||
self::DOC_COMMENT => "\033[90m", // Gray
|
||||
self::ATTRIBUTE,
|
||||
self::ATTRIBUTE_NAME => "\033[95m", // Light Magenta
|
||||
self::OPERATOR => "\033[31m", // Red
|
||||
default => "\033[0m" // Reset
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is a structural token type
|
||||
*/
|
||||
public function isStructural(): bool
|
||||
{
|
||||
return in_array($this, [
|
||||
self::CLASS_NAME,
|
||||
self::INTERFACE_NAME,
|
||||
self::TRAIT_NAME,
|
||||
self::ENUM_NAME,
|
||||
self::NAMESPACE_NAME,
|
||||
self::FUNCTION_NAME,
|
||||
self::METHOD_NAME,
|
||||
], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is a comment type
|
||||
*/
|
||||
public function isComment(): bool
|
||||
{
|
||||
return in_array($this, [
|
||||
self::COMMENT,
|
||||
self::DOC_COMMENT,
|
||||
self::DOC_TAG,
|
||||
self::DOC_TYPE,
|
||||
self::DOC_VARIABLE,
|
||||
self::DOC_TEXT,
|
||||
], true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user