Skip to content
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

Add support to more output formats #181

Closed
llaville opened this issue Jun 1, 2024 · 3 comments
Closed

Add support to more output formats #181

llaville opened this issue Jun 1, 2024 · 3 comments

Comments

@llaville
Copy link
Contributor

llaville commented Jun 1, 2024

Hello,

As author of the SARIF PHP binding solution https://github.com/llaville/sarif-php-sdk I would like to propose a SARIF support.

For audience that don't know yet what is SARIF (Static Analysis Results Interchange Format), I suggest to read :

But my proposal is not limited to SARIF. With it we could add support to other formats not yet supported.

That will include, for example :

And whatever else we will need !

Now that introduction is opened, here is in details my proposal !

A Povils\PHPMND\Printer\Custom class that implements the standard Povils\PHPMND\Printer\Printer contract
and inspired by https://github.com/phpmd/phpmd/blob/2.15.0/src/main/php/PHPMD/TextUI/CommandLineOptions.php#L780

CLI options will be only :

  -o, --output=OUTPUT                  Generate an output to the specified path [default: "php://stdout"]
      --format=FORMAT                  Format of the report [default: "console"]

And remove old --xml-ouptut option

Here are some use cases :

Console (default output)

No change because this is the default. (Option to write/redirect results to a file with --output option)

SARIF format

bin/phpmnd /path/to/source --format SarifPrinter
source code
<?php

require_once '/path/to/autoload.php';

class SarifPrinter extends \Bartlett\Sarif\Converter\PhpMndConverter
{
}

Note

no implemention here because I propose to add support to my project as I did since release 1.2.0 for at least 3 other PHP linters : PHPCS, PHPLint, PHPStan

Checkstyle format

bin/phpmnd /path/to/source --format CheckstylePrinter

Now a version of CheckStyle implementation we can have :

source code
<?php

use Povils\PHPMND\DetectionResult;
use Povils\PHPMND\HintList;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Output\StreamOutput;

class CheckstylePrinter implements \Povils\PHPMND\Printer\Printer
{
    public function printData(OutputInterface $output, HintList $hintList, array $detections): void
    {
        $groupedList = $this->groupDetectionResultPerFile($detections);

        $document = new DOMDocument('1.0', 'UTF-8');
        $document->formatOutput = true;

        $rootElement = $document->createElement('checkstyle');
        $document->appendChild($rootElement);

        foreach ($groupedList as $path => $detectionResults) {
            $fileNode = $document->createElement('file');
            $fileNode->setAttribute('name', $path);

            $rootElement->appendChild($fileNode);

            foreach ($detectionResults as $detectionResult) {
                $snippet = $this->getSnippet(
                    $detectionResult->getFile()->getContents(),
                    $detectionResult->getLine(),
                    $detectionResult->getValue()
                );

                $errorNode = $document->createElement('error');
                $errorNode->setAttribute('line', (string) $detectionResult->getLine());
                $errorNode->setAttribute('column', (string) $snippet['col']);
                $errorNode->setAttribute('severity', 'error');
                $errorNode->setAttribute(
                    'message',
                    sprintf('Magic Number: %s', $detectionResult->getValue())
                );

                $fileNode->appendChild($errorNode);
            }

            $rootElement->appendChild($fileNode);
        }

        $xmlString = $document->saveXML();
        if (is_string($xmlString)) {
            $output->write($xmlString);
        }
    }

    /**
     * @param array<int, DetectionResult> $list
     *
     * @return array<int, DetectionResult[]>
     */
    private function groupDetectionResultPerFile(array $list): array
    {
        $result = [];

        foreach ($list as $detectionResult) {
            $result[$detectionResult->getFile()->getRelativePathname()][] = $detectionResult;
        }

        return $result;
    }

    /**
     * Get the snippet and information about it
     *
     * @param int|string $text
     *
     * @return array<string, string>
     */
    private function getSnippet(string $content, int $line, $text): array
    {
        $content = str_replace(["\r\n", "\r"], "\n", $content);
        $lines = explode("\n", $content);

        $lineContent = array_slice($lines, $line - 1, 1);
        $lineContent = reset($lineContent);
        $start = strpos($lineContent, $text . '');

        return [
            'snippet' => $lineContent,
            'line' => $line,
            'magic' => $text,
            'col' => $start,
        ];
    }
}

I'll propose a POC PR (not optimized, because we can do better, but essential are available) and link to this feature request just after.

@llaville
Copy link
Contributor Author

llaville commented Jun 1, 2024

My SARIF PHP SDK has an upcoming version 1.4.0 that will add PHPMD (PHP Mess Detector) to support SARIF.

Even if PHPMD has already a native support, my version gave more informations, and is not maintained by authors of PHPMD.

This is the goal of my proposal here. No need to maintained a SARIF output format, because I'll do if you accept this POC !

@llaville
Copy link
Contributor Author

llaville commented Jun 2, 2024

I've just published https://github.com/llaville/sarif-php-sdk/releases/tag/1.4.0 that support PHPMD !

Do you want to be the next one on list ?

@llaville
Copy link
Contributor Author

Any feedback will be greatly appreciated ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant