Skip to content

Conversation

vrana
Copy link
Contributor

@vrana vrana commented Sep 15, 2025

Writing line numbers of errors in tests is very annoying. It also makes it impractical to add anything before the last error (e.g. group errors logically) because then all past errors need to be renumbered. This PR fixes this problem by parsing the errors directly from files.

I've considered using a separate method instead of $expectedErrors = null but this is quite handy especially with data providers as shown in dataBug4969(): detect errors with some setting, no errors without that setting.

I've used this on two random places. I can try to refactor more if there's an interest.

@staabm
Copy link
Contributor

staabm commented Sep 15, 2025

in case you are not aware of it: similar proposals have been made in the past.

there is even a dedicated package delivering a similar feature


see also #2742

@ondrejmirtes
Copy link
Member

RuleTestCase is one of the oldest parts of PHPStan and it shows. I'd like to take time to modernize it but it's a larger project.

Instead of:

		$this->analyse([__DIR__ . '/data/match-expr.php'], [
			[
				'Match arm comparison between 1|2|3 and \'foo\' is always false.',
				14,
			],
			[
				'Match arm comparison between 1|2|3 and 0 is always false.',
				19,
			],
		]);

I'd like to be able to write:

		$this->analyse(__DIR__ . '/data/match-expr.php', [
			RuleErrorBuilder::message('Match arm comparison between 1|2|3 and \'foo\' is always false.')
				->identifier('match.alwaysFalse')
				->line(14)
				->tip('...'),
			RuleErrorBuilder::message('Match arm comparison between 1|2|3 and 0 is always false.')
				->identifier('match.alwaysFalse')
				->line(19)
				->tip('...'),
		]);

Which would allow us to assert not just message/line/tip but also identifier and possibly more.

And of course also I'd like to be able to do this in-line similar to how type inference tests https://phpstan.org/developing-extensions/testing#type-inference already work.

But instead of:

$str = match($bar) { // error: Match expression does not handle remaining values: int<min, 0>|int<2, max>
	1 => 'test'
};

I'd like to be able to do:

assertErrorOnNextLine(RuleErrorBuilder::message(
	'Match expression does not handle remaining values: int<min, 0>|int<2, max>'
)->identifier('match.unhandled'));
$str = match($bar) {
	1 => 'test'
};

@vrana vrana closed this Sep 15, 2025
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 this pull request may close these issues.

3 participants