1<?php declare(strict_types=1); 2 3namespace PhpParser; 4 5/** 6 * Modifiers used (as a bit mask) by various flags subnodes, for example on classes, functions, 7 * properties and constants. 8 */ 9final class Modifiers { 10 public const PUBLIC = 1; 11 public const PROTECTED = 2; 12 public const PRIVATE = 4; 13 public const STATIC = 8; 14 public const ABSTRACT = 16; 15 public const FINAL = 32; 16 public const READONLY = 64; 17 public const PUBLIC_SET = 128; 18 public const PROTECTED_SET = 256; 19 public const PRIVATE_SET = 512; 20 21 public const VISIBILITY_MASK = self::PUBLIC | self::PROTECTED | self::PRIVATE; 22 23 public const VISIBILITY_SET_MASK = self::PUBLIC_SET | self::PROTECTED_SET | self::PRIVATE_SET; 24 25 private const TO_STRING_MAP = [ 26 self::PUBLIC => 'public', 27 self::PROTECTED => 'protected', 28 self::PRIVATE => 'private', 29 self::STATIC => 'static', 30 self::ABSTRACT => 'abstract', 31 self::FINAL => 'final', 32 self::READONLY => 'readonly', 33 self::PUBLIC_SET => 'public(set)', 34 self::PROTECTED_SET => 'protected(set)', 35 self::PRIVATE_SET => 'private(set)', 36 ]; 37 38 public static function toString(int $modifier): string { 39 if (!isset(self::TO_STRING_MAP[$modifier])) { 40 throw new \InvalidArgumentException("Unknown modifier $modifier"); 41 } 42 return self::TO_STRING_MAP[$modifier]; 43 } 44 45 private static function isValidModifier(int $modifier): bool { 46 $isPow2 = ($modifier & ($modifier - 1)) == 0 && $modifier != 0; 47 return $isPow2 && $modifier <= self::PRIVATE_SET; 48 } 49 50 /** 51 * @internal 52 */ 53 public static function verifyClassModifier(int $a, int $b): void { 54 assert(self::isValidModifier($b)); 55 if (($a & $b) != 0) { 56 throw new Error( 57 'Multiple ' . self::toString($b) . ' modifiers are not allowed'); 58 } 59 60 if ($a & 48 && $b & 48) { 61 throw new Error('Cannot use the final modifier on an abstract class'); 62 } 63 } 64 65 /** 66 * @internal 67 */ 68 public static function verifyModifier(int $a, int $b): void { 69 assert(self::isValidModifier($b)); 70 if (($a & Modifiers::VISIBILITY_MASK && $b & Modifiers::VISIBILITY_MASK) || 71 ($a & Modifiers::VISIBILITY_SET_MASK && $b & Modifiers::VISIBILITY_SET_MASK) 72 ) { 73 throw new Error('Multiple access type modifiers are not allowed'); 74 } 75 76 if (($a & $b) != 0) { 77 throw new Error( 78 'Multiple ' . self::toString($b) . ' modifiers are not allowed'); 79 } 80 81 if ($a & 48 && $b & 48) { 82 throw new Error('Cannot use the final modifier on an abstract class member'); 83 } 84 } 85} 86