Skip to content

Commit 4fd6318

Browse files
committed
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.
1 parent 42e6788 commit 4fd6318

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

scripts/dev/tidy.php

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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/standard/html_tables/html_table_gen.php',
27+
'ext/xmlrpc/libxmlrpc/',
28+
'sapi/cli/php_http_parser.c',
29+
'sapi/cli/php_http_parser.h',
30+
'sapi/litespeed/',
31+
// Not a PHP file.
32+
'ext/zlib/tests/data.inc',
33+
// Flexible HEREDOC/NOWDOC tests are likely whitespace sensitive.
34+
// TODO: Properly classify them.
35+
'Zend/tests/flexible-',
36+
];
37+
38+
foreach ($it as $file) {
39+
if (!$file->isFile()) {
40+
continue;
41+
}
42+
43+
$path = $file->getPathName();
44+
foreach ($excludes as $exclude) {
45+
if (strpos($path, $exclude) !== false) {
46+
continue 2;
47+
}
48+
}
49+
50+
$lang = getLanguageFromExtension($file->getExtension());
51+
if ($lang === null) {
52+
continue;
53+
}
54+
55+
$origCode = $code = file_get_contents($path);
56+
57+
if ($lang === 'c') {
58+
$code = stripTrailingWhitespace($code);
59+
// TODO: Avoid this for now.
60+
// $code = reindentToTabs($code);
61+
} else if ($lang === 'php') {
62+
$code = stripTrailingWhitespace($code);
63+
$code = reindentToSpaces($code);
64+
} else if ($lang === 'phpt') {
65+
// TODO: Don't reformat .phpt on PHP-7.4.
66+
/*$code = transformTestCode($code, function(string $code) {
67+
$code = stripTrailingWhitespace($code);
68+
$code = reindentToSpaces($code);
69+
return $code;
70+
});*/
71+
}
72+
73+
if ($origCode !== $code) {
74+
file_put_contents($path, $code);
75+
}
76+
}
77+
78+
function stripTrailingWhitespace(string $code): string {
79+
return preg_replace('/\h+$/m', '', $code);
80+
}
81+
82+
function reindentToTabs(string $code): string {
83+
return preg_replace_callback('/^ +/m', function(array $matches) {
84+
$tabSize = 4;
85+
$spaces = strlen($matches[0]);
86+
$tabs = intdiv($spaces, $tabSize);
87+
$spaces -= $tabs * $tabSize;
88+
return str_repeat("\t", $tabs) . str_repeat(" ", $spaces);
89+
}, $code);
90+
}
91+
92+
function reindentToSpaces(string $code): string {
93+
return preg_replace_callback('/^[ \t]+/m', function(array $matches) {
94+
$tabSize = 4;
95+
$indent = 0;
96+
foreach (str_split($matches[0]) as $char) {
97+
if ($char === ' ') {
98+
$indent++;
99+
} else {
100+
$partialIndent = $indent % $tabSize;
101+
if ($partialIndent === 0) {
102+
$indent += $tabSize;
103+
} else {
104+
$indent += $tabSize - $partialIndent;
105+
}
106+
}
107+
}
108+
return str_repeat(" ", $indent);
109+
}, $code);
110+
}
111+
112+
function transformTestCode(string $code, callable $transformer): string {
113+
// Don't transform whitespace-sensitive tests.
114+
if (strpos($code, '--WHITESPACE_SENSITIVE--') !== false) {
115+
return $code;
116+
}
117+
118+
return preg_replace_callback(
119+
'/(--FILE--)(.+?)(--[A-Z_]+--)/s',
120+
function(array $matches) use($transformer) {
121+
return $matches[1] . $transformer($matches[2]) . $matches[3];
122+
},
123+
$code
124+
);
125+
}
126+
127+
function getLanguageFromExtension(string $ext): ?string {
128+
switch ($ext) {
129+
case 'c':
130+
case 'h':
131+
case 'cpp':
132+
case 'y':
133+
case 'l':
134+
case 're':
135+
return 'c';
136+
case 'php':
137+
// TODO: Reformat .inc files.
138+
//case 'inc':
139+
return 'php';
140+
case 'phpt':
141+
return 'phpt';
142+
default:
143+
return null;
144+
}
145+
}

0 commit comments

Comments
 (0)