Skip to content

Commit 17bb014

Browse files
authored
Merge pull request #86 from sasezaki/context-type-rule-introduce
Introduce ContextTypeRule & LogMethodLevelRule to to support several context type
2 parents 92a1d2c + fb80b3f commit 17bb014

32 files changed

+1479
-49
lines changed

.laminas-ci.json

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,45 @@
11
{
22
"additional_checks": [
33
{
4-
"name": "phpstan",
4+
"name": "phpstan-lowest",
55
"job": {
66
"php": "@lowest",
77
"command": "./vendor/bin/phpstan analyse --no-progress"
88
}
99
},
1010
{
11-
"name": "psalm",
11+
"name": "phpstan-latest",
1212
"job": {
1313
"php": "@latest",
14+
"command": "./vendor/bin/phpstan analyse --no-progress"
15+
}
16+
},
17+
{
18+
"name": "psalm",
19+
"job": {
20+
"php": "8.3",
1421
"command": "./vendor/bin/psalm --shepherd --stats --output-format=github --no-cache -c psalm5.xml"
1522
}
1623
},
1724
{
18-
"name": "example",
25+
"name": "example-default",
26+
"job": {
27+
"php": "@latest",
28+
"command": "diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.default.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.default.output"
29+
}
30+
},
31+
{
32+
"name": "example-recommend",
33+
"job": {
34+
"php": "@latest",
35+
"command": "diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.recommend.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.recommend.output"
36+
}
37+
},
38+
{
39+
"name": "example-enableContextTypeRule",
1940
"job": {
2041
"php": "@latest",
21-
"command": "diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.output"
42+
"command": "diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.enableContextTypeRule.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.enableContextTypeRule.output"
2243
}
2344
}
2445
],

README.md

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,54 @@
44
[![License](https://poser.pugx.org/struggle-for-php/sfp-phpstan-psr-log/license)](https://packagist.org/packages/struggle-for-php/sfp-phpstan-psr-log)
55
[![Psalm coverage](https://shepherd.dev/github/struggle-for-php/sfp-phpstan-psr-log/coverage.svg)](https://shepherd.dev/github/struggle-for-php/sfp-phpstan-psr-log)
66

7+
> [!IMPORTANT]
8+
> The next version `0.25.0` will have a BC break. Please refer `Stubs` section.
9+
710
`struggle-for-php/sfp-phpstan-psr-log` is extra strict and opinionated psr/log (psr-3) rules for PHPStan.
811

912
* [PHPStan](https://phpstan.org/)
1013
* [PSR-3: Logger Interface - PHP-FIG](https://www.php-fig.org/psr/psr-3/)
1114
* [PSR-3 Meta Document](https://www.php-fig.org/psr/psr-3/meta/)
1215

13-
> [!IMPORTANT]
14-
> Since `0.20.0`, changed default rule settings.
16+
## Recommendation Settings
1517

16-
* MessageStaticStringRule is enabled by default.
17-
* ContextRequireExceptionKeyRule is disabled by default.
18-
* [Recommendation] write these parameters to your project's `phpstan.neon`.
18+
Write these parameters to your project's `phpstan.neon`.
1919

2020
```neon
2121
parameters:
2222
sfpPsrLog:
23-
enableMessageStaticStringRule: true
23+
enableMessageStaticStringRule: false # default:true
2424
enableContextRequireExceptionKeyRule: true
2525
reportContextExceptionLogLevel: 'info'
2626
contextKeyOriginalPattern: '#\A[A-Za-z0-9-_]+\z#'
2727
```
2828

2929
## Stubs
3030

31-
This extension depends on our psr/log stub to serve strictness.
31+
> [!IMPORTANT]
32+
> include psr/log stub be planned to dropped in next release.
33+
34+
To try out the changes in the next version,
35+
36+
DELETE `vendor/struggle-for-php/sfp-phpstan-psr-log/extension.neon` line from your `phpstan.neon`
37+
38+
```neon
39+
includes:
40+
- vendor/struggle-for-php/sfp-phpstan-psr-log/extension.neon
41+
```
42+
43+
and, set parameters `enableLogLevelMethodRule` and `enableContextTypeRule`
44+
45+
```neon
46+
parameters:
47+
sfpPsrLog:
48+
enableLogLevelMethodRule: true # default:false
49+
enableContextTypeRule: true # default:false
50+
```
51+
52+
### About stub
53+
54+
Currently, this extension depends on our psr/log stub to serve strictness.
3255

3356
* eg.
3457
* `@param LogLevel::* $level` at `log()` method
@@ -221,11 +244,9 @@ To use this extension, require it in [Composer](https://getcomposer.org/):
221244
composer require --dev struggle-for-php/sfp-phpstan-psr-log
222245
```
223246

224-
If you also install [phpstan/extension-installer](https://github.com/phpstan/extension-installer) then you're all set.
225-
226247
### Manual installation
227248

228-
If you don't want to use `phpstan/extension-installer`, include extension.neon & rules.neon in your project's PHPStan config:
249+
include extension.neon & rules.neon in your project's PHPStan config:
229250

230251
```neon
231252
includes:
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
declare(strict_types=1);
5+
6+
use PHPStan\DependencyInjection\ContainerFactory;
7+
use Sfp\PHPStan\Psr\Log\TypeMapping\BigQuery\GenericTableFieldSchemaJsonPayloadTypeMapper;
8+
use Sfp\PHPStan\Psr\Log\TypeProvider\BigQueryContextTypeProvider;
9+
10+
/**
11+
* borrowed from doctrine/sql-formatter 's sql-formatter
12+
*/
13+
14+
if ('cli' !== php_sapi_name()) {
15+
echo "<p>Run this PHP script from the command line to see mapping BigQuery schema to PHPStan Type. It supports Unix pipes or command line argument style.</p>";
16+
exit;
17+
}
18+
19+
if (isset($argv[1])) {
20+
$schema = $argv[1];
21+
} else {
22+
$schema = stream_get_contents(fopen('php://stdin', 'r'));
23+
}
24+
25+
$autoloadFiles = [
26+
2 => __DIR__ . '/../vendor/autoload.php',
27+
3 => __DIR__ . '/../../../autoload.php',
28+
];
29+
30+
$rootDir = false;
31+
foreach ($autoloadFiles as $deps => $autoloadFile) {
32+
if (file_exists($autoloadFile)) {
33+
$rootDir = dirname($autoloadFile, $deps);
34+
require_once $autoloadFile;
35+
break;
36+
}
37+
}
38+
39+
// bootstrap ReflectionProvider
40+
$containerFactory = new ContainerFactory($rootDir);
41+
$containerFactory->create(sys_get_temp_dir() . DIRECTORY_SEPARATOR . __FILE__, [], []);
42+
43+
$converter = new GenericTableFieldSchemaJsonPayloadTypeMapper();
44+
$provider = new BigQueryContextTypeProvider(
45+
'data://,' . $schema,
46+
$converter
47+
);
48+
49+
echo $provider->getType()->toPhpDocNode();

composer-require-checker.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
"PHPStan\\Type\\ArrayType",
1818
"PHPStan\\Type\\Constant\\ConstantStringType",
1919
"PHPStan\\Type\\ObjectType",
20-
"PHPStan\\Type\\Type"
20+
"PHPStan\\Type\\Type",
21+
"PHPStan\\Type\\Accessory\\AccessoryNumericStringType",
22+
"PHPStan\\Type\\BooleanType",
23+
"PHPStan\\Type\\Constant\\ConstantArrayType",
24+
"PHPStan\\Type\\Constant\\ConstantArrayTypeBuilder",
25+
"PHPStan\\Type\\FloatType",
26+
"PHPStan\\Type\\IntegerType",
27+
"PHPStan\\Type\\StringType",
28+
"PHPStan\\Type\\TypeCombinator"
2129
]
2230
}

composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
],
99
"require": {
1010
"php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
11+
"ext-json": "*",
1112
"phpstan/phpstan": "^1.12 || ^2.0",
1213
"struggle-for-php/sfp-stubs-psr-log": "^1.0.1 || ^2 || ^3.0.1"
1314
},
@@ -40,6 +41,7 @@
4041
"dealerdirect/phpcodesniffer-composer-installer": true
4142
}
4243
},
44+
"bin": ["bin/phpstan-type-mapping-from-bigquery"],
4345
"extra": {
4446
"phpstan": {
4547
"includes": [

example/phpstan.default.neon

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# usage.
2+
# ./vendor/bin/phpstan analyse -c ./example/phpstan.default.neon
3+
#
4+
# docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-continuous-integration:1 \
5+
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"./vendor/bin/phpstan analyse -c ./example/phpstan.default.neon --no-progress --error-format=junit | xmllint --format -"}'
6+
# docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-continuous-integration:1 \
7+
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.default.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.output"}'
8+
9+
parameters:
10+
level: 5
11+
bootstrapFiles:
12+
- %currentWorkingDirectory%/vendor/autoload.php
13+
paths:
14+
- %currentWorkingDirectory%/example/src
15+
stubFiles:
16+
# relative path can not work
17+
- ../vendor/struggle-for-php/sfp-stubs-psr-log/stubs-for-throwable/LoggerInterface.phpstub
18+
19+
includes:
20+
# relative path can not work
21+
# - %currentWorkingDirectory%/extension.neon
22+
- %currentWorkingDirectory%/rules.neon
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# usage.
2+
# ./vendor/bin/phpstan analyse -c ./example/phpstan.enableContextTypeRule.neon
3+
#
4+
# docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-continuous-integration:1 \
5+
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"./vendor/bin/phpstan analyse -c ./example/phpstan.enableContextTypeRule.neon --no-progress --error-format=junit | xmllint --format -"}'
6+
# docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-continuous-integration:1 \
7+
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.enableContextTypeRule.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.output"}'
8+
9+
parameters:
10+
level: 5
11+
bootstrapFiles:
12+
- %currentWorkingDirectory%/vendor/autoload.php
13+
paths:
14+
- %currentWorkingDirectory%/example/src
15+
sfpPsrLog:
16+
enableLogLevelMethodRule: true
17+
enableContextTypeRule: true
18+
19+
# services:
20+
# sfpPsrLogContextTypeProvider :
21+
# class: Sfp\PHPStan\Psr\Log\TypeProvider\Psr3ContextTypeProvider
22+
# arguments:
23+
# exceptionClass: '\Exception'
24+
25+
includes:
26+
- %currentWorkingDirectory%/rules.neon

example/phpstan.neon renamed to example/phpstan.recommend.neon

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# usage.
2-
# ./vendor/bin/phpstan analyse -c ./example/phpstan.neon
2+
# ./vendor/bin/phpstan analyse -c ./example/phpstan.recommend.neon
33
#
44
# docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-continuous-integration:1 \
5-
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"./vendor/bin/phpstan analyse -c ./example/phpstan.neon --no-progress --error-format=junit | xmllint --format -"}'
5+
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"./vendor/bin/phpstan analyse -c ./example/phpstan.recommend.neon --no-progress --error-format=junit | xmllint --format -"}'
66
# docker run -v $(realpath .):/github/workspace -w=/github/workspace ghcr.io/laminas/laminas-continuous-integration:1 \
7-
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.output"}'
7+
# '{"php":"8.2","dependencies":"latest","extensions":[],"ini":["memory_limit=-1"],"command":"diff <(./vendor/bin/phpstan analyse -c ./example/phpstan.recommend.neon --no-progress --error-format=junit | xmllint --format -) ./test/example.output"}'
88

99
parameters:
1010
level: 5
@@ -17,10 +17,11 @@ parameters:
1717
enableMessageStaticStringRule: true
1818
reportContextExceptionLogLevel: 'notice'
1919
contextKeyOriginalPattern: '#\A[A-Za-z0-9-]+\z#'
20+
enableContextTypeRule: false
2021
stubFiles:
2122
- ../vendor/struggle-for-php/sfp-stubs-psr-log/stubs-for-throwable/LoggerInterface.phpstub
2223

2324
includes:
2425
# relative path can not work
25-
# - %currentWorkingDirectory%/extension.neon
26+
# - %currentWorkingDirectory%/extension.neon
2627
- %currentWorkingDirectory%/rules.neon

example/src/Example.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace src;
66

77
use Psr\Log\LoggerInterface;
8-
use Throwable;
98

109
use function sprintf;
1110

@@ -19,8 +18,10 @@ public function __construct(LoggerInterface $logger)
1918
$this->logger = $logger;
2019
}
2120

22-
public function exceptionKeyOnlyAllowThrowable(Throwable $throwable): void
23-
{
21+
public function exceptionKeyOnlyAllowThrowable(
22+
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly
23+
\Throwable $throwable
24+
): void {
2425
// invalid
2526
$this->logger->notice('foo', ['exception' => $throwable->getMessage()]);
2627
$this->logger->log('panic', 'foo', ['exception' => $throwable]);
@@ -29,17 +30,21 @@ public function exceptionKeyOnlyAllowThrowable(Throwable $throwable): void
2930
$this->logger->log('notice', 'foo', ['exception' => $throwable]);
3031
}
3132

32-
public function mustIncludesCurrentScopeThrowableIntoContext(Throwable $throwable): void
33-
{
33+
public function mustIncludesCurrentScopeThrowableIntoContext(
34+
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly
35+
\Throwable $throwable
36+
): void {
3437
// Parameter $context of logger method Psr\Log\LoggerInterface::info() requires 'exception' key. Current scope has Throwable variable - $throwable
3538
$this->logger->notice('foo');
3639

3740
$this->logger->notice('foo', ['user' => 1]);
3841
}
3942

40-
public function reportContextExceptionLogLevel(Throwable $throwable): void
41-
{
42-
// phpstan.neon sfpPsrLog.reportContextExceptionLogLevel is 'notice'
43+
public function reportContextExceptionLogLevel(
44+
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly
45+
\Throwable $throwable
46+
): void {
47+
// phpstan.enableContextTypeRule.neon sfpPsrLog.reportContextExceptionLogLevel is 'notice'
4348
// so bellow would not report.
4449
$this->logger->debug('foo');
4550
}

phpcs.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
<file>src</file>
1717
<file>test</file>
1818

19+
<exclude-pattern>test/TypeProvider/data/*</exclude-pattern>
20+
1921
<!-- Include all rules from Laminas Coding Standard -->
2022
<rule ref="LaminasCodingStandard"/>
2123

2224
<rule ref="PSR12">
2325
<exclude name="Generic.Files.LineLength"/>
2426
<exclude name="WebimpressCodingStandard.Formatting.StringClassReference" />
2527
</rule>
26-
</ruleset>
28+
</ruleset>

0 commit comments

Comments
 (0)