<commit_before><?php
namespace Granam\Exceptions\Tools;

use Granam\Exceptions\Tools\Exceptions\InvalidExceptionHierarchy;

class TestOfExceptionsHierarchy
{
    /** @var string */
    private $testedNamespace;

    /** @var string */
    private $rootNamespace;

    /** @var string */
    private $exceptionsSubDir;

    /** @var array|string[] */
    private $externalRootNamespaces = array();

    /**
     * @param string $testedNamespace
     * @param string $rootNamespace
     * @param string|bool $exceptionsSubDir
     * @param array|string[] $externalRootNamespaces
     * @param string|bool $externalRootExceptionsSubDir
     */
    public function __construct(
        $testedNamespace,
        $rootNamespace,
        $exceptionsSubDir = 'Exceptions',
        array $externalRootNamespaces = array(),
        $externalRootExceptionsSubDir = 'Exceptions'
    )
    {
        $testedNamespace = $this->normalizeNamespace($testedNamespace);
        $rootNamespace = $this->normalizeNamespace($rootNamespace);
        $externalRootNamespaces = $this->normalizeNamespaces($externalRootNamespaces);
        $this->checkRootNamespace($rootNamespace, $testedNamespace);
        $this->checkExternalRootNamespaces($externalRootNamespaces, $externalRootExceptionsSubDir, $rootNamespace);

        $this->testedNamespace = $testedNamespace;
        $this->rootNamespace = $rootNamespace;
        $this->exceptionsSubDir = $exceptionsSubDir;
        $this->externalRootNamespaces = $externalRootNamespaces;
        $this->externalRootExceptionsSubDir = $externalRootExceptionsSubDir;
    }

    /**
     * @param string $namespace
     *
     * @return string
     */
    protected function normalizeNamespace($namespace)
    {
        if (!is_string($namespace)) {
            throw new Exceptions\MissingNamespace(
                'Namespace can be empty string for root, but given ' . var_export($namespace, true)
            );
        }

        return '\\' . trim($namespace, '\\');
    }

    protected function normalizeNamespaces(array $namespaces)
    {
        foreach ($namespaces as $index => $namespace) {
            $namespaces[$index] = $this->normalizeNamespace($namespace);
        }

        return $namespaces;
    }

    protected function checkRootNamespace($rootNamespace, $testedNamespace)
    {
        if (!preg_match('~^' . preg_quote($rootNamespace) . '~', $testedNamespace)) {
            throw new Exceptions\RootNamespaceHasToBeSuperior(
                "Root namespace $rootNamespace should be leading of currently tested namespace $testedNamespace"
            );
        }
    }

    protected function checkExternalRootNamespaces(array $externalRootNamespaces, $externalRootExceptionsSubDir, $rootNamespace)
    {
        if (!$externalRootNamespaces) {
            return;
        }
        foreach ($externalRootNamespaces as $externalRootNamespace) {
            if ($rootNamespace === $externalRootNamespace) {
                throw new Exceptions\ExternalRootNamespaceHasToBeSuperior(
                    "External root namespace $externalRootNamespace should differ to local root namespace $rootNamespace"
                );
            }
            if (strpos($externalRootNamespace, $rootNamespace) === 0) {
                throw new Exceptions\ExternalRootNamespaceHasToBeSuperior(
                    "External root namespace $externalRootNamespace should not be subordinate to local root namespace $rootNamespace"
                );
            }
            $this->My_tag_interfaces_are_in_hierarchy(
                $externalRootNamespace,
                $externalRootExceptionsSubDir,
                array() // no child namespaces to check
            );
        }
    }

    /**
     * @return string
     */
    protected function getTestedNamespace()
    {
        return $this->testedNamespace;
    }

    /**
     * @return string
     */
    protected function getRootNamespace()
    {
        return $this->rootNamespace;
    }

    /**
     * @return string
     */
    protected function getExceptionsSubDir()
    {
        return $this->exceptionsSubDir;
    }

    /**
     * @return array|string[]
     */
    protected function getExternalRootNamespaces()
    {
        return $this->externalRootNamespaces;
    }

    /**
     * @return bool|string
     */
    public function getExternalRootExceptionsSubDir()
    {
        return $this->externalRootExceptionsSubDir;
    }

    protected function My_tag_interfaces_are_in_hierarchy(
        $testedNamespace,
        $exceptionsSubDir,
        array $childNamespaces
    )
    {
        $exceptionInterface = $this->assembleExceptionInterfaceClass($testedNamespace, $exceptionsSubDir);
        $this->checkExceptionInterfaces($exceptionInterface);

        $runtimeInterface = $this->assembleRuntimeInterfaceClass($testedNamespace, $exceptionsSubDir);
        $this->checkRuntimeInterfaces($runtimeInterface, $exceptionInterface);

        $logicInterface = $this->assembleLogicInterfaceClass($testedNamespace, $exceptionsSubDir);
        $this->checkLogicInterfaces($logicInterface, $exceptionInterface);

        $this->checkInterfaceCollision($runtimeInterface, $logicInterface);

        $this->checkChildInterfaces($childNamespaces, $exceptionInterface, $runtimeInterface, $logicInterface);
    }
<commit_msg>Publicly used method made hidden for outer world<commit_after><?php
namespace Granam\Exceptions\Tools;

use Granam\Exceptions\Tools\Exceptions\InvalidExceptionHierarchy;

class TestOfExceptionsHierarchy
{
    /** @var string */
    private $testedNamespace;

