@flarum/cli 3.0.4 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/php-subsystem/composer.json +3 -0
- package/php-subsystem/composer.lock +76 -66
- package/php-subsystem/index.php +9 -0
- package/php-subsystem/vendor/composer/installed.json +63 -56
- package/php-subsystem/vendor/composer/installed.php +9 -9
- package/php-subsystem/vendor/composer/platform_check.php +2 -2
- package/php-subsystem/vendor/nikic/php-parser/README.md +1 -1
- package/php-subsystem/vendor/nikic/php-parser/composer.json +41 -41
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php +2 -2
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php +0 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php +22 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php +63 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php +1 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php +6 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Comment.php +2 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Error.php +2 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php +12 -5
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php +4 -4
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php +93 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php +6 -2
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php +19 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Modifiers.php +42 -26
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/NameContext.php +1 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php +11 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php +10 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php +28 -2
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node/PropertyHook.php +78 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Property.php +15 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php +27 -2
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Node.php +4 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php +3 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php +9 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php +6 -0
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php +1210 -1119
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Parser/Php8.php +1210 -1141
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php +82 -57
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/PhpVersion.php +1 -1
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php +17 -2
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php +49 -11
- package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/compatibility_tokens.php +5 -0
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
2
|
+
"name": "nikic/php-parser",
|
|
3
|
+
"type": "library",
|
|
4
|
+
"description": "A PHP parser written in PHP",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"php",
|
|
7
|
+
"parser"
|
|
8
|
+
],
|
|
9
|
+
"license": "BSD-3-Clause",
|
|
10
|
+
"authors": [
|
|
11
|
+
{
|
|
12
|
+
"name": "Nikita Popov"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"require": {
|
|
16
|
+
"php": ">=7.4",
|
|
17
|
+
"ext-tokenizer": "*",
|
|
18
|
+
"ext-json": "*",
|
|
19
|
+
"ext-ctype": "*"
|
|
20
|
+
},
|
|
21
|
+
"require-dev": {
|
|
22
|
+
"phpunit/phpunit": "^9.0",
|
|
23
|
+
"ircmaxell/php-yacc": "^0.0.7"
|
|
24
|
+
},
|
|
25
|
+
"extra": {
|
|
26
|
+
"branch-alias": {
|
|
27
|
+
"dev-master": "5.0-dev"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"autoload": {
|
|
31
|
+
"psr-4": {
|
|
32
|
+
"PhpParser\\": "lib/PhpParser"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"autoload-dev": {
|
|
36
|
+
"psr-4": {
|
|
37
|
+
"PhpParser\\": "test/PhpParser/"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"bin": [
|
|
41
|
+
"bin/php-parse"
|
|
42
|
+
]
|
|
43
43
|
}
|
|
@@ -28,7 +28,7 @@ class ClassConst implements PhpParser\Builder {
|
|
|
28
28
|
* Creates a class constant builder
|
|
29
29
|
*
|
|
30
30
|
* @param string|Identifier $name Name
|
|
31
|
-
* @param Node\Expr|bool|null|int|float|string|array $value Value
|
|
31
|
+
* @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value
|
|
32
32
|
*/
|
|
33
33
|
public function __construct($name, $value) {
|
|
34
34
|
$this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))];
|
|
@@ -38,7 +38,7 @@ class ClassConst implements PhpParser\Builder {
|
|
|
38
38
|
* Add another constant to const group
|
|
39
39
|
*
|
|
40
40
|
* @param string|Identifier $name Name
|
|
41
|
-
* @param Node\Expr|bool|null|int|float|string|array $value Value
|
|
41
|
+
* @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value Value
|
|
42
42
|
*
|
|
43
43
|
* @return $this The builder instance (for fluid interface)
|
|
44
44
|
*/
|
|
@@ -13,7 +13,6 @@ use PhpParser\Node\Stmt;
|
|
|
13
13
|
class EnumCase implements PhpParser\Builder {
|
|
14
14
|
/** @var Identifier|string */
|
|
15
15
|
protected $name;
|
|
16
|
-
/** @var ?Node\Expr */
|
|
17
16
|
protected ?Node\Expr $value = null;
|
|
18
17
|
/** @var array<string, mixed> */
|
|
19
18
|
protected array $attributes = [];
|
|
@@ -122,6 +122,28 @@ class Param implements PhpParser\Builder {
|
|
|
122
122
|
return $this;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Gives the promoted property private(set) visibility.
|
|
127
|
+
*
|
|
128
|
+
* @return $this The builder instance (for fluid interface)
|
|
129
|
+
*/
|
|
130
|
+
public function makePrivateSet() {
|
|
131
|
+
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE_SET);
|
|
132
|
+
|
|
133
|
+
return $this;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Gives the promoted property protected(set) visibility.
|
|
138
|
+
*
|
|
139
|
+
* @return $this The builder instance (for fluid interface)
|
|
140
|
+
*/
|
|
141
|
+
public function makeProtectedSet() {
|
|
142
|
+
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED_SET);
|
|
143
|
+
|
|
144
|
+
return $this;
|
|
145
|
+
}
|
|
146
|
+
|
|
125
147
|
/**
|
|
126
148
|
* Adds an attribute group.
|
|
127
149
|
*
|
|
@@ -23,6 +23,8 @@ class Property implements PhpParser\Builder {
|
|
|
23
23
|
protected ?Node $type = null;
|
|
24
24
|
/** @var list<Node\AttributeGroup> */
|
|
25
25
|
protected array $attributeGroups = [];
|
|
26
|
+
/** @var list<Node\PropertyHook> */
|
|
27
|
+
protected array $hooks = [];
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* Creates a property builder.
|
|
@@ -88,6 +90,50 @@ class Property implements PhpParser\Builder {
|
|
|
88
90
|
return $this;
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Makes the property abstract. Requires at least one property hook to be specified as well.
|
|
95
|
+
*
|
|
96
|
+
* @return $this The builder instance (for fluid interface)
|
|
97
|
+
*/
|
|
98
|
+
public function makeAbstract() {
|
|
99
|
+
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::ABSTRACT);
|
|
100
|
+
|
|
101
|
+
return $this;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Makes the property final.
|
|
106
|
+
*
|
|
107
|
+
* @return $this The builder instance (for fluid interface)
|
|
108
|
+
*/
|
|
109
|
+
public function makeFinal() {
|
|
110
|
+
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::FINAL);
|
|
111
|
+
|
|
112
|
+
return $this;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Gives the property private(set) visibility.
|
|
117
|
+
*
|
|
118
|
+
* @return $this The builder instance (for fluid interface)
|
|
119
|
+
*/
|
|
120
|
+
public function makePrivateSet() {
|
|
121
|
+
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PRIVATE_SET);
|
|
122
|
+
|
|
123
|
+
return $this;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gives the property protected(set) visibility.
|
|
128
|
+
*
|
|
129
|
+
* @return $this The builder instance (for fluid interface)
|
|
130
|
+
*/
|
|
131
|
+
public function makeProtectedSet() {
|
|
132
|
+
$this->flags = BuilderHelpers::addModifier($this->flags, Modifiers::PROTECTED_SET);
|
|
133
|
+
|
|
134
|
+
return $this;
|
|
135
|
+
}
|
|
136
|
+
|
|
91
137
|
/**
|
|
92
138
|
* Sets default value for the property.
|
|
93
139
|
*
|
|
@@ -142,12 +188,27 @@ class Property implements PhpParser\Builder {
|
|
|
142
188
|
return $this;
|
|
143
189
|
}
|
|
144
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Adds a property hook.
|
|
193
|
+
*
|
|
194
|
+
* @return $this The builder instance (for fluid interface)
|
|
195
|
+
*/
|
|
196
|
+
public function addHook(Node\PropertyHook $hook) {
|
|
197
|
+
$this->hooks[] = $hook;
|
|
198
|
+
|
|
199
|
+
return $this;
|
|
200
|
+
}
|
|
201
|
+
|
|
145
202
|
/**
|
|
146
203
|
* Returns the built class node.
|
|
147
204
|
*
|
|
148
205
|
* @return Stmt\Property The built property node
|
|
149
206
|
*/
|
|
150
207
|
public function getNode(): PhpParser\Node {
|
|
208
|
+
if ($this->flags & Modifiers::ABSTRACT && !$this->hooks) {
|
|
209
|
+
throw new PhpParser\Error('Only hooked properties may be declared abstract');
|
|
210
|
+
}
|
|
211
|
+
|
|
151
212
|
return new Stmt\Property(
|
|
152
213
|
$this->flags !== 0 ? $this->flags : Modifiers::PUBLIC,
|
|
153
214
|
[
|
|
@@ -155,7 +216,8 @@ class Property implements PhpParser\Builder {
|
|
|
155
216
|
],
|
|
156
217
|
$this->attributes,
|
|
157
218
|
$this->type,
|
|
158
|
-
$this->attributeGroups
|
|
219
|
+
$this->attributeGroups,
|
|
220
|
+
$this->hooks
|
|
159
221
|
);
|
|
160
222
|
}
|
|
161
223
|
}
|
|
@@ -210,7 +210,7 @@ class BuilderFactory {
|
|
|
210
210
|
/**
|
|
211
211
|
* Creates node a for a literal value.
|
|
212
212
|
*
|
|
213
|
-
* @param Expr|bool|null|int|float|string|array $value $value
|
|
213
|
+
* @param Expr|bool|null|int|float|string|array|\UnitEnum $value $value
|
|
214
214
|
*/
|
|
215
215
|
public function val($value): Expr {
|
|
216
216
|
return BuilderHelpers::normalizeValue($value);
|
|
@@ -6,6 +6,7 @@ use PhpParser\Node\ComplexType;
|
|
|
6
6
|
use PhpParser\Node\Expr;
|
|
7
7
|
use PhpParser\Node\Identifier;
|
|
8
8
|
use PhpParser\Node\Name;
|
|
9
|
+
use PhpParser\Node\Name\FullyQualified;
|
|
9
10
|
use PhpParser\Node\NullableType;
|
|
10
11
|
use PhpParser\Node\Scalar;
|
|
11
12
|
use PhpParser\Node\Stmt;
|
|
@@ -214,7 +215,7 @@ final class BuilderHelpers {
|
|
|
214
215
|
* Normalizes a value: Converts nulls, booleans, integers,
|
|
215
216
|
* floats, strings and arrays into their respective nodes
|
|
216
217
|
*
|
|
217
|
-
* @param Node\Expr|bool|null|int|float|string|array $value The value to normalize
|
|
218
|
+
* @param Node\Expr|bool|null|int|float|string|array|\UnitEnum $value The value to normalize
|
|
218
219
|
*
|
|
219
220
|
* @return Expr The normalized value
|
|
220
221
|
*/
|
|
@@ -268,6 +269,10 @@ final class BuilderHelpers {
|
|
|
268
269
|
return new Expr\Array_($items);
|
|
269
270
|
}
|
|
270
271
|
|
|
272
|
+
if ($value instanceof \UnitEnum) {
|
|
273
|
+
return new Expr\ClassConstFetch(new FullyQualified(\get_class($value)), new Identifier($value->name));
|
|
274
|
+
}
|
|
275
|
+
|
|
271
276
|
throw new \LogicException('Invalid value');
|
|
272
277
|
}
|
|
273
278
|
|
|
@@ -46,6 +46,7 @@ class Comment implements \JsonSerializable {
|
|
|
46
46
|
* Gets the line number the comment started on.
|
|
47
47
|
*
|
|
48
48
|
* @return int Line number (or -1 if not available)
|
|
49
|
+
* @phpstan-return -1|positive-int
|
|
49
50
|
*/
|
|
50
51
|
public function getStartLine(): int {
|
|
51
52
|
return $this->startLine;
|
|
@@ -73,6 +74,7 @@ class Comment implements \JsonSerializable {
|
|
|
73
74
|
* Gets the line number the comment ends on.
|
|
74
75
|
*
|
|
75
76
|
* @return int Line number (or -1 if not available)
|
|
77
|
+
* @phpstan-return -1|positive-int
|
|
76
78
|
*/
|
|
77
79
|
public function getEndLine(): int {
|
|
78
80
|
return $this->endLine;
|
|
@@ -32,6 +32,7 @@ class Error extends \RuntimeException {
|
|
|
32
32
|
* Gets the line the error starts in.
|
|
33
33
|
*
|
|
34
34
|
* @return int Error start line
|
|
35
|
+
* @phpstan-return -1|positive-int
|
|
35
36
|
*/
|
|
36
37
|
public function getStartLine(): int {
|
|
37
38
|
return $this->attributes['startLine'] ?? -1;
|
|
@@ -41,6 +42,7 @@ class Error extends \RuntimeException {
|
|
|
41
42
|
* Gets the line the error ends in.
|
|
42
43
|
*
|
|
43
44
|
* @return int Error end line
|
|
45
|
+
* @phpstan-return -1|positive-int
|
|
44
46
|
*/
|
|
45
47
|
public function getEndLine(): int {
|
|
46
48
|
return $this->attributes['endLine'] ?? -1;
|
|
@@ -20,9 +20,9 @@ class TokenStream {
|
|
|
20
20
|
*
|
|
21
21
|
* @param Token[] $tokens Tokens in PhpToken::tokenize() format
|
|
22
22
|
*/
|
|
23
|
-
public function __construct(array $tokens) {
|
|
23
|
+
public function __construct(array $tokens, int $tabWidth) {
|
|
24
24
|
$this->tokens = $tokens;
|
|
25
|
-
$this->indentMap = $this->calcIndentMap();
|
|
25
|
+
$this->indentMap = $this->calcIndentMap($tabWidth);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/**
|
|
@@ -248,7 +248,7 @@ class TokenStream {
|
|
|
248
248
|
*
|
|
249
249
|
* @return int[] Token position to indentation map
|
|
250
250
|
*/
|
|
251
|
-
private function calcIndentMap(): array {
|
|
251
|
+
private function calcIndentMap(int $tabWidth): array {
|
|
252
252
|
$indentMap = [];
|
|
253
253
|
$indent = 0;
|
|
254
254
|
foreach ($this->tokens as $i => $token) {
|
|
@@ -258,11 +258,11 @@ class TokenStream {
|
|
|
258
258
|
$content = $token->text;
|
|
259
259
|
$newlinePos = \strrpos($content, "\n");
|
|
260
260
|
if (false !== $newlinePos) {
|
|
261
|
-
$indent = \
|
|
261
|
+
$indent = $this->getIndent(\substr($content, $newlinePos + 1), $tabWidth);
|
|
262
262
|
} elseif ($i === 1 && $this->tokens[0]->id === \T_OPEN_TAG &&
|
|
263
263
|
$this->tokens[0]->text[\strlen($this->tokens[0]->text) - 1] === "\n") {
|
|
264
264
|
// Special case: Newline at the end of opening tag followed by whitespace.
|
|
265
|
-
$indent =
|
|
265
|
+
$indent = $this->getIndent($content, $tabWidth);
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
}
|
|
@@ -272,4 +272,11 @@ class TokenStream {
|
|
|
272
272
|
|
|
273
273
|
return $indentMap;
|
|
274
274
|
}
|
|
275
|
+
|
|
276
|
+
private function getIndent(string $ws, int $tabWidth): int {
|
|
277
|
+
$spaces = \substr_count($ws, " ");
|
|
278
|
+
$tabs = \substr_count($ws, "\t");
|
|
279
|
+
assert(\strlen($ws) === $spaces + $tabs);
|
|
280
|
+
return $spaces + $tabs * $tabWidth;
|
|
281
|
+
}
|
|
275
282
|
}
|
|
@@ -5,15 +5,13 @@ namespace PhpParser\Lexer;
|
|
|
5
5
|
use PhpParser\Error;
|
|
6
6
|
use PhpParser\ErrorHandler;
|
|
7
7
|
use PhpParser\Lexer;
|
|
8
|
+
use PhpParser\Lexer\TokenEmulator\AsymmetricVisibilityTokenEmulator;
|
|
8
9
|
use PhpParser\Lexer\TokenEmulator\AttributeEmulator;
|
|
9
10
|
use PhpParser\Lexer\TokenEmulator\EnumTokenEmulator;
|
|
10
|
-
use PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
|
|
11
11
|
use PhpParser\Lexer\TokenEmulator\ExplicitOctalEmulator;
|
|
12
|
-
use PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator;
|
|
13
|
-
use PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
|
|
14
12
|
use PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
|
|
15
13
|
use PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
|
|
16
|
-
use PhpParser\Lexer\TokenEmulator\
|
|
14
|
+
use PhpParser\Lexer\TokenEmulator\PropertyTokenEmulator;
|
|
17
15
|
use PhpParser\Lexer\TokenEmulator\ReadonlyFunctionTokenEmulator;
|
|
18
16
|
use PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator;
|
|
19
17
|
use PhpParser\Lexer\TokenEmulator\ReverseEmulator;
|
|
@@ -47,6 +45,8 @@ class Emulative extends Lexer {
|
|
|
47
45
|
new ReadonlyTokenEmulator(),
|
|
48
46
|
new ExplicitOctalEmulator(),
|
|
49
47
|
new ReadonlyFunctionTokenEmulator(),
|
|
48
|
+
new PropertyTokenEmulator(),
|
|
49
|
+
new AsymmetricVisibilityTokenEmulator(),
|
|
50
50
|
];
|
|
51
51
|
|
|
52
52
|
// Collect emulators that are relevant for the PHP version we're running
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<?php declare(strict_types=1);
|
|
2
|
+
|
|
3
|
+
namespace PhpParser\Lexer\TokenEmulator;
|
|
4
|
+
|
|
5
|
+
use PhpParser\PhpVersion;
|
|
6
|
+
use PhpParser\Token;
|
|
7
|
+
|
|
8
|
+
final class AsymmetricVisibilityTokenEmulator extends TokenEmulator {
|
|
9
|
+
public function getPhpVersion(): PhpVersion {
|
|
10
|
+
return PhpVersion::fromComponents(8, 4);
|
|
11
|
+
}
|
|
12
|
+
public function isEmulationNeeded(string $code): bool {
|
|
13
|
+
$code = strtolower($code);
|
|
14
|
+
return strpos($code, 'public(set)') !== false ||
|
|
15
|
+
strpos($code, 'protected(set)') !== false ||
|
|
16
|
+
strpos($code, 'private(set)') !== false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public function emulate(string $code, array $tokens): array {
|
|
20
|
+
$map = [
|
|
21
|
+
\T_PUBLIC => \T_PUBLIC_SET,
|
|
22
|
+
\T_PROTECTED => \T_PROTECTED_SET,
|
|
23
|
+
\T_PRIVATE => \T_PRIVATE_SET,
|
|
24
|
+
];
|
|
25
|
+
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
|
26
|
+
$token = $tokens[$i];
|
|
27
|
+
if (isset($map[$token->id]) && $i + 3 < $c && $tokens[$i + 1]->text === '(' &&
|
|
28
|
+
$tokens[$i + 2]->id === \T_STRING && \strtolower($tokens[$i + 2]->text) === 'set' &&
|
|
29
|
+
$tokens[$i + 3]->text === ')' &&
|
|
30
|
+
$this->isKeywordContext($tokens, $i)
|
|
31
|
+
) {
|
|
32
|
+
array_splice($tokens, $i, 4, [
|
|
33
|
+
new Token(
|
|
34
|
+
$map[$token->id], $token->text . '(' . $tokens[$i + 2]->text . ')',
|
|
35
|
+
$token->line, $token->pos),
|
|
36
|
+
]);
|
|
37
|
+
$c -= 3;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return $tokens;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public function reverseEmulate(string $code, array $tokens): array {
|
|
45
|
+
$reverseMap = [
|
|
46
|
+
\T_PUBLIC_SET => \T_PUBLIC,
|
|
47
|
+
\T_PROTECTED_SET => \T_PROTECTED,
|
|
48
|
+
\T_PRIVATE_SET => \T_PRIVATE,
|
|
49
|
+
];
|
|
50
|
+
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
|
51
|
+
$token = $tokens[$i];
|
|
52
|
+
if (isset($reverseMap[$token->id]) &&
|
|
53
|
+
\preg_match('/(public|protected|private)\((set)\)/i', $token->text, $matches)
|
|
54
|
+
) {
|
|
55
|
+
[, $modifier, $set] = $matches;
|
|
56
|
+
$modifierLen = \strlen($modifier);
|
|
57
|
+
array_splice($tokens, $i, 1, [
|
|
58
|
+
new Token($reverseMap[$token->id], $modifier, $token->line, $token->pos),
|
|
59
|
+
new Token(\ord('('), '(', $token->line, $token->pos + $modifierLen),
|
|
60
|
+
new Token(\T_STRING, $set, $token->line, $token->pos + $modifierLen + 1),
|
|
61
|
+
new Token(\ord(')'), ')', $token->line, $token->pos + $modifierLen + 4),
|
|
62
|
+
]);
|
|
63
|
+
$i += 3;
|
|
64
|
+
$c += 3;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return $tokens;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** @param Token[] $tokens */
|
|
72
|
+
protected function isKeywordContext(array $tokens, int $pos): bool {
|
|
73
|
+
$prevToken = $this->getPreviousNonSpaceToken($tokens, $pos);
|
|
74
|
+
if ($prevToken === null) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return $prevToken->id !== \T_OBJECT_OPERATOR
|
|
78
|
+
&& $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** @param Token[] $tokens */
|
|
82
|
+
private function getPreviousNonSpaceToken(array $tokens, int $start): ?Token {
|
|
83
|
+
for ($i = $start - 1; $i >= 0; --$i) {
|
|
84
|
+
if ($tokens[$i]->id === T_WHITESPACE) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return $tokens[$i];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
package/php-subsystem/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php
CHANGED
|
@@ -14,8 +14,12 @@ abstract class KeywordEmulator extends TokenEmulator {
|
|
|
14
14
|
|
|
15
15
|
/** @param Token[] $tokens */
|
|
16
16
|
protected function isKeywordContext(array $tokens, int $pos): bool {
|
|
17
|
-
$
|
|
18
|
-
|
|
17
|
+
$prevToken = $this->getPreviousNonSpaceToken($tokens, $pos);
|
|
18
|
+
if ($prevToken === null) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return $prevToken->id !== \T_OBJECT_OPERATOR
|
|
22
|
+
&& $prevToken->id !== \T_NULLSAFE_OBJECT_OPERATOR;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
public function emulate(string $code, array $tokens): array {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<?php declare(strict_types=1);
|
|
2
|
+
|
|
3
|
+
namespace PhpParser\Lexer\TokenEmulator;
|
|
4
|
+
|
|
5
|
+
use PhpParser\PhpVersion;
|
|
6
|
+
|
|
7
|
+
final class PropertyTokenEmulator extends KeywordEmulator {
|
|
8
|
+
public function getPhpVersion(): PhpVersion {
|
|
9
|
+
return PhpVersion::fromComponents(8, 4);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public function getKeywordString(): string {
|
|
13
|
+
return '__property__';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public function getKeywordToken(): int {
|
|
17
|
+
return \T_PROPERTY_C;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -14,23 +14,47 @@ final class Modifiers {
|
|
|
14
14
|
public const ABSTRACT = 16;
|
|
15
15
|
public const FINAL = 32;
|
|
16
16
|
public const READONLY = 64;
|
|
17
|
+
public const PUBLIC_SET = 128;
|
|
18
|
+
public const PROTECTED_SET = 256;
|
|
19
|
+
public const PRIVATE_SET = 512;
|
|
17
20
|
|
|
18
|
-
public const VISIBILITY_MASK =
|
|
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
|
+
}
|
|
19
49
|
|
|
20
50
|
/**
|
|
21
51
|
* @internal
|
|
22
52
|
*/
|
|
23
53
|
public static function verifyClassModifier(int $a, int $b): void {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if ($a & Modifiers::FINAL && $b & Modifiers::FINAL) {
|
|
29
|
-
throw new Error('Multiple final modifiers are not allowed');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if ($a & Modifiers::READONLY && $b & Modifiers::READONLY) {
|
|
33
|
-
throw new Error('Multiple readonly modifiers are not allowed');
|
|
54
|
+
assert(self::isValidModifier($b));
|
|
55
|
+
if (($a & $b) != 0) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
'Multiple ' . self::toString($b) . ' modifiers are not allowed');
|
|
34
58
|
}
|
|
35
59
|
|
|
36
60
|
if ($a & 48 && $b & 48) {
|
|
@@ -42,24 +66,16 @@ final class Modifiers {
|
|
|
42
66
|
* @internal
|
|
43
67
|
*/
|
|
44
68
|
public static function verifyModifier(int $a, int $b): void {
|
|
45
|
-
|
|
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
|
+
) {
|
|
46
73
|
throw new Error('Multiple access type modifiers are not allowed');
|
|
47
74
|
}
|
|
48
75
|
|
|
49
|
-
if ($a &
|
|
50
|
-
throw new Error(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if ($a & Modifiers::STATIC && $b & Modifiers::STATIC) {
|
|
54
|
-
throw new Error('Multiple static modifiers are not allowed');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if ($a & Modifiers::FINAL && $b & Modifiers::FINAL) {
|
|
58
|
-
throw new Error('Multiple final modifiers are not allowed');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if ($a & Modifiers::READONLY && $b & Modifiers::READONLY) {
|
|
62
|
-
throw new Error('Multiple readonly modifiers are not allowed');
|
|
76
|
+
if (($a & $b) != 0) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
'Multiple ' . self::toString($b) . ' modifiers are not allowed');
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
if ($a & 48 && $b & 48) {
|
|
@@ -185,7 +185,7 @@ class NameContext {
|
|
|
185
185
|
// Check for relevant type-specific use statements
|
|
186
186
|
foreach ($this->origAliases[$type] as $alias => $orig) {
|
|
187
187
|
if ($type === Stmt\Use_::TYPE_CONSTANT) {
|
|
188
|
-
// Constants are
|
|
188
|
+
// Constants are complicated-sensitive
|
|
189
189
|
$normalizedOrig = $this->normalizeConstName($orig->toString());
|
|
190
190
|
if ($normalizedOrig === $this->normalizeConstName($name)) {
|
|
191
191
|
$possibleNames[] = new Name($alias);
|
|
@@ -8,7 +8,10 @@ use PhpParser\NodeAbstract;
|
|
|
8
8
|
* Represents a non-namespaced name. Namespaced names are represented using Name nodes.
|
|
9
9
|
*/
|
|
10
10
|
class Identifier extends NodeAbstract {
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* @psalm-var non-empty-string
|
|
13
|
+
* @var string Identifier as string
|
|
14
|
+
*/
|
|
12
15
|
public string $name;
|
|
13
16
|
|
|
14
17
|
/** @var array<string, bool> */
|
|
@@ -25,6 +28,10 @@ class Identifier extends NodeAbstract {
|
|
|
25
28
|
* @param array<string, mixed> $attributes Additional attributes
|
|
26
29
|
*/
|
|
27
30
|
public function __construct(string $name, array $attributes = []) {
|
|
31
|
+
if ($name === '') {
|
|
32
|
+
throw new \InvalidArgumentException('Identifier name cannot be empty');
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
$this->attributes = $attributes;
|
|
29
36
|
$this->name = $name;
|
|
30
37
|
}
|
|
@@ -36,6 +43,7 @@ class Identifier extends NodeAbstract {
|
|
|
36
43
|
/**
|
|
37
44
|
* Get identifier as string.
|
|
38
45
|
*
|
|
46
|
+
* @psalm-return non-empty-string
|
|
39
47
|
* @return string Identifier as string.
|
|
40
48
|
*/
|
|
41
49
|
public function toString(): string {
|
|
@@ -45,6 +53,7 @@ class Identifier extends NodeAbstract {
|
|
|
45
53
|
/**
|
|
46
54
|
* Get lowercased identifier as string.
|
|
47
55
|
*
|
|
56
|
+
* @psalm-return non-empty-string
|
|
48
57
|
* @return string Lowercased identifier as string
|
|
49
58
|
*/
|
|
50
59
|
public function toLowerString(): string {
|
|
@@ -63,6 +72,7 @@ class Identifier extends NodeAbstract {
|
|
|
63
72
|
/**
|
|
64
73
|
* Get identifier as string.
|
|
65
74
|
*
|
|
75
|
+
* @psalm-return non-empty-string
|
|
66
76
|
* @return string Identifier as string
|
|
67
77
|
*/
|
|
68
78
|
public function __toString(): string {
|