annotate vendor/nikic/php-parser/lib/PhpParser/Comment.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 5fb285c0d0e3
children
rev   line source
Chris@13 1 <?php declare(strict_types=1);
Chris@0 2
Chris@0 3 namespace PhpParser;
Chris@0 4
Chris@0 5 class Comment implements \JsonSerializable
Chris@0 6 {
Chris@0 7 protected $text;
Chris@0 8 protected $line;
Chris@0 9 protected $filePos;
Chris@13 10 protected $tokenPos;
Chris@0 11
Chris@0 12 /**
Chris@0 13 * Constructs a comment node.
Chris@0 14 *
Chris@13 15 * @param string $text Comment text (including comment delimiters like /*)
Chris@13 16 * @param int $startLine Line number the comment started on
Chris@13 17 * @param int $startFilePos File offset the comment started on
Chris@13 18 * @param int $startTokenPos Token offset the comment started on
Chris@0 19 */
Chris@13 20 public function __construct(
Chris@13 21 string $text, int $startLine = -1, int $startFilePos = -1, int $startTokenPos = -1
Chris@13 22 ) {
Chris@0 23 $this->text = $text;
Chris@0 24 $this->line = $startLine;
Chris@0 25 $this->filePos = $startFilePos;
Chris@13 26 $this->tokenPos = $startTokenPos;
Chris@0 27 }
Chris@0 28
Chris@0 29 /**
Chris@0 30 * Gets the comment text.
Chris@0 31 *
Chris@0 32 * @return string The comment text (including comment delimiters like /*)
Chris@0 33 */
Chris@13 34 public function getText() : string {
Chris@0 35 return $this->text;
Chris@0 36 }
Chris@0 37
Chris@0 38 /**
Chris@0 39 * Gets the line number the comment started on.
Chris@0 40 *
Chris@0 41 * @return int Line number
Chris@0 42 */
Chris@13 43 public function getLine() : int {
Chris@0 44 return $this->line;
Chris@0 45 }
Chris@0 46
Chris@0 47 /**
Chris@0 48 * Gets the file offset the comment started on.
Chris@0 49 *
Chris@0 50 * @return int File offset
Chris@0 51 */
Chris@13 52 public function getFilePos() : int {
Chris@0 53 return $this->filePos;
Chris@0 54 }
Chris@0 55
Chris@0 56 /**
Chris@13 57 * Gets the token offset the comment started on.
Chris@13 58 *
Chris@13 59 * @return int Token offset
Chris@13 60 */
Chris@13 61 public function getTokenPos() : int {
Chris@13 62 return $this->tokenPos;
Chris@13 63 }
Chris@13 64
Chris@13 65 /**
Chris@0 66 * Gets the comment text.
Chris@0 67 *
Chris@0 68 * @return string The comment text (including comment delimiters like /*)
Chris@0 69 */
Chris@13 70 public function __toString() : string {
Chris@0 71 return $this->text;
Chris@0 72 }
Chris@0 73
Chris@0 74 /**
Chris@0 75 * Gets the reformatted comment text.
Chris@0 76 *
Chris@0 77 * "Reformatted" here means that we try to clean up the whitespace at the
Chris@0 78 * starts of the lines. This is necessary because we receive the comments
Chris@0 79 * without trailing whitespace on the first line, but with trailing whitespace
Chris@0 80 * on all subsequent lines.
Chris@0 81 *
Chris@0 82 * @return mixed|string
Chris@0 83 */
Chris@0 84 public function getReformattedText() {
Chris@0 85 $text = trim($this->text);
Chris@0 86 $newlinePos = strpos($text, "\n");
Chris@0 87 if (false === $newlinePos) {
Chris@0 88 // Single line comments don't need further processing
Chris@0 89 return $text;
Chris@0 90 } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
Chris@0 91 // Multi line comment of the type
Chris@0 92 //
Chris@0 93 // /*
Chris@0 94 // * Some text.
Chris@0 95 // * Some more text.
Chris@0 96 // */
Chris@0 97 //
Chris@0 98 // is handled by replacing the whitespace sequences before the * by a single space
Chris@0 99 return preg_replace('(^\s+\*)m', ' *', $this->text);
Chris@0 100 } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
Chris@0 101 // Multi line comment of the type
Chris@0 102 //
Chris@0 103 // /*
Chris@0 104 // Some text.
Chris@0 105 // Some more text.
Chris@0 106 // */
Chris@0 107 //
Chris@0 108 // is handled by removing the whitespace sequence on the line before the closing
Chris@0 109 // */ on all lines. So if the last line is " */", then " " is removed at the
Chris@0 110 // start of all lines.
Chris@0 111 return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
Chris@0 112 } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
Chris@0 113 // Multi line comment of the type
Chris@0 114 //
Chris@0 115 // /* Some text.
Chris@0 116 // Some more text.
Chris@0 117 // Indented text.
Chris@0 118 // Even more text. */
Chris@0 119 //
Chris@0 120 // is handled by removing the difference between the shortest whitespace prefix on all
Chris@0 121 // lines and the length of the "/* " opening sequence.
Chris@0 122 $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1));
Chris@0 123 $removeLen = $prefixLen - strlen($matches[0]);
Chris@0 124 return preg_replace('(^\s{' . $removeLen . '})m', '', $text);
Chris@0 125 }
Chris@0 126
Chris@0 127 // No idea how to format this comment, so simply return as is
Chris@0 128 return $text;
Chris@0 129 }
Chris@0 130
Chris@13 131 /**
Chris@13 132 * Get length of shortest whitespace prefix (at the start of a line).
Chris@13 133 *
Chris@13 134 * If there is a line with no prefix whitespace, 0 is a valid return value.
Chris@13 135 *
Chris@13 136 * @param string $str String to check
Chris@13 137 * @return int Length in characters. Tabs count as single characters.
Chris@13 138 */
Chris@13 139 private function getShortestWhitespacePrefixLen(string $str) : int {
Chris@0 140 $lines = explode("\n", $str);
Chris@13 141 $shortestPrefixLen = \INF;
Chris@0 142 foreach ($lines as $line) {
Chris@0 143 preg_match('(^\s*)', $line, $matches);
Chris@0 144 $prefixLen = strlen($matches[0]);
Chris@0 145 if ($prefixLen < $shortestPrefixLen) {
Chris@0 146 $shortestPrefixLen = $prefixLen;
Chris@0 147 }
Chris@0 148 }
Chris@0 149 return $shortestPrefixLen;
Chris@0 150 }
Chris@0 151
Chris@13 152 /**
Chris@13 153 * @return array
Chris@13 154 * @psalm-return array{nodeType:string, text:mixed, line:mixed, filePos:mixed}
Chris@13 155 */
Chris@13 156 public function jsonSerialize() : array {
Chris@0 157 // Technically not a node, but we make it look like one anyway
Chris@0 158 $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
Chris@0 159 return [
Chris@0 160 'nodeType' => $type,
Chris@0 161 'text' => $this->text,
Chris@0 162 'line' => $this->line,
Chris@0 163 'filePos' => $this->filePos,
Chris@13 164 'tokenPos' => $this->tokenPos,
Chris@0 165 ];
Chris@0 166 }
Chris@13 167 }