Skip to content
Open
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
16 changes: 16 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,22 @@ jobs:
../bashunit -a contains 'FooTrait.php:10:Strict comparison using === between int<0, max> and false will always evaluate to false.' "$OUTPUT"
../bashunit -a contains 'FooTrait.php (in context of class E2EInTrait\Bar):18:Strict comparison using === between E2EInTrait\Bar and null will always evaluate to false.' "$OUTPUT"
../bashunit -a contains 'FooTrait.php (in context of class E2EInTrait\Foo):18:Strict comparison using === between E2EInTrait\Foo and null will always evaluate to false.' "$OUTPUT"
- script: |
cd e2e/bug-14718
# https://github.com/phpstan/phpstan/issues/14718
# an inline @phpstan-ignore on an error deduplicated into the trait must suppress it,
# consistently with both an empty and a primed result cache
../../bin/phpstan clear-result-cache
../bashunit -a exit_code "0" "../../bin/phpstan --error-format=raw"
../bashunit -a exit_code "0" "../../bin/phpstan --error-format=raw"
# with the ignore removed, the error is reported in the trait file and a generated
# baseline records the trait file path, not the using-class file
sed -i 's# // @phpstan-ignore identical.alwaysFalse##' src/FooTrait.php
../../bin/phpstan clear-result-cache
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan --error-format=raw")
../bashunit -a contains 'FooTrait.php:10:Strict comparison using === between int<0, max> and false will always evaluate to false.' "$OUTPUT"
../../bin/phpstan --generate-baseline=baseline.neon
../bashunit -a contains 'path: src/FooTrait.php' "$(cat baseline.neon)"
- script: |
cd e2e/result-cache-meta-extension
composer install
Expand Down
2 changes: 1 addition & 1 deletion build/baseline-8.0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ parameters:
message: '#^Strict comparison using \=\=\= between list\<non\-falsy\-string\> and false will always evaluate to false\.$#'
identifier: identical.alwaysFalse
count: 1
path: ../src/Type/Php/StrSplitFunctionReturnTypeExtension.php
path: ../src/Type/Php/MbFunctionsReturnTypeExtensionTrait.php
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this a BC break? The ignore work correctly before. It's a bit awkward, but for errors reported in traits, I think on current stable version, both the trait or the class path can be used in path in ignoreErrors.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is achieved here:

$filePath = $this->fileHelper->normalizePath($error->getFilePath());
if (isset($this->ignoreErrorsByFile[$filePath])) {
foreach ($this->ignoreErrorsByFile[$filePath] as $ignoreError) {
$i = $ignoreError['index'];
$ignore = $ignoreError['ignoreError'];
$result = $processIgnoreError($error, $i, $ignore);
if (!$result) {
unset($errors[$errorIndex]);
$ignoredErrors[] = [$error, $ignore];
continue 2;
}
}
}
$traitFilePath = $error->getTraitFilePath();
if ($traitFilePath !== null) {
$normalizedTraitFilePath = $this->fileHelper->normalizePath($traitFilePath);
if (isset($this->ignoreErrorsByFile[$normalizedTraitFilePath])) {
foreach ($this->ignoreErrorsByFile[$normalizedTraitFilePath] as $ignoreError) {
$i = $ignoreError['index'];
$ignore = $ignoreError['ignoreError'];
$result = $processIgnoreError($error, $i, $ignore);
if (!$result) {
unset($errors[$errorIndex]);
$ignoredErrors[] = [$error, $ignore];
continue 2;
}
}
}
}

I suspect, wouldn't be a better place to fix this in FileAnalyser where @phpstan-ignore are processed?

4 changes: 4 additions & 0 deletions e2e/bug-14718/phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
level: 8
paths:
- src
10 changes: 10 additions & 0 deletions e2e/bug-14718/src/Bar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Bug14718;

class Bar
{

use FooTrait;

}
10 changes: 10 additions & 0 deletions e2e/bug-14718/src/Foo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Bug14718;

class Foo
{

use FooTrait;

}
15 changes: 15 additions & 0 deletions e2e/bug-14718/src/FooTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Bug14718;

trait FooTrait
{

public function doFoo(int $i): void
{
if (abs($i) === false) { // @phpstan-ignore identical.alwaysFalse

}
}

}
2 changes: 1 addition & 1 deletion src/Analyser/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public function removeTraitContext(): self
$this->traitFilePath,
$this->line,
$this->canBeIgnored,
$this->filePath,
$this->traitFilePath,
null,
$this->tip,
$this->nodeLine,
Expand Down
14 changes: 14 additions & 0 deletions tests/PHPStan/Analyser/ErrorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ public function testError(): void
$this->assertSame(10, $error->getLine());
}

public function testRemoveTraitContextUsesTraitFileAsFilePath(): void
{
$error = new Error('Message', 'trait.php (in context of class C)', 11, true, 'user.php', 'trait.php');
$this->assertSame('user.php', $error->getFilePath());
$this->assertSame('trait.php', $error->getTraitFilePath());

$withoutTraitContext = $error->removeTraitContext();
$this->assertSame('trait.php', $withoutTraitContext->getFile());
// filePath must follow the file onto the trait, otherwise editor URLs and
// inline ignore-comment lookups point at the using-class file (#14718).
$this->assertSame('trait.php', $withoutTraitContext->getFilePath());
$this->assertNull($withoutTraitContext->getTraitFilePath());
}

public static function dataValidIdentifier(): iterable
{
yield ['a'];
Expand Down
Loading