Учимся использовать регулярные выражения для исправления кода в PhpStorm.
Одну библиотеку, которую я писал, которая была покрыта тестами почти на 100% подверглась рефакторингу (оптимизации). Как результат, 450 тестов сигнатур, (450 юнит тестов!!!), которые раньше проходили на "УРА", стали падать. Изменения затронули только пару абстрактных классов, но тесты были явно привязаны к старому функционалу. Чтобы тесты снова заработали, нужно было исправить 450 php файлов c тестами.
После исправления 10-20 классов ручками, я понял, что ручками это делать будет очень-очень долго и мозго-выносяще.
На помощь пришли регулярные выражения. Сначала я подбирал паттерн поиска в PHPStorm (Ctrl+Shift+F), искал, и оценивал те ли результаты я ожидал найти, а затем (Ctrl+Shift+R) выполнял замену. Конечно, после замены отступы в коде не соответствовали правильному code style. Но Code -> Reformat Code ... в PHPstorm быстро всё поправил.
Некоторые регулярные выражения простые, а некоторые с первого взгляда суровые:
1)
Text to find:
'@?file_get_contents\(__DIR__ . '/../../(.*.html)'\);'
Replace with:
'\\$this->getBody('$1');'
2)
Text to find:
'public function testCheckNot(\w*)\(\)\s*\{\s*\$signature = \$this->getSignature\(\);\s*\$body = \$this->getBody\((.*)\)[^}]+}'
Replace width:
'public function testCheckNot$1() \{ \\$res = \\$this->check('http://url', array(), $2); \\$this->assertFalse(\\$res); \}'
Эта регулярка (№2) методы такого типа:
public function testCheckNotBigcommerce()
{
$signature = $this->getSignature();
$body = $this->getBody('CMS/BigCommerce.html');
$response = new Http_Response($body);
$request = new Http_Request(array(), array(), array(), array());
$request->setUrl(new Http_Url('http://url'));
$response->setRequest($request);
$res = $signature->check($response);
$this->assertFalse($res);
}
Приводила к таким:
public function testCheckNotBigcommerce()
{
$res = $this->check('http://url', array(), 'CMS/BigCommerce.html');
$this->assertFalse($res);
}
3)
Text to find:
'\$body = \$this->getBody\(('.*')\);\s*\$res = \$signature->checkMeta\(\$body\);'
Replace with:
'\\$body = \\$this->getBody($1); \\$metaValues = \\$this->getMetaValues(\\$body); \\$res = \\$signature->checkMeta(\\$metaValues);'
4)
Text to find:
'\$body = \$this->getBody\(('.*')\);\s*\$res = \$signature->checkScript\(\$body\);'
Replace with:
'\\$body = \\$this->getBody($1); \\$scriptLinks = \\$this->getScriptLinks(\\$body); \\$res = \\$signature->checkScript(\\$scriptLinks);'
5)
Text to find:
'\$signature = \$this->getSignature\(\);\s*\$body = \$this->getBody\((.*)\);[^}]*\$res = \$signatur
e->check\(\$response\);'
Replace with:
'\\$res = \\$this->check('http://url', array(), $1);'
Удаление конкретного метода целиком, и, коммента перед ним (если коммент есть):
6)
Text to find:
'(\/\*\*[^/]*\*\/)?\s*(protected|private) function getSignature\(\)\s*\{[^}]*\}[^}]*}'
Replace with:
'' #заменяем на пустую строку
7) Text to find: '\$this->assertTrue\(\$signature->checkMeta\(\$body\)\);' Replace with: '\\$metaValues = \\$this->getMetaValues(\\$body); \\$res = \\$signature->checkMeta(\\$metaValues); \\$this->assertTrue(\\$res);'
8) Text to find: '\$res = \$this->getSignature\(\)->checkScript\(\$body\);' Replace with: '\\$scriptLinks = \\$this->getScriptLinks(\\$body); \\$res = \\$this->getSignature()->checkScript(\\$scriptLinks);'
Изменить имена классов, добавить префикс перед именем класса, от которого наследуемся. PHPStorm регулярка для переименования имён классов может выглядеть так:
Text to find: 'extends (\w+)' Raplace with: 'extends Prefix_$1' Text to find: 'class (\w+)' Raplace with: 'class Prefix_$1'
Как видно из примеров, спецсимволы (например: (, ), $, ?) нужно экранировать символом '\'. В выражении для поиска те части, что в скобках, будут заматчены и сохранены в переменные $1, $2, $3 и т.д. в порядке появления. Чтобы в строке для замены (Replace with) написать переменную (например, $this->param), нужно выполнить экранирование 2 раза. Т.о. то, что мы найдём заменится на строку $this->param:
Raplace with: \\$this->param
В строке для поиска (регулярном выражении, Text to find) для того, чтобы, например найти эту же строку, экранирование нужно выполнить 1 раз:
Text to find: \$this->param
Обернуть строки в кавычки и поставить запятые в конце строк (напр, если нужно сформировать массив из скопированных строк, все строки разные, но начинаются на mozilla):
Text to find: '(mozilla.*)' Replace with: ''$1'',