From b44b30fa4aaed95dba2fcf75f0adb80a6f92f65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Dziewo=C5=84ski?= Date: Wed, 30 Oct 2024 16:31:20 +0100 Subject: [PATCH] Reports: Fix word wrapping edge cases The word wrapping in Code and Full reports did not correctly account for the ANSI color codes (producing differently wrapped text depending on the value of $showSources) and for the PHP_EOL constant values (producing differently wrapped text on Linux and Windows). Rewrite the code so that word wrapping is done first, and padding and colors are added afterwards. Also harmonize the implementation between the two reports. --- src/Reports/Code.php | 38 +++++++++++++++++----------- src/Reports/Full.php | 59 ++++++++++++++++---------------------------- 2 files changed, 45 insertions(+), 52 deletions(-) diff --git a/src/Reports/Code.php b/src/Reports/Code.php index 6cbd7eb1e7..11b889a198 100644 --- a/src/Reports/Code.php +++ b/src/Reports/Code.php @@ -153,10 +153,6 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, // The maximum amount of space an error message can use. $maxErrorSpace = ($width - $errorPaddingLength); - if ($showSources === true) { - // Account for the chars used to print colors. - $maxErrorSpace += 8; - } // Figure out the max report width we need and can use. $fileLength = strlen($file); @@ -291,19 +287,33 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, echo '] '; } - $message = $error['message']; - $message = str_replace("\n", "\n".$errorPadding, $message); - if ($showSources === true) { - $message = "\033[1m".$message."\033[0m".' ('.$error['source'].')'; + $message = wordwrap($error['message'], $maxErrorSpace, PHP_EOL); + $paddedMessage = ''; + // Add padding and colors to each line of the output. + foreach (explode(PHP_EOL, $message) as $i => $msgLine) { + if ($i !== 0) { + $paddedMessage .= PHP_EOL.$errorPadding; + } + + if ($showSources === true) { + $paddedMessage .= "\033[1m".$msgLine."\033[0m"; + } else { + $paddedMessage .= $msgLine; + } } - $errorMsg = wordwrap( - $message, - $maxErrorSpace, - PHP_EOL.$errorPadding - ); + if ($showSources === true) { + // Add sniff code, taking care to manually wrap the line if needed. + if ((strlen($msgLine) + strlen($error['source']) + 3) > $maxErrorSpace) { + $paddedMessage .= PHP_EOL.$errorPadding; + } else { + $paddedMessage .= ' '; + } + + $paddedMessage .= '('.$error['source'].')'; + } - echo $errorMsg.PHP_EOL; + echo $paddedMessage.PHP_EOL; }//end foreach }//end foreach diff --git a/src/Reports/Full.php b/src/Reports/Full.php index 9af4efaeab..5217fc4ec2 100644 --- a/src/Reports/Full.php +++ b/src/Reports/Full.php @@ -129,51 +129,34 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, // The maximum amount of space an error message can use. $maxErrorSpace = ($width - $paddingLength - 1); - $beforeMsg = ''; - $afterMsg = ''; - if ($showSources === true) { - $beforeMsg = "\033[1m"; - $afterMsg = "\033[0m"; - } - - $beforeAfterLength = strlen($beforeMsg.$afterMsg); - foreach ($report['messages'] as $line => $lineErrors) { foreach ($lineErrors as $colErrors) { foreach ($colErrors as $error) { - $errorMsg = wordwrap( - $error['message'], - $maxErrorSpace - ); - - // Add the padding _after_ the wordwrap as the message itself may contain line breaks - // and those lines will also need to receive padding. - $errorMsg = str_replace("\n", $afterMsg.PHP_EOL.$paddingLine2.$beforeMsg, $errorMsg); - $errorMsg = $beforeMsg.$errorMsg.$afterMsg; - - if ($showSources === true) { - $lastMsg = $errorMsg; - $startPosLastLine = strrpos($errorMsg, PHP_EOL.$paddingLine2.$beforeMsg); - if ($startPosLastLine !== false) { - // Message is multiline. Grab the text of last line of the message, including the color codes. - $lastMsg = substr($errorMsg, ($startPosLastLine + strlen(PHP_EOL.$paddingLine2))); + $message = wordwrap($error['message'], $maxErrorSpace, PHP_EOL); + $paddedMessage = ''; + // Add padding and colors to each line of the output. + foreach (explode(PHP_EOL, $message) as $i => $msgLine) { + if ($i !== 0) { + $paddedMessage .= PHP_EOL.$paddingLine2; } - // When show sources is used, the message itself will be bolded, so we need to correct the length. - $sourceSuffix = '('.$error['source'].')'; - - $lastMsgPlusSourceLength = strlen($lastMsg); - // Add space + source suffix length. - $lastMsgPlusSourceLength += (1 + strlen($sourceSuffix)); - // Correct for the color codes. - $lastMsgPlusSourceLength -= $beforeAfterLength; + if ($showSources === true) { + $paddedMessage .= "\033[1m".$msgLine."\033[0m"; + } else { + $paddedMessage .= $msgLine; + } + } - if ($lastMsgPlusSourceLength > $maxErrorSpace) { - $errorMsg .= PHP_EOL.$paddingLine2.$sourceSuffix; + if ($showSources === true) { + // Add sniff code, taking care to manually wrap the line if needed. + if ((strlen($msgLine) + strlen($error['source']) + 3) > $maxErrorSpace) { + $paddedMessage .= PHP_EOL.$paddingLine2; } else { - $errorMsg .= ' '.$sourceSuffix; + $paddedMessage .= ' '; } - }//end if + + $paddedMessage .= '('.$error['source'].')'; + } // The padding that goes on the front of the line. $padding = ($maxLineNumLength - strlen($line)); @@ -200,7 +183,7 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, echo '] '; } - echo $errorMsg.PHP_EOL; + echo $paddedMessage.PHP_EOL; }//end foreach }//end foreach }//end foreach