Skip to content
Permalink
Browse files

Fix #1787 - prevent initialisation when nullable isn’t set

  • Loading branch information...
muglug committed Jun 14, 2019
1 parent edf3307 commit d1630863ad64e6beb915ac255c41c744b56f3b4a
@@ -11,7 +11,7 @@
],
"require": {
"php": "^7.1",
"nikic/php-parser": "^4.0.2 || ^4.1",
"nikic/php-parser": "^4.2",
"openlss/lib-array2xml": "^1.0",
"ocramius/package-versions": "^1.2",
"composer/xdebug-handler": "^1.1",
@@ -657,7 +657,7 @@ public function analyze(
if (!$property_type->isMixed() &&
!$property_storage->has_default &&
!$property_type->isNullable()
!($property_type->isNullable() && $property_type->from_docblock)
) {
$property_type->initialized = false;
}
@@ -1026,7 +1026,9 @@ private function checkPropertyInitialization(
continue;
}
if ($property->type->isMixed() || $property->type->isNullable()) {
if ($property->type->isMixed()
|| ($property->type->isNullable() && $property->type->from_docblock)
) {
continue;
}
@@ -1077,8 +1079,7 @@ private function checkPropertyInitialization(
$constructor_storage = $constructor_class_storage->methods['__construct'];
$fake_constructor_params = array_map(
/** @return PhpParser\Node\Param */
function (FunctionLikeParameter $param) {
function (FunctionLikeParameter $param) : PhpParser\Node\Param {
$fake_param = (new PhpParser\Builder\Param($param->name));
if ($param->signature_type) {
/** @psalm-suppress DeprecatedMethod */
@@ -1091,8 +1092,7 @@ function (FunctionLikeParameter $param) {
);
$fake_constructor_stmt_args = array_map(
/** @return PhpParser\Node\Arg */
function (FunctionLikeParameter $param) {
function (FunctionLikeParameter $param) : PhpParser\Node\Arg {
return new PhpParser\Node\Arg(new PhpParser\Node\Expr\Variable($param->name));
},
$constructor_storage->params
@@ -2729,12 +2729,11 @@ private function visitPropertyDeclaration(
$signature_type = null;
$signature_type_location = null;
/** @var null|PhpParser\Node\Identifier|PhpParser\Node\Name|PhpParser\Node\NullableType */
$parser_property_type = isset($stmt->type) ? $stmt->type : null;
if ($parser_property_type) {
if ($stmt->type) {
$suffix = '';
$parser_property_type = $stmt->type;
if ($parser_property_type instanceof PhpParser\Node\NullableType) {
$suffix = '|null';
$parser_property_type = $parser_property_type->type;
@@ -1609,6 +1609,33 @@ public function getBar() : string {
}
}',
],
'nullableDocblockTypedPropertyNoConstructor' => [
'<?php
class A {
/** @var ?bool */
private $foo;
}',
],
'nullableDocblockTypedPropertyEmptyConstructor' => [
'<?php
class A {
/** @var ?bool */
private $foo;
public function __construct() {}
}',
],
'nullableDocblockTypedPropertyUseBeforeInitialised' => [
'<?php
class A {
/** @var ?bool */
private $foo;
public function __construct() {
echo $this->foo;
}
}',
],
];
}
@@ -2460,6 +2487,63 @@ public function __construct(FooMore $foo) {
}',
'error_message' => 'UndefinedInterfaceMethod'
],
'nullableTypedPropertyNoConstructor' => [
'<?php
class A {
private ?bool $foo;
}',
'error_message' => 'MissingConstructor'
],
'nullableTypedPropertyEmptyConstructor' => [
'<?php
class A {
private ?bool $foo;
public function __construct() {}
}',
'error_message' => 'PropertyNotSetInConstructor'
],
'nullableTypedPropertyUseBeforeInitialised' => [
'<?php
class A {
private ?bool $foo;
public function __construct() {
echo $this->foo;
}
}',
'error_message' => 'UninitializedProperty'
],
'nullableTypedPropertyNoConstructorWithDocblock' => [
'<?php
class A {
/** @var ?bool */
private ?bool $foo;
}',
'error_message' => 'MissingConstructor'
],
'nullableTypedPropertyEmptyConstructorWithDocblock' => [
'<?php
class A {
/** @var ?bool */
private ?bool $foo;
public function __construct() {}
}',
'error_message' => 'PropertyNotSetInConstructor'
],
'nullableTypedPropertyUseBeforeInitialisedWithDocblock' => [
'<?php
class A {
/** @var ?bool */
private ?bool $foo;
public function __construct() {
echo $this->foo;
}
}',
'error_message' => 'UninitializedProperty'
],
];
}
}

0 comments on commit d163086

Please sign in to comment.
You can’t perform that action at this time.