/** * Tries to find specific an specialized optimizer for function calls * * @param string $funcName * @param array $expression * @param Call $call * @param CompilationContext $compilationContext */ protected function optimize($funcName, array $expression, Call $call, CompilationContext $compilationContext) { $optimizer = false; /** * Check if the optimizer is already cached */ if (!isset(self::$_optimizers[$funcName])) { $camelizeFunctionName = Utils::camelize($funcName); /** * Check every optimizer directory for an optimizer */ foreach (self::$_optimizerDirectories as $directory) { $path = $directory . DIRECTORY_SEPARATOR . $camelizeFunctionName . 'Optimizer.php'; if (file_exists($path)) { require_once $path; $className = 'Zephir\\Optimizers\\FunctionCall\\' . $camelizeFunctionName . 'Optimizer'; if (!class_exists($className, false)) { throw new \Exception('Class ' . $className . ' cannot be loaded'); } $optimizer = new $className(); if (!$optimizer instanceof OptimizerAbstract) { throw new \Exception('Class ' . $className . ' must be instance of OptimizerAbstract'); } break; } } self::$_optimizers[$funcName] = $optimizer; } else { $optimizer = self::$_optimizers[$funcName]; } if ($optimizer) { return $optimizer->optimize($expression, $call, $compilationContext); } return false; }
/** * Creates the property shortcuts * * @param array $property * @param ClassDefinition $classDefinition * @throws CompilerException */ protected function _processShorcuts(array $property, ClassDefinition $classDefinition) { foreach ($property['shortcuts'] as $shortcut) { if (substr($property['name'], 0, 1) == '_') { $name = substr($property['name'], 1); } else { $name = $property['name']; } $docBlock = isset($shortcut['docblock']) ? $shortcut['docblock'] : isset($property['docblock']) ? $property['docblock'] : null; $returnsType = array(); if ($docBlock) { $docBlockParser = new DocblockParser('/' . $docBlock . '/'); $docBlockParsed = $docBlockParser->parse(); if ($annotations = $docBlockParsed->getAnnotationsByType('var')) { $returnsType = array_map(function ($type) { return ($type = trim($type)) == 'mixed' ? 'variable' : $type; }, (array) explode('|', $annotations[0]->getString())); } // Clear annotations $docBlockParsed->setAnnotations(array()); $docBlock = $docBlockParsed->generate(); } switch ($shortcut['name']) { case 'get': $classDefinition->addMethod(new ClassMethod($classDefinition, array('public'), 'get' . Utils::camelize($name), null, new StatementsBlock(array(array('type' => 'return', 'expr' => array('type' => 'property-access', 'left' => array('type' => 'variable', 'value' => 'this'), 'right' => array('type' => 'variable', 'value' => $property['name']))))), $docBlock, $this->createReturnsType($returnsType), $shortcut), $shortcut); break; case 'set': $classDefinition->addMethod(new ClassMethod($classDefinition, array('public'), 'set' . Utils::camelize($name), new ClassMethodParameters(array(array('type' => 'parameter', 'name' => $name, 'const' => 0, 'data-type' => count($returnsType) == 1 ? $returnsType[0] : 'variable', 'mandatory' => 0))), new StatementsBlock(array(array('type' => 'let', 'assignments' => array(array('assign-type' => 'object-property', 'operator' => 'assign', 'variable' => 'this', 'property' => $property['name'], 'expr' => array('type' => 'variable', 'value' => $name, 'file' => $property['file'], 'line' => $property['line'], 'char' => $property['char']), 'file' => $property['file'], 'line' => $property['line'], 'char' => $property['char']))))), $docBlock, null, $shortcut), $shortcut); break; case 'toString': case '__toString': $classDefinition->addMethod(new ClassMethod($classDefinition, array('public'), '__toString', null, new StatementsBlock(array(array('type' => 'return', 'expr' => array('type' => 'property-access', 'left' => array('type' => 'variable', 'value' => 'this'), 'right' => array('type' => 'variable', 'value' => $property['name']))))), $docBlock, $this->createReturnsType(array('string')), $shortcut), $shortcut); break; default: throw new CompilerException("Unknown shortcut '" . $shortcut['name'] . "'", $shortcut); } } }
/** * Test camelize method. */ public function testCamelize() { $name = 'foo_Bar_Foo_bar'; $this->assertSame(Utils::camelize($name), 'FooBarFooBar'); }