Closed llaville closed 1 day ago
Now, the major version 2.0 of SARIF PHP SDK is available, I'm focus to prepare the first release of bartlett/sarif-php-converters
that will support natively a reporter for PHPLint.
This is the reason, why PHPLint SarifOutput code should be upgrade before apply any dependency constraint (reason why I've declined https://github.com/overtrue/phplint/pull/209)
FYI @overtrue : I've just pushed code on new branch 9.4
. This code is operational, and I hope to release it tomorrow, unless we found a big issue.
In summary:
PS: see also examples https://github.com/overtrue/phplint/tree/9.4/examples/outputFormat
it's OK π
FYI @overtrue : I've just tested upcoming PHPLint 9.4.0 with bartlett/sarif-php-converters
and upgrade its doc accordingly.
More details on how to use/print SARIF report with PHPLint may be found at https://github.com/llaville/sarif-php-converters/blob/1.0/docs/converter/phplint.md
I should be able to publish the new version 9.4.0 stable (in state) later today.
Here is an example of how to invoke PHPLint on command line, to print results in console
, checkstyle
and sarif
format (human-readable with help of -v
verbose mode level)
bin/phplint --format checkstyle -p meter --no-cache --format console --format '\Overtrue\PHPLint\Output\SarifOutput' --bootstrap /shared/backups/bartlett/sarif-php-converters/vendor/autoload.php -v
[!NOTE]
--bootstrap
identify my local autoloader version of upcoming suppleant packagebartlett/sarif-php-converters
phplint 9.4.0-dev by overtrue and contributors.
Runtime : PHP 8.1.29
Configuration : /shared/backups/github/phplint/.phplint.yml
ββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ¬ββββββββββ
β Name β Value β Help β
ββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββ€
β path β ["src/","tests/"] β command β
ββββββββββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββ€
β configuration β ".phplint.yml" β command β
β no-configuration β false β command β
β exclude β ["vendor"] β command β
β extensions β ["php"] β command β
β jobs β 10 β command β
β no-cache β true β command β
β cache β ".phplint.cache" β command β
β no-progress β false β command β
β progress β "meter" β command β
β output β null β command β
β format β ["checkstyle","console","\\Overtrue\\PHPLint\\Output\\SarifOutput"] β command β
β warning β true β command β
β memory-limit β -1 β command β
β ignore-exit-code β false β command β
β bootstrap β "/shared/backups/bartlett/sarif-php-converters/vendor/autoload.php" β command β
ββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββ
Time: < 1 sec, Memory: 8.0 MiB, Cache: 0 hit, 54 misses, Processes: 54
[ERROR] 54 files, 3 errors
There was 3 errors:
1. /shared/backups/github/phplint/tests/fixtures/syntax_error.php:4
1| <?php
2|
3| print($a)
> 4|
unexpected end of file in line 4
2. /shared/backups/github/phplint/tests/fixtures/php-8.2_syntax.php:12
9| * with this source code in the file LICENSE.
10| */
11|
> 12| function alwaysReturnsFalse(): false
13| {
14| }
15|
False can not be used as a standalone type in line 12
3. /shared/backups/github/phplint/tests/fixtures/syntax_warning.php:12
9| * with this source code in the file LICENSE.
10| */
11|
> 12| declare(encoding="utf8");
13|
declare(encoding=...) ignored because Zend multibyte feature is turned off by settings in line 12
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "PHPLint",
"shortDescription": {
"text": "Syntax check only (lint) of PHP files"
},
"fullDescription": {
"text": "PHPLint is a tool that can speed up linting of php files by running several lint processes at once."
},
"fullName": "PHPLint version 9.4.9999999.9999999-dev by overtrue and contributors",
"semanticVersion": "9.4.9999999.9999999-dev",
"informationUri": "https://github.com/overtrue/phplint",
"rules": [
{
"id": "PHPLINT101",
"shortDescription": {
"text": "Syntax error"
},
"fullDescription": {
"text": "Syntax error detected when lint a file"
},
"helpUri": "https://www.php.net/manual/en/langref.php",
"help": {
"text": "https://www.php.net/manual/en/features.commandline.options.php"
}
}
]
},
"extensions": [
{
"name": "bartlett/sarif-php-converters",
"shortDescription": {
"text": "PHPLint SARIF Converter"
},
"version": "1.0.9999999.9999999-dev"
}
]
},
"invocations": [
{
"executionSuccessful": true,
"commandLine": "bin/phplint",
"arguments": [
"--format",
"checkstyle",
"-p",
"meter",
"--no-cache",
"--format",
"console",
"--format",
"\\Overtrue\\PHPLint\\Output\\SarifOutput",
"--bootstrap",
"/shared/backups/bartlett/sarif-php-converters/vendor/autoload.php",
"-v"
],
"workingDirectory": {
"uri": "file:///shared/backups/github/phplint/"
}
}
],
"originalUriBaseIds": {
"WORKINGDIR": {
"uri": "file:///shared/backups/github/phplint/"
}
},
"results": [
{
"message": {
"text": "unexpected end of file in line 4"
},
"ruleId": "PHPLINT101",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "tests/fixtures/syntax_error.php",
"uriBaseId": "WORKINGDIR"
},
"region": {
"startLine": 4,
"snippet": {
"rendered": {
"text": "\u001b[31m > \u001b[0m\u001b[90m4| \u001b[0m"
}
}
},
"contextRegion": {
"startLine": 2,
"endLine": 6,
"snippet": {
"rendered": {
"text": "\u001b[31m > \u001b[0m\u001b[90m2| \u001b[0m\n \u001b[90m3| \u001b[0m\u001b[32mprint(\u001b[0m\u001b[39m$a\u001b[0m\u001b[32m)\u001b[0m\n \u001b[90m4| \u001b[0m"
}
}
}
}
}
],
"partialFingerprints": {
"PHPLINT101": "9d2c5cee410c5007acb62ee25b9a0dfb740fb8f531235e6abc5dd7535930ef2f"
}
},
{
"message": {
"text": "False can not be used as a standalone type in line 12"
},
"ruleId": "PHPLINT101",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "tests/fixtures/php-8.2_syntax.php",
"uriBaseId": "WORKINGDIR"
},
"region": {
"startLine": 12,
"snippet": {
"rendered": {
"text": "\u001b[31m > \u001b[0m\u001b[90m12| \u001b[0m\u001b[32mfunction \u001b[0m\u001b[39malwaysReturnsFalse\u001b[0m\u001b[32m(): \u001b[0m\u001b[39mfalse\u001b[0m"
}
}
},
"contextRegion": {
"startLine": 10,
"endLine": 14,
"snippet": {
"rendered": {
"text": "\u001b[31m > \u001b[0m\u001b[90m10| \u001b[0m\u001b[33m */\u001b[0m\n \u001b[90m11| \u001b[0m\n \u001b[90m12| \u001b[0m\u001b[32mfunction \u001b[0m\u001b[39malwaysReturnsFalse\u001b[0m\u001b[32m(): \u001b[0m\u001b[39mfalse\u001b[0m\n \u001b[90m13| \u001b[0m\u001b[32m{\u001b[0m\n \u001b[90m14| \u001b[0m\u001b[32m}\u001b[0m"
}
}
}
}
}
],
"partialFingerprints": {
"PHPLINT101": "b4f5ba1d66790be578109d251ced990b42fe6117554a275142ab750f50ca39f4"
}
},
{
"message": {
"text": " declare(encoding=...) ignored because Zend multibyte feature is turned off by settings in line 12"
},
"ruleId": "PHPLINT101",
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "tests/fixtures/syntax_warning.php",
"uriBaseId": "WORKINGDIR"
},
"region": {
"startLine": 12,
"snippet": {
"rendered": {
"text": "\u001b[31m > \u001b[0m\u001b[90m12| \u001b[0m\u001b[32mdeclare(\u001b[0m\u001b[39mencoding\u001b[0m\u001b[32m=\u001b[0m\u001b[31m\"utf8\"\u001b[0m\u001b[32m);\u001b[0m"
}
}
},
"contextRegion": {
"startLine": 10,
"endLine": 14,
"snippet": {
"rendered": {
"text": "\u001b[31m > \u001b[0m\u001b[90m10| \u001b[0m\u001b[33m */\u001b[0m\n \u001b[90m11| \u001b[0m\n \u001b[90m12| \u001b[0m\u001b[32mdeclare(\u001b[0m\u001b[39mencoding\u001b[0m\u001b[32m=\u001b[0m\u001b[31m\"utf8\"\u001b[0m\u001b[32m);\u001b[0m\n \u001b[90m13| \u001b[0m"
}
}
}
}
}
],
"partialFingerprints": {
"PHPLINT101": "a1bed88116ad4e69c924107f5fa77a80379a08f2723871f5d0af6eb272dcf3c2"
}
}
],
"automationDetails": {
"id": "Daily run 2024-07-05T03:49:55+00:00"
}
}
]
}
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle>
<file name="/shared/backups/github/phplint/tests/fixtures/syntax_error.php">
<error line="4" severity="error" message="unexpected end of file in line 4"/>
</file>
<file name="/shared/backups/github/phplint/tests/fixtures/php-8.2_syntax.php">
<error line="12" severity="error" message="False can not be used as a standalone type in line 12"/>
</file>
<file name="/shared/backups/github/phplint/tests/fixtures/syntax_warning.php">
<error line="12" severity="error" message=" declare(encoding=...) ignored because Zend multibyte feature is turned off by settings in line 12"/>
</file>
</checkstyle>
Summary
Simplify ability to add support to more formats
Context
Even if I consider SARIF as the futur of reporter solution, I must admit that PHP project leaders/maintainers are a little reluctant to set up this format, and prefer to implement
checkstyle
,junit
,codeclimate
... to reference only few of them.This is the reason why I've already provided a PHP binding solution https://github.com/llaville/sarif-php-sdk,, and I'm currently working on an improvement with upcoming version 2.0
My goal is to maintain all classes for PHP Linters and Static Code Analyser on a new package
bartlett/sarif-php-converters
and removed converters from base package packagebartlett/sarif-php-sdk
See Reference below
Description
Even, If I've already implemented a solution into PHPLint, I must admit that it's a bit hard, and current OutputFormat extension did not allow to add support to more format easily. This is the MAIN goal of this feature request !
Recently, I've look on PHP Insights source code (especially the
FormatResolver
component), and I like ability to load custom format (not predefined). BTW, it suffer from a problem that PHPLint has not : the bootstrapping option.This is the main reason of new upcoming version 9.4.0 (/cc @overtrue)
Secondary goal is to simplify
OutputFormat
extension and respect the O (SRP) of SOLID principle.And last but not least, clean-up SARIF current implementation in PHPLint.
v9.4.0 will come after I've finished https://github.com/llaville/sarif-php-converters and release the first version 1.0 with sarif-php-sdk 2.0
FormatResolver source code
```php ConsoleOutput::class, 'json' => JsonOutput::class, 'junit' => JunitOutput::class, 'sarif' => SarifOutput::class, ]; public function __construct(private readonly Resolver $configResolver) { } /** * @return OutputInterface[] */ public function resolve(SymfonyInputInterface $input, SymfonyOutputInterface $output): array { $filename = $input->getOption('output'); if ($filename) { $stream = fopen($filename, 'w'); } else { $errOutput = $output instanceof SymfonyConsoleOutputInterface ? $output->getErrorOutput() : $output; if ($errOutput instanceof StreamOutput) { $stream = $errOutput->getStream(); } else { $stream = fopen('php://stdout', 'w'); } } $requestedFormats = array_merge($input->getOption('format'), $this->legacyLogOption()); $handlers = [$output]; foreach ($requestedFormats as $requestedFormat) { if ('console' === $requestedFormat) { // default behaviour continue; } if (array_key_exists($requestedFormat, self::FORMATTERS)) { // use built-in formatter $formatterClass = self::FORMATTERS[$requestedFormat]; $handlers[] = new $formatterClass($stream, $output->getVerbosity(), $output->isDecorated(), $output->getFormatter()); continue; } if (class_exists($requestedFormat)) { // try to load custom/external formatter $formatter = new $requestedFormat($stream, $output->getVerbosity(), $output->isDecorated(), $output->getFormatter()); if (!$formatter instanceof OutputInterface) { // skip invalid instance that does not implement contract continue; } $handlers[] = $formatter; } } return $handlers; } /** * Checks if there is any `--log-[*]` legacy options * * @return string[] */ private function legacyLogOption(): array { $outputOptions = [ OptionDefinition::LOG_JSON => 'json', OptionDefinition::LOG_JUNIT => 'junit', OptionDefinition::LOG_SARIF => 'sarif', ]; $requestedFormats = []; foreach ($outputOptions as $name => $format) { if ($this->configResolver->getOption($name)) { $requestedFormats[] = $format; } } return $requestedFormats; } } ```We will continue to support legacy options
--log-[*]
but we also add more genericReference
Here are officially what I will support