• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nikic / PHP-Parser / 10727048340

05 Sep 2024 07:38PM UTC coverage: 93.265% (-0.1%) from 93.396%
10727048340

push

github

nikic
[8.4] Add support for asymmetric visibility modifiers

Represented using new PRIVATE_SET, PROTECTED_SET and PUBLIC_SET
bits in Modifiers.

RFC: https://wiki.php.net/rfc/asymmetric-visibility-v2

730 of 751 new or added lines in 9 files covered. (97.2%)

21 existing lines in 1 file now uncovered.

7159 of 7676 relevant lines covered (93.26%)

228.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.78
/lib/PhpParser/Modifiers.php
1
<?php declare(strict_types=1);
2

3
namespace PhpParser;
4

5
/**
6
 * Modifiers used (as a bit mask) by various flags subnodes, for example on classes, functions,
7
 * properties and constants.
8
 */
9
final 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])) {
18✔
40
            throw new \InvalidArgumentException("Unknown modifier $modifier");
1✔
41
        }
42
        return self::TO_STRING_MAP[$modifier];
17✔
43
    }
44

45
    private static function isValidModifier(int $modifier): bool {
NEW
46
        $isPow2 = ($modifier & ($modifier - 1)) == 0 && $modifier != 0;
×
NEW
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) {
8✔
NEW
56
            throw new Error(
×
NEW
57
                'Multiple ' . self::toString($b) . ' modifiers are not allowed');
×
58
        }
59

60
        if ($a & 48 && $b & 48) {
8✔
61
            throw new Error('Cannot use the final modifier on an abstract class');
2✔
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) ||
72✔
71
            ($a & Modifiers::VISIBILITY_SET_MASK && $b & Modifiers::VISIBILITY_SET_MASK)
72✔
72
        ) {
73
            throw new Error('Multiple access type modifiers are not allowed');
9✔
74
        }
75

76
        if (($a & $b) != 0) {
64✔
77
            throw new Error(
8✔
78
                'Multiple ' . self::toString($b) . ' modifiers are not allowed');
8✔
79
        }
80

81
        if ($a & 48 && $b & 48) {
56✔
82
            throw new Error('Cannot use the final modifier on an abstract class member');
2✔
83
        }
84
    }
85
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc