Skip to content

Commit 167f213

Browse files
authored
Update phpstan to v2 (#30)
1 parent 26bcd92 commit 167f213

16 files changed

+116
-50
lines changed

Diff for: composer.json

+7-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
"digitalrevolution/utils": "^1.9",
2929
"phpmd/phpmd": "^2.14",
3030
"phpstan/extension-installer": "^1.3",
31-
"phpstan/phpstan": "^1.10",
32-
"phpstan/phpstan-phpunit": "^1.3",
33-
"phpstan/phpstan-strict-rules": "^1.5",
34-
"phpstan/phpstan-symfony": "^1.3",
31+
"phpstan/phpstan": "^2.0",
32+
"phpstan/phpstan-phpunit": "^2.0",
33+
"phpstan/phpstan-strict-rules": "^2.0",
34+
"phpstan/phpstan-symfony": "^2.0",
3535
"phpunit/phpunit": "^10.4 || ^11.0",
3636
"ramsey/uuid": "^4.7",
3737
"roave/security-advisories": "dev-latest",
@@ -62,6 +62,9 @@
6262
}
6363
},
6464
"scripts": {
65+
"baseline": ["@baseline:phpstan", "@baseline:phpmd"],
66+
"baseline:phpstan": "phpstan --generate-baseline",
67+
"baseline:phpmd": "phpmd src,tests xml phpmd.xml.dist --generate-baseline",
6568
"check": ["@check:phpstan", "@check:phpmd", "@check:phpcs"],
6669
"check:phpstan": "phpstan analyse",
6770
"check:phpmd": "phpmd src,tests text phpmd.xml.dist --suffixes php",

Diff for: phpmd.baseline.xml

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<?xml version="1.0"?>
22
<phpmd-baseline>
3+
<violation rule="PHPMD\Rule\UnusedLocalVariable" file="src/DependencyInjection/Compiler/HttpClientTracePass.php"/>
34
<violation rule="PHPMD\Rule\Design\CouplingBetweenObjects" file="src/DependencyInjection/SymfonyTraceExtension.php"/>
45
<violation rule="PHPMD\Rule\Controversial\Superglobals" file="tests/Functional/AbstractKernelTestCase.php" method="createKernel"/>
56
<violation rule="PHPMD\Rule\Controversial\Superglobals" file="tests/Functional/AbstractWebTestCase.php" method="createKernel"/>
7+
<violation rule="PHPMD\Rule\UnusedFormalParameter" file="tests/Functional/App/Service/MockClientCallbackHelper.php"/>
68
<violation rule="PHPMD\Rule\Design\TooManyPublicMethods" file="tests/Functional/App/Service/MockSentryHub.php"/>
79
</phpmd-baseline>

Diff for: phpstan-baseline.neon

+27-36
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,67 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: "#^Parameter \\#1 \\$mergedConfig \\(array\\{traceMode\\: 'tracecontext'\\|'traceid', traceid\\: array\\{request_header\\: string, response_header\\: string, generator_service\\: string\\|null\\}, request\\: array\\{trust_header\\: bool, trusted_ips\\: array\\<string\\>\\|string\\|null\\}, response\\: array\\{send_header\\: bool, trusted_ips\\: array\\<string\\>\\|string\\|null\\}, storage_service\\: string\\|null, enable_monolog\\: bool, enable_console\\: bool, console\\: array\\{enabled\\: bool, trace_id\\: string\\|null\\}, \\.\\.\\.\\}\\) of method DR\\\\SymfonyTraceBundle\\\\DependencyInjection\\\\SymfonyTraceExtension\\:\\:loadInternal\\(\\) should be contravariant with parameter \\$mergedConfig \\(array\\) of method Symfony\\\\Component\\\\HttpKernel\\\\DependencyInjection\\\\ConfigurableExtension\\:\\:loadInternal\\(\\)$#"
4+
message: '#^Cannot access offset ''response_header'' on mixed\.$#'
5+
identifier: offsetAccess.nonOffsetAccessible
56
count: 1
67
path: src/DependencyInjection/SymfonyTraceExtension.php
78

89
-
9-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Http\\\\TraceAwareHttpClient\\:\\:request\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
10+
message: '#^Parameter \#1 \$mergedConfig \(array\{traceMode\: ''tracecontext''\|''traceid'', traceid\: array\{request_header\: string, response_header\: string, generator_service\: string\|null\}, request\: array\{trust_header\: bool, trusted_ips\: array\<string\>\|string\|null\}, response\: array\{send_header\: bool, trusted_ips\: array\<string\>\|string\|null\}, storage_service\: string\|null, enable_monolog\: bool, enable_console\: bool\|null, console\: array\{enabled\: bool, trace_id\: string\|null\}, \.\.\.\}\) of method DR\\SymfonyTraceBundle\\DependencyInjection\\SymfonyTraceExtension\:\:loadInternal\(\) should be contravariant with parameter \$mergedConfig \(array\) of method Symfony\\Component\\HttpKernel\\DependencyInjection\\ConfigurableExtension\:\:loadInternal\(\)$#'
11+
identifier: method.childParameterType
1012
count: 1
11-
path: src/Http/TraceAwareHttpClient.php
13+
path: src/DependencyInjection/SymfonyTraceExtension.php
1214

1315
-
14-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Http\\\\TraceAwareHttpClient\\:\\:withOptions\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
16+
message: '#^Parameter \#1 \$options \(array\{auth_basic\?\: array\<string\>\|string, auth_bearer\?\: string, query\?\: array\<string\>, headers\?\: array\<array\<string\>\|string\>, body\?\: object\|resource\|string, json\?\: mixed, user_data\?\: mixed, max_redirects\?\: int, \.\.\.\}\) of method DR\\SymfonyTraceBundle\\Http\\TraceAwareHttpClient\:\:withOptions\(\) should be contravariant with parameter \$options \(array\) of method Symfony\\Contracts\\HttpClient\\HttpClientInterface\:\:withOptions\(\)$#'
17+
identifier: method.childParameterType
1518
count: 1
1619
path: src/Http/TraceAwareHttpClient.php
1720

1821
-
19-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Monolog\\\\TraceProcessor\\:\\:__invoke\\(\\) has parameter \\$record with no value type specified in iterable type array\\.$#"
22+
message: '#^Parameter \#3 \$options \(array\{auth_basic\?\: array\<string\>\|string, auth_bearer\?\: string, query\?\: array\<string\>, headers\?\: array\<array\<string\>\|string\>, body\?\: object\|resource\|string, json\?\: mixed, user_data\?\: mixed, max_redirects\?\: int, \.\.\.\}\) of method DR\\SymfonyTraceBundle\\Http\\TraceAwareHttpClient\:\:request\(\) should be contravariant with parameter \$options \(array\) of method Symfony\\Contracts\\HttpClient\\HttpClientInterface\:\:request\(\)$#'
23+
identifier: method.childParameterType
2024
count: 1
21-
path: src/Monolog/TraceProcessor.php
25+
path: src/Http/TraceAwareHttpClient.php
2226

2327
-
24-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Monolog\\\\TraceProcessor\\:\\:__invoke\\(\\) return type has no value type specified in iterable type array\\.$#"
28+
message: '#^Method DR\\SymfonyTraceBundle\\Monolog\\TraceProcessor\:\:__invoke\(\) return type has no value type specified in iterable type array\.$#'
29+
identifier: missingType.iterableValue
2530
count: 1
2631
path: src/Monolog/TraceProcessor.php
2732

2833
-
29-
message: "#^Return type \\(array\\|Monolog\\\\LogRecord\\) of method DR\\\\SymfonyTraceBundle\\\\Monolog\\\\TraceProcessor\\:\\:__invoke\\(\\) should be covariant with return type \\(Monolog\\\\LogRecord\\) of method Monolog\\\\Processor\\\\ProcessorInterface\\:\\:__invoke\\(\\)$#"
34+
message: '#^Return type \(array\|Monolog\\LogRecord\) of method DR\\SymfonyTraceBundle\\Monolog\\TraceProcessor\:\:__invoke\(\) should be covariant with return type \(Monolog\\LogRecord\) of method Monolog\\Processor\\ProcessorInterface\:\:__invoke\(\)$#'
35+
identifier: method.childReturnType
3036
count: 1
3137
path: src/Monolog/TraceProcessor.php
3238

3339
-
34-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Service\\\\TraceContext\\\\TraceContextService\\:\\:handleClientRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
35-
count: 1
36-
path: src/Service/TraceContext/TraceContextService.php
37-
38-
-
39-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Service\\\\TraceContext\\\\TraceContextService\\:\\:handleClientRequest\\(\\) return type has no value type specified in iterable type array\\.$#"
40-
count: 1
41-
path: src/Service/TraceContext/TraceContextService.php
42-
43-
-
44-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Service\\\\TraceId\\\\TraceIdService\\:\\:handleClientRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
40+
message: '#^Cannot cast mixed to string\.$#'
41+
identifier: cast.string
4542
count: 1
46-
path: src/Service/TraceId/TraceIdService.php
47-
48-
-
49-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Service\\\\TraceId\\\\TraceIdService\\:\\:handleClientRequest\\(\\) return type has no value type specified in iterable type array\\.$#"
50-
count: 1
51-
path: src/Service/TraceId/TraceIdService.php
52-
53-
-
54-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Service\\\\TraceServiceInterface\\:\\:handleClientRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
55-
count: 1
56-
path: src/Service/TraceServiceInterface.php
43+
path: tests/Functional/AbstractKernelTestCase.php
5744

5845
-
59-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Service\\\\TraceServiceInterface\\:\\:handleClientRequest\\(\\) return type has no value type specified in iterable type array\\.$#"
46+
message: '#^Parameter \#1 \$options \(array\{environment\?\: string, debug\?\: bool, tracemode\?\: string\}\) of method DR\\SymfonyTraceBundle\\Tests\\Functional\\AbstractKernelTestCase\:\:createKernel\(\) should be contravariant with parameter \$options \(array\) of method Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase\:\:createKernel\(\)$#'
47+
identifier: method.childParameterType
6048
count: 1
61-
path: src/Service/TraceServiceInterface.php
49+
path: tests/Functional/AbstractKernelTestCase.php
6250

6351
-
64-
message: "#^Parameter \\#1 \\$options \\(array\\{environment\\?\\: string, debug\\?\\: bool, tracemode\\?\\: string\\}\\) of method DR\\\\SymfonyTraceBundle\\\\Tests\\\\Functional\\\\AbstractKernelTestCase\\:\\:createKernel\\(\\) should be contravariant with parameter \\$options \\(array\\) of method Symfony\\\\Bundle\\\\FrameworkBundle\\\\Test\\\\KernelTestCase\\:\\:createKernel\\(\\)$#"
52+
message: '#^Cannot cast mixed to string\.$#'
53+
identifier: cast.string
6554
count: 1
66-
path: tests/Functional/AbstractKernelTestCase.php
55+
path: tests/Functional/AbstractWebTestCase.php
6756

6857
-
69-
message: "#^Parameter \\#1 \\$options \\(array\\{environment\\?\\: string, debug\\?\\: bool, tracemode\\?\\: string\\}\\) of method DR\\\\SymfonyTraceBundle\\\\Tests\\\\Functional\\\\AbstractWebTestCase\\:\\:createKernel\\(\\) should be contravariant with parameter \\$options \\(array\\) of method Symfony\\\\Bundle\\\\FrameworkBundle\\\\Test\\\\KernelTestCase\\:\\:createKernel\\(\\)$#"
58+
message: '#^Parameter \#1 \$options \(array\{environment\?\: string, debug\?\: bool, tracemode\?\: string\}\) of method DR\\SymfonyTraceBundle\\Tests\\Functional\\AbstractWebTestCase\:\:createKernel\(\) should be contravariant with parameter \$options \(array\) of method Symfony\\Bundle\\FrameworkBundle\\Test\\KernelTestCase\:\:createKernel\(\)$#'
59+
identifier: method.childParameterType
7060
count: 1
7161
path: tests/Functional/AbstractWebTestCase.php
7262

7363
-
74-
message: "#^Method DR\\\\SymfonyTraceBundle\\\\Tests\\\\Functional\\\\App\\\\Monolog\\\\MemoryHandler\\:\\:write\\(\\) has parameter \\$record with no value type specified in iterable type array\\.$#"
64+
message: '#^Method DR\\SymfonyTraceBundle\\Tests\\Functional\\App\\Monolog\\MemoryHandler\:\:write\(\) has parameter \$record with no value type specified in iterable type array\.$#'
65+
identifier: missingType.iterableValue
7566
count: 1
7667
path: tests/Functional/App/Monolog/MemoryHandler.php

Diff for: src/DependencyInjection/Compiler/HttpClientTracePass.php

-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
*/
1818
class HttpClientTracePass implements CompilerPassInterface
1919
{
20-
/**
21-
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
22-
*/
2320
public function process(ContainerBuilder $container): void
2421
{
2522
if ($container->hasParameter(SymfonyTraceExtension::PARAMETER_KEY . '.http_client.enabled') === false ||

Diff for: src/DependencyInjection/SymfonyTraceExtension.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
* },
4949
* storage_service: ?string,
5050
* enable_monolog: bool,
51-
* enable_console: bool,
51+
* enable_console: bool|null,
5252
* console: array{
5353
* enabled: bool,
5454
* trace_id: ?string

Diff for: src/Http/TraceAwareHttpClient.php

+39
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,39 @@
1313
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
1414
use Symfony\Contracts\Service\ResetInterface;
1515

16+
/**
17+
* @phpstan-type HttpClientOptions array{
18+
* auth_basic?: string[]|string,
19+
* auth_bearer?: string,
20+
* query?: string[],
21+
* headers?: string[]|string[][],
22+
* body?: mixed[]|string|resource|\Traversable|\Closure|object,
23+
* json?: mixed,
24+
* user_data?: mixed,
25+
* max_redirects?: int,
26+
* http_version?: string,
27+
* base_uri?: string,
28+
* buffer?: bool|resource|\Closure,
29+
* on_progress?: callable(int $dlNow, int $dlSize, mixed[] $info): void,
30+
* resolve?: string[],
31+
* proxy?: string,
32+
* no_proxy?: string,
33+
* timeout?: int|float,
34+
* max_duration?: int|float,
35+
* bindto?: string,
36+
* verify_peer?: bool,
37+
* verify_host?: bool,
38+
* cafile?: string,
39+
* capath?: string,
40+
* local_cert?: string,
41+
* local_pk?: string,
42+
* passphrase?: string,
43+
* ciphers?: string,
44+
* peer_fingerprint?: string,
45+
* capture_peer_cert_chain?: bool,
46+
* extra?: mixed[]
47+
* }
48+
*/
1649
class TraceAwareHttpClient implements HttpClientInterface, ResetInterface, LoggerAwareInterface
1750
{
1851
public function __construct(
@@ -22,6 +55,9 @@ public function __construct(
2255
) {
2356
}
2457

58+
/**
59+
* @param HttpClientOptions $options
60+
*/
2561
public function request(string $method, string $url, array $options = []): ResponseInterface
2662
{
2763
$options = $this->service->handleClientRequest($this->storage->getTrace(), $method, $url, $options);
@@ -48,6 +84,9 @@ public function setLogger(LoggerInterface $logger): void
4884
}
4985
}
5086

87+
/**
88+
* @param HttpClientOptions $options
89+
*/
5190
public function withOptions(array $options): static
5291
{
5392
$this->client = $this->client->withOptions($options);

Diff for: src/Monolog/TraceProcessor.php

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public function __construct(private readonly TraceStorageInterface $storage)
1919
}
2020

2121
/**
22+
* @param array<string, mixed[]>|LogRecord $record
2223
* @inheritDoc
2324
*/
2425
public function __invoke(array|LogRecord $record): array|LogRecord

Diff for: src/Service/TraceContext/TraceContextParser.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private static function parseTraceState(string $traceState): array
3939
{
4040
$vendorStates = explode(',', $traceState);
4141
$vendorStates = array_map('trim', $vendorStates);
42-
$vendorStates = array_filter($vendorStates);
42+
$vendorStates = array_filter($vendorStates, static fn(string $value) => $value !== '');
4343

4444
$result = [];
4545
foreach ($vendorStates as $item) {

Diff for: src/Service/TraceId/TraceIdService.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ public function handleResponse(Response $response, TraceContext $context): void
6464

6565
public function handleClientRequest(TraceContext $trace, string $method, string $url, array $options = []): array
6666
{
67-
$options['headers'][$this->clientHeader] ??= $trace->getTraceId();
67+
$traceId = $trace->getTraceId();
68+
if ($traceId !== null) {
69+
$options['headers'][$this->clientHeader] ??= $traceId;
70+
}
6871

6972
return $options;
7073
}

Diff for: src/Service/TraceServiceInterface.php

+8
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44

55
namespace DR\SymfonyTraceBundle\Service;
66

7+
use DR\SymfonyTraceBundle\Http\TraceAwareHttpClient;
78
use DR\SymfonyTraceBundle\TraceContext;
89
use Symfony\Component\HttpFoundation\Request;
910
use Symfony\Component\HttpFoundation\Response;
1011

12+
/**
13+
* @phpstan-import-type HttpClientOptions from TraceAwareHttpClient
14+
*/
1115
interface TraceServiceInterface
1216
{
1317
public function supports(Request $request): bool;
@@ -20,5 +24,9 @@ public function getRequestTrace(Request $request): TraceContext;
2024

2125
public function handleResponse(Response $response, TraceContext $context): void;
2226

27+
/**
28+
* @param HttpClientOptions $options
29+
* @return HttpClientOptions
30+
*/
2331
public function handleClientRequest(TraceContext $trace, string $method, string $url, array $options = []): array;
2432
}

Diff for: tests/Functional/AbstractKernelTestCase.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ protected static function createKernel(array $options = []): TestKernel
1818
$env = $options['environment'] ?? $_ENV['APP_ENV'] ?? $_SERVER['APP_ENV'] ?? 'test';
1919
$debug = $options['debug'] ?? $_ENV['APP_DEBUG'] ?? $_SERVER['APP_DEBUG'] ?? true;
2020

21-
return new TestKernel($env, $debug, $options['tracemode'] ?? Configuration::TRACEMODE_TRACEID);
21+
return new TestKernel((string)$env, (bool)$debug, $options['tracemode'] ?? Configuration::TRACEMODE_TRACEID);
2222
}
2323
}

Diff for: tests/Functional/AbstractWebTestCase.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ protected static function createKernel(array $options = []): TestKernel
1818
$env = $options['environment'] ?? $_ENV['APP_ENV'] ?? $_SERVER['APP_ENV'] ?? 'test';
1919
$debug = $options['debug'] ?? $_ENV['APP_DEBUG'] ?? $_SERVER['APP_DEBUG'] ?? false;
2020

21-
return new TestKernel($env, $debug, $options['tracemode'] ?? Configuration::TRACEMODE_TRACEID);
21+
return new TestKernel((string)$env, (bool)$debug, $options['tracemode'] ?? Configuration::TRACEMODE_TRACEID);
2222
}
2323
}

Diff for: tests/Functional/App/Service/MockClientCallbackHelper.php

-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ class MockClientCallbackHelper
1313
* @param array{
1414
* headers: string[]
1515
* } $options
16-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
1716
*/
1817
public function __invoke(string $method, string $url, array $options): ResponseInterface
1918
{

Diff for: tests/Unit/Monolog/TraceIdProcessorTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public function testProcessorAddsTraceIdWhenIdIsPresentArrayFormat(): void
6161
$this->idStorage->expects(static::once())->method('getTraceId')->willReturn('abc123');
6262

6363
$record = ($this->processor)([]);
64-
static::assertIsArray($record);
64+
static::assertIsArray($record['extra']);
6565
static::assertArrayHasKey('trace_id', $record['extra']);
6666
static::assertSame('abc123', $record['extra']['trace_id']);
6767
}

Diff for: tests/Unit/Service/TraceContext/TraceContextParserTest.php

+14
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ public function testParseTraceContext(): void
3131
static::assertSame(['foo' => 'bar', 'bar' => 'baz'], $traceContext->getTraceState());
3232
}
3333

34+
public function testParseTraceContextLeadingComma(): void
35+
{
36+
$traceContext = TraceContextParser::parseTraceContext(
37+
'00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-00',
38+
'foo=bar,bar=baz,'
39+
);
40+
41+
static::assertSame('00', $traceContext->getVersion());
42+
static::assertSame('0af7651916cd43dd8448eb211c80319c', $traceContext->getTraceId());
43+
static::assertSame('b7ad6b7169203331', $traceContext->getParentTransactionId());
44+
static::assertSame('00', $traceContext->getFlags());
45+
static::assertSame(['foo' => 'bar', 'bar' => 'baz'], $traceContext->getTraceState());
46+
}
47+
3448
public function testParseTraceContextInvalidParent(): void
3549
{
3650
$this->expectExceptionMessage('Invalid traceparent header');

Diff for: tests/Unit/Service/TraceId/TraceIdServiceTest.php

+9
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@ public function testHandleClientRequest(): void
9393
$trace->setTransactionId('123');
9494

9595
$options = $this->service->handleClientRequest($trace, 'GET', 'http://example.com');
96+
static::assertArrayHasKey('headers', $options);
97+
static::assertArrayHasKey(self::CLIENT_HEADER, $options['headers']);
9698
static::assertSame('abc', $options['headers'][self::CLIENT_HEADER]);
9799
}
100+
101+
public function testHandleClientRequestNullTraceId(): void
102+
{
103+
$options = $this->service->handleClientRequest(new TraceContext(), 'GET', 'http://example.com', ['headers' => []]);
104+
static::assertArrayHasKey('headers', $options);
105+
static::assertArrayNotHasKey(self::CLIENT_HEADER, $options['headers']);
106+
}
98107
}

0 commit comments

Comments
 (0)