-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from wata727/unneeded_regexp
Add UnneededRegularExpression
- Loading branch information
Showing
5 changed files
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# UnneededRegularExpression | ||
|
||
Under the following conditions, using `strpos()` instead of `preg_match()` will be faster. | ||
|
||
1. Not using `matches` variables. | ||
2. Not using a pattern including pattern modifiers. | ||
3. Not using a pattern including meta characters. | ||
|
||
## Before | ||
|
||
```php | ||
<?php | ||
|
||
if (preg_match("/abc/", $var)) { // UnneededRegularExpression: Using `strpos()` instead of `preg_match()` will be faster. | ||
something($var); | ||
} | ||
``` | ||
|
||
## After | ||
|
||
```php | ||
<?php | ||
|
||
if (strpos($var, "abc") !== false) { | ||
something($var); | ||
} | ||
``` | ||
|
||
|
||
## Reference | ||
|
||
https://secure.php.net/manual/en/function.preg-match.php |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php declare(strict_types=1); | ||
|
||
namespace Pahout\Tool; | ||
|
||
use \ast\Node; | ||
use Pahout\Logger; | ||
use Pahout\Hint; | ||
|
||
/** | ||
* Find `preg_match()` which does not need regular expressions. | ||
* | ||
* Under the following conditions, using `strpos()` instead of `preg_match()` will be faster. | ||
* | ||
* 1. Not using `matches` variables. | ||
* 2. Not using a pattern including pattern modifiers. | ||
* 3. Not using a pattern including meta characters. | ||
* | ||
*/ | ||
class UnneededRegularExpression implements Base | ||
{ | ||
use Howdah; | ||
|
||
public const ENTRY_POINT = \ast\AST_CALL; | ||
public const PHP_VERSION = '0.0.0'; | ||
public const HINT_TYPE = "UnneededRegularExpression"; | ||
private const HINT_MESSAGE = 'Using `strpos()` instead of `preg_match()` will be faster.'; | ||
private const HINT_LINK = Hint::DOCUMENT_LINK."/UnneededRegularExpression.md"; | ||
|
||
/** | ||
* Find `preg_match()` which does not need regular expressions. | ||
* | ||
* @param string $file File name to be analyzed. | ||
* @param Node $node AST node to be analyzed. | ||
* @return Hint[] List of hints obtained from results. | ||
*/ | ||
public function run(string $file, Node $node): array | ||
{ | ||
if ($this->isFunctionCall($node, 'preg_match')) { | ||
$args = $node->children['args']->children; | ||
if (count($args) > 2) { | ||
return []; | ||
} | ||
|
||
if (is_string($args[0]) && $this->isUnneededRegExp($args[0])) { | ||
return [new Hint( | ||
self::HINT_TYPE, | ||
self::HINT_MESSAGE, | ||
$file, | ||
$node->lineno, | ||
self::HINT_LINK | ||
)]; | ||
} | ||
} | ||
|
||
return []; | ||
} | ||
|
||
/** | ||
* Check whether it is a regular expression pattern that can use `strpos()`. | ||
* | ||
* The following pattern returns false: | ||
* | ||
* 1. Including pattern modifiers. | ||
* 2. Including meta characters. | ||
* | ||
* @param string $str A regular expression pattern for testing. | ||
* @return boolean The result of testing. | ||
*/ | ||
private function isUnneededRegExp(string $str): Bool | ||
{ | ||
if (substr($str, -1) !== "/") { | ||
return false; | ||
} | ||
|
||
return $str === preg_quote($str); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<?php | ||
|
||
namespace Pahout\Test\Tool; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Pahout\Test\helper\PahoutHelper; | ||
use Pahout\Tool\UnneededRegularExpression; | ||
use Pahout\Hint; | ||
use Pahout\Logger; | ||
use Pahout\Config; | ||
use Symfony\Component\Console\Output\ConsoleOutput; | ||
|
||
class UnneededRegularExpressionTest extends TestCase | ||
{ | ||
public function setUp() | ||
{ | ||
Logger::getInstance(new ConsoleOutput()); | ||
} | ||
|
||
public function test_unneeded_regular_expression() | ||
{ | ||
$code = <<<'CODE' | ||
<?php | ||
if (preg_match("/abc/", $var)) { | ||
something($var); | ||
} | ||
CODE; | ||
$root = \ast\parse_code($code, Config::AST_VERSION); | ||
|
||
$tester = PahoutHelper::create(new UnneededRegularExpression()); | ||
$tester->test($root); | ||
|
||
$this->assertEquals( | ||
[ | ||
new Hint( | ||
'UnneededRegularExpression', | ||
'Using `strpos()` instead of `preg_match()` will be faster.', | ||
'./test.php', | ||
2, | ||
Hint::DOCUMENT_LINK.'/UnneededRegularExpression.md' | ||
) | ||
], | ||
$tester->hints | ||
); | ||
} | ||
|
||
public function test_using_complex_regular_expression() | ||
{ | ||
$code = <<<'CODE' | ||
<?php | ||
if (preg_match("/^[a-z]$/", $var)) { | ||
something($var); | ||
} | ||
CODE; | ||
$root = \ast\parse_code($code, Config::AST_VERSION); | ||
|
||
$tester = PahoutHelper::create(new UnneededRegularExpression()); | ||
$tester->test($root); | ||
|
||
$this->assertEmpty($tester->hints); | ||
} | ||
|
||
|
||
public function test_using_match_value() | ||
{ | ||
$code = <<<'CODE' | ||
<?php | ||
if (preg_match("/abc/", $var, $match)) { | ||
something($var); | ||
} | ||
CODE; | ||
$root = \ast\parse_code($code, Config::AST_VERSION); | ||
|
||
$tester = PahoutHelper::create(new UnneededRegularExpression()); | ||
$tester->test($root); | ||
|
||
$this->assertEmpty($tester->hints); | ||
} | ||
|
||
public function test_using_pattern_modifier() | ||
{ | ||
$code = <<<'CODE' | ||
<?php | ||
if (preg_match("/abc/i", $var, $match)) { | ||
something($var); | ||
} | ||
CODE; | ||
$root = \ast\parse_code($code, Config::AST_VERSION); | ||
|
||
$tester = PahoutHelper::create(new UnneededRegularExpression()); | ||
$tester->test($root); | ||
|
||
$this->assertEmpty($tester->hints); | ||
} | ||
} |