Skip to content

Commit b8da95b

Browse files
Rename SymplifyQuoteEscapeRector to SimplifyQuoteEscapeRector (#7658)
* Rename SimplifyQuoteEscapeRector * Rework
1 parent b5e9d7b commit b8da95b

File tree

12 files changed

+167
-153
lines changed

12 files changed

+167
-153
lines changed

build/target-repository/docs/rector_rules_overview.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,11 +2083,11 @@ Makes array_search search for identical elements
20832083

20842084
<br>
20852085

2086-
### SymplifyQuoteEscapeRector
2086+
### SimplifyQuoteEscapeRector
20872087

20882088
Prefer quote that are not inside the string
20892089

2090-
- class: [`Rector\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector`](../rules/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector.php)
2090+
- class: [`Rector\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector`](../rules/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector.php)
20912091

20922092
```diff
20932093
class SomeClass

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/Fixture/fixture.php.inc renamed to rules-tests/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector/Fixture/fixture.php.inc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector\Fixture;
3+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\Fixture;
44

55
class Fixture
66
{
@@ -15,7 +15,7 @@ class Fixture
1515
-----
1616
<?php
1717

18-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector\Fixture;
18+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\Fixture;
1919

2020
class Fixture
2121
{

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/Fixture/skip.php.inc renamed to rules-tests/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector/Fixture/skip.php.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector\Fixture;
3+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\Fixture;
44

55
class Skip
66
{

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/Fixture/skip_inversed_other_chars.php.inc renamed to rules-tests/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector/Fixture/skip_inversed_other_chars.php.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector\Fixture;
3+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\Fixture;
44

55
class SkipInversedOtherChars
66
{

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/Fixture/skip_newline_escape_sequence.php.inc renamed to rules-tests/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector/Fixture/skip_newline_escape_sequence.php.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector\Fixture;
3+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\Fixture;
44

55
class SkipNewlineEscapeSequence
66
{

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/Fixture/skip_non_printable_chars.php.inc renamed to rules-tests/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector/Fixture/skip_non_printable_chars.php.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector\Fixture;
3+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\Fixture;
44

55
final class SkipNonPrintableChars
66
{

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/SymplifyQuoteEscapeRectorTest.php renamed to rules-tests/CodingStyle/Rector/String_/SimplifyQuoteEscapeRector/SimplifyQuoteEscapeRectorTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
declare(strict_types=1);
44

5-
namespace Rector\Tests\CodingStyle\Rector\String_\SymplifyQuoteEscapeRector;
5+
namespace Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector;
66

77
use Iterator;
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
1010

11-
final class SymplifyQuoteEscapeRectorTest extends AbstractRectorTestCase
11+
final class SimplifyQuoteEscapeRectorTest extends AbstractRectorTestCase
1212
{
1313
#[DataProvider('provideData')]
1414
public function test(string $filePath): void
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector;
6+
use Rector\Config\RectorConfig;
7+
8+
return RectorConfig::configure()
9+
->withRules([SimplifyQuoteEscapeRector::class]);

rules-tests/CodingStyle/Rector/String_/SymplifyQuoteEscapeRector/config/configured_rule.php

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\CodingStyle\Rector\String_;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Scalar\String_;
9+
use Rector\NodeTypeResolver\Node\AttributeKey;
10+
use Rector\Rector\AbstractRector;
11+
use Rector\Util\StringUtils;
12+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
13+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
14+
15+
/**
16+
* @see \Rector\Tests\CodingStyle\Rector\String_\SimplifyQuoteEscapeRector\SimplifyQuoteEscapeRectorTest
17+
*/
18+
class SimplifyQuoteEscapeRector extends AbstractRector
19+
{
20+
/**
21+
* @var string
22+
* @see https://regex101.com/r/qEkCe9/2
23+
*/
24+
private const ESCAPED_CHAR_REGEX = '#\\\\|\$|\\n|\\t#sim';
25+
26+
/**
27+
* @var string
28+
* @see https://alvinalexander.com/php/how-to-remove-non-printable-characters-in-string-regex/
29+
* @see https://regex101.com/r/lGUhRb/1
30+
*/
31+
private const HAS_NON_PRINTABLE_CHARS = '#[\x00-\x1F\x80-\xFF]#';
32+
33+
private bool $hasChanged = false;
34+
35+
public function getRuleDefinition(): RuleDefinition
36+
{
37+
return new RuleDefinition(
38+
'Prefer quote that are not inside the string',
39+
[
40+
new CodeSample(
41+
<<<'CODE_SAMPLE'
42+
class SomeClass
43+
{
44+
public function run()
45+
{
46+
$name = "\" Tom";
47+
$name = '\' Sara';
48+
}
49+
}
50+
CODE_SAMPLE
51+
,
52+
<<<'CODE_SAMPLE'
53+
class SomeClass
54+
{
55+
public function run()
56+
{
57+
$name = '" Tom';
58+
$name = "' Sara";
59+
}
60+
}
61+
CODE_SAMPLE
62+
),
63+
]
64+
);
65+
}
66+
67+
/**
68+
* @return array<class-string<Node>>
69+
*/
70+
public function getNodeTypes(): array
71+
{
72+
return [String_::class];
73+
}
74+
75+
/**
76+
* @param String_ $node
77+
*/
78+
public function refactor(Node $node): ?String_
79+
{
80+
$this->hasChanged = false;
81+
82+
if (StringUtils::isMatch($node->value, self::HAS_NON_PRINTABLE_CHARS)) {
83+
return null;
84+
}
85+
86+
$doubleQuoteCount = substr_count($node->value, '"');
87+
$singleQuoteCount = substr_count($node->value, "'");
88+
$kind = $node->getAttribute(AttributeKey::KIND);
89+
90+
if ($kind === String_::KIND_SINGLE_QUOTED) {
91+
$this->processSingleQuoted($node, $doubleQuoteCount, $singleQuoteCount);
92+
}
93+
94+
$quoteKind = $node->getAttribute(AttributeKey::KIND);
95+
if ($quoteKind === String_::KIND_DOUBLE_QUOTED) {
96+
$this->processDoubleQuoted($node, $singleQuoteCount, $doubleQuoteCount);
97+
}
98+
99+
if (! $this->hasChanged) {
100+
return null;
101+
}
102+
103+
return $node;
104+
}
105+
106+
private function processSingleQuoted(String_ $string, int $doubleQuoteCount, int $singleQuoteCount): void
107+
{
108+
if ($doubleQuoteCount === 0 && $singleQuoteCount > 0) {
109+
// contains chars that will be newly escaped
110+
if ($this->isMatchEscapedChars($string->value)) {
111+
return;
112+
}
113+
114+
$string->setAttribute(AttributeKey::KIND, String_::KIND_DOUBLE_QUOTED);
115+
// invoke override
116+
$string->setAttribute(AttributeKey::ORIGINAL_NODE, null);
117+
118+
$this->hasChanged = true;
119+
}
120+
}
121+
122+
private function processDoubleQuoted(String_ $string, int $singleQuoteCount, int $doubleQuoteCount): void
123+
{
124+
if ($singleQuoteCount === 0 && $doubleQuoteCount > 0) {
125+
// contains chars that will be newly escaped
126+
if ($this->isMatchEscapedChars($string->value)) {
127+
return;
128+
}
129+
130+
$string->setAttribute(AttributeKey::KIND, String_::KIND_SINGLE_QUOTED);
131+
// invoke override
132+
$string->setAttribute(AttributeKey::ORIGINAL_NODE, null);
133+
134+
$this->hasChanged = true;
135+
}
136+
}
137+
138+
private function isMatchEscapedChars(string $string): bool
139+
{
140+
return StringUtils::isMatch($string, self::ESCAPED_CHAR_REGEX);
141+
}
142+
}

0 commit comments

Comments
 (0)