Skip to content
Merged
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
4 changes: 3 additions & 1 deletion .github/workflows/coding-conventions.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: Coding Conventions

on:
push:
branches: [3.x]
Comment thread
brendt marked this conversation as resolved.
pull_request:
workflow_dispatch:

Expand Down Expand Up @@ -63,7 +65,7 @@ jobs:
phpstan-result-cache-
- name: Run PHPStan
run: vendor/bin/phpstan --error-format=github
run: vendor/bin/phpstan --error-format=github -vv

- name: Save PHPStan result cache
uses: actions/cache/save@v4
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0|^2.0",
"psr/log": "^3.0.0",
"rector/rector": "2.3.8",
"rector/rector": "2.5.8",
"symfony/cache": "^7.3|^8.0",
"symfony/filesystem": "^7.3|^8.0",
"symfony/mailer": "^7.2.6|^8.0",
Expand Down Expand Up @@ -77,7 +77,7 @@
"php-di/php-di": "^7.0",
"phpat/phpat": "^0.11.0",
"phpbench/phpbench": "^1.4",
"phpstan/phpstan": "2.1.40",
"phpstan/phpstan": "2.2.6",
"phpunit/phpunit": "^12.5.22",
"predis/predis": "^3.0.0",
"riskio/oauth2-auth0": "^2.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ final class InteractiveComponentRenderer

/** @var list<string> */
private array $pendingKeys = [];

private string $pendingInput = '';

public function __construct(
Expand Down
3 changes: 0 additions & 3 deletions packages/console/src/Components/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,12 @@ final class Option
return $this->value;
}

/** @phpstan-ignore-next-line */
if (method_exists($this->value, 'toString')) {
/** @phpstan-ignore-next-line */
return $this->value->toString();
}

$reflection = new ReflectionEnum($this->value::class);

