Class_.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. <?php
  2. namespace PhpParser\Node\Stmt;
  3. use PhpParser\Node;
  4. use PhpParser\Error;
  5. class Class_ extends ClassLike
  6. {
  7. const MODIFIER_PUBLIC = 1;
  8. const MODIFIER_PROTECTED = 2;
  9. const MODIFIER_PRIVATE = 4;
  10. const MODIFIER_STATIC = 8;
  11. const MODIFIER_ABSTRACT = 16;
  12. const MODIFIER_FINAL = 32;
  13. const VISIBILITY_MODIFER_MASK = 7; // 1 | 2 | 4
  14. /** @var int Type */
  15. public $type;
  16. /** @var null|Node\Name Name of extended class */
  17. public $extends;
  18. /** @var Node\Name[] Names of implemented interfaces */
  19. public $implements;
  20. protected static $specialNames = array(
  21. 'self' => true,
  22. 'parent' => true,
  23. 'static' => true,
  24. );
  25. /**
  26. * Constructs a class node.
  27. *
  28. * @param string|null $name Name
  29. * @param array $subNodes Array of the following optional subnodes:
  30. * 'type' => 0 : Type
  31. * 'extends' => null : Name of extended class
  32. * 'implements' => array(): Names of implemented interfaces
  33. * 'stmts' => array(): Statements
  34. * @param array $attributes Additional attributes
  35. */
  36. public function __construct($name, array $subNodes = array(), array $attributes = array()) {
  37. parent::__construct(null, $attributes);
  38. $this->type = isset($subNodes['type']) ? $subNodes['type'] : 0;
  39. $this->name = $name;
  40. $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : null;
  41. $this->implements = isset($subNodes['implements']) ? $subNodes['implements'] : array();
  42. $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array();
  43. if (null !== $this->name && isset(self::$specialNames[strtolower($this->name)])) {
  44. throw new Error(sprintf('Cannot use \'%s\' as class name as it is reserved', $this->name));
  45. }
  46. if (isset(self::$specialNames[strtolower($this->extends)])) {
  47. throw new Error(
  48. sprintf('Cannot use \'%s\' as class name as it is reserved', $this->extends),
  49. $this->extends->getAttributes()
  50. );
  51. }
  52. foreach ($this->implements as $interface) {
  53. if (isset(self::$specialNames[strtolower($interface)])) {
  54. throw new Error(
  55. sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface),
  56. $interface->getAttributes()
  57. );
  58. }
  59. }
  60. }
  61. public function getSubNodeNames() {
  62. return array('type', 'name', 'extends', 'implements', 'stmts');
  63. }
  64. public function isAbstract() {
  65. return (bool) ($this->type & self::MODIFIER_ABSTRACT);
  66. }
  67. public function isFinal() {
  68. return (bool) ($this->type & self::MODIFIER_FINAL);
  69. }
  70. public function isAnonymous() {
  71. return null === $this->name;
  72. }
  73. /**
  74. * @internal
  75. */
  76. public static function verifyModifier($a, $b) {
  77. if ($a & self::VISIBILITY_MODIFER_MASK && $b & self::VISIBILITY_MODIFER_MASK) {
  78. throw new Error('Multiple access type modifiers are not allowed');
  79. }
  80. if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) {
  81. throw new Error('Multiple abstract modifiers are not allowed');
  82. }
  83. if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) {
  84. throw new Error('Multiple static modifiers are not allowed');
  85. }
  86. if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
  87. throw new Error('Multiple final modifiers are not allowed');
  88. }
  89. if ($a & 48 && $b & 48) {
  90. throw new Error('Cannot use the final modifier on an abstract class member');
  91. }
  92. }
  93. }