Skip to content

Commit ccd3d55

Browse files
authored
Merge pull request #35 from Jean85/phpstan-2
PHPStan 2 + GHA CI
2 parents 8a7b88e + 4c802d0 commit ccd3d55

13 files changed

+276
-152
lines changed

.github/workflows/tests.yaml

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: CI
2+
3+
on:
4+
pull_request: ~
5+
push:
6+
branches:
7+
- master
8+
schedule:
9+
- cron: "47 6 * * 1" # once a month, to surface issues with newer dependencies
10+
11+
jobs:
12+
Tests:
13+
runs-on: 'ubuntu-latest'
14+
strategy:
15+
matrix:
16+
php:
17+
- '7.4'
18+
- '8.0'
19+
- '8.1'
20+
- '8.2'
21+
- '8.3'
22+
- '8.4'
23+
dependencies: ['highest']
24+
include:
25+
- description: '(lowest)'
26+
php: '7.4'
27+
dependencies: 'lowest'
28+
29+
name: PHP ${{ matrix.php }} ${{ matrix.description }}
30+
steps:
31+
- name: "Checkout"
32+
uses: actions/checkout@v4
33+
- name: "Install PHP"
34+
uses: shivammathur/setup-php@v2
35+
with:
36+
php-version: ${{ matrix.php }}
37+
coverage: xdebug
38+
- name: "Install dependencies"
39+
uses: ramsey/composer-install@v3
40+
with:
41+
dependency-versions: ${{ matrix.dependencies }}
42+
- name: "Run PHPStan analysis"
43+
run: composer phpstan
44+
- name: "Run tests"
45+
run: vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always
46+
- name: "Upload test coverage"
47+
uses: codecov/codecov-action@v5
48+
with:
49+
files: './coverage.xml'
50+
fail_ci_if_error: true

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44
/composer.lock
55
/phpunit.xml
66
/tmp
7-
/build/
7+
/build/
8+
*.cache

.travis.yml

-34
This file was deleted.

