Skip to content

Commit 0baa0ad

Browse files
committed
Add tidy.php to enforce formatting
1 parent bbfa3fe commit 0baa0ad

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

scripts/dev/tidy.php

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<?php
2+
3+
set_error_handler(function($_, $msg) {
4+
throw new Exception($msg);
5+
});
6+
7+
$rootDir = __DIR__ . '/../..';
8+
$it = new RecursiveIteratorIterator(
9+
new RecursiveDirectoryIterator($rootDir),
10+
RecursiveIteratorIterator::LEAVES_ONLY
11+
);
12+
13+
$excludes = [
14+
// Bundled libraries / files.
15+
'ext/bcmath/libbcmath/',
16+
'ext/date/lib/',
17+
'ext/fileinfo/data_file.c',
18+
'ext/fileinfo/libmagic/',
19+
'ext/gd/libgd/',
20+
'ext/hash/sha3/',
21+
'ext/hash/hash_whirlpool.c',
22+
'ext/hash/php_hash_whirlpool_tables.h',
23+
'ext/mbstring/libmbfl/',
24+
'ext/mbstring/unicode_data.h',
25+
'ext/pcre/pcre2lib/',
26+
'ext/xmlrpc/libxmlrpc/',
27+
'sapi/cli/php_http_parser.c',
28+
'sapi/cli/php_http_parser.h',
29+
'sapi/litespeed/',
30+
// Not a PHP file.
31+
'ext/zlib/tests/data.inc',
32+
// Flexible HEREDOC/NOWDOC tests are likely whitespace sensitive.
33+
// TODO: Properly classify them.
34+
'Zend/tests/flexible-',
35+
];
36+
37+
foreach ($it as $file) {
38+
if (!$file->isFile()) {
39+
continue;
40+
}
41+
42+
$path = $file->getPathName();
43+
foreach ($excludes as $exclude) {
44+
if (strpos($path, $exclude) !== false) {
45+
continue 2;
46+
}
47+
}
48+
49+
$lang = getLanguageFromExtension($file->getExtension());
50+
if ($lang === null) {
51+
continue;
52+
}
53+
54+
$origCode = $code = file_get_contents($path);
55+
56+
if ($lang === 'c') {
57+
$code = stripTrailingWhitespace($code);
58+
// Avoid this for now.
59+
// $code = reindentToTabs($code);
60+
} else if ($lang === 'php') {
61+
$code = stripTrailingWhitespace($code);
62+
$code = reindentToSpaces($code);
63+
} else if ($lang === 'phpt') {
64+
$code = transformTestCode($code, function(string $code) {
65+
$code = stripTrailingWhitespace($code);
66+
$code = reindentToSpaces($code);
67+
return $code;
68+
});
69+
}
70+
71+
if ($origCode !== $code) {
72+
file_put_contents($path, $code);
73+
}
74+
}
75+
76+
function stripTrailingWhitespace(string $code): string {
77+
return preg_replace('/\h+$/m', '', $code);
78+
}
79+
80+
function reindentToTabs(string $code): string {
81+
return preg_replace_callback('/^ +/m', function(array $matches) {
82+
$tabSize = 4;
83+
$spaces = strlen($matches[0]);
84+
$tabs = intdiv($spaces, $tabSize);
85+
$spaces -= $tabs * $tabSize;
86+
return str_repeat("\t", $tabs) . str_repeat(" ", $spaces);
87+
}, $code);
88+
}
89+
90+
function reindentToSpaces(string $code): string {
91+
return preg_replace_callback('/^\t+/m', function(array $matches) {
92+
$tabSize = 4;
93+
$tabs = strlen($matches[0]);
94+
$spaces = $tabs * $tabSize;
95+
return str_repeat(" ", $spaces);
96+
}, $code);
97+
}
98+
99+
function transformTestCode(string $code, callable $transformer): string {
100+
// Don't transform whitespace-sensitive tests.
101+
if (strpos($code, '--WHITESPACE_SENSITIVE--') !== false) {
102+
return $code;
103+
}
104+
105+
return preg_replace_callback(
106+
'/(--FILE--)(.+?)(--[A-Z_]+--)/s',
107+
function(array $matches) use($transformer) {
108+
return $matches[1] . $transformer($matches[2]) . $matches[3];
109+
},
110+
$code
111+
);
112+
}
113+
114+
function getLanguageFromExtension(string $ext): ?string {
115+
switch ($ext) {
116+
case 'c':
117+
case 'h':
118+
case 'cpp':
119+
case 'y':
120+
case 'l':
121+
case 're':
122+
return 'c';
123+
case 'php':
124+
case 'inc':
125+
return 'php';
126+
case 'phpt':
127+
return 'phpt';
128+
default:
129+
return null;
130+
}
131+
}

0 commit comments

Comments
 (0)