mirror of
https://github.com/symfony/debug.git
synced 2026-03-25 01:32:09 +01:00
Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb2001e5d8 | ||
|
|
d120b899c0 | ||
|
|
ab84a63772 | ||
|
|
e72a0340dc | ||
|
|
38fdc933c7 | ||
|
|
24b7bbfc7c | ||
|
|
b25b18421a | ||
|
|
74557880e2 | ||
|
|
def1666122 | ||
|
|
9ebd154442 | ||
|
|
2854347f27 | ||
|
|
a0a29e9867 | ||
|
|
271c75c24d | ||
|
|
723643a94b | ||
|
|
5f49adc996 | ||
|
|
08bf2c53db | ||
|
|
f0546da70c | ||
|
|
147025beaf | ||
|
|
88e1bd3ad2 | ||
|
|
d295479508 | ||
|
|
d2d11379b5 | ||
|
|
44c8fb3f90 | ||
|
|
eb95d9ce8f | ||
|
|
eaaec993ca | ||
|
|
e12a6f1168 | ||
|
|
34d945c4eb | ||
|
|
1407679206 | ||
|
|
c0a3a6b4f2 | ||
|
|
820b5ae4c3 | ||
|
|
3bea0cdeb5 | ||
|
|
2827a6e8c2 | ||
|
|
9c5b622f5a | ||
|
|
33f6f36c28 | ||
|
|
8beb24eec7 | ||
|
|
f43bc2e05d | ||
|
|
084d804fe3 | ||
|
|
efc9656dcb | ||
|
|
f45a908634 | ||
|
|
50bda5b4b8 | ||
|
|
f28018d622 | ||
|
|
b7190d5620 | ||
|
|
0920d5f066 | ||
|
|
3be4178b91 | ||
|
|
c9fcef80c3 | ||
|
|
e06181ae56 | ||
|
|
97592888b9 | ||
|
|
7c13ae8ce1 | ||
|
|
ba7276868c | ||
|
|
236ca98a42 | ||
|
|
0946243775 | ||
|
|
e1ce6a4ded | ||
|
|
296d63b9b2 | ||
|
|
ee6732177c | ||
|
|
18ac7ae10d | ||
|
|
9d40ad561e | ||
|
|
6694bfe6ac | ||
|
|
0f82f184dd | ||
|
|
20bb3a9837 | ||
|
|
91dc1c8129 | ||
|
|
627c397b80 |
@@ -1,6 +1,11 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()`
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
|
||||
@@ -26,18 +26,16 @@ class DebugClassLoader
|
||||
{
|
||||
private $classLoader;
|
||||
private $isFinder;
|
||||
private $loaded = array();
|
||||
private static $caseCheck;
|
||||
private static $final = array();
|
||||
private static $finalMethods = array();
|
||||
private static $deprecated = array();
|
||||
private static $internal = array();
|
||||
private static $internalMethods = array();
|
||||
private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
|
||||
private static $darwinCache = array('/' => array('/', array()));
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param callable $classLoader A class loader
|
||||
*/
|
||||
public function __construct(callable $classLoader)
|
||||
{
|
||||
$this->classLoader = $classLoader;
|
||||
@@ -136,19 +134,20 @@ class DebugClassLoader
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
ErrorHandler::stackErrors();
|
||||
$e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
|
||||
|
||||
try {
|
||||
if ($this->isFinder) {
|
||||
if ($this->isFinder && !isset($this->loaded[$class])) {
|
||||
$this->loaded[$class] = true;
|
||||
if ($file = $this->classLoader[0]->findFile($class)) {
|
||||
require_once $file;
|
||||
require $file;
|
||||
}
|
||||
} else {
|
||||
call_user_func($this->classLoader, $class);
|
||||
$file = false;
|
||||
}
|
||||
} finally {
|
||||
ErrorHandler::unstackErrors();
|
||||
error_reporting($e);
|
||||
}
|
||||
|
||||
$exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
|
||||
@@ -165,90 +164,96 @@ class DebugClassLoader
|
||||
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
|
||||
}
|
||||
|
||||
$parent = get_parent_class($class);
|
||||
// Don't trigger deprecations for classes in the same vendor
|
||||
if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
|
||||
$len = 0;
|
||||
$ns = '';
|
||||
} else {
|
||||
$ns = substr($name, 0, $len);
|
||||
}
|
||||
|
||||
// Not an interface nor a trait
|
||||
if (class_exists($name, false)) {
|
||||
if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
|
||||
self::$final[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
|
||||
// Detect annotations on the class
|
||||
if (false !== $doc = $refl->getDocComment()) {
|
||||
foreach (array('final', 'deprecated', 'internal') as $annotation) {
|
||||
if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) {
|
||||
self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent && isset(self::$final[$parent])) {
|
||||
$parentAndTraits = class_uses($name, false);
|
||||
if ($parent = get_parent_class($class)) {
|
||||
$parentAndTraits[] = $parent;
|
||||
|
||||
if (isset(self::$final[$parent])) {
|
||||
@trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
// Inherit @final annotations
|
||||
self::$finalMethods[$name] = $parent && isset(self::$finalMethods[$parent]) ? self::$finalMethods[$parent] : array();
|
||||
// Detect if the parent is annotated
|
||||
foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) {
|
||||
if (isset(self::$deprecated[$use]) && strncmp($ns, $use, $len)) {
|
||||
$type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait');
|
||||
$verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
|
||||
|
||||
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
|
||||
if ($method->class !== $name) {
|
||||
continue;
|
||||
@trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED);
|
||||
}
|
||||
if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) {
|
||||
@trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
// Inherit @final and @internal annotations for methods
|
||||
self::$finalMethods[$name] = array();
|
||||
self::$internalMethods[$name] = array();
|
||||
foreach ($parentAndTraits as $use) {
|
||||
foreach (array('finalMethods', 'internalMethods') as $property) {
|
||||
if (isset(self::${$property}[$use])) {
|
||||
self::${$property}[$name] = array_merge(self::${$property}[$name], self::${$property}[$use]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
|
||||
@trigger_error(sprintf('%s It may change without further notice as of its next major version. You should not extend it from "%s".', self::$finalMethods[$parent][$method->name], $name), E_USER_DEPRECATED);
|
||||
$isClass = class_exists($name, false);
|
||||
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
|
||||
if ($method->class !== $name) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Method from a trait
|
||||
if ($method->getFilename() !== $refl->getFileName()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) {
|
||||
list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
|
||||
@trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
foreach ($parentAndTraits as $use) {
|
||||
if (isset(self::$internalMethods[$use][$method->name])) {
|
||||
list($declaringClass, $message) = self::$internalMethods[$use][$method->name];
|
||||
if (strncmp($ns, $declaringClass, $len)) {
|
||||
@trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$doc = $method->getDocComment();
|
||||
if (false === $doc || false === strpos($doc, '@final')) {
|
||||
continue;
|
||||
}
|
||||
// Detect method annotations
|
||||
if (false === $doc = $method->getDocComment()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (preg_match('#\n\s+\* @final(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
|
||||
foreach (array('final', 'internal') as $annotation) {
|
||||
if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
|
||||
$message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
|
||||
self::$finalMethods[$name][$method->name] = sprintf('The "%s::%s()" method is considered final%s.', $name, $method->name, $message);
|
||||
self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
|
||||
@trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
|
||||
} elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
|
||||
self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
|
||||
} else {
|
||||
// Don't trigger deprecations for classes in the same vendor
|
||||
if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
|
||||
$len = 0;
|
||||
$ns = '';
|
||||
} else {
|
||||
switch ($ns = substr($name, 0, $len)) {
|
||||
case 'Symfony\Bridge\\':
|
||||
case 'Symfony\Bundle\\':
|
||||
case 'Symfony\Component\\':
|
||||
$ns = 'Symfony\\';
|
||||
$len = strlen($ns);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$parent || strncmp($ns, $parent, $len)) {
|
||||
if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
|
||||
@trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$parentInterfaces = array();
|
||||
$deprecatedInterfaces = array();
|
||||
if ($parent) {
|
||||
foreach (class_implements($parent) as $interface) {
|
||||
$parentInterfaces[$interface] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($refl->getInterfaceNames() as $interface) {
|
||||
if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
|
||||
$deprecatedInterfaces[] = $interface;
|
||||
}
|
||||
foreach (class_implements($interface) as $interface) {
|
||||
$parentInterfaces[$interface] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($deprecatedInterfaces as $interface) {
|
||||
if (!isset($parentInterfaces[$interface])) {
|
||||
@trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,4 +354,31 @@ class DebugClassLoader
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `class_implements` includes interfaces from the parents so we have to manually exclude them.
|
||||
*
|
||||
* @param string $class
|
||||
* @param string|false $parent
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function getOwnInterfaces($class, $parent)
|
||||
{
|
||||
$ownInterfaces = class_implements($class, false);
|
||||
|
||||
if ($parent) {
|
||||
foreach (class_implements($parent, false) as $interface) {
|
||||
unset($ownInterfaces[$interface]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($ownInterfaces as $interface) {
|
||||
foreach (class_implements($interface) as $interface) {
|
||||
unset($ownInterfaces[$interface]);
|
||||
}
|
||||
}
|
||||
|
||||
return $ownInterfaces;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,21 +409,25 @@ class ErrorHandler
|
||||
$errorAsException = self::$toStringException;
|
||||
self::$toStringException = null;
|
||||
} elseif (!$throw && !($type & $level)) {
|
||||
if (isset(self::$silencedErrorCache[$message])) {
|
||||
$lightTrace = null;
|
||||
$errorAsException = self::$silencedErrorCache[$message];
|
||||
++$errorAsException->count;
|
||||
} else {
|
||||
if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
|
||||
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
|
||||
$errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
|
||||
} elseif (isset(self::$silencedErrorCache[$id][$message])) {
|
||||
$lightTrace = null;
|
||||
$errorAsException = self::$silencedErrorCache[$id][$message];
|
||||
++$errorAsException->count;
|
||||
} else {
|
||||
$lightTrace = array();
|
||||
$errorAsException = null;
|
||||
}
|
||||
|
||||
if (100 < ++self::$silencedErrorCount) {
|
||||
self::$silencedErrorCache = $lightTrace = array();
|
||||
self::$silencedErrorCount = 1;
|
||||
}
|
||||
self::$silencedErrorCache[$message] = $errorAsException;
|
||||
|
||||
if ($errorAsException) {
|
||||
self::$silencedErrorCache[$id][$message] = $errorAsException;
|
||||
}
|
||||
if (null === $lightTrace) {
|
||||
return;
|
||||
}
|
||||
@@ -494,13 +498,13 @@ class ErrorHandler
|
||||
$this->loggers[$type][0],
|
||||
($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG,
|
||||
$logMessage,
|
||||
array('exception' => $errorAsException),
|
||||
$errorAsException ? array('exception' => $errorAsException) : array(),
|
||||
);
|
||||
} else {
|
||||
try {
|
||||
$this->isRecursive = true;
|
||||
$level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
|
||||
$this->loggers[$type][0]->log($level, $logMessage, array('exception' => $errorAsException));
|
||||
$this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array());
|
||||
} finally {
|
||||
$this->isRecursive = false;
|
||||
}
|
||||
@@ -648,17 +652,25 @@ class ErrorHandler
|
||||
*
|
||||
* The most important feature of this is to prevent
|
||||
* autoloading until unstackErrors() is called.
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0.
|
||||
*/
|
||||
public static function stackErrors()
|
||||
{
|
||||
@trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
|
||||
|
||||
self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unstacks stacked errors and forwards to the logger.
|
||||
*
|
||||
* @deprecated since version 3.4, to be removed in 4.0.
|
||||
*/
|
||||
public static function unstackErrors()
|
||||
{
|
||||
@trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
|
||||
|
||||
$level = array_pop(self::$stackedErrorLevels);
|
||||
|
||||
if (null !== $level) {
|
||||
@@ -707,7 +719,7 @@ class ErrorHandler
|
||||
}
|
||||
if (!($throw || $this->scopedErrors & $type)) {
|
||||
for ($i = 0; isset($lightTrace[$i]); ++$i) {
|
||||
unset($lightTrace[$i]['args']);
|
||||
unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -196,8 +196,6 @@ class ExceptionHandler
|
||||
/**
|
||||
* Gets the HTML content associated with the given exception.
|
||||
*
|
||||
* @param FlattenException $exception A FlattenException instance
|
||||
*
|
||||
* @return string The content as a string
|
||||
*/
|
||||
public function getContent(FlattenException $exception)
|
||||
@@ -276,8 +274,6 @@ EOF;
|
||||
/**
|
||||
* Gets the stylesheet associated with the given exception.
|
||||
*
|
||||
* @param FlattenException $exception A FlattenException instance
|
||||
*
|
||||
* @return string The stylesheet as a string
|
||||
*/
|
||||
public function getStylesheet(FlattenException $exception)
|
||||
@@ -310,8 +306,8 @@ EOF;
|
||||
.exception-message { flex-grow: 1; padding: 30px 0; }
|
||||
.exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; }
|
||||
.exception-message.long { font-size: 18px; }
|
||||
.exception-message a { text-decoration: none; }
|
||||
.exception-message a:hover { text-decoration: underline; }
|
||||
.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; }
|
||||
.exception-message a:hover { border-bottom-color: #ffffff; }
|
||||
|
||||
.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
|
||||
|
||||
@@ -320,11 +316,11 @@ EOF;
|
||||
|
||||
.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }
|
||||
|
||||
.trace-file-path, .trace-file-path a { margin-top: 3px; color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; }
|
||||
.trace-file-path, .trace-file-path a { color: #222; margin-top: 3px; font-size: 13px; }
|
||||
.trace-class { color: #B0413E; }
|
||||
.trace-type { padding: 0 2px; }
|
||||
.trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; }
|
||||
.trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; }
|
||||
.trace-method { color: #B0413E; font-weight: bold; }
|
||||
.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; }
|
||||
|
||||
@media (min-width: 575px) {
|
||||
.hidden-xs-down { display: initial; }
|
||||
@@ -393,7 +389,7 @@ EOF;
|
||||
$formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true)));
|
||||
}
|
||||
|
||||
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
|
||||
$result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
|
||||
@@ -59,6 +59,23 @@ class DebugClassLoaderTest extends TestCase
|
||||
$this->fail('DebugClassLoader did not register');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
* @expectedExceptionMessage boo
|
||||
*/
|
||||
public function testThrowingClass()
|
||||
{
|
||||
try {
|
||||
class_exists(__NAMESPACE__.'\Fixtures\Throwing');
|
||||
$this->fail('Exception expected');
|
||||
} catch (\Exception $e) {
|
||||
$this->assertSame('boo', $e->getMessage());
|
||||
}
|
||||
|
||||
// the second call also should throw
|
||||
class_exists(__NAMESPACE__.'\Fixtures\Throwing');
|
||||
}
|
||||
|
||||
public function testUnsilencing()
|
||||
{
|
||||
if (\PHP_VERSION_ID >= 70000) {
|
||||
@@ -124,6 +141,7 @@ class DebugClassLoaderTest extends TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Case mismatch between loaded and declared class names
|
||||
*/
|
||||
public function testNameCaseMismatch()
|
||||
{
|
||||
@@ -145,6 +163,7 @@ class DebugClassLoaderTest extends TestCase
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage Case mismatch between loaded and declared class names
|
||||
*/
|
||||
public function testPsr4CaseMismatch()
|
||||
{
|
||||
@@ -312,6 +331,42 @@ class DebugClassLoaderTest extends TestCase
|
||||
|
||||
$this->assertSame($xError, $lastError);
|
||||
}
|
||||
|
||||
public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice()
|
||||
{
|
||||
set_error_handler(function () { return false; });
|
||||
$e = error_reporting(0);
|
||||
trigger_error('', E_USER_NOTICE);
|
||||
|
||||
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true);
|
||||
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$lastError = error_get_last();
|
||||
unset($lastError['file'], $lastError['line']);
|
||||
|
||||
$this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError);
|
||||
}
|
||||
|
||||
public function testInternalsUse()
|
||||
{
|
||||
$deprecations = array();
|
||||
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
|
||||
$e = error_reporting(E_USER_DEPRECATED);
|
||||
|
||||
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true);
|
||||
|
||||
error_reporting($e);
|
||||
restore_error_handler();
|
||||
|
||||
$this->assertSame($deprecations, array(
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
|
||||
'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class ClassLoader
|
||||
@@ -335,22 +390,12 @@ class ClassLoader
|
||||
eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }');
|
||||
} elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
|
||||
eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
|
||||
} elseif (__NAMESPACE__.'\Fixtures\CaseMismatch' === $class) {
|
||||
return $fixtureDir.'CaseMismatch.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
|
||||
return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
|
||||
return $fixtureDir.'reallyNotPsr0.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
|
||||
return $fixtureDir.'notPsr0Bis.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\DeprecatedInterface' === $class) {
|
||||
return $fixtureDir.'DeprecatedInterface.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\FinalClass' === $class) {
|
||||
return $fixtureDir.'FinalClass.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\FinalMethod' === $class) {
|
||||
return $fixtureDir.'FinalMethod.php';
|
||||
} elseif (__NAMESPACE__.'\Fixtures\ExtendedFinalMethod' === $class) {
|
||||
return $fixtureDir.'ExtendedFinalMethod.php';
|
||||
} elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) {
|
||||
eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) {
|
||||
@@ -363,6 +408,18 @@ class ClassLoader
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
|
||||
public function deprecatedMethod() { }
|
||||
}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent {
|
||||
use \\'.__NAMESPACE__.'\Fixtures\InternalTrait;
|
||||
|
||||
public function internalMethod() { }
|
||||
}');
|
||||
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) {
|
||||
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,8 +98,6 @@ class ErrorHandlerTest extends TestCase
|
||||
// dummy function to test trace in error handler.
|
||||
private static function triggerNotice($that)
|
||||
{
|
||||
// dummy variable to check for in error handler.
|
||||
$foobar = 123;
|
||||
$that->assertSame('', $foo.$foo.$bar);
|
||||
}
|
||||
|
||||
@@ -342,6 +340,9 @@ class ErrorHandlerTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
public function testErrorStacking()
|
||||
{
|
||||
try {
|
||||
|
||||
13
Tests/Fixtures/AnnotatedClass.php
Normal file
13
Tests/Fixtures/AnnotatedClass.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
class AnnotatedClass
|
||||
{
|
||||
/**
|
||||
* @deprecated since version 3.4.
|
||||
*/
|
||||
public function deprecatedMethod()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @deprecated but this is a test
|
||||
* deprecation notice.
|
||||
* deprecation notice
|
||||
* @foobar
|
||||
*/
|
||||
class DeprecatedClass
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @deprecated but this is a test
|
||||
* deprecation notice.
|
||||
* deprecation notice
|
||||
* @foobar
|
||||
*/
|
||||
interface DeprecatedInterface
|
||||
|
||||
15
Tests/Fixtures/InternalClass.php
Normal file
15
Tests/Fixtures/InternalClass.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @internal since version 3.4.
|
||||
*/
|
||||
class InternalClass
|
||||
{
|
||||
use InternalTrait2;
|
||||
|
||||
public function usedInInternalClass()
|
||||
{
|
||||
}
|
||||
}
|
||||
10
Tests/Fixtures/InternalInterface.php
Normal file
10
Tests/Fixtures/InternalInterface.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface InternalInterface
|
||||
{
|
||||
}
|
||||
10
Tests/Fixtures/InternalTrait.php
Normal file
10
Tests/Fixtures/InternalTrait.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait InternalTrait
|
||||
{
|
||||
}
|
||||
23
Tests/Fixtures/InternalTrait2.php
Normal file
23
Tests/Fixtures/InternalTrait2.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Debug\Tests\Fixtures;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
trait InternalTrait2
|
||||
{
|
||||
/**
|
||||
* @internal since version 3.4
|
||||
*/
|
||||
public function internalMethod()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal but should not trigger a deprecation
|
||||
*/
|
||||
public function usedInInternalClass()
|
||||
{
|
||||
}
|
||||
}
|
||||
3
Tests/Fixtures/Throwing.php
Normal file
3
Tests/Fixtures/Throwing.php
Normal file
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
|
||||
throw new \Exception('boo');
|
||||
@@ -16,14 +16,14 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.5.9",
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-kernel": "~2.8|~3.0"
|
||||
"symfony/http-kernel": "~2.8|~3.0|~4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Debug\\": "" },
|
||||
@@ -34,7 +34,7 @@
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev"
|
||||
"dev-master": "3.4-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user