5 class Comment implements \JsonSerializable
12 * Constructs a comment node.
14 * @param string $text Comment text (including comment delimiters like /*)
15 * @param int $startLine Line number the comment started on
16 * @param int $startFilePos File offset the comment started on
18 public function __construct($text, $startLine = -1, $startFilePos = -1) {
20 $this->line = $startLine;
21 $this->filePos = $startFilePos;
25 * Gets the comment text.
27 * @return string The comment text (including comment delimiters like /*)
29 public function getText() {
34 * Gets the line number the comment started on.
36 * @return int Line number
38 public function getLine() {
43 * Gets the file offset the comment started on.
45 * @return int File offset
47 public function getFilePos() {
48 return $this->filePos;
52 * Gets the comment text.
54 * @return string The comment text (including comment delimiters like /*)
56 public function __toString() {
61 * Gets the reformatted comment text.
63 * "Reformatted" here means that we try to clean up the whitespace at the
64 * starts of the lines. This is necessary because we receive the comments
65 * without trailing whitespace on the first line, but with trailing whitespace
66 * on all subsequent lines.
68 * @return mixed|string
70 public function getReformattedText() {
71 $text = trim($this->text);
72 $newlinePos = strpos($text, "\n");
73 if (false === $newlinePos) {
74 // Single line comments don't need further processing
76 } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
77 // Multi line comment of the type
84 // is handled by replacing the whitespace sequences before the * by a single space
85 return preg_replace('(^\s+\*)m', ' *', $this->text);
86 } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
87 // Multi line comment of the type
94 // is handled by removing the whitespace sequence on the line before the closing
95 // */ on all lines. So if the last line is " */", then " " is removed at the
96 // start of all lines.
97 return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
98 } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
99 // Multi line comment of the type
104 // Even more text. */
106 // is handled by removing the difference between the shortest whitespace prefix on all
107 // lines and the length of the "/* " opening sequence.
108 $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1));
109 $removeLen = $prefixLen - strlen($matches[0]);
110 return preg_replace('(^\s{' . $removeLen . '})m', '', $text);
113 // No idea how to format this comment, so simply return as is
117 private function getShortestWhitespacePrefixLen($str) {
118 $lines = explode("\n", $str);
119 $shortestPrefixLen = INF;
120 foreach ($lines as $line) {
121 preg_match('(^\s*)', $line, $matches);
122 $prefixLen = strlen($matches[0]);
123 if ($prefixLen < $shortestPrefixLen) {
124 $shortestPrefixLen = $prefixLen;
127 return $shortestPrefixLen;
130 public function jsonSerialize() {
131 // Technically not a node, but we make it look like one anyway
132 $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
135 'text' => $this->text,
136 'line' => $this->line,
137 'filePos' => $this->filePos,