/** @phpstan-ignore-next-line */
if (! $reflection->isBacked()) {
return $this->value->name;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/console/src/Input/ConsoleArgumentBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,11 @@ public function addMany(array $arguments): self

// Otherwise, $arguments is an array of flags or positional argument.
foreach ($arguments as $key => $argument) {
if (! (str_starts_with($argument, '-') && ! str_starts_with($argument, '--'))) {
if (! str_starts_with($argument, '-')) {
continue;
}

if (str_starts_with($argument, '--')) {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/container/src/GenericContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public function invoke(ClassReflector|MethodReflector|FunctionReflector|callable
return $this->invokeClosure($method, ...$params);
}

if (is_array($method) && count($method) === 2) {
if (is_array($method)) {
Comment thread
brendt marked this conversation as resolved.
return $this->invokeClosure($method(...), ...$params);
}

Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/PublishesFiles.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ function (string $content) use ($callback) {
// PHP will output empty arrays for empty dependencies,
// which is invalid and will make package managers crash.
foreach (['dependencies', 'devDependencies', 'peerDependencies'] as $key) {
if (! (isset($json[$key]) && ! $json[$key])) {
if (! isset($json[$key])) {
continue;
}

if ($json[$key]) {
continue;
}

Expand Down
5 changes: 5 additions & 0 deletions packages/cryptography/src/Signing/SigningKey.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

final readonly class SigningKey implements Stringable
{
/**
* @throws SigningKeyWasInvalid
*/
public function __construct(
private(set) string $value,
) {
Expand All @@ -17,6 +20,8 @@ public function __construct(

/**
* Creates a signing key from a string.
*
* @throws SigningKeyWasInvalid
*/
public static function fromString(?string $key): self
{
Expand Down
2 changes: 1 addition & 1 deletion packages/cryptography/tests/Signing/SignerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public function no_signing_key(): void
minimumExecutionDuration: false,
));

$signer->sign('important data');
$signed = $signer->sign('important data');
}

#[Test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ public function compile(DatabaseDialect $dialect): string
$dialect->quoteIdentifier($this->tableName),
arr($this->statements)
// Remove BelongsTo for sqlLite as it does not support those queries
->filter(fn (QueryStatement $queryStatement) => ! ($dialect === DatabaseDialect::SQLITE && $queryStatement instanceof BelongsToStatement))
->filter(fn (QueryStatement $queryStatement) => $dialect !== DatabaseDialect::SQLITE || ! $queryStatement instanceof BelongsToStatement)
->map(fn (QueryStatement $queryStatement) => str($queryStatement->compile($dialect))->trim()->replace(' ', ' '))
->filter(fn (ImmutableString $str) => $str->isNotEmpty())
->implode(', ' . PHP_EOL . ' ')
Expand Down
4 changes: 2 additions & 2 deletions packages/datetime/src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function high_resolution_time(): array
if ($offset === null) {
$offset = hrtime();

if ($offset === false) { // @phpstan-ignore-line identical.alwaysFalse
if ($offset === false) {
throw new RuntimeException('The system does not provide a monotonic timer.');
}

Expand Down Expand Up @@ -243,7 +243,7 @@ function to_intl_timezone(Timezone $timezone): IntlTimeZone

$tz = IntlTimeZone::createTimeZone($value);

if ($tz === null) { // @phpstan-ignore-line identical.alwaysFalse
if ($tz === null) {
throw new RuntimeException(sprintf(
'Failed to create intl timezone from timezone "%s" ("%s" / "%s").',
$timezone->name,
Expand Down
2 changes: 1 addition & 1 deletion packages/discovery/src/BootDiscovery.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ private function resolveDiscovery(string $discoveryClass): Discovery
if ($discovery === null) {
try {
$discovery = new $discoveryClass();
} catch (ArgumentCountError) { // @phpstan-ignore catch.neverThrown
} catch (ArgumentCountError) {
throw DiscoveryClassCouldNotBeResolved::forDiscoveryClass($discoveryClass);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/event-bus/tests/EventBusTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public function closure_based_handlers_using_listen_method_and_enums(): void

$eventBus->dispatch(EventEnum::TWO);

/** @var bool $hasHappened */
/** @phpstan-ignore method.impossibleType */
$this->assertTrue($hasHappened);
}
}
6 changes: 5 additions & 1 deletion packages/generation/src/Php/SimplifiesClassNames.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ function ($param) use (&$types): void {
}

foreach ($type->getTypes() as $subtype) {
if (! ($subtype->isClass() && ! $subtype->isClassKeyword())) {
if (! $subtype->isClass()) {
continue;
}

if ($subtype->isClassKeyword()) {
continue;
}

Expand Down
2 changes: 0 additions & 2 deletions packages/generation/src/Php/StubFileGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ public function generateClassFile(
->setClassName($classname);

foreach ($replacements as $placeholder => $replacement) {
// @phpstan-ignore function.alreadyNarrowedType
if (! is_string($replacement)) {
continue;
}
Expand Down Expand Up @@ -117,7 +116,6 @@ public function generateRawFile(
$fileContent = Filesystem\read_file($stubFile->filePath);

foreach ($replacements as $placeholder => $replacement) {
// @phpstan-ignore function.alreadyNarrowedType
if (! is_string($replacement)) {
continue;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/http/src/Cookie/Cookie.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ public static function createFromString(string $string): self

return new Cookie(
key: $cookie['name'],
value: $cookie['value'] ?? null,
value: $cookie['value'],
expiresAt: isset($cookie['expires']) ? (int) $cookie['expires'] : null,
maxAge: isset($cookie['max-age']) ? (int) $cookie['max-age'] : null,
domain: $cookie['domain'] ?? null,
path: $cookie['path'] ?? '/',
secure: isset($cookie['secure']) && $cookie['secure'] === true,
httpOnly: isset($cookie['httponly']) && $cookie['httponly'] === true,
secure: isset($cookie['secure']),
httpOnly: isset($cookie['httponly']),
sameSite: isset($cookie['samesite']) ? SameSite::from($cookie['samesite']) : null,
);
}
Expand Down
1 change: 0 additions & 1 deletion packages/support/tests/IsEnumHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ public function try_from_method_with_backed_enum(): void
);

// It's case sensitive
// @phpstan-ignore method.alreadyNarrowedType ( Because it's a regression test )
$this->assertNull(
SampleStatusBackedEnum::tryFrom('PUBLISH'),
);
Expand Down
2 changes: 1 addition & 1 deletion packages/validation/src/Rules/IsPassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function isValid(mixed $value): bool
return false;
}

return ! ($this->symbols && ! preg_match('/\p{Z}|\p{S}|\p{P}/u', $value));
return ! $this->symbols || preg_match('/\p{Z}|\p{S}|\p{P}/u', $value);
}

public function getTranslationVariables(): array
Expand Down
30 changes: 0 additions & 30 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,6 @@ parameters:
- packages/core/src/Exceptions/ExceptionTester.php
- packages/**/tests/**/*.php
- packages/**/tests/*.php
-
identifier: smaller.alwaysFalse
path: packages/support/src/Arr/functions.php
count: 1
# Runtime guard: positive-int type guarantees $number >= 1, but we keep the check for safety
-
identifier: instanceof.alwaysTrue
path: packages/support/src/Arr/functions.php
count: 1
# Runtime guard: closure return type guarantees Generator, but we validate for a clear error message
-
identifier: disallowed.function
path: packages/clock/src/MockClock.php
Expand Down Expand Up @@ -81,21 +71,6 @@ parameters:
path: packages/datetime/src/TemporalConvenienceMethods.php
count: 2
# Intentional: dd() is the purpose of TemporalInterface::dd()
-
identifier: identical.alwaysFalse
path: packages/datetime/src/DateTime.php
count: 6
# Runtime guard: IntlCalendar::get() returns false at runtime for extreme year values
-
identifier: booleanOr.alwaysFalse
path: packages/datetime/src/DateTime.php
count: 5
# Runtime guard: IntlCalendar::get() returns false at runtime for extreme year values
-
identifier: instanceof.alwaysTrue
path: packages/datetime/src/DateTime.php
count: 1
# Runtime guard: DateTimeInterface::getTimezone() can return false at runtime
-
identifier: disallowed.function
path: packages/console/src/Testing/ConsoleTester.php
Expand All @@ -121,11 +96,6 @@ parameters:
path: packages/support/tests/Fixtures/Phar/normalize_path.php
count: 1
# Intentional: require_once target exists only inside generated Phar archive at runtime
-
identifier: function.alreadyNarrowedType
path: packages/console/src/GenericConsole.php
count: 1
# Runtime guard: PHPDoc narrows string to class-string<BackedEnum>, but is_a() check is needed at runtime
-
identifier: argument.type
path: packages/validation/tests/Rules/IsEnumTest.php
Expand Down
4 changes: 2 additions & 2 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ services:
parameters:
level: 5
tmpDir: .cache/phpstan
tips:
treatPhpDocTypesAsCertain: false
treatPhpDocTypesAsCertain: false

paths:
- src
- packages
Expand Down
2 changes: 2 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Rector\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector;
use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector;
use Rector\Privatization\Rector\ClassMethod\PrivatizeFinalClassMethodRector;
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\SafeDeclareStrictTypesRector;
use Tempest\Rector\ImportClassNamesRector;

return RectorConfig::configure()
Expand Down Expand Up @@ -54,6 +55,7 @@
ArrayKeyExistsNullToEmptyStringRector::class,
StringClassNameToClassConstantRector::class,
ReturnBinaryOrToEarlyReturnRector::class,
SafeDeclareStrictTypesRector::class,
Comment thread
brendt marked this conversation as resolved.
])
->withConfiguredRule(ImportClassNamesRector::class, [
'importShortClasses' => true,
Expand Down
3 changes: 1 addition & 2 deletions tests/Integration/Cache/LockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function lock_execution_without_timeout(): void

$lock = $cache->lock('processing');

$this->assertTrue($lock->execute(fn () => true)); // @phpstan-ignore method.alreadyNarrowedType
$this->assertTrue($lock->execute(fn () => true));
$this->assertFalse($lock->release());
}

Expand Down Expand Up @@ -121,7 +121,6 @@ public function lock_execution_when_already_locked_by_another_owner_with_timeout
$clock->plus(Duration::hours(1));

// Try executing a callback for the specified duration
/** @phpstan-ignore-next-line */
$this->assertTrue($cache->lock('processing')->execute(fn () => true, wait: Duration::hours(1)));
}

Expand Down
Loading