菜谱项目

Name.php 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <?php
  2. namespace PhpParser\Node;
  3. use PhpParser\NodeAbstract;
  4. class Name extends NodeAbstract
  5. {
  6. /**
  7. * @var string[] Parts of the name
  8. */
  9. public $parts;
  10. /**
  11. * Constructs a name node.
  12. *
  13. * @param string|array|self $name Name as string, part array or Name instance (copy ctor)
  14. * @param array $attributes Additional attributes
  15. */
  16. public function __construct($name, array $attributes = array()) {
  17. parent::__construct($attributes);
  18. $this->parts = self::prepareName($name);
  19. }
  20. public function getSubNodeNames() {
  21. return array('parts');
  22. }
  23. /**
  24. * Gets the first part of the name, i.e. everything before the first namespace separator.
  25. *
  26. * @return string First part of the name
  27. */
  28. public function getFirst() {
  29. return $this->parts[0];
  30. }
  31. /**
  32. * Gets the last part of the name, i.e. everything after the last namespace separator.
  33. *
  34. * @return string Last part of the name
  35. */
  36. public function getLast() {
  37. return $this->parts[count($this->parts) - 1];
  38. }
  39. /**
  40. * Checks whether the name is unqualified. (E.g. Name)
  41. *
  42. * @return bool Whether the name is unqualified
  43. */
  44. public function isUnqualified() {
  45. return 1 == count($this->parts);
  46. }
  47. /**
  48. * Checks whether the name is qualified. (E.g. Name\Name)
  49. *
  50. * @return bool Whether the name is qualified
  51. */
  52. public function isQualified() {
  53. return 1 < count($this->parts);
  54. }
  55. /**
  56. * Checks whether the name is fully qualified. (E.g. \Name)
  57. *
  58. * @return bool Whether the name is fully qualified
  59. */
  60. public function isFullyQualified() {
  61. return false;
  62. }
  63. /**
  64. * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
  65. *
  66. * @return bool Whether the name is relative
  67. */
  68. public function isRelative() {
  69. return false;
  70. }
  71. /**
  72. * Returns a string representation of the name by imploding the namespace parts with the
  73. * namespace separator.
  74. *
  75. * @return string String representation
  76. */
  77. public function toString() {
  78. return implode('\\', $this->parts);
  79. }
  80. /**
  81. * Returns a string representation of the name by imploding the namespace parts with the
  82. * namespace separator.
  83. *
  84. * @return string String representation
  85. */
  86. public function __toString() {
  87. return implode('\\', $this->parts);
  88. }
  89. /**
  90. * Gets a slice of a name (similar to array_slice).
  91. *
  92. * This method returns a new instance of the same type as the original and with the same
  93. * attributes.
  94. *
  95. * If the slice is empty, null is returned. The null value will be correctly handled in
  96. * concatenations using concat().
  97. *
  98. * Offset and length have the same meaning as in array_slice().
  99. *
  100. * @param int $offset Offset to start the slice at (may be negative)
  101. * @param int|null $length Length of the slice (may be negative)
  102. *
  103. * @return static|null Sliced name
  104. */
  105. public function slice($offset, $length = null) {
  106. $numParts = count($this->parts);
  107. $realOffset = $offset < 0 ? $offset + $numParts : $offset;
  108. if ($realOffset < 0 || $realOffset > $numParts) {
  109. throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset));
  110. }
  111. if (null === $length) {
  112. $realLength = $numParts - $realOffset;
  113. } else {
  114. $realLength = $length < 0 ? $length + $numParts - $realOffset : $length;
  115. if ($realLength < 0 || $realLength > $numParts) {
  116. throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length));
  117. }
  118. }
  119. if ($realLength === 0) {
  120. // Empty slice is represented as null
  121. return null;
  122. }
  123. return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes);
  124. }
  125. /**
  126. * Concatenate two names, yielding a new Name instance.
  127. *
  128. * The type of the generated instance depends on which class this method is called on, for
  129. * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance.
  130. *
  131. * If one of the arguments is null, a new instance of the other name will be returned. If both
  132. * arguments are null, null will be returned. As such, writing
  133. * Name::concat($namespace, $shortName)
  134. * where $namespace is a Name node or null will work as expected.
  135. *
  136. * @param string|array|self|null $name1 The first name
  137. * @param string|array|self|null $name2 The second name
  138. * @param array $attributes Attributes to assign to concatenated name
  139. *
  140. * @return static|null Concatenated name
  141. */
  142. public static function concat($name1, $name2, array $attributes = []) {
  143. if (null === $name1 && null === $name2) {
  144. return null;
  145. } elseif (null === $name1) {
  146. return new static(self::prepareName($name2), $attributes);
  147. } else if (null === $name2) {
  148. return new static(self::prepareName($name1), $attributes);
  149. } else {
  150. return new static(
  151. array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes
  152. );
  153. }
  154. }
  155. /**
  156. * Prepares a (string, array or Name node) name for use in name changing methods by converting
  157. * it to an array.
  158. *
  159. * @param string|array|self $name Name to prepare
  160. *
  161. * @return array Prepared name
  162. */
  163. private static function prepareName($name) {
  164. if (\is_string($name)) {
  165. return explode('\\', $name);
  166. } elseif (\is_array($name)) {
  167. return $name;
  168. } elseif ($name instanceof self) {
  169. return $name->parts;
  170. }
  171. throw new \InvalidArgumentException(
  172. 'Expected string, array of parts or Name instance'
  173. );
  174. }
  175. }