summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-01-10 15:52:42 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-02-03 13:34:42 +0100
commit4fd63185803aad42790c0ac38c144b346e283009 (patch)
tree22de45dadbe5a5737352cd0b3620e31dcca6e9a4 /scripts
parent42e67881c9597681196f215c2122e90ee7427e7e (diff)
downloadphp-git-4fd63185803aad42790c0ac38c144b346e283009.tar.gz
Add tidy.php to enforce formatting
Many parts are disabled for the PHP-7.4 branch. We only strip trailing whitespace in C files and reindent .php files to spaces.
Diffstat (limited to 'scripts')
-rw-r--r--scripts/dev/tidy.php145
1 files changed, 145 insertions, 0 deletions
diff --git a/scripts/dev/tidy.php b/scripts/dev/tidy.php
new file mode 100644
index 0000000000..267f838a61
--- /dev/null
+++ b/scripts/dev/tidy.php
@@ -0,0 +1,145 @@
+<?php
+
+set_error_handler(function($_, $msg) {
+ throw new Exception($msg);
+});
+
+$rootDir = __DIR__ . '/../..';
+$it = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($rootDir),
+ RecursiveIteratorIterator::LEAVES_ONLY
+);
+
+$excludes = [
+ // Bundled libraries / files.
+ 'ext/bcmath/libbcmath/',
+ 'ext/date/lib/',
+ 'ext/fileinfo/data_file.c',
+ 'ext/fileinfo/libmagic/',
+ 'ext/gd/libgd/',
+ 'ext/hash/sha3/',
+ 'ext/hash/hash_whirlpool.c',
+ 'ext/hash/php_hash_whirlpool_tables.h',
+ 'ext/mbstring/libmbfl/',
+ 'ext/mbstring/unicode_data.h',
+ 'ext/pcre/pcre2lib/',
+ 'ext/standard/html_tables/html_table_gen.php',
+ 'ext/xmlrpc/libxmlrpc/',
+ 'sapi/cli/php_http_parser.c',
+ 'sapi/cli/php_http_parser.h',
+ 'sapi/litespeed/',
+ // Not a PHP file.
+ 'ext/zlib/tests/data.inc',
+ // Flexible HEREDOC/NOWDOC tests are likely whitespace sensitive.
+ // TODO: Properly classify them.
+ 'Zend/tests/flexible-',
+];
+
+foreach ($it as $file) {
+ if (!$file->isFile()) {
+ continue;
+ }
+
+ $path = $file->getPathName();
+ foreach ($excludes as $exclude) {
+ if (strpos($path, $exclude) !== false) {
+ continue 2;
+ }
+ }
+
+ $lang = getLanguageFromExtension($file->getExtension());
+ if ($lang === null) {
+ continue;
+ }
+
+ $origCode = $code = file_get_contents($path);
+
+ if ($lang === 'c') {
+ $code = stripTrailingWhitespace($code);
+ // TODO: Avoid this for now.
+ // $code = reindentToTabs($code);
+ } else if ($lang === 'php') {
+ $code = stripTrailingWhitespace($code);
+ $code = reindentToSpaces($code);
+ } else if ($lang === 'phpt') {
+ // TODO: Don't reformat .phpt on PHP-7.4.
+ /*$code = transformTestCode($code, function(string $code) {
+ $code = stripTrailingWhitespace($code);
+ $code = reindentToSpaces($code);
+ return $code;
+ });*/
+ }
+
+ if ($origCode !== $code) {
+ file_put_contents($path, $code);
+ }
+}
+
+function stripTrailingWhitespace(string $code): string {
+ return preg_replace('/\h+$/m', '', $code);
+}
+
+function reindentToTabs(string $code): string {
+ return preg_replace_callback('/^ +/m', function(array $matches) {
+ $tabSize = 4;
+ $spaces = strlen($matches[0]);
+ $tabs = intdiv($spaces, $tabSize);
+ $spaces -= $tabs * $tabSize;
+ return str_repeat("\t", $tabs) . str_repeat(" ", $spaces);
+ }, $code);
+}
+
+function reindentToSpaces(string $code): string {
+ return preg_replace_callback('/^[ \t]+/m', function(array $matches) {
+ $tabSize = 4;
+ $indent = 0;
+ foreach (str_split($matches[0]) as $char) {
+ if ($char === ' ') {
+ $indent++;
+ } else {
+ $partialIndent = $indent % $tabSize;
+ if ($partialIndent === 0) {
+ $indent += $tabSize;
+ } else {
+ $indent += $tabSize - $partialIndent;
+ }
+ }
+ }
+ return str_repeat(" ", $indent);
+ }, $code);
+}
+
+function transformTestCode(string $code, callable $transformer): string {
+ // Don't transform whitespace-sensitive tests.
+ if (strpos($code, '--WHITESPACE_SENSITIVE--') !== false) {
+ return $code;
+ }
+
+ return preg_replace_callback(
+ '/(--FILE--)(.+?)(--[A-Z_]+--)/s',
+ function(array $matches) use($transformer) {
+ return $matches[1] . $transformer($matches[2]) . $matches[3];
+ },
+ $code
+ );
+}
+
+function getLanguageFromExtension(string $ext): ?string {
+ switch ($ext) {
+ case 'c':
+ case 'h':
+ case 'cpp':
+ case 'y':
+ case 'l':
+ case 're':
+ return 'c';
+ case 'php':
+ // TODO: Reformat .inc files.
+ //case 'inc':
+ return 'php';
+ case 'phpt':
+ return 'phpt';
+ default:
+ return null;
+ }
+}