Skip to content

Commit

Permalink
Add flags support to PregDelimiterFixer
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Jan 8, 2019
1 parent f15ee6c commit d5ca66e
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 20 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,27 @@ services:

### Consistent Delimiter in Regular Expression

- :wrench:
- class: [`Symplify\CodingStandard\Fixer\ControlStructure\PregDelimiterFixer`](src/Fixer/ControlStructure/PregDelimiterFixer.php)

```diff
-preg_match('~pattern~', $value);
+preg_match('#pattern#', $value);
-preg_match("~pattern~d", $value);
+preg_match("#pattern#d", $value);
-Nette\Utils\Strings::match($value, '/pattern/');
+Nette\Utils\Strings::match($value, '#pattern#');
```

Do you want another char than `#`? Configure it:

```yaml
# ecs.yml
services:
Symplify\CodingStandard\Fixer\ControlStructure\PregDelimiterFixer:
delimiter: '_' # default "#"
```

<br>
Expand Down
61 changes: 42 additions & 19 deletions src/Fixer/ControlStructure/PregDelimiterFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Symplify\CodingStandard\Fixer\ControlStructure;

use Nette\Utils\Strings;
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
Expand All @@ -12,8 +14,14 @@
use SplFileInfo;
use Symplify\CodingStandard\Fixer\AbstractSymplifyFixer;

final class PregDelimiterFixer extends AbstractSymplifyFixer
final class PregDelimiterFixer extends AbstractSymplifyFixer implements ConfigurableFixerInterface
{
/**
* @var string
* @see https://regex101.com/r/pd1KvP/1/
*/
private const INNER_PATTERN_PATTERN = '#(?<open>[\'|"])(?<content>.*?)(?<close>[A-z]*[\'|"])#';
/**
* All with pattern as 1st argument
* @var int[]
Expand Down Expand Up @@ -44,7 +52,7 @@ final class PregDelimiterFixer extends AbstractSymplifyFixer
/**
* @var string
*/
private const PREFERRED_DELIMITER = '#';
private $delimiter = '#';

/**
* @var ArgumentsAnalyzer
Expand Down Expand Up @@ -92,6 +100,16 @@ public function fix(SplFileInfo $file, Tokens $tokens): void
}
}

/**
* @param mixed[]|null $configuration
*/
public function configure(?array $configuration = null): void
{
if (isset($configuration['delimiter']) && $configuration['delimiter']) {
$this->delimiter = $configuration['delimiter'];
}
}

private function resolveRegexArgumentPosition(Tokens $tokens, Token $token, int $position): ?int
{
if (isset(self::FUNCTIONS_WITH_REGEX_PATTERN[$token->getContent()])) {
Expand Down Expand Up @@ -140,36 +158,41 @@ private function processArgumentInfo(ArgumentAnalysis $argumentAnalysis, Tokens
return;
}

$argumentValue = $argumentAnalysis->getTypeAnalysis()->getName();

// clean
$argumentValue = trim($argumentValue, '\'');

// is delimiter wrapped?
if ($argumentValue[0] !== $argumentValue[strlen($argumentValue) - 1]) {
$argumentPosition = $argumentAnalysis->getTypeAnalysis()->getStartIndex();
if ($tokens[$argumentPosition]->isGivenKind(T_CONSTANT_ENCAPSED_STRING) === false) {
return;
}

if ($argumentValue[0] === self::PREFERRED_DELIMITER) {
return;
}
$argumentValue = $argumentAnalysis->getTypeAnalysis()->getName();
$newArgumentValue = Strings::replace(
$argumentValue,
self::INNER_PATTERN_PATTERN,
function (array $match) {
$innerPattern = $match['content'];

if (strlen($innerPattern) > 2) {
// change delimiter
if ($innerPattern[0] === $innerPattern[strlen($innerPattern) - 1]) {
$innerPattern[0] = $this->delimiter;
$innerPattern[strlen($innerPattern) - 1] = $this->delimiter;
}
}

$argumentValue[0] = self::PREFERRED_DELIMITER;
$argumentValue[strlen($argumentValue) - 1] = self::PREFERRED_DELIMITER;
$argumentPosition = $argumentAnalysis->getTypeAnalysis()->getStartIndex();
return $match['open'] . $innerPattern . $match['close'];
}
);

// not a string, cannot replace it
if (! $tokens[$argumentPosition]->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) {
// no change
if ($newArgumentValue === $argumentValue) {
return;
}

$tokens[$argumentPosition] = new Token([T_CONSTANT_ENCAPSED_STRING, "'" . $argumentValue . "'"]);
$tokens[$argumentPosition] = new Token([T_CONSTANT_ENCAPSED_STRING, $newArgumentValue]);
}

private function isStaticCall(Tokens $tokens, int $position, string $class, string $method): bool
{
$token = $tokens[$position];

if (! $tokens[$position - 1]->isGivenKind(T_PAAMAYIM_NEKUDOTAYIM)) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

use Nette\Utils\Strings;

Strings::replace($file, '#' . preg_quote(getcwd() . '/') . '#');
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@

preg_match('~value~', $value);
preg_match_all('~value~', $value);
preg_match_all("~value~", $value);
preg_match_all("~value~i", $value);
preg_match_all('~value~im', $value);
preg_match_all('', $value);

?>
-----
<?php

preg_match('#value#', $value);
preg_match_all('#value#', $value);
preg_match_all("#value#", $value);
preg_match_all("#value#i", $value);
preg_match_all('#value#im', $value);
preg_match_all('', $value);

?>
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,25 @@ final class PregDelimiterFixerTest extends AbstractCheckerTestCase
{
public function test(): void
{
$this->doTestFiles([__DIR__ . '/Fixture/function.php.inc', __DIR__ . '/Fixture/static_call.php.inc']);
$this->doTestFiles([
__DIR__ . '/Fixture/function.php.inc',
__DIR__ . '/Fixture/static_call.php.inc',
__DIR__ . '/Fixture/concat_skip.php.inc',
]);
}

protected function getCheckerClass(): string
{
return PregDelimiterFixer::class;
}

/**
* @return mixed[]
*/
protected function getCheckerConfiguration(): ?array
{
return [
'delimiter' => '#',
];
}
}

0 comments on commit d5ca66e

Please sign in to comment.