Skip to content

Commit d4486eb

Browse files
pjcdawkinsclaude
andcommitted
build: add PHPStan static analysis at level 5
Add phpstan/phpstan ^2 at level 5 with a baseline of 13 errors (all interface method gaps on ClientInterface and ConnectorInterface). Globally ignore new.static (deliberate polymorphism pattern). Add PHPStan step to GitHub Actions CI and a Makefile with lint/test targets. Fixes found by PHPStan: - Project::systemInformation() return type missing false case - RestoreOptions: redundant @return PHPDocs conflicting with native static return type - LogItem: static:: to self:: for private method - Tree::getBlob(): always-true instanceof and unreachable code - Resolver: always-true explode() assignment in condition - ResourceWithReferences: always-true getResponse() check - Result::getEntity(): redundant isset() on initialized property - Subscription::create(): new self() vs new static() return mismatch - EnvironmentTest: incorrect @var annotation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 61c1a74 commit d4486eb

15 files changed

Lines changed: 168 additions & 30 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,8 @@ jobs:
2626
- name: Install dependencies
2727
run: composer install --no-progress --no-suggest --no-interaction
2828

29+
- name: Run PHPStan
30+
run: ./vendor/bin/phpstan analyse
31+
2932
- name: Run PHPUnit tests
3033
run: ./vendor/bin/phpunit

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.PHONY: lint lint-phpstan test
2+
3+
lint: lint-phpstan
4+
5+
lint-phpstan:
6+
./vendor/bin/phpstan analyse
7+
8+
test:
9+
./vendor/bin/phpunit

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
},
1313
"require-dev": {
1414
"phpunit/phpunit": "^11",
15-
"symplify/easy-coding-standard": "^12.3"
15+
"symplify/easy-coding-standard": "^12.3",
16+
"phpstan/phpstan": "^2"
1617
},
1718
"autoload": {
1819
"psr-4": {

composer.lock

Lines changed: 54 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpstan-baseline.neon

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:get\(\)\.$#'
5+
identifier: method.notFound
6+
count: 1
7+
path: src/Model/Activity.php
8+
9+
-
10+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:patch\(\)\.$#'
11+
identifier: method.notFound
12+
count: 1
13+
path: src/Model/Organization/Address.php
14+
15+
-
16+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:get\(\)\.$#'
17+
identifier: method.notFound
18+
count: 2
19+
path: src/Model/Organization/Organization.php
20+
21+
-
22+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:patch\(\)\.$#'
23+
identifier: method.notFound
24+
count: 1
25+
path: src/Model/Organization/Organization.php
26+
27+
-
28+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:patch\(\)\.$#'
29+
identifier: method.notFound
30+
count: 1
31+
path: src/Model/Organization/Profile.php
32+
33+
-
34+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:get\(\)\.$#'
35+
identifier: method.notFound
36+
count: 1
37+
path: src/Model/Ref/Resolver.php
38+
39+
-
40+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:get\(\)\.$#'
41+
identifier: method.notFound
42+
count: 1
43+
path: src/Model/SetupOptions.php
44+
45+
-
46+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:patch\(\)\.$#'
47+
identifier: method.notFound
48+
count: 1
49+
path: src/Model/Team/Team.php
50+
51+
-
52+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:patch\(\)\.$#'
53+
identifier: method.notFound
54+
count: 1
55+
path: src/Model/UserAccess/ProjectUserAccess.php
56+
57+
-
58+
message: '#^Call to an undefined method GuzzleHttp\\ClientInterface\:\:post\(\)\.$#'
59+
identifier: method.notFound
60+
count: 1
61+
path: src/PlatformClient.php
62+
63+
-
64+
message: '#^Call to an undefined method Platformsh\\Client\\Connection\\ConnectorInterface\:\:getAccessToken\(\)\.$#'
65+
identifier: method.notFound
66+
count: 1
67+
path: src/PlatformClient.php
68+
69+
-
70+
message: '#^Call to an undefined method Platformsh\\Client\\Connection\\ConnectorInterface\:\:getAccountsEndpoint\(\)\.$#'
71+
identifier: method.notFound
72+
count: 2
73+
path: src/PlatformClient.php
74+
75+
-
76+
message: '#^Call to an undefined method Platformsh\\Client\\Connection\\ConnectorInterface\:\:getConfig\(\)\.$#'
77+
identifier: method.notFound
78+
count: 3
79+
path: src/PlatformClient.php

phpstan.neon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
includes:
2+
- phpstan-baseline.neon
3+
4+
parameters:
5+
level: 5
6+
paths:
7+
- src
8+
- tests
9+
ignoreErrors:
10+
# Deliberate pattern: resource classes use new static() for polymorphism.
11+
-
12+
identifier: new.static

src/Model/ActivityLog/LogItem.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function __toString()
3434
*/
3535
public static function singleFromJson(string $str): self|false
3636
{
37-
$data = static::decode($str);
37+
$data = self::decode($str);
3838
if (isset($data['data']['timestamp'], $data['data']['message'])) {
3939
$id = isset($data['_id']) ? (string) $data['_id'] : '';
4040
return new static($data['data']['timestamp'], $data['data']['message'], $id);
@@ -43,7 +43,7 @@ public static function singleFromJson(string $str): self|false
4343
}
4444

4545
/**
46-
* @return static[]
46+
* @return self[]
4747
*@deprecated use LogItem::multipleFromJsonStreamWithSeal() instead
4848
*/
4949
public static function multipleFromJsonStream(string $str): array
@@ -77,7 +77,7 @@ public static function multipleFromJsonStreamWithSeal(string $str): array
7777
if ($line === '') {
7878
continue;
7979
}
80-
$data = static::decode($line);
80+
$data = self::decode($line);
8181
if (is_array($data)) {
8282
if (! empty($data['seal'])) {
8383
$seal = true;

src/Model/Backups/RestoreOptions.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,30 @@ class RestoreOptions
1616

1717
private ?string $resourcesInit;
1818

19-
/**
20-
* @return RestoreOptions
21-
*/
2219
public function setEnvironmentName(?string $environmentName): static
2320
{
2421
$this->environmentName = $environmentName;
2522
return $this;
2623
}
2724

28-
/**
29-
* @return RestoreOptions
30-
*/
3125
public function setBranchFrom(?string $branchFrom): static
3226
{
3327
$this->branchFrom = $branchFrom;
3428
return $this;
3529
}
3630

37-
/**
38-
* @return RestoreOptions
39-
*/
4031
public function setRestoreCode(?bool $restoreCode): static
4132
{
4233
$this->restoreCode = $restoreCode;
4334
return $this;
4435
}
4536

46-
/**
47-
* @return RestoreOptions
48-
*/
4937
public function setRestoreResources(?bool $restoreResources): static
5038
{
5139
$this->restoreResources = $restoreResources;
5240
return $this;
5341
}
5442

55-
/**
56-
* @return RestoreOptions
57-
*/
5843
public function setResourcesInit(?string $init): static
5944
{
6045
$this->resourcesInit = $init;

src/Model/Git/Tree.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,11 @@ public function getBlob(string $path): false|Blob
6868
if ($object === false) {
6969
return false;
7070
}
71-
if ($object instanceof Blob) {
72-
return $object;
73-
}
7471
if ($object instanceof self) {
7572
throw new GitObjectTypeException('The requested file is a directory', $path);
7673
}
7774

78-
return false;
75+
return $object;
7976
}
8077

8178
/**

src/Model/Project.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ public function clearBuildCache(): Result
508508
/**
509509
* Returns system information about the project, e.g. the API version.
510510
*/
511-
public function systemInformation(): System
511+
public function systemInformation(): System|false
512512
{
513513
return System::get($this->getLink('#system'), '', $this->client);
514514
}

0 commit comments

Comments
 (0)