Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/Reflection/Php/PhpClassReflectionExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ private function createMethod(
$acceptsNamedArguments = true;
$selfOutType = null;
$phpDocComment = null;
$currentResolvedPhpDoc = null;
$methodSignaturesResult = $this->signatureMapProvider->getMethodSignatures($declaringClassName, $methodReflection->getName(), $methodReflection);
foreach ($methodSignaturesResult as $signatureType => $methodSignatures) {
if ($methodSignatures === null) {
Expand Down Expand Up @@ -732,6 +733,22 @@ private function createMethod(
} else {
$hasSideEffects = TrinaryLogic::createMaybe();
}

$isPure = null;
if ($currentResolvedPhpDoc !== null) {
$isPure = $currentResolvedPhpDoc->isPure();
}
if ($isPure === null) {
$classResolvedPhpDoc = $declaringClass->getResolvedPhpDoc();
if ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsPure()) {
$isPure = true;
} elseif ($classResolvedPhpDoc !== null && $classResolvedPhpDoc->areAllMethodsImpure()) {
$isPure = false;
}
}
if ($isPure !== null) {
$hasSideEffects = TrinaryLogic::createFromBoolean(!$isPure);
}
return new NativeMethodReflection(
$this->reflectionProviderProvider->getReflectionProvider(),
$declaringClass,
Expand Down
40 changes: 40 additions & 0 deletions tests/PHPStan/Rules/Comparison/Bug14534MethodImpureTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Comparison;

use PHPStan\Analyser\RicherScopeGetTypeHelper;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use function array_merge;

/**
* @extends RuleTestCase<StrictComparisonOfDifferentTypesRule>
*/
class Bug14534MethodImpureTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new StrictComparisonOfDifferentTypesRule(
self::getContainer()->getByType(RicherScopeGetTypeHelper::class),
new PossiblyImpureTipHelper(true),
true,
true,
true,
);
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/bug-14534-method-impure.php'], []);
}

public static function getAdditionalConfigFiles(): array
{
return array_merge(
parent::getAdditionalConfigFiles(),
[__DIR__ . '/bug-14534-method-impure.neon'],
);
}

}
40 changes: 40 additions & 0 deletions tests/PHPStan/Rules/Comparison/Bug14534Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Comparison;

use PHPStan\Analyser\RicherScopeGetTypeHelper;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use function array_merge;

/**
* @extends RuleTestCase<StrictComparisonOfDifferentTypesRule>
*/
class Bug14534Test extends RuleTestCase
{

protected function getRule(): Rule
{
return new StrictComparisonOfDifferentTypesRule(
self::getContainer()->getByType(RicherScopeGetTypeHelper::class),
new PossiblyImpureTipHelper(true),
true,
true,
true,
);
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/bug-14534.php'], []);
}

public static function getAdditionalConfigFiles(): array
{
return array_merge(
parent::getAdditionalConfigFiles(),
[__DIR__ . '/bug-14534.neon'],
);
}

}
3 changes: 3 additions & 0 deletions tests/PHPStan/Rules/Comparison/bug-14534-method-impure.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parameters:
stubFiles:
- data/bug-14534-method-impure.stub
3 changes: 3 additions & 0 deletions tests/PHPStan/Rules/Comparison/bug-14534.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parameters:
stubFiles:
- data/bug-14534.stub
27 changes: 27 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-14534-method-impure.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);

namespace Bug14534MethodImpure;

function sayStoreCas(string $key): void
{
$memcached = new \Memcached();

do {
$extendedReturn = $memcached->get($key, null, \Memcached::GET_EXTENDED);

if ($memcached->getResultCode() !== \Memcached::RES_SUCCESS) {
return;
}

if (!is_array($extendedReturn) || !isset($extendedReturn['value']) || !isset($extendedReturn['cas'])) {
return;
}

$data = $extendedReturn['value'];
$cas = $extendedReturn['cas'];
\assert(is_float($cas));

$memcached->cas($cas, $key, $data);

} while ($memcached->getResultCode() !== \Memcached::RES_SUCCESS);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

class Memcached {
/**
* @phpstan-impure
*/
public function getResultCode(): int {}
}
27 changes: 27 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-14534.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php declare(strict_types = 1);

namespace Bug14534;

function sayStoreCas(string $key): void
{
$memcached = new \Memcached();

do {
$extendedReturn = $memcached->get($key, null, \Memcached::GET_EXTENDED);

if ($memcached->getResultCode() !== \Memcached::RES_SUCCESS) {
return;
}

if (!is_array($extendedReturn) || !isset($extendedReturn['value']) || !isset($extendedReturn['cas'])) {
return;
}

$data = $extendedReturn['value'];
$cas = $extendedReturn['cas'];
\assert(is_float($cas));

$memcached->cas($cas, $key, $data);

} while ($memcached->getResultCode() !== \Memcached::RES_SUCCESS);
}
6 changes: 6 additions & 0 deletions tests/PHPStan/Rules/Comparison/data/bug-14534.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

/**
* @phpstan-all-methods-impure
*/
class Memcached {}
33 changes: 33 additions & 0 deletions tests/PHPStan/Rules/Pure/Bug14534AllPureBuiltinTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Pure;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use function array_merge;

/**
* @extends RuleTestCase<PureFunctionRule>
*/
class Bug14534AllPureBuiltinTest extends RuleTestCase
{

protected function getRule(): Rule
{
return new PureFunctionRule(new FunctionPurityCheck());
}

public function testRule(): void
{
$this->analyse([__DIR__ . '/data/bug-14534-all-pure-builtin.php'], []);
}

public static function getAdditionalConfigFiles(): array
{
return array_merge(
parent::getAdditionalConfigFiles(),
[__DIR__ . '/bug-14534-all-pure-builtin.neon'],
);
}

}
3 changes: 3 additions & 0 deletions tests/PHPStan/Rules/Pure/bug-14534-all-pure-builtin.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
parameters:
stubFiles:
- data/bug-14534-all-pure-builtin.stub
11 changes: 11 additions & 0 deletions tests/PHPStan/Rules/Pure/data/bug-14534-all-pure-builtin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php declare(strict_types = 1);

namespace Bug14534AllPureBuiltin;

/**
* @phpstan-pure
*/
function getResultCode(\Memcached $m): int
{
return $m->getResultCode();
}
6 changes: 6 additions & 0 deletions tests/PHPStan/Rules/Pure/data/bug-14534-all-pure-builtin.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

/**
* @phpstan-all-methods-pure
*/
class Memcached {}
Loading