<commit_before><?php
namespace Peridot\Core;

/**
 * Property bag for scoping tests "instance variables". This exists to
 * prevent tests from creating instance variable collisions.
 *
 * @package Peridot\Core
 */
class Scope
{
    /**
     * @var \SplObjectStorage
     */
    protected $peridotChildScopes;

    /**
     * @param Scope $scope
     */
    public function peridotAddChildScope(Scope $scope)
    {
        $this->peridotGetChildScopes()->attach($scope);
    }

    /**
     * @return \SplObjectStorage
     */
    public function peridotGetChildScopes()
    {
        if (!isset($this->peridotChildScopes)) {
            $this->peridotChildScopes = new \SplObjectStorage();
        }
        return $this->peridotChildScopes;
    }

    /**
     * @param $name
     * @param $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        list($result, $found) = $this->peridotLookupScopeMethod($this, $name, $arguments);
        if ($found) {
            return $result;
        }
        throw new \BadMethodCallException("Scope method $name not found");
    }

    /**
     * @param $name
     */
    public function __get($name)
    {
        list($result, $found) = $this->peridotLookupScopeProperty($this, $name);
        if ($found) {
            return $result;
        }
        throw new \DomainException("Scope property $name not found");
    }

    /**
     * Return a method result by searching against a scope and
     * all of its children
     *
     * @param Scope $scope
     * @param $methodName
     * @param $arguments
     * @param $accumulator
     * @return array index 0 is the result and index 1 is whether the method was found
     */
    protected function peridotLookupScopeMethod(Scope $scope, $methodName, $arguments, &$accumulator = [])
    {
        $children = $scope->peridotGetChildScopes();
        foreach ($children as $childScope) {
            if (method_exists($childScope, $methodName)) {
                return [call_user_func_array([$childScope, $methodName], $arguments), true];
            }
            $accumulator = $this->peridotLookupScopeMethod($childScope, $methodName, $arguments);
        }
        return $accumulator;
    }

    /**
     * Return a property by searching against a scope and
     * all of its children
     *
     * @param Scope $scope
     * @param $propertyName
     * @return array index 0 is the result and index 1 is whether the property was found
     */
    protected function peridotLookupScopeProperty(Scope $scope, $propertyName, &$accumulator = [])
    {
        $children = $scope->peridotGetChildScopes();
        foreach ($children as $childScope) {
            if (property_exists($childScope, $propertyName)) {
                return [$childScope->$propertyName, true];
            }
            $accumulator = $this->peridotLookupScopeProperty($childScope, $propertyName);
        }
        return $accumulator;
    }
}<commit_msg>make sure recursive scope lookup terminates as soon as method or property is found<commit_after><?php
namespace Peridot\Core;

/**
 * Property bag for scoping tests "instance variables". This exists to
 * prevent tests from creating instance variable collisions.
 *
 * @package Peridot\Core
 */
class Scope
{
    /**
     * @var \SplObjectStorage
     */
    protected $peridotChildScopes;

    /**
     * @param Scope $scope
     */
    public function peridotAddChildScope(Scope $scope)
    {
        $this->peridotGetChildScopes()->attach($scope);
    }

    /**
     * @return \SplObjectStorage
     */
    public function peridotGetChildScopes()
    {
        if (!isset($this->peridotChildScopes)) {
            $this->peridotChildScopes = new \SplObjectStorage();
        }
        return $this->peridotChildScopes;
    }

    /**
     * @param $name
     * @param $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        list($result, $found) = $this->peridotLookupScopeMethod($this, $name, $arguments);
        if ($found) {
            return $result;
        }
        throw new \BadMethodCallException("Scope method $name not found");
    }

    /**
     * @param $name
     */
    public function __get($name)
    {
        list($result, $found) = $this->peridotLookupScopeProperty($this, $name);
        if ($found) {
            return $result;
        }
        throw new \DomainException("Scope property $name not found");
    }

    /**
     * Return a method result by searching against a scope and
     * all of its children
     *
     * @param Scope $scope
     * @param $methodName
     * @param $arguments
     * @param $accumulator
     * @return array index 0 is the result and index 1 is whether the method was found
     */
    protected function peridotLookupScopeMethod(Scope $scope, $methodName, $arguments, &$accumulator = [])
    {
        if (! empty($accumulator)) {
            return $accumulator;
        }

        $children = $scope->peridotGetChildScopes();
        foreach ($children as $childScope) {
            if (method_exists($childScope, $methodName)) {
                $accumulator = [call_user_func_array([$childScope, $methodName], $arguments), true];
            }
            $this->peridotLookupScopeMethod($childScope, $methodName, $arguments, $accumulator);
        }
        return $accumulator;
    }

    /**
     * Return a property by searching against a scope and
     * all of its children
     *
     * @param Scope $scope
     * @param $propertyName
     * @return array index 0 is the result and index 1 is whether the property was found
     */
    protected function peridotLookupScopeProperty(Scope $scope, $propertyName, &$accumulator = [])
    {
        if (! empty($accumulator)) {
            return $accumulator;
        }

        $children = $scope->peridotGetChildScopes();
        foreach ($children as $childScope) {
            if (property_exists($childScope, $propertyName)) {
                $accumulator = [$childScope->$propertyName, true];
            }
            $this->peridotLookupScopeProperty($childScope, $propertyName, $accumulator);
        }
        return $accumulator;
    }
}
{'fraction_non_alphanumeric': 0.11561440335863071, 'fraction_numerical': 0.0012917810431131924, 'mean_word_length': 2.322961373390558, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, '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': '6843143', 'n_tokens_mistral': 1776, 'n_tokens_neox': 1715, 'n_words': 455}