@@ -132,9 +132,9 @@ public function run(InputInterface $input = null, OutputInterface $output = null
132132 $ e = class_exists (ErrorException::class) ? new ErrorException ($ e ) : (class_exists (LegacyFatalThrowableError::class) ? new LegacyFatalThrowableError ($ e ) : new \ErrorException ($ e ->getMessage (), $ e ->getCode (), E_ERROR , $ e ->getFile (), $ e ->getLine ()));
133133 }
134134 if ($ output instanceof ConsoleOutputInterface) {
135- $ this ->renderException ($ e , $ output ->getErrorOutput ());
135+ $ this ->renderThrowable ($ e , $ output ->getErrorOutput ());
136136 } else {
137- $ this ->renderException ($ e , $ output );
137+ $ this ->renderThrowable ($ e , $ output );
138138 }
139139 };
140140 if ($ phpHandler = set_exception_handler ($ renderException )) {
@@ -792,9 +792,13 @@ public static function getAbbreviations($names)
792792
793793 /**
794794 * Renders a caught exception.
795+ *
796+ * @deprecated since Symfony 4.4, use "renderThrowable()" instead
795797 */
796798 public function renderException (\Exception $ e , OutputInterface $ output )
797799 {
800+ @trigger_error (sprintf ('The "%s::renderException()" method is deprecated since Symfony 4.4, use "renderThrowable()" instead. ' , __CLASS__ ));
801+
798802 $ output ->writeln ('' , OutputInterface::VERBOSITY_QUIET );
799803
800804 $ this ->doRenderException ($ e , $ output );
@@ -805,8 +809,124 @@ public function renderException(\Exception $e, OutputInterface $output)
805809 }
806810 }
807811
812+ public function renderThrowable (\Throwable $ e , OutputInterface $ output ): void
813+ {
814+ if (__CLASS__ !== \get_class ($ this ) && __CLASS__ !== (new \ReflectionMethod ($ this , 'renderException ' ))->getDeclaringClass ()->getName ()) {
815+ @trigger_error (sprintf ('The "%s::renderException()" method is deprecated since Symfony 4.4, use "renderThrowable()" instead. ' , __CLASS__ ));
816+
817+ if (!$ e instanceof \Exception) {
818+ $ e = new ErrorException ($ e );
819+ }
820+
821+ $ this ->renderException ($ e , $ output );
822+
823+ return ;
824+ }
825+
826+ $ output ->writeln ('' , OutputInterface::VERBOSITY_QUIET );
827+
828+ $ this ->doRenderThrowable ($ e , $ output );
829+
830+ if (null !== $ this ->runningCommand ) {
831+ $ output ->writeln (sprintf ('<info>%s</info> ' , sprintf ($ this ->runningCommand ->getSynopsis (), $ this ->getName ())), OutputInterface::VERBOSITY_QUIET );
832+ $ output ->writeln ('' , OutputInterface::VERBOSITY_QUIET );
833+ }
834+ }
835+
836+ /**
837+ * @deprecated since Symfony 4.4, use "doRenderThrowable()" instead
838+ */
808839 protected function doRenderException (\Exception $ e , OutputInterface $ output )
809840 {
841+ @trigger_error (sprintf ('The "%s::doRenderException()" method is deprecated since Symfony 4.4, use "doRenderThrowable()" instead. ' , __CLASS__ ));
842+
843+ do {
844+ $ message = trim ($ e ->getMessage ());
845+ if ('' === $ message || OutputInterface::VERBOSITY_VERBOSE <= $ output ->getVerbosity ()) {
846+ $ class = \get_class ($ e );
847+ $ class = 'c ' === $ class [0 ] && 0 === strpos ($ class , "class@anonymous \0" ) ? get_parent_class ($ class ).'@anonymous ' : $ class ;
848+ $ title = sprintf (' [%s%s] ' , $ class , 0 !== ($ code = $ e ->getCode ()) ? ' ( ' .$ code .') ' : '' );
849+ $ len = Helper::strlen ($ title );
850+ } else {
851+ $ len = 0 ;
852+ }
853+
854+ if (false !== strpos ($ message , "class@anonymous \0" )) {
855+ $ message = preg_replace_callback ('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/ ' , function ($ m ) {
856+ return class_exists ($ m [0 ], false ) ? get_parent_class ($ m [0 ]).'@anonymous ' : $ m [0 ];
857+ }, $ message );
858+ }
859+
860+ $ width = $ this ->terminal ->getWidth () ? $ this ->terminal ->getWidth () - 1 : PHP_INT_MAX ;
861+ $ lines = [];
862+ foreach ('' !== $ message ? preg_split ('/\r?\n/ ' , $ message ) : [] as $ line ) {
863+ foreach ($ this ->splitStringByWidth ($ line , $ width - 4 ) as $ line ) {
864+ // pre-format lines to get the right string length
865+ $ lineLength = Helper::strlen ($ line ) + 4 ;
866+ $ lines [] = [$ line , $ lineLength ];
867+
868+ $ len = max ($ lineLength , $ len );
869+ }
870+ }
871+
872+ $ messages = [];
873+ if (!$ e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $ output ->getVerbosity ()) {
874+ $ messages [] = sprintf ('<comment>%s</comment> ' , OutputFormatter::escape (sprintf ('In %s line %s: ' , basename ($ e ->getFile ()) ?: 'n/a ' , $ e ->getLine () ?: 'n/a ' )));
875+ }
876+ $ messages [] = $ emptyLine = sprintf ('<error>%s</error> ' , str_repeat (' ' , $ len ));
877+ if ('' === $ message || OutputInterface::VERBOSITY_VERBOSE <= $ output ->getVerbosity ()) {
878+ $ messages [] = sprintf ('<error>%s%s</error> ' , $ title , str_repeat (' ' , max (0 , $ len - Helper::strlen ($ title ))));
879+ }
880+ foreach ($ lines as $ line ) {
881+ $ messages [] = sprintf ('<error> %s %s</error> ' , OutputFormatter::escape ($ line [0 ]), str_repeat (' ' , $ len - $ line [1 ]));
882+ }
883+ $ messages [] = $ emptyLine ;
884+ $ messages [] = '' ;
885+
886+ $ output ->writeln ($ messages , OutputInterface::VERBOSITY_QUIET );
887+
888+ if (OutputInterface::VERBOSITY_VERBOSE <= $ output ->getVerbosity ()) {
889+ $ output ->writeln ('<comment>Exception trace:</comment> ' , OutputInterface::VERBOSITY_QUIET );
890+
891+ // exception related properties
892+ $ trace = $ e ->getTrace ();
893+
894+ array_unshift ($ trace , [
895+ 'function ' => '' ,
896+ 'file ' => $ e ->getFile () ?: 'n/a ' ,
897+ 'line ' => $ e ->getLine () ?: 'n/a ' ,
898+ 'args ' => [],
899+ ]);
900+
901+ for ($ i = 0 , $ count = \count ($ trace ); $ i < $ count ; ++$ i ) {
902+ $ class = isset ($ trace [$ i ]['class ' ]) ? $ trace [$ i ]['class ' ] : '' ;
903+ $ type = isset ($ trace [$ i ]['type ' ]) ? $ trace [$ i ]['type ' ] : '' ;
904+ $ function = isset ($ trace [$ i ]['function ' ]) ? $ trace [$ i ]['function ' ] : '' ;
905+ $ file = isset ($ trace [$ i ]['file ' ]) ? $ trace [$ i ]['file ' ] : 'n/a ' ;
906+ $ line = isset ($ trace [$ i ]['line ' ]) ? $ trace [$ i ]['line ' ] : 'n/a ' ;
907+
908+ $ output ->writeln (sprintf (' %s%s at <info>%s:%s</info> ' , $ class , $ function ? $ type .$ function .'() ' : '' , $ file , $ line ), OutputInterface::VERBOSITY_QUIET );
909+ }
910+
911+ $ output ->writeln ('' , OutputInterface::VERBOSITY_QUIET );
912+ }
913+ } while ($ e = $ e ->getPrevious ());
914+ }
915+
916+ protected function doRenderThrowable (\Throwable $ e , OutputInterface $ output ): void
917+ {
918+ if (__CLASS__ !== \get_class ($ this ) && __CLASS__ !== (new \ReflectionMethod ($ this , 'doRenderException ' ))->getDeclaringClass ()->getName ()) {
919+ @trigger_error (sprintf ('The "%s::doRenderException()" method is deprecated since Symfony 4.4, use "doRenderThrowable()" instead. ' , __CLASS__ ));
920+
921+ if (!$ e instanceof \Exception) {
922+ $ e = new ErrorException ($ e );
923+ }
924+
925+ $ this ->doRenderException ($ e , $ output );
926+
927+ return ;
928+ }
929+
810930 do {
811931 $ message = trim ($ e ->getMessage ());
812932 if ('' === $ message || OutputInterface::VERBOSITY_VERBOSE <= $ output ->getVerbosity ()) {
0 commit comments