comparison vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 7a779792577d
children c2387f117808
comparison
equal deleted inserted replaced
13:5fb285c0d0e3 14:1fec387a4317
17 * @author Nicolas Grekas <p@tchwork.com> 17 * @author Nicolas Grekas <p@tchwork.com>
18 */ 18 */
19 class DeprecationErrorHandler 19 class DeprecationErrorHandler
20 { 20 {
21 const MODE_WEAK = 'weak'; 21 const MODE_WEAK = 'weak';
22 const MODE_WEAK_VENDORS = 'weak_vendors';
22 const MODE_DISABLED = 'disabled'; 23 const MODE_DISABLED = 'disabled';
23 24
24 private static $isRegistered = false; 25 private static $isRegistered = false;
25 26
26 /** 27 /**
27 * Registers and configures the deprecation handler. 28 * Registers and configures the deprecation handler.
28 * 29 *
29 * The following reporting modes are supported: 30 * The following reporting modes are supported:
30 * - use "weak" to hide the deprecation report but keep a global count; 31 * - use "weak" to hide the deprecation report but keep a global count;
32 * - use "weak_vendors" to act as "weak" but only for vendors;
31 * - use "/some-regexp/" to stop the test suite whenever a deprecation 33 * - use "/some-regexp/" to stop the test suite whenever a deprecation
32 * message matches the given regular expression; 34 * message matches the given regular expression;
33 * - use a number to define the upper bound of allowed deprecations, 35 * - use a number to define the upper bound of allowed deprecations,
34 * making the test suite fail whenever more notices are trigerred. 36 * making the test suite fail whenever more notices are trigerred.
35 * 37 *
39 { 41 {
40 if (self::$isRegistered) { 42 if (self::$isRegistered) {
41 return; 43 return;
42 } 44 }
43 45
46 $UtilPrefix = class_exists('PHPUnit_Util_ErrorHandler') ? 'PHPUnit_Util_' : 'PHPUnit\Util\\';
47
44 $getMode = function () use ($mode) { 48 $getMode = function () use ($mode) {
45 static $memoizedMode = false; 49 static $memoizedMode = false;
46 50
47 if (false !== $memoizedMode) { 51 if (false !== $memoizedMode) {
48 return $memoizedMode; 52 return $memoizedMode;
49 } 53 }
50 if (false === $mode) { 54 if (false === $mode) {
51 $mode = getenv('SYMFONY_DEPRECATIONS_HELPER'); 55 $mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
52 } 56 }
53 if (DeprecationErrorHandler::MODE_WEAK !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) { 57 if (DeprecationErrorHandler::MODE_WEAK !== $mode && DeprecationErrorHandler::MODE_WEAK_VENDORS !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) {
54 $mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0; 58 $mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
55 } 59 }
56 60
57 return $memoizedMode = $mode; 61 return $memoizedMode = $mode;
62 };
63
64 $inVendors = function ($path) {
65 /** @var string[] absolute paths to vendor directories */
66 static $vendors;
67 if (null === $vendors) {
68 foreach (get_declared_classes() as $class) {
69 if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
70 $r = new \ReflectionClass($class);
71 $v = dirname(dirname($r->getFileName()));
72 if (file_exists($v.'/composer/installed.json')) {
73 $vendors[] = $v;
74 }
75 }
76 }
77 }
78 $realPath = realpath($path);
79 if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
80 return true;
81 }
82 foreach ($vendors as $vendor) {
83 if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) {
84 return true;
85 }
86 }
87
88 return false;
58 }; 89 };
59 90
60 $deprecations = array( 91 $deprecations = array(
61 'unsilencedCount' => 0, 92 'unsilencedCount' => 0,
62 'remainingCount' => 0, 93 'remainingCount' => 0,
63 'legacyCount' => 0, 94 'legacyCount' => 0,
64 'otherCount' => 0, 95 'otherCount' => 0,
96 'remaining vendorCount' => 0,
65 'unsilenced' => array(), 97 'unsilenced' => array(),
66 'remaining' => array(), 98 'remaining' => array(),
67 'legacy' => array(), 99 'legacy' => array(),
68 'other' => array(), 100 'other' => array(),
101 'remaining vendor' => array(),
69 ); 102 );
70 $deprecationHandler = function ($type, $msg, $file, $line, $context = array()) use (&$deprecations, $getMode) { 103 $deprecationHandler = function ($type, $msg, $file, $line, $context = array()) use (&$deprecations, $getMode, $UtilPrefix, $inVendors) {
71 $mode = $getMode(); 104 $mode = $getMode();
72 if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || DeprecationErrorHandler::MODE_DISABLED === $mode) { 105 if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || DeprecationErrorHandler::MODE_DISABLED === $mode) {
73 return \PHPUnit_Util_ErrorHandler::handleError($type, $msg, $file, $line, $context); 106 $ErrorHandler = $UtilPrefix.'ErrorHandler';
107
108 return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
74 } 109 }
75 110
76 $trace = debug_backtrace(true); 111 $trace = debug_backtrace(true);
77 $group = 'other'; 112 $group = 'other';
113 $isVendor = DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $inVendors($file);
78 114
79 $i = count($trace); 115 $i = count($trace);
80 while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_')))) { 116 while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) {
81 // No-op 117 // No-op
82 } 118 }
83 119
84 if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) { 120 if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) {
85 $class = isset($trace[$i]['object']) ? get_class($trace[$i]['object']) : $trace[$i]['class']; 121 if (isset($trace[$i]['class']) && 0 === strpos($trace[$i]['class'], 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor')) {
86 $method = $trace[$i]['function']; 122 $parsedMsg = unserialize($msg);
123 $msg = $parsedMsg['deprecation'];
124 $class = $parsedMsg['class'];
125 $method = $parsedMsg['method'];
126 // If the deprecation has been triggered via
127 // \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
128 // then we need to use the serialized information to determine
129 // if the error has been triggered from vendor code.
130 $isVendor = DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && isset($parsedMsg['triggering_file']) && $inVendors($parsedMsg['triggering_file']);
131 } else {
132 $class = isset($trace[$i]['object']) ? get_class($trace[$i]['object']) : $trace[$i]['class'];
133 $method = $trace[$i]['function'];
134 }
135
136 $Test = $UtilPrefix.'Test';
87 137
88 if (0 !== error_reporting()) { 138 if (0 !== error_reporting()) {
89 $group = 'unsilenced'; 139 $group = 'unsilenced';
90 } elseif (0 === strpos($method, 'testLegacy') 140 } elseif (0 === strpos($method, 'testLegacy')
91 || 0 === strpos($method, 'provideLegacy') 141 || 0 === strpos($method, 'provideLegacy')
92 || 0 === strpos($method, 'getLegacy') 142 || 0 === strpos($method, 'getLegacy')
93 || strpos($class, '\Legacy') 143 || strpos($class, '\Legacy')
94 || in_array('legacy', \PHPUnit_Util_Test::getGroups($class, $method), true) 144 || in_array('legacy', $Test::getGroups($class, $method), true)
95 ) { 145 ) {
96 $group = 'legacy'; 146 $group = 'legacy';
147 } elseif ($isVendor) {
148 $group = 'remaining vendor';
97 } else { 149 } else {
98 $group = 'remaining'; 150 $group = 'remaining';
99 } 151 }
100 152
101 if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) { 153 if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) {
126 }; 178 };
127 $oldErrorHandler = set_error_handler($deprecationHandler); 179 $oldErrorHandler = set_error_handler($deprecationHandler);
128 180
129 if (null !== $oldErrorHandler) { 181 if (null !== $oldErrorHandler) {
130 restore_error_handler(); 182 restore_error_handler();
131 if (array('PHPUnit_Util_ErrorHandler', 'handleError') === $oldErrorHandler) { 183 if (array($UtilPrefix.'ErrorHandler', 'handleError') === $oldErrorHandler) {
132 restore_error_handler(); 184 restore_error_handler();
133 self::register($mode); 185 self::register($mode);
134 } 186 }
135 } else { 187 } else {
136 self::$isRegistered = true; 188 self::$isRegistered = true;
160 212
161 $cmp = function ($a, $b) { 213 $cmp = function ($a, $b) {
162 return $b['count'] - $a['count']; 214 return $b['count'] - $a['count'];
163 }; 215 };
164 216
165 foreach (array('unsilenced', 'remaining', 'legacy', 'other') as $group) { 217 $groups = array('unsilenced', 'remaining');
166 if ($deprecations[$group.'Count']) { 218 if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode) {
167 echo "\n", $colorize(sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']), 'legacy' !== $group), "\n"; 219 $groups[] = 'remaining vendor';
168 220 }
169 uasort($deprecations[$group], $cmp); 221 array_push($groups, 'legacy', 'other');
170 222
171 foreach ($deprecations[$group] as $msg => $notices) { 223 $displayDeprecations = function ($deprecations) use ($colorize, $cmp, $groups) {
172 echo "\n", rtrim($msg, '.'), ': ', $notices['count'], "x\n"; 224 foreach ($groups as $group) {
173 225 if ($deprecations[$group.'Count']) {
174 arsort($notices); 226 echo "\n", $colorize(
175 227 sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']),
176 foreach ($notices as $method => $count) { 228 'legacy' !== $group && 'remaining vendor' !== $group
177 if ('count' !== $method) { 229 ), "\n";
178 echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n"; 230
231 uasort($deprecations[$group], $cmp);
232
233 foreach ($deprecations[$group] as $msg => $notices) {
234 echo "\n ", $notices['count'], 'x: ', $msg, "\n";
235
236 arsort($notices);
237
238 foreach ($notices as $method => $count) {
239 if ('count' !== $method) {
240 echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
241 }
179 } 242 }
180 } 243 }
181 } 244 }
182 } 245 }
183 } 246 if (!empty($notices)) {
184 if (!empty($notices)) { 247 echo "\n";
185 echo "\n"; 248 }
186 } 249 };
187 250
188 if (DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) { 251 $displayDeprecations($deprecations);
189 exit(1); 252
190 } 253 // store failing status
254 $isFailing = DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount'];
255
256 // reset deprecations array
257 foreach ($deprecations as $group => $arrayOrInt) {
258 $deprecations[$group] = is_int($arrayOrInt) ? 0 : array();
259 }
260
261 register_shutdown_function(function () use (&$deprecations, $isFailing, $displayDeprecations, $mode) {
262 foreach ($deprecations as $group => $arrayOrInt) {
263 if (0 < (is_int($arrayOrInt) ? $arrayOrInt : count($arrayOrInt))) {
264 echo "Shutdown-time deprecations:\n";
265 break;
266 }
267 }
268 $displayDeprecations($deprecations);
269 if ($isFailing || DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) {
270 exit(1);
271 }
272 });
191 }); 273 });
192 } 274 }
275 }
276
277 public static function collectDeprecations($outputFile)
278 {
279 $deprecations = array();
280 $previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$deprecations, &$previousErrorHandler) {
281 if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
282 if ($previousErrorHandler) {
283 return $previousErrorHandler($type, $msg, $file, $line, $context);
284 }
285 static $autoload = true;
286
287 $ErrorHandler = class_exists('PHPUnit_Util_ErrorHandler', $autoload) ? 'PHPUnit_Util_ErrorHandler' : 'PHPUnit\Util\ErrorHandler';
288 $autoload = false;
289
290 return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
291 }
292 $deprecations[] = array(error_reporting(), $msg, $file);
293 });
294
295 register_shutdown_function(function () use ($outputFile, &$deprecations) {
296 file_put_contents($outputFile, serialize($deprecations));
297 });
193 } 298 }
194 299
195 private static function hasColorSupport() 300 private static function hasColorSupport()
196 { 301 {
197 if ('\\' === DIRECTORY_SEPARATOR) { 302 if ('\\' === DIRECTORY_SEPARATOR) {
198 return 303 return
199 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD 304 defined('STDOUT') && function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(STDOUT)
305 || '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
200 || false !== getenv('ANSICON') 306 || false !== getenv('ANSICON')
201 || 'ON' === getenv('ConEmuANSI') 307 || 'ON' === getenv('ConEmuANSI')
202 || 'xterm' === getenv('TERM'); 308 || 'xterm' === getenv('TERM');
203 } 309 }
204 310