diff --git a/.travis.yml b/.travis.yml index a7eec88c7..ca9be8193 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,16 @@ language: php php: - 5.6 - 7.0 + - 7.1 matrix: include: - php: 5.6 env: dependencies="--prefer-lowest --prefer-stable" + allow_failures: + - php: 7.1 + script: - vendor/bin/tester tests -s -c tests/php-unix.ini $coverage - php temp/code-checker/src/code-checker.php --short-arrays diff --git a/composer.json b/composer.json index e6f076fc0..ef4a5da58 100644 --- a/composer.json +++ b/composer.json @@ -15,6 +15,7 @@ ], "require": { "php": ">=5.6.0", + "ext-tokenizer": "*", "nette/neon": "^2.3.3", "nette/php-generator": "^2.4", "nette/utils": "^2.4" diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index 703eead2c..588a02f17 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -440,7 +440,7 @@ private function resolveImplement(ServiceDefinition $def, $name) throw new ServiceCreationException("Unused parameter \${$param->getName()} when implementing method $interface::$methodName()" . ($hint ? ", did you mean \${$hint}?" : '.')); } $paramDef = $hint . ' ' . $param->getName(); - if ($param->isOptional()) { + if ($param->isDefaultValueAvailable()) { $def->parameters[$paramDef] = $param->getDefaultValue(); } else { $def->parameters[] = $paramDef; diff --git a/src/DI/DependencyChecker.php b/src/DI/DependencyChecker.php index 21d245576..d52726e9f 100644 --- a/src/DI/DependencyChecker.php +++ b/src/DI/DependencyChecker.php @@ -108,7 +108,7 @@ private static function calculateHash($classes, $functions) $name, $method->getName(), $method->getDocComment(), - implode('', $method->getParameters()), + self::hashParameters($method), PHP_VERSION >= 70000 ? $method->getReturnType() : NULL ]; } @@ -130,7 +130,7 @@ private static function calculateHash($classes, $functions) $name, $class ? PhpReflection::getUseStatements($method->getDeclaringClass()) : NULL, $method->getDocComment(), - implode('', $method->getParameters()), + self::hashParameters($method), PHP_VERSION >= 70000 ? $method->getReturnType() : NULL ]; } @@ -138,4 +138,20 @@ private static function calculateHash($classes, $functions) return md5(serialize($hash)); } + + private static function hashParameters(\ReflectionFunctionAbstract $method) + { + $res = []; + foreach ($method->getParameters() as $param) { + $res[] = [ + $param->getName(), + PhpReflection::getParameterType($param), + $param->isDefaultValueAvailable() + ? ($param->isDefaultValueConstant() ? $param->getDefaultValueConstantName() : [$param->getDefaultValue()]) + : NULL + ]; + } + return $res; + } + } diff --git a/src/DI/Extensions/DIExtension.php b/src/DI/Extensions/DIExtension.php index 4d314360c..35023d1e6 100644 --- a/src/DI/Extensions/DIExtension.php +++ b/src/DI/Extensions/DIExtension.php @@ -19,6 +19,7 @@ class DIExtension extends Nette\DI\CompilerExtension 'debugger' => TRUE, 'accessors' => FALSE, 'excluded' => [], + 'parentClass' => NULL, ]; /** @var bool */ @@ -45,6 +46,10 @@ public function loadConfiguration() public function afterCompile(Nette\PhpGenerator\ClassType $class) { + if ($this->config['parentClass']) { + $class->setExtends($this->config['parentClass']); + } + $initialize = $class->getMethod('initialize'); $builder = $this->getContainerBuilder(); diff --git a/src/DI/PhpReflection.php b/src/DI/PhpReflection.php index e0a6f3c50..832076b98 100644 --- a/src/DI/PhpReflection.php +++ b/src/DI/PhpReflection.php @@ -31,6 +31,7 @@ public static function parseAnnotation(\Reflector $ref, $name) } $ok = TRUE; } + $name = preg_quote($name, '#'); if ($ref->getDocComment() && preg_match("#[\\s*]@$name(?:\\s++([^@]\\S*)?|$)#", trim($ref->getDocComment(), '/*'), $m)) { return isset($m[1]) ? $m[1] : ''; } diff --git a/tests/DI/Compiler.generatedFactory.phpt b/tests/DI/Compiler.generatedFactory.phpt index 839ab7d6f..e6e2c5c61 100644 --- a/tests/DI/Compiler.generatedFactory.phpt +++ b/tests/DI/Compiler.generatedFactory.phpt @@ -97,6 +97,28 @@ interface IFooFactory public function create(Baz $baz = NULL); } +class Dolor +{ + public $bar; + + public $foo; + + public function __construct(Bar $bar = NULL, $foo) + { + $this->bar = $bar; + $this->foo = $foo; + } +} + +interface DolorFactory +{ + + /** @return Dolor */ + public function create(Bar $bar = NULL, $foo); + +} + + class TestClass { public $foo; @@ -220,6 +242,15 @@ $obj = $container->getService('factory5')->create('bar'); Assert::same('foo', $obj->foo); Assert::same('bar', $obj->bar); +Assert::type(DolorFactory::class, $factory = $container->getService('dolorFactory')); +Assert::type(Dolor::class, $obj = $factory->create($bar = new Bar(), 'abc')); +Assert::same($bar, $obj->bar); +Assert::same('abc', $obj->foo); + +Assert::type(Dolor::class, $obj = $factory->create(NULL, 'abc')); +Assert::null($obj->bar); +Assert::same('abc', $obj->foo); + class Bad1 { diff --git a/tests/DI/DIExtension.parentClass.phpt b/tests/DI/DIExtension.parentClass.phpt new file mode 100644 index 000000000..083038c55 --- /dev/null +++ b/tests/DI/DIExtension.parentClass.phpt @@ -0,0 +1,26 @@ +addExtension('di', new DIExtension); +$container = createContainer($compiler, ' +di: + parentClass: MyContainer +', 'neon'); + +Assert::type(MyContainer::class, $container); diff --git a/tests/DI/files/compiler.generatedFactory.neon b/tests/DI/files/compiler.generatedFactory.neon index d4583e97f..b89ef067c 100644 --- a/tests/DI/files/compiler.generatedFactory.neon +++ b/tests/DI/files/compiler.generatedFactory.neon @@ -31,3 +31,4 @@ services: factory5: implement: ITestClassFactory arguments: ['foo'] + dolorFactory: DolorFactory