InheritanceExtractorTrait.php

Code Hygiene Score: 100

Keine Issues gefunden.

Klassen 1

Funktionen 5

Verwendet von 1

Code

<?php

declare(strict_types=1);

namespace Infrastructure\CodeAnalysis;

// @responsibility: Extraktion von Vererbungs-Beziehungen (extends, implements, traits)

/**
 * Trait for extracting inheritance relationships from PHP token arrays.
 *
 * Extracts parent classes, implemented interfaces, and used traits.
 */
trait InheritanceExtractorTrait
{
    /**
     * Extract the parent class (extends clause).
     *
     * @param array<mixed> $tokens
     */
    private function extractExtends(array $tokens): ?string
    {
        $count = count($tokens);

        for ($i = 0; $i < $count; $i++) {
            $token = $tokens[$i];

            if (!is_array($token) || $token[0] !== T_EXTENDS) {
                continue;
            }

            // Find the class name after extends
            $className = $this->extractTypeName($tokens, $i + 1);
            if ($className !== null) {
                return $this->resolveFqcn($className);
            }
        }

        return null;
    }

    /**
     * Extract implemented interfaces.
     *
     * @param array<mixed> $tokens
     * @return array<string>
     */
    private function extractImplements(array $tokens): array
    {
        $interfaces = [];
        $count = count($tokens);

        for ($i = 0; $i < $count; $i++) {
            $token = $tokens[$i];

            if (!is_array($token) || $token[0] !== T_IMPLEMENTS) {
                continue;
            }

            // Collect interface names until { or extends
            for ($j = $i + 1; $j < $count; $j++) {
                if ($tokens[$j] === '{') {
                    break;
                }

                if ($tokens[$j] === ',') {
                    continue;
                }

                if (!is_array($tokens[$j])) {
                    continue;
                }

                if ($tokens[$j][0] === T_EXTENDS) {
                    break;
                }

                if (in_array($tokens[$j][0], [T_STRING, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED], true)) {
                    $interfaces[] = $this->resolveFqcn($tokens[$j][1]);
                }
            }

            break;
        }

        return array_unique($interfaces);
    }

    /**
     * Extract traits used inside class body.
     *
     * @param array<mixed> $tokens
     * @return array<string>
     */
    private function extractTraits(array $tokens): array
    {
        $traits = [];
        $count = count($tokens);
        $braceDepth = 0;
        $inClass = false;

        for ($i = 0; $i < $count; $i++) {
            $token = $tokens[$i];

            if (!is_array($token)) {
                if ($token === '{') {
                    $braceDepth++;
                } elseif ($token === '}') {
                    $braceDepth--;
                    if ($braceDepth === 0) {
                        $inClass = false;
                    }
                }

                continue;
            }

            if (in_array($token[0], [T_CLASS, T_TRAIT, T_ENUM], true)) {
                $inClass = true;

                continue;
            }

            // T_USE inside class body = trait use
            if ($token[0] === T_USE && $inClass && $braceDepth === 1) {
                // Collect trait names until ; or {
                for ($j = $i + 1; $j < $count; $j++) {
                    if ($tokens[$j] === ';' || $tokens[$j] === '{') {
                        break;
                    }

                    if ($tokens[$j] === ',') {
                        continue;
                    }

                    if (!is_array($tokens[$j])) {
                        continue;
                    }

                    if (in_array($tokens[$j][0], [T_STRING, T_NAME_QUALIFIED, T_NAME_FULLY_QUALIFIED], true)) {
                        $traits[] = $this->resolveFqcn($tokens[$j][1]);
                    }
                }
            }
        }

        return array_unique($traits);
    }

    /**
     * Required from TokenNavigatorTrait.
     *
     * @param array<mixed> $tokens
     */
    abstract private function extractTypeName(array $tokens, int $startIndex): ?string;

    /**
     * Required from main class - resolves short names to FQCN.
     */
    abstract private function resolveFqcn(string $name): string;
}
← Übersicht Graph