/** * Extract method from position * * @param int $n * @param TokenCollection$tokens * @return ReflectedMethod * @throws \Exception */ public function extract(&$n, TokenCollection $tokens) { $declaration = $this->searcher->getUnder(array(')'), $n, $tokens); if (!preg_match('!function\\s+(.*)\\(\\s*(.*)!is', $declaration, $matches)) { throw new \Exception(sprintf("Closure detected instead of method\nDetails:\n%s", $declaration)); } list(, $name, $args) = $matches; $method = new ReflectedMethod($name); $arguments = preg_split('!\\s*,\\s*!m', $args); foreach ($arguments as $argDecl) { if (0 == strlen($argDecl)) { continue; } $elems = preg_split('!([\\s=]+)!', $argDecl); $isRequired = 2 == sizeof($elems, COUNT_NORMAL); if (sizeof($elems, COUNT_NORMAL) == 1) { list($name, $type) = array_pad($elems, 2, null); } else { if ('$' == $elems[0][0]) { $name = $elems[0]; $type = null; $isRequired = false; } else { list($type, $name) = array_pad($elems, 2, null); } } $argument = new ReflectedArgument($name, $type, $isRequired); $method->pushArgument($argument); } // // Body $this->extractContent($method, $n, $tokens); // Tokens $end = $this->searcher->getPositionOfClosingBrace($n, $tokens); if ($end > 0) { $method->setTokens($tokens->extract($n, $end)); } // // Dependencies $this->extractDependencies($method, $n, $tokens); // returns $this->extractReturns($method, $method->getContent()); // usage $this->extractUsage($method); return $method; }