composer.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
}
1111
],
1212
"require": {
13-
"php": "^7.1 || ^8.0",
14-
"phpstan/phpstan": "^1.0",
13+
"php": "^7.4 || ^8.0",
14+
"phpstan/phpstan": "^2.0",
1515
"thecodingmachine/safe": "^1.0 || ^2.0"
1616
},
1717
"require-dev": {
18-
"phpunit/phpunit": "^7.5.2 || ^8.0",
18+
"phpunit/phpunit": "^9.6",
1919
"php-coveralls/php-coveralls": "^2.1",
2020
"squizlabs/php_codesniffer": "^3.4"
2121
},
@@ -30,13 +30,13 @@
3030
}
3131
},
3232
"scripts": {
33-
"phpstan": "phpstan analyse src -c phpstan.neon --level=7 --no-progress -vvv",
33+
"phpstan": "phpstan analyse -c phpstan.neon --no-progress -vvv",
3434
"cs-fix": "phpcbf",
3535
"cs-check": "phpcs"
3636
},
3737
"extra": {
3838
"branch-alias": {
39-
"dev-master": "1.1-dev"
39+
"dev-master": "2.0-dev"
4040
},
4141
"phpstan": {
4242
"includes": [

phpstan.neon

+20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
11
parameters:
2+
level: max
3+
paths:
4+
- src
25
ignoreErrors:
6+
-
7+
message: '#^Implementing PHPStan\\Rules\\IdentifierRuleError is not covered by backward compatibility promise\. The interface might change in a minor PHPStan version\.$#'
8+
identifier: phpstanApi.interface
9+
count: 1
10+
path: src/Rules/Error/SafeRuleError.php
11+
12+
-
13+
message: '#^Implementing PHPStan\\Rules\\LineRuleError is not covered by backward compatibility promise\. The interface might change in a minor PHPStan version\.$#'
14+
identifier: phpstanApi.interface
15+
count: 1
16+
path: src/Rules/Error/SafeRuleError.php
17+
18+
-
19+
message: '#^Implementing PHPStan\\Rules\\RuleError is not covered by backward compatibility promise\. The interface might change in a minor PHPStan version\.$#'
20+
identifier: phpstanApi.interface
21+
count: 1
22+
path: src/Rules/Error/SafeRuleError.php
323
includes:
424
- phpstan-safe-rule.neon

phpunit.xml.dist

+31-34
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,33 @@
1-
<phpunit
2-
bootstrap="tests/bootstrap.php"
3-
colors="true"
4-
backupGlobals="false"
5-
backupStaticAttributes="false"
6-
beStrictAboutChangesToGlobalState="true"
7-
beStrictAboutOutputDuringTests="true"
8-
beStrictAboutTestsThatDoNotTestAnything="true"
9-
beStrictAboutTodoAnnotatedTests="true"
10-
failOnRisky="true"
11-
failOnWarning="true"
12-
convertErrorsToExceptions="true"
13-
convertNoticesToExceptions="true"
14-
convertWarningsToExceptions="true"
1+
<?xml version="1.0"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
4+
bootstrap="tests/bootstrap.php"
5+
colors="true"
6+
backupGlobals="false"
7+
backupStaticAttributes="false"
8+
beStrictAboutChangesToGlobalState="true"
9+
beStrictAboutOutputDuringTests="true"
10+
beStrictAboutTestsThatDoNotTestAnything="true"
11+
beStrictAboutTodoAnnotatedTests="true"
12+
failOnRisky="true"
13+
failOnWarning="true"
14+
convertErrorsToExceptions="true"
15+
convertNoticesToExceptions="true"
16+
convertWarningsToExceptions="true"
1517
>
16-
<testsuites>
17-
<testsuite name="Test suite">
18-
<directory>./tests/</directory>
19-
</testsuite>
20-
</testsuites>
21-
<filter>
22-
<whitelist>
23-
<directory suffix=".php">./src</directory>
24-
</whitelist>
25-
</filter>
26-
<logging>
27-
<log
28-
type="coverage-text"
29-
target="php://stdout"
30-
showUncoveredFiles="true"
31-
showOnlySummary="true"
32-
/>
33-
<log type="coverage-html" target="build/coverage"/>
34-
<log type="coverage-clover" target="build/logs/clover.xml"/>
35-
</logging>
18+
<testsuites>
19+
<testsuite name="Test suite">
20+
<directory>./tests/</directory>
21+
</testsuite>
22+
</testsuites>
23+
<coverage>
24+
<include>
25+
<directory suffix=".php">./src</directory>
26+
</include>
27+
<report>
28+
<clover outputFile="build/logs/clover.xml"/>
29+
<html outputDirectory="build/coverage"/>
30+
<text outputFile="php://stdout" showUncoveredFiles="true" showOnlySummary="true"/>
31+
</report>
32+
</coverage>
3633
</phpunit>
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace TheCodingMachine\Safe\PHPStan\Rules\Error;
4+
5+
use PhpParser\Node\Name;
6+
7+
class SafeClassRuleError extends SafeRuleError
8+
{
9+
public function __construct(Name $className, int $line)
10+
{
11+
parent::__construct(
12+
"Class $className is unsafe to use. Its methods can return FALSE instead of throwing an exception. Please add 'use Safe\\$className;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library.",
13+
$line,
14+
);
15+
}
16+
17+
public function getIdentifier(): string
18+
{
19+
return self::IDENTIFIER_PREFIX . 'class';
20+
}
21+
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace TheCodingMachine\Safe\PHPStan\Rules\Error;
4+
5+
use PhpParser\Node\Name;
6+
7+
class SafeFunctionRuleError extends SafeRuleError
8+
{
9+
public function __construct(Name $nodeName, int $line)
10+
{
11+
$functionName = $nodeName->toString();
12+
13+
parent::__construct(
14+
"Function $functionName is unsafe to use. It can return FALSE instead of throwing an exception. Please add 'use function Safe\\$functionName;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library.",
15+
$line,
16+
);
17+
}
18+
19+
public function getIdentifier(): string
20+
{
21+
return self::IDENTIFIER_PREFIX . 'class';
22+
}
23+
}

src/Rules/Error/SafeRuleError.php

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace TheCodingMachine\Safe\PHPStan\Rules\Error;
4+
5+
use PHPStan\Rules\IdentifierRuleError;
6+
use PHPStan\Rules\LineRuleError;
7+
use PHPStan\Rules\RuleError;
8+
9+
abstract class SafeRuleError implements RuleError, LineRuleError, IdentifierRuleError
10+
{
11+
protected const IDENTIFIER_PREFIX = 'theCodingMachineSafe.';
12+
13+
private string $message;
14+
private int $line;
15+
16+
public function __construct(string $message, int $line)
17+
{
18+
$this->message = $message;
19+
$this->line = $line;
20+
}
21+
22+
public function getMessage(): string
23+
{
24+
return $this->message;
25+
}
26+
27+
public function getLine(): int
28+
{
29+
return $this->line;
30+
}
31+
}

src/Rules/UseSafeClassesRule.php

+4-13
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@
55

66
use PhpParser\Node;
77
use PHPStan\Analyser\Scope;
8-
use PHPStan\Reflection\FunctionReflection;
9-
use PHPStan\Reflection\MethodReflection;
108
use PHPStan\Rules\Rule;
11-
use PHPStan\ShouldNotHappenException;
9+
use TheCodingMachine\Safe\PHPStan\Rules\Error\SafeClassRuleError;
1210
use TheCodingMachine\Safe\PHPStan\Utils\ClassListLoader;
13-
use TheCodingMachine\Safe\PHPStan\Utils\FunctionListLoader;
14-
use PhpParser\Node\Arg;
15-
use PhpParser\Node\Expr;
16-
use PhpParser\Node\Scalar;
1711

1812
/**
1913
* This rule checks that no "unsafe" classes are instantiated in code.
@@ -27,11 +21,6 @@ public function getNodeType(): string
2721
return Node\Expr\New_::class;
2822
}
2923

30-
/**
31-
* @param Node\Expr\New_ $node
32-
* @param \PHPStan\Analyser\Scope $scope
33-
* @return string[]
34-
*/
3524
public function processNode(Node $node, Scope $scope): array
3625
{
3726
$classNode = $node->class;
@@ -43,7 +32,9 @@ public function processNode(Node $node, Scope $scope): array
4332
$unsafeClasses = ClassListLoader::getClassList();
4433

4534
if (isset($unsafeClasses[$className])) {
46-
return ["Class $className is unsafe to use. Its methods can return FALSE instead of throwing an exception. Please add 'use Safe\\$className;' at the beginning of the file to use the variant provided by the 'thecodingmachine/safe' library."];
35+
return [
36+
new SafeClassRuleError($classNode, $node->getStartLine()),
37+
];
4738
}
4839

4940
return [];

0 commit comments

Comments
 (0)