Comment.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. <?php
  2. namespace PhpParser;
  3. class Comment
  4. {
  5. protected $text;
  6. protected $line;
  7. protected $filePos;
  8. /**
  9. * Constructs a comment node.
  10. *
  11. * @param string $text Comment text (including comment delimiters like /*)
  12. * @param int $startLine Line number the comment started on
  13. * @param int $startFilePos File offset the comment started on
  14. */
  15. public function __construct($text, $startLine = -1, $startFilePos = -1) {
  16. $this->text = $text;
  17. $this->line = $startLine;
  18. $this->filePos = $startFilePos;
  19. }
  20. /**
  21. * Gets the comment text.
  22. *
  23. * @return string The comment text (including comment delimiters like /*)
  24. */
  25. public function getText() {
  26. return $this->text;
  27. }
  28. /**
  29. * Sets the comment text.
  30. *
  31. * @param string $text The comment text (including comment delimiters like /*)
  32. *
  33. * @deprecated Construct a new comment instead
  34. */
  35. public function setText($text) {
  36. $this->text = $text;
  37. }
  38. /**
  39. * Gets the line number the comment started on.
  40. *
  41. * @return int Line number
  42. */
  43. public function getLine() {
  44. return $this->line;
  45. }
  46. /**
  47. * Sets the line number the comment started on.
  48. *
  49. * @param int $line Line number
  50. *
  51. * @deprecated Construct a new comment instead
  52. */
  53. public function setLine($line) {
  54. $this->line = $line;
  55. }
  56. /**
  57. * Gets the file offset the comment started on.
  58. *
  59. * @return int File offset
  60. */
  61. public function getFilePos() {
  62. return $this->filePos;
  63. }
  64. /**
  65. * Gets the comment text.
  66. *
  67. * @return string The comment text (including comment delimiters like /*)
  68. */
  69. public function __toString() {
  70. return $this->text;
  71. }
  72. /**
  73. * Gets the reformatted comment text.
  74. *
  75. * "Reformatted" here means that we try to clean up the whitespace at the
  76. * starts of the lines. This is necessary because we receive the comments
  77. * without trailing whitespace on the first line, but with trailing whitespace
  78. * on all subsequent lines.
  79. *
  80. * @return mixed|string
  81. */
  82. public function getReformattedText() {
  83. $text = trim($this->text);
  84. $newlinePos = strpos($text, "\n");
  85. if (false === $newlinePos) {
  86. // Single line comments don't need further processing
  87. return $text;
  88. } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) {
  89. // Multi line comment of the type
  90. //
  91. // /*
  92. // * Some text.
  93. // * Some more text.
  94. // */
  95. //
  96. // is handled by replacing the whitespace sequences before the * by a single space
  97. return preg_replace('(^\s+\*)m', ' *', $this->text);
  98. } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) {
  99. // Multi line comment of the type
  100. //
  101. // /*
  102. // Some text.
  103. // Some more text.
  104. // */
  105. //
  106. // is handled by removing the whitespace sequence on the line before the closing
  107. // */ on all lines. So if the last line is " */", then " " is removed at the
  108. // start of all lines.
  109. return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text);
  110. } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) {
  111. // Multi line comment of the type
  112. //
  113. // /* Some text.
  114. // Some more text.
  115. // Indented text.
  116. // Even more text. */
  117. //
  118. // is handled by removing the difference between the shortest whitespace prefix on all
  119. // lines and the length of the "/* " opening sequence.
  120. $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1));
  121. $removeLen = $prefixLen - strlen($matches[0]);
  122. return preg_replace('(^\s{' . $removeLen . '})m', '', $text);
  123. }
  124. // No idea how to format this comment, so simply return as is
  125. return $text;
  126. }
  127. private function getShortestWhitespacePrefixLen($str) {
  128. $lines = explode("\n", $str);
  129. $shortestPrefixLen = INF;
  130. foreach ($lines as $line) {
  131. preg_match('(^\s*)', $line, $matches);
  132. $prefixLen = strlen($matches[0]);
  133. if ($prefixLen < $shortestPrefixLen) {
  134. $shortestPrefixLen = $prefixLen;
  135. }
  136. }
  137. return $shortestPrefixLen;
  138. }
  139. }