Skip to content

Commit

Permalink
Support for relative paths in editorUrl for Docker environment
Browse files Browse the repository at this point in the history
  • Loading branch information
Wirone committed Jun 18, 2022
1 parent 518b413 commit e61a782
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 34 deletions.
1 change: 1 addition & 0 deletions conf/config.neon
Expand Up @@ -1954,6 +1954,7 @@ services:
errorFormatter.table:
class: PHPStan\Command\ErrorFormatter\TableErrorFormatter
arguments:
simpleRelativePathHelper: @simpleRelativePathHelper
showTipsOfTheDay: %tipsOfTheDay%
editorUrl: %editorUrl%

Expand Down
8 changes: 7 additions & 1 deletion src/Command/ErrorFormatter/TableErrorFormatter.php
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Command\AnalysisResult;
use PHPStan\Command\Output;
use PHPStan\File\RelativePathHelper;
use PHPStan\File\SimpleRelativePathHelper;
use Symfony\Component\Console\Formatter\OutputFormatter;
use function array_map;
use function count;
Expand All @@ -19,6 +20,7 @@ class TableErrorFormatter implements ErrorFormatter

public function __construct(
private RelativePathHelper $relativePathHelper,
private SimpleRelativePathHelper $simpleRelativePathHelper,
private CiDetectedErrorFormatter $ciDetectedErrorFormatter,
private bool $showTipsOfTheDay,
private ?string $editorUrl,
Expand Down Expand Up @@ -78,7 +80,11 @@ public function formatErrors(
}
if (is_string($this->editorUrl)) {
$editorFile = $error->getTraitFilePath() ?? $error->getFilePath();
$url = str_replace(['%file%', '%line%'], [$editorFile, (string) $error->getLine()], $this->editorUrl);
$url = str_replace(
['%file%', '%relFile%', '%line%'],
[$editorFile, $this->simpleRelativePathHelper->getRelativePath($editorFile), (string) $error->getLine()],
$this->editorUrl,
);
$message .= "\n✏️ <href=" . OutputFormatter::escape($url) . '>' . $this->relativePathHelper->getRelativePath($editorFile) . '</>';
}
$rows[] = [
Expand Down
36 changes: 22 additions & 14 deletions src/Testing/ErrorFormatterTestCase.php
Expand Up @@ -25,38 +25,46 @@ abstract class ErrorFormatterTestCase extends PHPStanTestCase

protected const DIRECTORY_PATH = '/data/folder/with space/and unicode 😃/project';

private ?StreamOutput $outputStream = null;
private const KIND_DECORATED = 'decorated';
private const KIND_PLAIN = 'plain';

private ?Output $output = null;
/** @var array<string, StreamOutput> */
private array $outputStream = [];

private function getOutputStream(): StreamOutput
/** @var array<string, Output> */
private array $output = [];

private function getOutputStream(bool $decorated = false): StreamOutput
{
if ($this->outputStream === null) {
$kind = $decorated ? self::KIND_DECORATED : self::KIND_PLAIN;
if (!isset($this->outputStream[$kind])) {
$resource = fopen('php://memory', 'w', false);
if ($resource === false) {
throw new ShouldNotHappenException();
}
$this->outputStream = new StreamOutput($resource, StreamOutput::VERBOSITY_NORMAL, false);
$this->outputStream[$kind] = new StreamOutput($resource, StreamOutput::VERBOSITY_NORMAL, $decorated);
}

return $this->outputStream;
return $this->outputStream[$kind];
}

protected function getOutput(): Output
protected function getOutput(bool $decorated = false): Output
{
if ($this->output === null) {
$errorConsoleStyle = new ErrorsConsoleStyle(new StringInput(''), $this->getOutputStream());
$this->output = new SymfonyOutput($this->getOutputStream(), new SymfonyStyle($errorConsoleStyle));
$kind = $decorated ? self::KIND_DECORATED : self::KIND_PLAIN;
if (!isset($this->output[$kind])) {
$outputStream = $this->getOutputStream($decorated);
$errorConsoleStyle = new ErrorsConsoleStyle(new StringInput(''), $outputStream);
$this->output[$kind] = new SymfonyOutput($outputStream, new SymfonyStyle($errorConsoleStyle));
}

return $this->output;
return $this->output[$kind];
}

protected function getOutputContent(): string
protected function getOutputContent(bool $decorated = false): string
{
rewind($this->getOutputStream()->getStream());
rewind($this->getOutputStream($decorated)->getStream());

$contents = stream_get_contents($this->getOutputStream()->getStream());
$contents = stream_get_contents($this->getOutputStream($decorated)->getStream());
if ($contents === false) {
throw new ShouldNotHappenException();
}
Expand Down
15 changes: 11 additions & 4 deletions tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php
Expand Up @@ -10,6 +10,7 @@
use PHPStan\Command\Symfony\SymfonyOutput;
use PHPStan\File\FuzzyRelativePathHelper;
use PHPStan\File\NullRelativePathHelper;
use PHPStan\File\SimpleRelativePathHelper;
use PHPStan\ShouldNotHappenException;
use PHPStan\Testing\PHPStanTestCase;
use Symfony\Component\Console\Input\InputInterface;
Expand Down Expand Up @@ -67,10 +68,16 @@ private function runPath(string $path, int $expectedStatusCode): string
$memoryLimitFile = self::getContainer()->getParameter('memoryLimitFile');

$relativePathHelper = new FuzzyRelativePathHelper(new NullRelativePathHelper(), __DIR__, [], DIRECTORY_SEPARATOR);
$errorFormatter = new TableErrorFormatter($relativePathHelper, new CiDetectedErrorFormatter(
new GithubErrorFormatter($relativePathHelper),
new TeamcityErrorFormatter($relativePathHelper),
), false, null);
$errorFormatter = new TableErrorFormatter(
$relativePathHelper,
new SimpleRelativePathHelper(__DIR__),
new CiDetectedErrorFormatter(
new GithubErrorFormatter($relativePathHelper),
new TeamcityErrorFormatter($relativePathHelper),
),
false,
null,
);
$analysisResult = $analyserApplication->analyse(
[$path],
true,
Expand Down
44 changes: 29 additions & 15 deletions tests/PHPStan/Command/ErrorFormatter/TableErrorFormatterTest.php
Expand Up @@ -6,6 +6,7 @@
use PHPStan\Command\AnalysisResult;
use PHPStan\File\FuzzyRelativePathHelper;
use PHPStan\File\NullRelativePathHelper;
use PHPStan\File\SimpleRelativePathHelper;
use PHPStan\Testing\ErrorFormatterTestCase;
use function putenv;
use function sprintf;
Expand Down Expand Up @@ -164,11 +165,7 @@ public function testFormatErrors(
if (PHP_VERSION_ID >= 80100) {
self::markTestSkipped('Skipped on PHP 8.1 because of different result');
}
$relativePathHelper = new FuzzyRelativePathHelper(new NullRelativePathHelper(), self::DIRECTORY_PATH, [], '/');
$formatter = new TableErrorFormatter($relativePathHelper, new CiDetectedErrorFormatter(
new GithubErrorFormatter($relativePathHelper),
new TeamcityErrorFormatter($relativePathHelper),
), false, null);
$formatter = $this->createErrorFormatter(null);

$this->assertSame($exitCode, $formatter->formatErrors(
$this->getAnalysisResult($numFileErrors, $numGenericErrors),
Expand All @@ -180,25 +177,26 @@ public function testFormatErrors(

public function testEditorUrlWithTrait(): void
{
$relativePathHelper = new FuzzyRelativePathHelper(new NullRelativePathHelper(), self::DIRECTORY_PATH, [], '/');
$formatter = new TableErrorFormatter($relativePathHelper, new CiDetectedErrorFormatter(
new GithubErrorFormatter($relativePathHelper),
new TeamcityErrorFormatter($relativePathHelper),
), false, 'editor://%file%/%line%');
$formatter = $this->createErrorFormatter('editor://%file%/%line%');
$error = new Error('Test', 'Foo.php (in context of trait)', 12, true, 'Foo.php', 'Bar.php');
$formatter->formatErrors(new AnalysisResult([$error], [], [], [], false, null, true), $this->getOutput());

$this->assertStringContainsString('Bar.php', $this->getOutputContent());
}

public function testEditorUrlWithRelativePath(): void
{
$formatter = $this->createErrorFormatter('editor://custom/path/%relFile%/%line%');
$error = new Error('Test', 'Foo.php', 12, true, self::DIRECTORY_PATH . '/rel/Foo.php');
$formatter->formatErrors(new AnalysisResult([$error], [], [], [], false, null, true), $this->getOutput(true));

$this->assertStringContainsString('editor://custom/path/rel/Foo.php', $this->getOutputContent(true));
}

public function testBug6727(): void
{
putenv('COLUMNS=30');
$relativePathHelper = new FuzzyRelativePathHelper(new NullRelativePathHelper(), self::DIRECTORY_PATH, [], '/');
$formatter = new TableErrorFormatter($relativePathHelper, new CiDetectedErrorFormatter(
new GithubErrorFormatter($relativePathHelper),
new TeamcityErrorFormatter($relativePathHelper),
), false, null);
$formatter = $this->createErrorFormatter(null);
$formatter->formatErrors(
new AnalysisResult(
[
Expand All @@ -220,4 +218,20 @@ public function testBug6727(): void
self::expectNotToPerformAssertions();
}

private function createErrorFormatter(?string $editorUrl): TableErrorFormatter
{
$relativePathHelper = new FuzzyRelativePathHelper(new NullRelativePathHelper(), self::DIRECTORY_PATH, [], '/');

return new TableErrorFormatter(
$relativePathHelper,
new SimpleRelativePathHelper(self::DIRECTORY_PATH),
new CiDetectedErrorFormatter(
new GithubErrorFormatter($relativePathHelper),
new TeamcityErrorFormatter($relativePathHelper),
),
false,
$editorUrl,
);
}

}

0 comments on commit e61a782

Please sign in to comment.