-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 option to ternary_operator_spaces
to fix to separate lines
#7587
Comments
By the way, there seem to be no fixers that would handle the indentation of a ternary operation, is there ? If not, should it be covered by |
@bachinblack yeah, seems like a good place for that 🙂. Standalone fixer would be an overkill. |
This comment was marked as outdated.
This comment was marked as outdated.
I would love to have this. For code coverage, but more importantly for readability 🙂 |
@christian-kolb probably |
@Wirone Is there any kind of documentation on the structure and inner workings of the fixers? I've tried with a timebox but only copied stuff from other fixers without really understanding the dependencies of the moving parts. |
@christian-kolb you can use anything within this repo, including internal parts. These are marked as internal only to exclude it from public API so people don't build external stuff around it (or do it on their own responsibility). Unfortunately we don't have developer docs, so you basically need to learn from existing code. |
@Wirone Thanks for the quick reply. Unfortunately my timebox to tackle that topic ran out. I might tackle in the future, but can't work on it any further for now. If anyone else is interested, that's my current version. It does work for the very simpelst parts (simple assignment of a variable at the start of a function), but not for 80% of my codebase yet. <?php
declare(strict_types=1);
namespace App\CSFixer;
use PhpCsFixer\Fixer\FixerInterface;
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Tokenizer\Analyzer\AlternativeSyntaxAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\GotoLabelAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\SwitchAnalyzer;
use PhpCsFixer\Tokenizer\Analyzer\WhitespacesAnalyzer;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixer\WhitespacesFixerConfig;
final class TernaryOperatorMultilineFixer implements FixerInterface, WhitespacesAwareFixerInterface
{
public const string NAME = 'Namespace/ternary_operator_multiline';
/**
* @var WhitespacesFixerConfig
*/
private $whitespacesConfig;
public function isRisky(): bool
{
return false;
}
public function getDefinition(): FixerDefinitionInterface
{
return new FixerDefinition(
'Ternary operators must always be used as multiline.',
[
new CodeSample(
'<?php
$value = $condition
? $foo
: $bar;
',
),
],
);
}
public function getName(): string
{
return self::NAME;
}
/**
* {@inheritdoc}
*
* Must run after ArraySyntaxFixer, ListSyntaxFixer, TernaryToElvisOperatorFixer.
*/
public function getPriority(): int
{
return 1;
}
// Default
public function supports(\SplFileInfo $file): bool
{
return true;
}
// Default
public function setWhitespacesConfig(WhitespacesFixerConfig $config): void
{
$this->whitespacesConfig = $config;
}
public function isCandidate(Tokens $tokens): bool
{
return $tokens->isAllTokenKindsFound(['?', ':']);
}
public function fix(
\SplFileInfo $file,
Tokens $tokens,
): void {
$alternativeSyntaxAnalyzer = new AlternativeSyntaxAnalyzer();
$gotoLabelAnalyzer = new GotoLabelAnalyzer();
$ternaryOperatorIndices = [];
foreach ($tokens as $index => $token) {
if (!$token->equalsAny(['?', ':'])) {
continue;
}
if (SwitchAnalyzer::belongsToSwitch($tokens, $index)) {
continue;
}
if ($alternativeSyntaxAnalyzer->belongsToAlternativeSyntax($tokens, $index)) {
continue;
}
if ($gotoLabelAnalyzer->belongsToGoToLabel($tokens, $index)) {
continue;
}
$ternaryOperatorIndices[] = $index;
}
foreach (array_reverse($ternaryOperatorIndices) as $index) {
$token = $tokens[$index];
if ($token->equals('?')) {
$nextNonWhitespaceIndex = $tokens->getNextNonWhitespace($index);
if ($tokens[$nextNonWhitespaceIndex]->equals(':')) {
// Ignore ?: syntax
continue;
}
$previousNonWhitespaceIndex = $tokens->getPrevNonWhitespace($index);
$tokens->ensureWhitespaceAtIndex(
$index - 1,
1,
sprintf(
'%s%s%s',
$this->whitespacesConfig->getLineEnding(),
WhitespacesAnalyzer::detectIndent($tokens, $previousNonWhitespaceIndex),
$this->whitespacesConfig->getIndent()
),
);
continue;
}
if ($token->equals(':')) {
$previousNonWhitespaceIndex = $tokens->getPrevNonWhitespace($index);
if ($tokens[$previousNonWhitespaceIndex]->equals('?')) {
// Ignore ?: syntax
continue;
}
$tokens->ensureWhitespaceAtIndex(
$index - 1,
1,
sprintf(
'%s%s',
$this->whitespacesConfig->getLineEnding(),
WhitespacesAnalyzer::detectIndent($tokens, $previousNonWhitespaceIndex),
),
);
}
}
}
} |
The PR should support |
@mvorisek I don't agree. I don't see a point in making @christian-kolb sorry to hear that. I understand you worked on it in your work time and had some specific timeframe, but maybe you could continue in your free time 🙂? Anyway, thanks for your work. |
Given this issue is motivated with improved CS but also better coverage measure, it is closely related and the coverage motivation applies to |
@Wirone Good that you ask, I wasn't clear enough. I do intend on finishing it. But due to my family with two small children and 3 open source packages (which I'm primarily maintaining), there won't be much time (which it needs to get into the complex code base without documentation) 🙂. @mvorisek I guess it's personal taste, but I wouldn't use those just for the reduced readability (in my opinion). So when I'll finish it, I won't include the configuration in the first version. Maybe in future ones, but I would at least do it step by step. First making it work with the "normal" ternary operator then perhaps improving it in the future. |
Since this issue has not had any activity within the last 90 days, I have marked it as stale. The purpose of this action is to enforce backlog review once in a while. This is mostly for maintainers and helps with keeping repository in good condition, because stale issues and PRs can accumulate over time and make it harder for others to find relevant information. It is also possible that some changes has been made to the repo already, and issue or PR became outdated, but wasn't closed for some reason. This action helps with periodic review and closing of such stale items in automated way. You may let maintainers handle this or verify current relevancy by yourself, to help with re-triage. Any activity will remove stale label so it won't be automatically closed at this point. I will close it if no further activity occurs within the next 30 days. |
This topic is still very relevant, it's just that nobody tackled it yet 🙂 |
Since this issue has not had any activity within the last 90 days, I have marked it as stale. The purpose of this action is to enforce backlog review once in a while. This is mostly for maintainers and helps with keeping repository in good condition, because stale issues and PRs can accumulate over time and make it harder for others to find relevant information. It is also possible that some changes has been made to the repo already, and issue or PR became outdated, but wasn't closed for some reason. This action helps with periodic review and closing of such stale items in automated way. You may let maintainers handle this or verify current relevancy by yourself, to help with re-triage. Any activity will remove stale label so it won't be automatically closed at this point. I will close it if no further activity occurs within the next 30 days. |
This topic is still very relevant, it's just that nobody tackled it yet 🙂 |
Since this issue has not had any activity within the last 90 days, I have marked it as stale. The purpose of this action is to enforce backlog review once in a while. This is mostly for maintainers and helps with keeping repository in good condition, because stale issues and PRs can accumulate over time and make it harder for others to find relevant information. It is also possible that some changes has been made to the repo already, and issue or PR became outdated, but wasn't closed for some reason. This action helps with periodic review and closing of such stale items in automated way. You may let maintainers handle this or verify current relevancy by yourself, to help with re-triage. Any activity will remove stale label so it won't be automatically closed at this point. I will close it if no further activity occurs within the next 30 days. |
This topic is still very relevant, it's just that nobody tackled it yet 🙂 |
closing as I am against any bot noise - help welcomed |
Is it because I copied the answer I gave last time? The bot noice is coming from the the project, not from me 🙂 |
@christian-kolb definitely nothing personal, actually thanks ❤, I just do not agree with https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/v3.73.1/.github/workflows/issues_and_pull_requests.yml workflow. Valid issues should never go stale IMO and I do not want to get any notifications except only meaningful communication to move things forward. I expressed this multiple times to the maintainers, but ATM all I can do is to respect their decision. |
Feature request
Code like:
to be fixed to:
The motivation is line coverage. I do not think this CS should be default, but I would be grateful if an option for formatting on a separate lines would exist, so projects with strong coverage requirements can be measured better.
The text was updated successfully, but these errors were encountered: