-
Notifications
You must be signed in to change notification settings - Fork 548
Allow setting error format in configuration #841
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
Conversation
|
I'm interested - what's the error formatter you prefer to the default one? Thanks. |
|
It has the following features:
final class MyErrorFormatter implements ErrorFormatter
{
private const FORMAT = "{message}\n↳ <href={editorUrl}>{shortPath}:{line}</>\n";
public function __construct(
private RelativePathHelper $relativePathHelper,
private ?string $editorUrl
) {
}
public function formatErrors(AnalysisResult $analysisResult, Output $output) : int
{
if ($analysisResult->hasErrors() === false) {
$output->writeLineFormatted('<fg=green;options=bold>No errors</>');
$output->writeLineFormatted('');
return 0;
}
foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) {
$output->writeLineFormatted(sprintf('<unknown location> %s', $notFileSpecificError));
}
foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
$absolutePath = $fileSpecificError->getTraitFilePath() ?? $fileSpecificError->getFilePath();
$message = $fileSpecificError->getMessage();
// Remove escaped wildcard that breaks coloring
$message = str_replace('\*', '*', $message);
// Full Qualified Class Names
$message = (string) preg_replace(
"/([A-Z0-9]{1}[A-Za-z0-9_\-]+[\\\]+[A-Z0-9]{1}[A-Za-z0-9_\-\\\]+)/",
'<fg=yellow>$1</>',
$message
);
// Quoted strings
$message = (string) preg_replace(
"/(?<=[\"'])([A-Za-z0-9_\-\\\]+)(?=[\"'])/",
'<fg=yellow>$1</>',
$message
);
// Variable
$message = (string) preg_replace(
"/(?<=[:]{2}|[\s\"\(])([.]{3})?(\\$[A-Za-z0-9_\\-]+)(?=[\s|\"|\)])/",
'<fg=green>$1$2</>',
$message
);
// Method
$message = (string) preg_replace(
'/(?<=[:]{2}|[\s])(\w+\(\))/',
'<fg=blue>$1</>',
$message
);
// Function
$message = (string) preg_replace(
'/(?<=function\s)(\w+)(?=\s)/',
'<fg=blue>$1</>',
$message
);
// Types
$message = (string) preg_replace(
'/(?<=[\s\|])(null|true|false|int|float|bool|string|array|object|mixed|resource|iterable)(?=[:]{2}|[\.\s\|<,]+)/',
'<fg=magenta>$1</>',
$message
);
$output->writeLineFormatted(
strtr(
self::FORMAT,
[
'{absolutePath}' => $absolutePath,
'{editorUrl}' => str_replace(
['%file%', '%line%'],
[$absolutePath, (int) $fileSpecificError->getLine()],
$this->editorUrl ?? ''
),
'{shortPath}' => $this->trimPath($this->relativePathHelper->getRelativePath($fileSpecificError->getFile())),
'{line}' => (int) $fileSpecificError->getLine(),
'{message}' => $message,
'{identifier}' => $fileSpecificError->getIdentifier(),
]
)
);
}
$output->writeLineFormatted(sprintf(
'<bg=red;options=bold>Found %d error%s</>',
$analysisResult->getTotalErrorsCount(),
$analysisResult->getTotalErrorsCount() === 1 ? '' : 's'
));
$output->writeLineFormatted('');
return 1;
}
private function trimPath(string $path) : string
{
$parts = explode(DIRECTORY_SEPARATOR, $path);
if (count($parts) < 6) {
return $path;
}
if (str_contains($path, 'in context of class')) {
return $path;
}
return implode(
DIRECTORY_SEPARATOR,
[
...array_slice($parts, 0, 3),
'...',
...array_slice($parts, -2),
]
);
}
} |
|
The above formatter is a different approach to solve my previous attempt: |
|
After using the new highlighted output for a while, I'm in love. It makes it so much easier to quickly spot the important parts... I'm now wondering if this can't be part of the core (I want to do the work). If all errors would annotate dynamic parts like variables and type info with Symfony Color Styles. For example: phpstan-src/src/Rules/Methods/ReturnTypeRule.php Lines 57 to 61 in 0f2fbff
sprintf(
'Method <class>%s</>::<method>%s()</> should return <type>%%s</type> but empty return statement found.',
$method->getDeclaringClass()->getDisplayName(),
$method->getName()
), |
ddd20b4 to
95d480b
Compare
|
@ondrejmirtes I'm still using my own error format and I think it's superior to the default. Do you think this PR can be merged (after I rebase + cleanup)? |
|
Hi, I appreciate this and I'd like this because further down the road in PHPStan 1.x I'd like a different default error formatter to try out in bleedingEdge (and maybe make it the default one in 2.0). To review this PR - Also - one thing to think about is the behaviour with CI-detected environment. Right now it isn't overriden if the user uses So please do not change the error formatter if one is already supplied in the config, to match the current behaviour with Also please change the base to 1.6.x., thanks. |
c768b40 to
5f51ddf
Compare
5f51ddf to
dfbb0d5
Compare
|
@ondrejmirtes I updated the PR. When |
|
Perfect now, thank you! BTW I'm definitely interested in improving the default error formatter, and introducing a new About the syntax highlighting (totally unrelated to file vs. table formatter, it could be used by both, so it's a separate discussion/feature), the regex approach is too fuzzy for me, I worry it could break in some more complex situations, for example let's say someone has
Yes, it makes sense, but I don't want to break the original message with some Symfony Console-specific tags, because that wouldn't be compatible with other non-console formatters, it's too dangerous to do that. But - we can attach additional information to RuleErrorBuilder::message(sprintf(
'Method %s::%s() should return %%s but empty return statement found.',
$method->getDeclaringClass()->getDisplayName(),
$method->getName(),
))->richMessage(sprintf(
'Method <class>%s</>::<method>%s()</> should return <type>%%s</type> but empty return statement found.',
$method->getDeclaringClass()->getDisplayName(),
$method->getName()
))->build();WDYT? |
|
Oh, and please update the docs in these places:
Thank you. |
|
@ondrejmirtes Thanks, I created a PR to document it.
Not really sure if I want a formatter like that. Me and my team really like the minimalistic format that we're using for the last months. If I may suggest: please make the
Yes, the regex approach is not scalable although it does a really good job. I had to work with what I was getting: raw strings 🙈
Can't we just scrub all known tags ( Maybe we can start with already adding the named color styles (https://symfony.com/doc/current/console/coloring.html#using-color-styles)? Then it's possible to use them in custom rules already. |
Could be a different formatter - something like
You're just asking for parse issues - someone can have
We don't know them from the outside so we need a backward-compatible approach.
Tedious but necessary :) |

In my project I'm using a custom error format that I'd like to have as the default.
I need to run PHPStan with
--error-format=my-format.The idea of this PR is to introduce an
errorFormatconfiguration option that is picked by default, and can still be overwritten with the CLI option.Before I fix the todo, is this something you would consider merging?
Todo