    /** @var string */
    private $rootNamespace;

    /** @var string */
    private $exceptionsSubDir;

    /** @var array|string[] */
    private $externalRootNamespaces = array();

    /**
     * @param string $testedNamespace
     * @param string $rootNamespace
     * @param string|bool $exceptionsSubDir
     * @param array|string[] $externalRootNamespaces
     * @param string|bool $externalRootExceptionsSubDir
     */
    public function __construct(
        $testedNamespace,
        $rootNamespace,
        $exceptionsSubDir = 'Exceptions',
        array $externalRootNamespaces = array(),
        $externalRootExceptionsSubDir = 'Exceptions'
    )
    {
        $testedNamespace = $this->normalizeNamespace($testedNamespace);
        $rootNamespace = $this->normalizeNamespace($rootNamespace);
        $externalRootNamespaces = $this->normalizeNamespaces($externalRootNamespaces);
        $this->checkRootNamespace($rootNamespace, $testedNamespace);
        $this->checkExternalRootNamespaces($externalRootNamespaces, $externalRootExceptionsSubDir, $rootNamespace);

        $this->testedNamespace = $testedNamespace;
        $this->rootNamespace = $rootNamespace;
        $this->exceptionsSubDir = $exceptionsSubDir;
        $this->externalRootNamespaces = $externalRootNamespaces;
        $this->externalRootExceptionsSubDir = $externalRootExceptionsSubDir;
    }

    /**
     * @param string $namespace
     *
     * @return string
     */
    protected function normalizeNamespace($namespace)
    {
        if (!is_string($namespace)) {
            throw new Exceptions\MissingNamespace(
                'Namespace can be empty string for root, but given ' . var_export($namespace, true)
            );
        }

        return '\\' . trim($namespace, '\\');
    }

    protected function normalizeNamespaces(array $namespaces)
    {
        foreach ($namespaces as $index => $namespace) {
            $namespaces[$index] = $this->normalizeNamespace($namespace);
        }

        return $namespaces;
    }

    protected function checkRootNamespace($rootNamespace, $testedNamespace)
    {
        if (!preg_match('~^' . preg_quote($rootNamespace) . '~', $testedNamespace)) {
            throw new Exceptions\RootNamespaceHasToBeSuperior(
                "Root namespace $rootNamespace should be leading of currently tested namespace $testedNamespace"
            );
        }
    }

    protected function checkExternalRootNamespaces(array $externalRootNamespaces, $externalRootExceptionsSubDir, $rootNamespace)
    {
        if (!$externalRootNamespaces) {
            return;
        }
        foreach ($externalRootNamespaces as $externalRootNamespace) {
            if ($rootNamespace === $externalRootNamespace) {
                throw new Exceptions\ExternalRootNamespaceHasToBeSuperior(
                    "External root namespace $externalRootNamespace should differ to local root namespace $rootNamespace"
                );
            }
            if (strpos($externalRootNamespace, $rootNamespace) === 0) {
                throw new Exceptions\ExternalRootNamespaceHasToBeSuperior(
                    "External root namespace $externalRootNamespace should not be subordinate to local root namespace $rootNamespace"
                );
            }
            $this->My_tag_interfaces_are_in_hierarchy(
                $externalRootNamespace,
                $externalRootExceptionsSubDir,
                array() // no child namespaces to check
            );
        }
    }

    /**
     * @return string
     */
    protected function getTestedNamespace()
    {
        return $this->testedNamespace;
    }

    /**
     * @return string
     */
    protected function getRootNamespace()
    {
        return $this->rootNamespace;
    }

    /**
     * @return string
     */
    protected function getExceptionsSubDir()
    {
        return $this->exceptionsSubDir;
    }

    /**
     * @return array|string[]
     */
    protected function getExternalRootNamespaces()
    {
        return $this->externalRootNamespaces;
    }

    /**
     * @return bool|string
     */
    protected function getExternalRootExceptionsSubDir()
    {
        return $this->externalRootExceptionsSubDir;
    }

    protected function My_tag_interfaces_are_in_hierarchy(
        $testedNamespace,
        $exceptionsSubDir,
        array $childNamespaces
    )
    {
        $exceptionInterface = $this->assembleExceptionInterfaceClass($testedNamespace, $exceptionsSubDir);
        $this->checkExceptionInterfaces($exceptionInterface);

        $runtimeInterface = $this->assembleRuntimeInterfaceClass($testedNamespace, $exceptionsSubDir);
        $this->checkRuntimeInterfaces($runtimeInterface, $exceptionInterface);

        $logicInterface = $this->assembleLogicInterfaceClass($testedNamespace, $exceptionsSubDir);
        $this->checkLogicInterfaces($logicInterface, $exceptionInterface);

        $this->checkInterfaceCollision($runtimeInterface, $logicInterface);

        $this->checkChildInterfaces($childNamespaces, $exceptionInterface, $runtimeInterface, $logicInterface);
    }

{'fraction_non_alphanumeric': 0.09917818453492716, 'fraction_numerical': 0.00018677624206200972, 'mean_word_length': 2.7522775052557815, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1786126', 'n_tokens_mistral': 2769, 'n_tokens_neox': 2656, 'n_words': 515}