Skip to content

PHPStan 2 + GHA CI #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 22, 2024
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
50 changes: 50 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: CI

on:
pull_request: ~
push:
branches:
- master
schedule:
- cron: "47 6 * * 1" # once a month, to surface issues with newer dependencies

jobs:
Tests:
runs-on: 'ubuntu-latest'
strategy:
matrix:
php:
- '7.4'
- '8.0'
- '8.1'
- '8.2'
- '8.3'
- '8.4'
dependencies: ['highest']
include:
- description: '(lowest)'
php: '7.4'
dependencies: 'lowest'

name: PHP ${{ matrix.php }} ${{ matrix.description }}
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: "Install PHP"
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: xdebug
- name: "Install dependencies"
uses: ramsey/composer-install@v3
with:
dependency-versions: ${{ matrix.dependencies }}
- name: "Run PHPStan analysis"
run: composer phpstan
- name: "Run tests"
run: vendor/bin/phpunit --coverage-clover=coverage.xml --colors=always
- name: "Upload test coverage"
uses: codecov/codecov-action@v5
with:
files: './coverage.xml'
fail_ci_if_error: true
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
/composer.lock
/phpunit.xml
/tmp
/build/
/build/
*.cache
34 changes: 0 additions & 34 deletions .travis.yml

This file was deleted.

10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
}
],
"require": {
"php": "^7.1 || ^8.0",
"phpstan/phpstan": "^1.0",
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^2.0",
"thecodingmachine/safe": "^1.0 || ^2.0"
},
"require-dev": {
"phpunit/phpunit": "^7.5.2 || ^8.0",
"phpunit/phpunit": "^9.6",
"php-coveralls/php-coveralls": "^2.1",
"squizlabs/php_codesniffer": "^3.4"
},
Expand All @@ -30,13 +30,13 @@
}
},
"scripts": {
"phpstan": "phpstan analyse src -c phpstan.neon --level=7 --no-progress -vvv",
"phpstan": "phpstan analyse -c phpstan.neon --no-progress -vvv",
"cs-fix": "phpcbf",
"cs-check": "phpcs"
},
"extra": {
"branch-alias": {
"dev-master": "1.1-dev"
"dev-master": "2.0-dev"
},
"phpstan": {
"includes": [
Expand Down
20 changes: 20 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
parameters:
level: max
paths:
- src
ignoreErrors:
-
message: '#^Implementing PHPStan\\Rules\\IdentifierRuleError is not covered by backward compatibility promise\. The interface might change in a minor PHPStan version\.$#'
identifier: phpstanApi.interface
count: 1
path: src/Rules/Error/SafeRuleError.php

-
message: '#^Implementing PHPStan\\Rules\\LineRuleError is not covered by backward compatibility promise\. The interface might change in a minor PHPStan version\.$#'
identifier: phpstanApi.interface
count: 1
path: src/Rules/Error/SafeRuleError.php

-
message: '#^Implementing PHPStan\\Rules\\RuleError is not covered by backward compatibility promise\. The interface might change in a minor PHPStan version\.$#'
identifier: phpstanApi.interface
count: 1
path: src/Rules/Error/SafeRuleError.php
includes:
- phpstan-safe-rule.neon
65 changes: 31 additions & 34 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,36 +1,33 @@
<phpunit
bootstrap="tests/bootstrap.php"
colors="true"
backupGlobals="false"
backupStaticAttributes="false"
beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
failOnWarning="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
bootstrap="tests/bootstrap.php"
colors="true"
backupGlobals="false"
backupStaticAttributes="false"
beStrictAboutChangesToGlobalState="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
failOnWarning="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<testsuites>
<testsuite name="Test suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
<logging>
<log
type="coverage-text"
target="php://stdout"
showUncoveredFiles="true"
showOnlySummary="true"
/>
<log type="coverage-html" target="build/coverage"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<testsuites>
<testsuite name="Test suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">./src</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"/>
<html outputDirectory="build/coverage"/>
<text outputFile="php://stdout" showUncoveredFiles="true" showOnlySummary="true"/>
</report>
</coverage>
</phpunit>
21 changes: 21 additions & 0 deletions src/Rules/Error/SafeClassRuleError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace TheCodingMachine\Safe\PHPStan\Rules\Error;

use PhpParser\Node\Name;

class SafeClassRuleError extends SafeRuleError
{
public function __construct(Name $className, int $line)
{
parent::__construct(
"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.",
$line,
);
}

public function getIdentifier(): string
{
return self::IDENTIFIER_PREFIX . 'class';
}
}
23 changes: 23 additions & 0 deletions src/Rules/Error/SafeFunctionRuleError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace TheCodingMachine\Safe\PHPStan\Rules\Error;

use PhpParser\Node\Name;

class SafeFunctionRuleError extends SafeRuleError
{
public function __construct(Name $nodeName, int $line)
{
$functionName = $nodeName->toString();

parent::__construct(
"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.",
$line,
);
}

public function getIdentifier(): string
{
return self::IDENTIFIER_PREFIX . 'class';
}
}
31 changes: 31 additions & 0 deletions src/Rules/Error/SafeRuleError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace TheCodingMachine\Safe\PHPStan\Rules\Error;

use PHPStan\Rules\IdentifierRuleError;
use PHPStan\Rules\LineRuleError;
use PHPStan\Rules\RuleError;

abstract class SafeRuleError implements RuleError, LineRuleError, IdentifierRuleError
{
protected const IDENTIFIER_PREFIX = 'theCodingMachineSafe.';

private string $message;
private int $line;

public function __construct(string $message, int $line)
{
$this->message = $message;
$this->line = $line;
}

public function getMessage(): string
{
return $this->message;
}

public function getLine(): int
{
return $this->line;
}
}
17 changes: 4 additions & 13 deletions src/Rules/UseSafeClassesRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,9 @@

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Rules\Rule;
use PHPStan\ShouldNotHappenException;
use TheCodingMachine\Safe\PHPStan\Rules\Error\SafeClassRuleError;
use TheCodingMachine\Safe\PHPStan\Utils\ClassListLoader;
use TheCodingMachine\Safe\PHPStan\Utils\FunctionListLoader;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Scalar;

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

/**
* @param Node\Expr\New_ $node
* @param \PHPStan\Analyser\Scope $scope
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
$classNode = $node->class;
Expand All @@ -43,7 +32,9 @@ public function processNode(Node $node, Scope $scope): array
$unsafeClasses = ClassListLoader::getClassList();

if (isset($unsafeClasses[$className])) {
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."];
return [
new SafeClassRuleError($classNode, $node->getStartLine()),
];
}

return [];
Expand Down
Loading