UseStatementExtractorTrait.php
- Pfad:
src/Infrastructure/CodeAnalysis/UseStatementExtractorTrait.php - Namespace: Infrastructure\CodeAnalysis
- Zeilen: 155 | Größe: 4,405 Bytes
- Geändert: 2025-12-25 09:25:10 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 100
- Dependencies: 100 (25%)
- LOC: 100 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Klassen 1
-
UseStatementExtractorTraittrait Zeile 15
Funktionen 3
-
extractUseStatements()private Zeile 23 -
parseUseStatement()private Zeile 72 -
findNextNonWhitespace()private Zeile 153
Verwendet von 1
- PhpFileParser.php trait
Versionen 4
-
v4
2025-12-25 09:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v3
2025-12-25 09:25 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v2
2025-12-25 09:24 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation -
v1
2025-12-25 01:48 | claude-code-hook | modified
Claude Code Pre-Hook Backup vor Edit-Operation
Code
<?php
declare(strict_types=1);
namespace Infrastructure\CodeAnalysis;
// @responsibility: Use-Statement-Extraktion aus PHP-Token-Arrays
/**
* Trait for extracting use statements from PHP token arrays.
*
* Handles grouped imports, aliases, and distinguishes between
* top-level use statements and trait use statements inside classes.
*/
trait UseStatementExtractorTrait
{
/**
* Extracts use statements (top-level imports only).
*
* @param array<mixed> $tokens
* @return array<string>
*/
private function extractUseStatements(array $tokens): array
{
$uses = [];
$count = count($tokens);
$braceDepth = 0;
for ($i = 0; $i < $count; $i++) {
$token = $tokens[$i];
// Track brace depth to distinguish top-level use from trait use
if (!is_array($token)) {
if ($token === '{') {
$braceDepth++;
} elseif ($token === '}') {
$braceDepth--;
}
continue;
}
// Only process top-level use statements
if ($token[0] !== T_USE || $braceDepth > 0) {
continue;
}
// Skip function/const imports
$nextToken = $this->findNextNonWhitespace($tokens, $i);
if ($nextToken !== null && is_array($tokens[$nextToken])) {
if ($tokens[$nextToken][0] === T_FUNCTION || $tokens[$nextToken][0] === T_CONST) {
continue;
}
}
// Extract the use statement(s)
$useResult = $this->parseUseStatement($tokens, $i);
foreach ($useResult['fqcns'] as $fqcn) {
$uses[] = $fqcn;
}
}
return array_unique($uses);
}
/**
* Parse a single use statement, handling grouped imports.
*
* @param array<mixed> $tokens
* @return array{fqcns: array<string>, endIndex: int}
*/
private function parseUseStatement(array $tokens, int $startIndex): array
{
$fqcns = [];
$count = count($tokens);
$baseNamespace = '';
$currentName = '';
$inGroup = false;
$endIndex = $startIndex;
for ($i = $startIndex + 1; $i < $count; $i++) {
$endIndex = $i;
$token = $tokens[$i];
if ($token === ';') {
if ($currentName !== '') {
$fqcns[] = $inGroup ? $baseNamespace . $currentName : $currentName;
}
break;
}
if ($token === '{') {
$baseNamespace = $currentName;
$currentName = '';
$inGroup = true;
continue;
}
if ($token === '}') {
if ($currentName !== '') {
$fqcns[] = $baseNamespace . $currentName;
}
continue;
}
if ($token === ',') {
if ($currentName !== '') {
$fqcns[] = $inGroup ? $baseNamespace . $currentName : $currentName;
}
$currentName = '';
continue;
}
if (!is_array($token)) {
continue;
}
// Skip 'as' aliases - we only care about the original FQCN
if ($token[0] === T_AS) {
// Skip until comma or semicolon
for ($j = $i + 1; $j < $count; $j++) {
if ($tokens[$j] === ',' || $tokens[$j] === ';' || $tokens[$j] === '}') {
$i = $j - 1;
break;
}
}
continue;
}
if ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) {
$currentName .= ltrim($token[1], '\\');
} elseif ($token[0] === T_STRING) {
$currentName .= $token[1];
} elseif ($token[0] === T_NS_SEPARATOR) {
$currentName .= '\\';
}
}
return ['fqcns' => $fqcns, 'endIndex' => $endIndex];
}
/**
* Required from TokenNavigatorTrait.
*
* @param array<mixed> $tokens
*/
abstract private function findNextNonWhitespace(array $tokens, int $index): ?int;
}