4 * This file is part of the Prophecy.
5 * (c) Konstantin Kudryashov <ever.zet@gmail.com>
6 * Marcello Duarte <marcello.duarte@gmail.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Prophecy\Doubler\Generator;
16 * Generates PHP code for specific class node tree.
18 * @author Konstantin Kudryashov <ever.zet@gmail.com>
20 class ClassCodeGenerator
23 * @var TypeHintReference
25 private $typeHintReference;
27 public function __construct(TypeHintReference $typeHintReference = null)
29 $this->typeHintReference = $typeHintReference ?: new TypeHintReference();
33 * Generates PHP code for class node.
35 * @param string $classname
36 * @param Node\ClassNode $class
40 public function generate($classname, Node\ClassNode $class)
42 $parts = explode('\\', $classname);
43 $classname = array_pop($parts);
44 $namespace = implode('\\', $parts);
46 $code = sprintf("class %s extends \%s implements %s {\n",
47 $classname, $class->getParentClass(), implode(', ',
48 array_map(function ($interface) {return '\\'.$interface;}, $class->getInterfaces())
52 foreach ($class->getProperties() as $name => $visibility) {
53 $code .= sprintf("%s \$%s;\n", $visibility, $name);
57 foreach ($class->getMethods() as $method) {
58 $code .= $this->generateMethod($method)."\n";
62 return sprintf("namespace %s {\n%s\n}", $namespace, $code);
65 private function generateMethod(Node\MethodNode $method)
67 $php = sprintf("%s %s function %s%s(%s)%s {\n",
68 $method->getVisibility(),
69 $method->isStatic() ? 'static' : '',
70 $method->returnsReference() ? '&':'',
72 implode(', ', $this->generateArguments($method->getArguments())),
73 $this->getReturnType($method)
75 $php .= $method->getCode()."\n";
83 private function getReturnType(Node\MethodNode $method)
85 if (version_compare(PHP_VERSION, '7.1', '>=')) {
86 if ($method->hasReturnType()) {
87 return $method->hasNullableReturnType()
88 ? sprintf(': ?%s', $method->getReturnType())
89 : sprintf(': %s', $method->getReturnType());
93 if (version_compare(PHP_VERSION, '7.0', '>=')) {
94 return $method->hasReturnType() && $method->getReturnType() !== 'void'
95 ? sprintf(': %s', $method->getReturnType())
102 private function generateArguments(array $arguments)
104 $typeHintReference = $this->typeHintReference;
105 return array_map(function (Node\ArgumentNode $argument) use ($typeHintReference) {
108 if (version_compare(PHP_VERSION, '7.1', '>=')) {
109 $php .= $argument->isNullable() ? '?' : '';
112 if ($hint = $argument->getTypeHint()) {
113 $php .= $typeHintReference->isBuiltInParamTypeHint($hint) ? $hint : '\\'.$hint;
116 $php .= ' '.($argument->isPassedByReference() ? '&' : '');
118 $php .= $argument->isVariadic() ? '...' : '';
120 $php .= '$'.$argument->getName();
122 if ($argument->isOptional() && !$argument->isVariadic()) {
123 $php .= ' = '.var_export($argument->getDefault(), true);