Completed
Pull Request — master (#430)
by
unknown
02:43
created
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php 2 patches
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -6,25 +6,25 @@
 block discarded – undo
6 6
 
7 7
 class ErrorSuppress extends Expr
8 8
 {
9
-    /** @var Expr Expression */
10
-    public $expr;
9
+	/** @var Expr Expression */
10
+	public $expr;
11 11
 
12
-    /**
13
-     * Constructs an error suppress node.
14
-     *
15
-     * @param Expr  $expr       Expression
16
-     * @param array $attributes Additional attributes
17
-     */
18
-    public function __construct(Expr $expr, array $attributes = []) {
19
-        $this->attributes = $attributes;
20
-        $this->expr = $expr;
21
-    }
12
+	/**
13
+	 * Constructs an error suppress node.
14
+	 *
15
+	 * @param Expr  $expr       Expression
16
+	 * @param array $attributes Additional attributes
17
+	 */
18
+	public function __construct(Expr $expr, array $attributes = []) {
19
+		$this->attributes = $attributes;
20
+		$this->expr = $expr;
21
+	}
22 22
 
23
-    public function getSubNodeNames() : array {
24
-        return ['expr'];
25
-    }
23
+	public function getSubNodeNames() : array {
24
+		return ['expr'];
25
+	}
26 26
     
27
-    public function getType() : string {
28
-        return 'Expr_ErrorSuppress';
29
-    }
27
+	public function getType() : string {
28
+		return 'Expr_ErrorSuppress';
29
+	}
30 30
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -4,8 +4,7 @@
 block discarded – undo
4 4
 
5 5
 use PhpParser\Node\Expr;
6 6
 
7
-class ErrorSuppress extends Expr
8
-{
7
+class ErrorSuppress extends Expr {
9 8
     /** @var Expr Expression */
10 9
     public $expr;
11 10
 
Please login to merge, or discard this patch.
vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php 2 patches
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -9,37 +9,37 @@
 block discarded – undo
9 9
 
10 10
 class NullsafeMethodCall extends CallLike
11 11
 {
12
-    /** @var Expr Variable holding object */
13
-    public $var;
14
-    /** @var Identifier|Expr Method name */
15
-    public $name;
16
-    /** @var array<Arg|VariadicPlaceholder> Arguments */
17
-    public $args;
12
+	/** @var Expr Variable holding object */
13
+	public $var;
14
+	/** @var Identifier|Expr Method name */
15
+	public $name;
16
+	/** @var array<Arg|VariadicPlaceholder> Arguments */
17
+	public $args;
18 18
 
19
-    /**
20
-     * Constructs a nullsafe method call node.
21
-     *
22
-     * @param Expr                           $var        Variable holding object
23
-     * @param string|Identifier|Expr         $name       Method name
24
-     * @param array<Arg|VariadicPlaceholder> $args       Arguments
25
-     * @param array                          $attributes Additional attributes
26
-     */
27
-    public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
28
-        $this->attributes = $attributes;
29
-        $this->var = $var;
30
-        $this->name = \is_string($name) ? new Identifier($name) : $name;
31
-        $this->args = $args;
32
-    }
19
+	/**
20
+	 * Constructs a nullsafe method call node.
21
+	 *
22
+	 * @param Expr                           $var        Variable holding object
23
+	 * @param string|Identifier|Expr         $name       Method name
24
+	 * @param array<Arg|VariadicPlaceholder> $args       Arguments
25
+	 * @param array                          $attributes Additional attributes
26
+	 */
27
+	public function __construct(Expr $var, $name, array $args = [], array $attributes = []) {
28
+		$this->attributes = $attributes;
29
+		$this->var = $var;
30
+		$this->name = \is_string($name) ? new Identifier($name) : $name;
31
+		$this->args = $args;
32
+	}
33 33
 
34
-    public function getSubNodeNames() : array {
35
-        return ['var', 'name', 'args'];
36
-    }
34
+	public function getSubNodeNames() : array {
35
+		return ['var', 'name', 'args'];
36
+	}
37 37
     
38
-    public function getType() : string {
39
-        return 'Expr_NullsafeMethodCall';
40
-    }
38
+	public function getType() : string {
39
+		return 'Expr_NullsafeMethodCall';
40
+	}
41 41
 
42
-    public function getRawArgs(): array {
43
-        return $this->args;
44
-    }
42
+	public function getRawArgs(): array {
43
+		return $this->args;
44
+	}
45 45
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -7,8 +7,7 @@
 block discarded – undo
7 7
 use PhpParser\Node\Identifier;
8 8
 use PhpParser\Node\VariadicPlaceholder;
9 9
 
10
-class NullsafeMethodCall extends CallLike
11
-{
10
+class NullsafeMethodCall extends CallLike {
12 11
     /** @var Expr Variable holding object */
13 12
     public $var;
14 13
     /** @var Identifier|Expr Method name */
Please login to merge, or discard this patch.
php-scoper/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php 2 patches
Indentation   +18 added lines, -18 removed lines patch added patch discarded remove patch
@@ -6,25 +6,25 @@
 block discarded – undo
6 6
 
7 7
 class Isset_ extends Expr
8 8
 {
9
-    /** @var Expr[] Variables */
10
-    public $vars;
9
+	/** @var Expr[] Variables */
10
+	public $vars;
11 11
 
12
-    /**
13
-     * Constructs an array node.
14
-     *
15
-     * @param Expr[] $vars       Variables
16
-     * @param array  $attributes Additional attributes
17
-     */
18
-    public function __construct(array $vars, array $attributes = []) {
19
-        $this->attributes = $attributes;
20
-        $this->vars = $vars;
21
-    }
12
+	/**
13
+	 * Constructs an array node.
14
+	 *
15
+	 * @param Expr[] $vars       Variables
16
+	 * @param array  $attributes Additional attributes
17
+	 */
18
+	public function __construct(array $vars, array $attributes = []) {
19
+		$this->attributes = $attributes;
20
+		$this->vars = $vars;
21
+	}
22 22
 
23
-    public function getSubNodeNames() : array {
24
-        return ['vars'];
25
-    }
23
+	public function getSubNodeNames() : array {
24
+		return ['vars'];
25
+	}
26 26
     
27
-    public function getType() : string {
28
-        return 'Expr_Isset';
29
-    }
27
+	public function getType() : string {
28
+		return 'Expr_Isset';
29
+	}
30 30
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -4,8 +4,7 @@
 block discarded – undo
4 4
 
5 5
 use PhpParser\Node\Expr;
6 6
 
7
-class Isset_ extends Expr
8
-{
7
+class Isset_ extends Expr {
9 8
     /** @var Expr[] Variables */
10 9
     public $vars;
11 10
 
Please login to merge, or discard this patch.
php-scoper/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php 2 patches
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -9,67 +9,67 @@
 block discarded – undo
9 9
  */
10 10
 class Identifier extends NodeAbstract
11 11
 {
12
-    /** @var string Identifier as string */
13
-    public $name;
12
+	/** @var string Identifier as string */
13
+	public $name;
14 14
 
15
-    private static $specialClassNames = [
16
-        'self'   => true,
17
-        'parent' => true,
18
-        'static' => true,
19
-    ];
15
+	private static $specialClassNames = [
16
+		'self'   => true,
17
+		'parent' => true,
18
+		'static' => true,
19
+	];
20 20
 
21
-    /**
22
-     * Constructs an identifier node.
23
-     *
24
-     * @param string $name       Identifier as string
25
-     * @param array  $attributes Additional attributes
26
-     */
27
-    public function __construct(string $name, array $attributes = []) {
28
-        $this->attributes = $attributes;
29
-        $this->name = $name;
30
-    }
21
+	/**
22
+	 * Constructs an identifier node.
23
+	 *
24
+	 * @param string $name       Identifier as string
25
+	 * @param array  $attributes Additional attributes
26
+	 */
27
+	public function __construct(string $name, array $attributes = []) {
28
+		$this->attributes = $attributes;
29
+		$this->name = $name;
30
+	}
31 31
 
32
-    public function getSubNodeNames() : array {
33
-        return ['name'];
34
-    }
32
+	public function getSubNodeNames() : array {
33
+		return ['name'];
34
+	}
35 35
 
36
-    /**
37
-     * Get identifier as string.
38
-     *
39
-     * @return string Identifier as string.
40
-     */
41
-    public function toString() : string {
42
-        return $this->name;
43
-    }
36
+	/**
37
+	 * Get identifier as string.
38
+	 *
39
+	 * @return string Identifier as string.
40
+	 */
41
+	public function toString() : string {
42
+		return $this->name;
43
+	}
44 44
 
45
-    /**
46
-     * Get lowercased identifier as string.
47
-     *
48
-     * @return string Lowercased identifier as string
49
-     */
50
-    public function toLowerString() : string {
51
-        return strtolower($this->name);
52
-    }
45
+	/**
46
+	 * Get lowercased identifier as string.
47
+	 *
48
+	 * @return string Lowercased identifier as string
49
+	 */
50
+	public function toLowerString() : string {
51
+		return strtolower($this->name);
52
+	}
53 53
 
54
-    /**
55
-     * Checks whether the identifier is a special class name (self, parent or static).
56
-     *
57
-     * @return bool Whether identifier is a special class name
58
-     */
59
-    public function isSpecialClassName() : bool {
60
-        return isset(self::$specialClassNames[strtolower($this->name)]);
61
-    }
54
+	/**
55
+	 * Checks whether the identifier is a special class name (self, parent or static).
56
+	 *
57
+	 * @return bool Whether identifier is a special class name
58
+	 */
59
+	public function isSpecialClassName() : bool {
60
+		return isset(self::$specialClassNames[strtolower($this->name)]);
61
+	}
62 62
 
63
-    /**
64
-     * Get identifier as string.
65
-     *
66
-     * @return string Identifier as string
67
-     */
68
-    public function __toString() : string {
69
-        return $this->name;
70
-    }
63
+	/**
64
+	 * Get identifier as string.
65
+	 *
66
+	 * @return string Identifier as string
67
+	 */
68
+	public function __toString() : string {
69
+		return $this->name;
70
+	}
71 71
     
72
-    public function getType() : string {
73
-        return 'Identifier';
74
-    }
72
+	public function getType() : string {
73
+		return 'Identifier';
74
+	}
75 75
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -7,8 +7,7 @@
 block discarded – undo
7 7
 /**
8 8
  * Represents a non-namespaced name. Namespaced names are represented using Name nodes.
9 9
  */
10
-class Identifier extends NodeAbstract
11
-{
10
+class Identifier extends NodeAbstract {
12 11
     /** @var string Identifier as string */
13 12
     public $name;
14 13
 
Please login to merge, or discard this patch.
vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php 2 patches
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -4,47 +4,47 @@
 block discarded – undo
4 4
 
5 5
 class FullyQualified extends \PhpParser\Node\Name
6 6
 {
7
-    /**
8
-     * Checks whether the name is unqualified. (E.g. Name)
9
-     *
10
-     * @return bool Whether the name is unqualified
11
-     */
12
-    public function isUnqualified() : bool {
13
-        return false;
14
-    }
7
+	/**
8
+	 * Checks whether the name is unqualified. (E.g. Name)
9
+	 *
10
+	 * @return bool Whether the name is unqualified
11
+	 */
12
+	public function isUnqualified() : bool {
13
+		return false;
14
+	}
15 15
 
16
-    /**
17
-     * Checks whether the name is qualified. (E.g. Name\Name)
18
-     *
19
-     * @return bool Whether the name is qualified
20
-     */
21
-    public function isQualified() : bool {
22
-        return false;
23
-    }
16
+	/**
17
+	 * Checks whether the name is qualified. (E.g. Name\Name)
18
+	 *
19
+	 * @return bool Whether the name is qualified
20
+	 */
21
+	public function isQualified() : bool {
22
+		return false;
23
+	}
24 24
 
25
-    /**
26
-     * Checks whether the name is fully qualified. (E.g. \Name)
27
-     *
28
-     * @return bool Whether the name is fully qualified
29
-     */
30
-    public function isFullyQualified() : bool {
31
-        return true;
32
-    }
25
+	/**
26
+	 * Checks whether the name is fully qualified. (E.g. \Name)
27
+	 *
28
+	 * @return bool Whether the name is fully qualified
29
+	 */
30
+	public function isFullyQualified() : bool {
31
+		return true;
32
+	}
33 33
 
34
-    /**
35
-     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
36
-     *
37
-     * @return bool Whether the name is relative
38
-     */
39
-    public function isRelative() : bool {
40
-        return false;
41
-    }
34
+	/**
35
+	 * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
36
+	 *
37
+	 * @return bool Whether the name is relative
38
+	 */
39
+	public function isRelative() : bool {
40
+		return false;
41
+	}
42 42
 
43
-    public function toCodeString() : string {
44
-        return '\\' . $this->toString();
45
-    }
43
+	public function toCodeString() : string {
44
+		return '\\' . $this->toString();
45
+	}
46 46
     
47
-    public function getType() : string {
48
-        return 'Name_FullyQualified';
49
-    }
47
+	public function getType() : string {
48
+		return 'Name_FullyQualified';
49
+	}
50 50
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -41,7 +41,7 @@
 block discarded – undo
41 41
     }
42 42
 
43 43
     public function toCodeString() : string {
44
-        return '\\' . $this->toString();
44
+        return '\\'.$this->toString();
45 45
     }
46 46
     
47 47
     public function getType() : string {
Please login to merge, or discard this patch.
php-scoper/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php 2 patches
Indentation   +38 added lines, -38 removed lines patch added patch discarded remove patch
@@ -4,47 +4,47 @@
 block discarded – undo
4 4
 
5 5
 class Relative extends \PhpParser\Node\Name
6 6
 {
7
-    /**
8
-     * Checks whether the name is unqualified. (E.g. Name)
9
-     *
10
-     * @return bool Whether the name is unqualified
11
-     */
12
-    public function isUnqualified() : bool {
13
-        return false;
14
-    }
7
+	/**
8
+	 * Checks whether the name is unqualified. (E.g. Name)
9
+	 *
10
+	 * @return bool Whether the name is unqualified
11
+	 */
12
+	public function isUnqualified() : bool {
13
+		return false;
14
+	}
15 15
 
16
-    /**
17
-     * Checks whether the name is qualified. (E.g. Name\Name)
18
-     *
19
-     * @return bool Whether the name is qualified
20
-     */
21
-    public function isQualified() : bool {
22
-        return false;
23
-    }
16
+	/**
17
+	 * Checks whether the name is qualified. (E.g. Name\Name)
18
+	 *
19
+	 * @return bool Whether the name is qualified
20
+	 */
21
+	public function isQualified() : bool {
22
+		return false;
23
+	}
24 24
 
25
-    /**
26
-     * Checks whether the name is fully qualified. (E.g. \Name)
27
-     *
28
-     * @return bool Whether the name is fully qualified
29
-     */
30
-    public function isFullyQualified() : bool {
31
-        return false;
32
-    }
25
+	/**
26
+	 * Checks whether the name is fully qualified. (E.g. \Name)
27
+	 *
28
+	 * @return bool Whether the name is fully qualified
29
+	 */
30
+	public function isFullyQualified() : bool {
31
+		return false;
32
+	}
33 33
 
34
-    /**
35
-     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
36
-     *
37
-     * @return bool Whether the name is relative
38
-     */
39
-    public function isRelative() : bool {
40
-        return true;
41
-    }
34
+	/**
35
+	 * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
36
+	 *
37
+	 * @return bool Whether the name is relative
38
+	 */
39
+	public function isRelative() : bool {
40
+		return true;
41
+	}
42 42
 
43
-    public function toCodeString() : string {
44
-        return 'namespace\\' . $this->toString();
45
-    }
43
+	public function toCodeString() : string {
44
+		return 'namespace\\' . $this->toString();
45
+	}
46 46
     
47
-    public function getType() : string {
48
-        return 'Name_Relative';
49
-    }
47
+	public function getType() : string {
48
+		return 'Name_Relative';
49
+	}
50 50
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -41,7 +41,7 @@
 block discarded – undo
41 41
     }
42 42
 
43 43
     public function toCodeString() : string {
44
-        return 'namespace\\' . $this->toString();
44
+        return 'namespace\\'.$this->toString();
45 45
     }
46 46
     
47 47
     public function getType() : string {
Please login to merge, or discard this patch.
php-scoper/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php 2 patches
Indentation   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -7,23 +7,23 @@
 block discarded – undo
7 7
 
8 8
 class AttributeGroup extends NodeAbstract
9 9
 {
10
-    /** @var Attribute[] Attributes */
11
-    public $attrs;
10
+	/** @var Attribute[] Attributes */
11
+	public $attrs;
12 12
 
13
-    /**
14
-     * @param Attribute[] $attrs PHP attributes
15
-     * @param array $attributes Additional node attributes
16
-     */
17
-    public function __construct(array $attrs, array $attributes = []) {
18
-        $this->attributes = $attributes;
19
-        $this->attrs = $attrs;
20
-    }
13
+	/**
14
+	 * @param Attribute[] $attrs PHP attributes
15
+	 * @param array $attributes Additional node attributes
16
+	 */
17
+	public function __construct(array $attrs, array $attributes = []) {
18
+		$this->attributes = $attributes;
19
+		$this->attrs = $attrs;
20
+	}
21 21
 
22
-    public function getSubNodeNames() : array {
23
-        return ['attrs'];
24
-    }
22
+	public function getSubNodeNames() : array {
23
+		return ['attrs'];
24
+	}
25 25
 
26
-    public function getType() : string {
27
-        return 'AttributeGroup';
28
-    }
26
+	public function getType() : string {
27
+		return 'AttributeGroup';
28
+	}
29 29
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -5,8 +5,7 @@
 block discarded – undo
5 5
 use PhpParser\Node;
6 6
 use PhpParser\NodeAbstract;
7 7
 
8
-class AttributeGroup extends NodeAbstract
9
-{
8
+class AttributeGroup extends NodeAbstract {
10 9
     /** @var Attribute[] Attributes */
11 10
     public $attrs;
12 11
 
Please login to merge, or discard this patch.
php-scoper/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php 3 patches
Indentation   +199 added lines, -199 removed lines patch added patch discarded remove patch
@@ -27,203 +27,203 @@
 block discarded – undo
27 27
  */
28 28
 class ConstExprEvaluator
29 29
 {
30
-    private $fallbackEvaluator;
31
-
32
-    /**
33
-     * Create a constant expression evaluator.
34
-     *
35
-     * The provided fallback evaluator is invoked whenever a subexpression cannot be evaluated. See
36
-     * class doc comment for more information.
37
-     *
38
-     * @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated
39
-     */
40
-    public function __construct(?callable $fallbackEvaluator = null) {
41
-        $this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) {
42
-            throw new ConstExprEvaluationException(
43
-                "Expression of type {$expr->getType()} cannot be evaluated"
44
-            );
45
-        };
46
-    }
47
-
48
-    /**
49
-     * Silently evaluates a constant expression into a PHP value.
50
-     *
51
-     * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException.
52
-     * The original source of the exception is available through getPrevious().
53
-     *
54
-     * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
55
-     * constructor will be invoked. By default, if no fallback is provided, an exception of type
56
-     * ConstExprEvaluationException is thrown.
57
-     *
58
-     * See class doc comment for caveats and limitations.
59
-     *
60
-     * @param Expr $expr Constant expression to evaluate
61
-     * @return mixed Result of evaluation
62
-     *
63
-     * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred
64
-     */
65
-    public function evaluateSilently(Expr $expr) {
66
-        set_error_handler(function($num, $str, $file, $line) {
67
-            throw new \ErrorException($str, 0, $num, $file, $line);
68
-        });
69
-
70
-        try {
71
-            return $this->evaluate($expr);
72
-        } catch (\Throwable $e) {
73
-            if (!$e instanceof ConstExprEvaluationException) {
74
-                $e = new ConstExprEvaluationException(
75
-                    "An error occurred during constant expression evaluation", 0, $e);
76
-            }
77
-            throw $e;
78
-        } finally {
79
-            restore_error_handler();
80
-        }
81
-    }
82
-
83
-    /**
84
-     * Directly evaluates a constant expression into a PHP value.
85
-     *
86
-     * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these
87
-     * into a ConstExprEvaluationException.
88
-     *
89
-     * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
90
-     * constructor will be invoked. By default, if no fallback is provided, an exception of type
91
-     * ConstExprEvaluationException is thrown.
92
-     *
93
-     * See class doc comment for caveats and limitations.
94
-     *
95
-     * @param Expr $expr Constant expression to evaluate
96
-     * @return mixed Result of evaluation
97
-     *
98
-     * @throws ConstExprEvaluationException if the expression cannot be evaluated
99
-     */
100
-    public function evaluateDirectly(Expr $expr) {
101
-        return $this->evaluate($expr);
102
-    }
103
-
104
-    private function evaluate(Expr $expr) {
105
-        if ($expr instanceof Scalar\LNumber
106
-            || $expr instanceof Scalar\DNumber
107
-            || $expr instanceof Scalar\String_
108
-        ) {
109
-            return $expr->value;
110
-        }
111
-
112
-        if ($expr instanceof Expr\Array_) {
113
-            return $this->evaluateArray($expr);
114
-        }
115
-
116
-        // Unary operators
117
-        if ($expr instanceof Expr\UnaryPlus) {
118
-            return +$this->evaluate($expr->expr);
119
-        }
120
-        if ($expr instanceof Expr\UnaryMinus) {
121
-            return -$this->evaluate($expr->expr);
122
-        }
123
-        if ($expr instanceof Expr\BooleanNot) {
124
-            return !$this->evaluate($expr->expr);
125
-        }
126
-        if ($expr instanceof Expr\BitwiseNot) {
127
-            return ~$this->evaluate($expr->expr);
128
-        }
129
-
130
-        if ($expr instanceof Expr\BinaryOp) {
131
-            return $this->evaluateBinaryOp($expr);
132
-        }
133
-
134
-        if ($expr instanceof Expr\Ternary) {
135
-            return $this->evaluateTernary($expr);
136
-        }
137
-
138
-        if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) {
139
-            return $this->evaluate($expr->var)[$this->evaluate($expr->dim)];
140
-        }
141
-
142
-        if ($expr instanceof Expr\ConstFetch) {
143
-            return $this->evaluateConstFetch($expr);
144
-        }
145
-
146
-        return ($this->fallbackEvaluator)($expr);
147
-    }
148
-
149
-    private function evaluateArray(Expr\Array_ $expr) {
150
-        $array = [];
151
-        foreach ($expr->items as $item) {
152
-            if (null !== $item->key) {
153
-                $array[$this->evaluate($item->key)] = $this->evaluate($item->value);
154
-            } elseif ($item->unpack) {
155
-                $array = array_merge($array, $this->evaluate($item->value));
156
-            } else {
157
-                $array[] = $this->evaluate($item->value);
158
-            }
159
-        }
160
-        return $array;
161
-    }
162
-
163
-    private function evaluateTernary(Expr\Ternary $expr) {
164
-        if (null === $expr->if) {
165
-            return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else);
166
-        }
167
-
168
-        return $this->evaluate($expr->cond)
169
-            ? $this->evaluate($expr->if)
170
-            : $this->evaluate($expr->else);
171
-    }
172
-
173
-    private function evaluateBinaryOp(Expr\BinaryOp $expr) {
174
-        if ($expr instanceof Expr\BinaryOp\Coalesce
175
-            && $expr->left instanceof Expr\ArrayDimFetch
176
-        ) {
177
-            // This needs to be special cased to respect BP_VAR_IS fetch semantics
178
-            return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)]
179
-                ?? $this->evaluate($expr->right);
180
-        }
181
-
182
-        // The evaluate() calls are repeated in each branch, because some of the operators are
183
-        // short-circuiting and evaluating the RHS in advance may be illegal in that case
184
-        $l = $expr->left;
185
-        $r = $expr->right;
186
-        switch ($expr->getOperatorSigil()) {
187
-            case '&':   return $this->evaluate($l) &   $this->evaluate($r);
188
-            case '|':   return $this->evaluate($l) |   $this->evaluate($r);
189
-            case '^':   return $this->evaluate($l) ^   $this->evaluate($r);
190
-            case '&&':  return $this->evaluate($l) &&  $this->evaluate($r);
191
-            case '||':  return $this->evaluate($l) ||  $this->evaluate($r);
192
-            case '??':  return $this->evaluate($l) ??  $this->evaluate($r);
193
-            case '.':   return $this->evaluate($l) .   $this->evaluate($r);
194
-            case '/':   return $this->evaluate($l) /   $this->evaluate($r);
195
-            case '==':  return $this->evaluate($l) ==  $this->evaluate($r);
196
-            case '>':   return $this->evaluate($l) >   $this->evaluate($r);
197
-            case '>=':  return $this->evaluate($l) >=  $this->evaluate($r);
198
-            case '===': return $this->evaluate($l) === $this->evaluate($r);
199
-            case 'and': return $this->evaluate($l) and $this->evaluate($r);
200
-            case 'or':  return $this->evaluate($l) or  $this->evaluate($r);
201
-            case 'xor': return $this->evaluate($l) xor $this->evaluate($r);
202
-            case '-':   return $this->evaluate($l) -   $this->evaluate($r);
203
-            case '%':   return $this->evaluate($l) %   $this->evaluate($r);
204
-            case '*':   return $this->evaluate($l) *   $this->evaluate($r);
205
-            case '!=':  return $this->evaluate($l) !=  $this->evaluate($r);
206
-            case '!==': return $this->evaluate($l) !== $this->evaluate($r);
207
-            case '+':   return $this->evaluate($l) +   $this->evaluate($r);
208
-            case '**':  return $this->evaluate($l) **  $this->evaluate($r);
209
-            case '<<':  return $this->evaluate($l) <<  $this->evaluate($r);
210
-            case '>>':  return $this->evaluate($l) >>  $this->evaluate($r);
211
-            case '<':   return $this->evaluate($l) <   $this->evaluate($r);
212
-            case '<=':  return $this->evaluate($l) <=  $this->evaluate($r);
213
-            case '<=>': return $this->evaluate($l) <=> $this->evaluate($r);
214
-        }
215
-
216
-        throw new \Exception('Should not happen');
217
-    }
218
-
219
-    private function evaluateConstFetch(Expr\ConstFetch $expr) {
220
-        $name = $expr->name->toLowerString();
221
-        switch ($name) {
222
-            case 'null': return null;
223
-            case 'false': return false;
224
-            case 'true': return true;
225
-        }
226
-
227
-        return ($this->fallbackEvaluator)($expr);
228
-    }
30
+	private $fallbackEvaluator;
31
+
32
+	/**
33
+	 * Create a constant expression evaluator.
34
+	 *
35
+	 * The provided fallback evaluator is invoked whenever a subexpression cannot be evaluated. See
36
+	 * class doc comment for more information.
37
+	 *
38
+	 * @param callable|null $fallbackEvaluator To call if subexpression cannot be evaluated
39
+	 */
40
+	public function __construct(?callable $fallbackEvaluator = null) {
41
+		$this->fallbackEvaluator = $fallbackEvaluator ?? function(Expr $expr) {
42
+			throw new ConstExprEvaluationException(
43
+				"Expression of type {$expr->getType()} cannot be evaluated"
44
+			);
45
+		};
46
+	}
47
+
48
+	/**
49
+	 * Silently evaluates a constant expression into a PHP value.
50
+	 *
51
+	 * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException.
52
+	 * The original source of the exception is available through getPrevious().
53
+	 *
54
+	 * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
55
+	 * constructor will be invoked. By default, if no fallback is provided, an exception of type
56
+	 * ConstExprEvaluationException is thrown.
57
+	 *
58
+	 * See class doc comment for caveats and limitations.
59
+	 *
60
+	 * @param Expr $expr Constant expression to evaluate
61
+	 * @return mixed Result of evaluation
62
+	 *
63
+	 * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred
64
+	 */
65
+	public function evaluateSilently(Expr $expr) {
66
+		set_error_handler(function($num, $str, $file, $line) {
67
+			throw new \ErrorException($str, 0, $num, $file, $line);
68
+		});
69
+
70
+		try {
71
+			return $this->evaluate($expr);
72
+		} catch (\Throwable $e) {
73
+			if (!$e instanceof ConstExprEvaluationException) {
74
+				$e = new ConstExprEvaluationException(
75
+					"An error occurred during constant expression evaluation", 0, $e);
76
+			}
77
+			throw $e;
78
+		} finally {
79
+			restore_error_handler();
80
+		}
81
+	}
82
+
83
+	/**
84
+	 * Directly evaluates a constant expression into a PHP value.
85
+	 *
86
+	 * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these
87
+	 * into a ConstExprEvaluationException.
88
+	 *
89
+	 * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
90
+	 * constructor will be invoked. By default, if no fallback is provided, an exception of type
91
+	 * ConstExprEvaluationException is thrown.
92
+	 *
93
+	 * See class doc comment for caveats and limitations.
94
+	 *
95
+	 * @param Expr $expr Constant expression to evaluate
96
+	 * @return mixed Result of evaluation
97
+	 *
98
+	 * @throws ConstExprEvaluationException if the expression cannot be evaluated
99
+	 */
100
+	public function evaluateDirectly(Expr $expr) {
101
+		return $this->evaluate($expr);
102
+	}
103
+
104
+	private function evaluate(Expr $expr) {
105
+		if ($expr instanceof Scalar\LNumber
106
+			|| $expr instanceof Scalar\DNumber
107
+			|| $expr instanceof Scalar\String_
108
+		) {
109
+			return $expr->value;
110
+		}
111
+
112
+		if ($expr instanceof Expr\Array_) {
113
+			return $this->evaluateArray($expr);
114
+		}
115
+
116
+		// Unary operators
117
+		if ($expr instanceof Expr\UnaryPlus) {
118
+			return +$this->evaluate($expr->expr);
119
+		}
120
+		if ($expr instanceof Expr\UnaryMinus) {
121
+			return -$this->evaluate($expr->expr);
122
+		}
123
+		if ($expr instanceof Expr\BooleanNot) {
124
+			return !$this->evaluate($expr->expr);
125
+		}
126
+		if ($expr instanceof Expr\BitwiseNot) {
127
+			return ~$this->evaluate($expr->expr);
128
+		}
129
+
130
+		if ($expr instanceof Expr\BinaryOp) {
131
+			return $this->evaluateBinaryOp($expr);
132
+		}
133
+
134
+		if ($expr instanceof Expr\Ternary) {
135
+			return $this->evaluateTernary($expr);
136
+		}
137
+
138
+		if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) {
139
+			return $this->evaluate($expr->var)[$this->evaluate($expr->dim)];
140
+		}
141
+
142
+		if ($expr instanceof Expr\ConstFetch) {
143
+			return $this->evaluateConstFetch($expr);
144
+		}
145
+
146
+		return ($this->fallbackEvaluator)($expr);
147
+	}
148
+
149
+	private function evaluateArray(Expr\Array_ $expr) {
150
+		$array = [];
151
+		foreach ($expr->items as $item) {
152
+			if (null !== $item->key) {
153
+				$array[$this->evaluate($item->key)] = $this->evaluate($item->value);
154
+			} elseif ($item->unpack) {
155
+				$array = array_merge($array, $this->evaluate($item->value));
156
+			} else {
157
+				$array[] = $this->evaluate($item->value);
158
+			}
159
+		}
160
+		return $array;
161
+	}
162
+
163
+	private function evaluateTernary(Expr\Ternary $expr) {
164
+		if (null === $expr->if) {
165
+			return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else);
166
+		}
167
+
168
+		return $this->evaluate($expr->cond)
169
+			? $this->evaluate($expr->if)
170
+			: $this->evaluate($expr->else);
171
+	}
172
+
173
+	private function evaluateBinaryOp(Expr\BinaryOp $expr) {
174
+		if ($expr instanceof Expr\BinaryOp\Coalesce
175
+			&& $expr->left instanceof Expr\ArrayDimFetch
176
+		) {
177
+			// This needs to be special cased to respect BP_VAR_IS fetch semantics
178
+			return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)]
179
+				?? $this->evaluate($expr->right);
180
+		}
181
+
182
+		// The evaluate() calls are repeated in each branch, because some of the operators are
183
+		// short-circuiting and evaluating the RHS in advance may be illegal in that case
184
+		$l = $expr->left;
185
+		$r = $expr->right;
186
+		switch ($expr->getOperatorSigil()) {
187
+			case '&':   return $this->evaluate($l) &   $this->evaluate($r);
188
+			case '|':   return $this->evaluate($l) |   $this->evaluate($r);
189
+			case '^':   return $this->evaluate($l) ^   $this->evaluate($r);
190
+			case '&&':  return $this->evaluate($l) &&  $this->evaluate($r);
191
+			case '||':  return $this->evaluate($l) ||  $this->evaluate($r);
192
+			case '??':  return $this->evaluate($l) ??  $this->evaluate($r);
193
+			case '.':   return $this->evaluate($l) .   $this->evaluate($r);
194
+			case '/':   return $this->evaluate($l) /   $this->evaluate($r);
195
+			case '==':  return $this->evaluate($l) ==  $this->evaluate($r);
196
+			case '>':   return $this->evaluate($l) >   $this->evaluate($r);
197
+			case '>=':  return $this->evaluate($l) >=  $this->evaluate($r);
198
+			case '===': return $this->evaluate($l) === $this->evaluate($r);
199
+			case 'and': return $this->evaluate($l) and $this->evaluate($r);
200
+			case 'or':  return $this->evaluate($l) or  $this->evaluate($r);
201
+			case 'xor': return $this->evaluate($l) xor $this->evaluate($r);
202
+			case '-':   return $this->evaluate($l) -   $this->evaluate($r);
203
+			case '%':   return $this->evaluate($l) %   $this->evaluate($r);
204
+			case '*':   return $this->evaluate($l) *   $this->evaluate($r);
205
+			case '!=':  return $this->evaluate($l) !=  $this->evaluate($r);
206
+			case '!==': return $this->evaluate($l) !== $this->evaluate($r);
207
+			case '+':   return $this->evaluate($l) +   $this->evaluate($r);
208
+			case '**':  return $this->evaluate($l) **  $this->evaluate($r);
209
+			case '<<':  return $this->evaluate($l) <<  $this->evaluate($r);
210
+			case '>>':  return $this->evaluate($l) >>  $this->evaluate($r);
211
+			case '<':   return $this->evaluate($l) <   $this->evaluate($r);
212
+			case '<=':  return $this->evaluate($l) <=  $this->evaluate($r);
213
+			case '<=>': return $this->evaluate($l) <=> $this->evaluate($r);
214
+		}
215
+
216
+		throw new \Exception('Should not happen');
217
+	}
218
+
219
+	private function evaluateConstFetch(Expr\ConstFetch $expr) {
220
+		$name = $expr->name->toLowerString();
221
+		switch ($name) {
222
+			case 'null': return null;
223
+			case 'false': return false;
224
+			case 'true': return true;
225
+		}
226
+
227
+		return ($this->fallbackEvaluator)($expr);
228
+	}
229 229
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -184,32 +184,32 @@
 block discarded – undo
184 184
         $l = $expr->left;
185 185
         $r = $expr->right;
186 186
         switch ($expr->getOperatorSigil()) {
187
-            case '&':   return $this->evaluate($l) &   $this->evaluate($r);
188
-            case '|':   return $this->evaluate($l) |   $this->evaluate($r);
189
-            case '^':   return $this->evaluate($l) ^   $this->evaluate($r);
190
-            case '&&':  return $this->evaluate($l) &&  $this->evaluate($r);
191
-            case '||':  return $this->evaluate($l) ||  $this->evaluate($r);
192
-            case '??':  return $this->evaluate($l) ??  $this->evaluate($r);
193
-            case '.':   return $this->evaluate($l) .   $this->evaluate($r);
194
-            case '/':   return $this->evaluate($l) /   $this->evaluate($r);
195
-            case '==':  return $this->evaluate($l) ==  $this->evaluate($r);
196
-            case '>':   return $this->evaluate($l) >   $this->evaluate($r);
197
-            case '>=':  return $this->evaluate($l) >=  $this->evaluate($r);
187
+            case '&':   return $this->evaluate($l) & $this->evaluate($r);
188
+            case '|':   return $this->evaluate($l) | $this->evaluate($r);
189
+            case '^':   return $this->evaluate($l) ^ $this->evaluate($r);
190
+            case '&&':  return $this->evaluate($l) && $this->evaluate($r);
191
+            case '||':  return $this->evaluate($l) || $this->evaluate($r);
192
+            case '??':  return $this->evaluate($l) ?? $this->evaluate($r);
193
+            case '.':   return $this->evaluate($l).$this->evaluate($r);
194
+            case '/':   return $this->evaluate($l) / $this->evaluate($r);
195
+            case '==':  return $this->evaluate($l) == $this->evaluate($r);
196
+            case '>':   return $this->evaluate($l) > $this->evaluate($r);
197
+            case '>=':  return $this->evaluate($l) >= $this->evaluate($r);
198 198
             case '===': return $this->evaluate($l) === $this->evaluate($r);
199 199
             case 'and': return $this->evaluate($l) and $this->evaluate($r);
200
-            case 'or':  return $this->evaluate($l) or  $this->evaluate($r);
200
+            case 'or':  return $this->evaluate($l) or $this->evaluate($r);
201 201
             case 'xor': return $this->evaluate($l) xor $this->evaluate($r);
202
-            case '-':   return $this->evaluate($l) -   $this->evaluate($r);
203
-            case '%':   return $this->evaluate($l) %   $this->evaluate($r);
204
-            case '*':   return $this->evaluate($l) *   $this->evaluate($r);
205
-            case '!=':  return $this->evaluate($l) !=  $this->evaluate($r);
202
+            case '-':   return $this->evaluate($l) - $this->evaluate($r);
203
+            case '%':   return $this->evaluate($l) % $this->evaluate($r);
204
+            case '*':   return $this->evaluate($l) * $this->evaluate($r);
205
+            case '!=':  return $this->evaluate($l) != $this->evaluate($r);
206 206
             case '!==': return $this->evaluate($l) !== $this->evaluate($r);
207
-            case '+':   return $this->evaluate($l) +   $this->evaluate($r);
207
+            case '+':   return $this->evaluate($l) + $this->evaluate($r);
208 208
             case '**':  return $this->evaluate($l) **  $this->evaluate($r);
209
-            case '<<':  return $this->evaluate($l) <<  $this->evaluate($r);
210
-            case '>>':  return $this->evaluate($l) >>  $this->evaluate($r);
211
-            case '<':   return $this->evaluate($l) <   $this->evaluate($r);
212
-            case '<=':  return $this->evaluate($l) <=  $this->evaluate($r);
209
+            case '<<':  return $this->evaluate($l) << $this->evaluate($r);
210
+            case '>>':  return $this->evaluate($l) >> $this->evaluate($r);
211
+            case '<':   return $this->evaluate($l) < $this->evaluate($r);
212
+            case '<=':  return $this->evaluate($l) <= $this->evaluate($r);
213 213
             case '<=>': return $this->evaluate($l) <=> $this->evaluate($r);
214 214
         }
215 215
 
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -25,8 +25,7 @@
 block discarded – undo
25 25
  * point to string conversions are affected by the precision ini setting. Secondly, they are also
26 26
  * affected by the LC_NUMERIC locale.
27 27
  */
28
-class ConstExprEvaluator
29
-{
28
+class ConstExprEvaluator {
30 29
     private $fallbackEvaluator;
31 30
 
32 31
     /**
Please login to merge, or discard this patch.
vendor-bin/php-scoper/vendor/nikic/php-parser/lib/PhpParser/Lexer.php 3 patches
Indentation   +551 added lines, -551 removed lines patch added patch discarded remove patch
@@ -6,555 +6,555 @@
 block discarded – undo
6 6
 
7 7
 class Lexer
8 8
 {
9
-    protected $code;
10
-    protected $tokens;
11
-    protected $pos;
12
-    protected $line;
13
-    protected $filePos;
14
-    protected $prevCloseTagHasNewline;
15
-
16
-    protected $tokenMap;
17
-    protected $dropTokens;
18
-    protected $identifierTokens;
19
-
20
-    private $attributeStartLineUsed;
21
-    private $attributeEndLineUsed;
22
-    private $attributeStartTokenPosUsed;
23
-    private $attributeEndTokenPosUsed;
24
-    private $attributeStartFilePosUsed;
25
-    private $attributeEndFilePosUsed;
26
-    private $attributeCommentsUsed;
27
-
28
-    /**
29
-     * Creates a Lexer.
30
-     *
31
-     * @param array $options Options array. Currently only the 'usedAttributes' option is supported,
32
-     *                       which is an array of attributes to add to the AST nodes. Possible
33
-     *                       attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos',
34
-     *                       'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the
35
-     *                       first three. For more info see getNextToken() docs.
36
-     */
37
-    public function __construct(array $options = []) {
38
-        // Create Map from internal tokens to PhpParser tokens.
39
-        $this->defineCompatibilityTokens();
40
-        $this->tokenMap = $this->createTokenMap();
41
-        $this->identifierTokens = $this->createIdentifierTokenMap();
42
-
43
-        // map of tokens to drop while lexing (the map is only used for isset lookup,
44
-        // that's why the value is simply set to 1; the value is never actually used.)
45
-        $this->dropTokens = array_fill_keys(
46
-            [\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1
47
-        );
48
-
49
-        $defaultAttributes = ['comments', 'startLine', 'endLine'];
50
-        $usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true);
51
-
52
-        // Create individual boolean properties to make these checks faster.
53
-        $this->attributeStartLineUsed = isset($usedAttributes['startLine']);
54
-        $this->attributeEndLineUsed = isset($usedAttributes['endLine']);
55
-        $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
56
-        $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
57
-        $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
58
-        $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
59
-        $this->attributeCommentsUsed = isset($usedAttributes['comments']);
60
-    }
61
-
62
-    /**
63
-     * Initializes the lexer for lexing the provided source code.
64
-     *
65
-     * This function does not throw if lexing errors occur. Instead, errors may be retrieved using
66
-     * the getErrors() method.
67
-     *
68
-     * @param string $code The source code to lex
69
-     * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to
70
-     *                                        ErrorHandler\Throwing
71
-     */
72
-    public function startLexing(string $code, ?ErrorHandler $errorHandler = null) {
73
-        if (null === $errorHandler) {
74
-            $errorHandler = new ErrorHandler\Throwing();
75
-        }
76
-
77
-        $this->code = $code; // keep the code around for __halt_compiler() handling
78
-        $this->pos  = -1;
79
-        $this->line =  1;
80
-        $this->filePos = 0;
81
-
82
-        // If inline HTML occurs without preceding code, treat it as if it had a leading newline.
83
-        // This ensures proper composability, because having a newline is the "safe" assumption.
84
-        $this->prevCloseTagHasNewline = true;
85
-
86
-        $scream = ini_set('xdebug.scream', '0');
87
-
88
-        $this->tokens = @token_get_all($code);
89
-        $this->postprocessTokens($errorHandler);
90
-
91
-        if (false !== $scream) {
92
-            ini_set('xdebug.scream', $scream);
93
-        }
94
-    }
95
-
96
-    private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
97
-        $tokens = [];
98
-        for ($i = $start; $i < $end; $i++) {
99
-            $chr = $this->code[$i];
100
-            if ($chr === "\0") {
101
-                // PHP cuts error message after null byte, so need special case
102
-                $errorMsg = 'Unexpected null byte';
103
-            } else {
104
-                $errorMsg = sprintf(
105
-                    'Unexpected character "%s" (ASCII %d)', $chr, ord($chr)
106
-                );
107
-            }
108
-
109
-            $tokens[] = [\T_BAD_CHARACTER, $chr, $line];
110
-            $errorHandler->handleError(new Error($errorMsg, [
111
-                'startLine' => $line,
112
-                'endLine' => $line,
113
-                'startFilePos' => $i,
114
-                'endFilePos' => $i,
115
-            ]));
116
-        }
117
-        return $tokens;
118
-    }
119
-
120
-    /**
121
-     * Check whether comment token is unterminated.
122
-     *
123
-     * @return bool
124
-     */
125
-    private function isUnterminatedComment($token) : bool {
126
-        return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT)
127
-            && substr($token[1], 0, 2) === '/*'
128
-            && substr($token[1], -2) !== '*/';
129
-    }
130
-
131
-    protected function postprocessTokens(ErrorHandler $errorHandler) {
132
-        // PHP's error handling for token_get_all() is rather bad, so if we want detailed
133
-        // error information we need to compute it ourselves. Invalid character errors are
134
-        // detected by finding "gaps" in the token array. Unterminated comments are detected
135
-        // by checking if a trailing comment has a "*/" at the end.
136
-        //
137
-        // Additionally, we perform a number of canonicalizations here:
138
-        //  * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore.
139
-        //  * Use PHP 8.0 T_NAME_* tokens.
140
-        //  * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and
141
-        //    T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types.
142
-
143
-        $filePos = 0;
144
-        $line = 1;
145
-        $numTokens = \count($this->tokens);
146
-        for ($i = 0; $i < $numTokens; $i++) {
147
-            $token = $this->tokens[$i];
148
-
149
-            // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
150
-            // In this case we only need to emit an error.
151
-            if ($token[0] === \T_BAD_CHARACTER) {
152
-                $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
153
-            }
154
-
155
-            if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*'
156
-                    && preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) {
157
-                $trailingNewline = $matches[0];
158
-                $token[1] = substr($token[1], 0, -strlen($trailingNewline));
159
-                $this->tokens[$i] = $token;
160
-                if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
161
-                    // Move trailing newline into following T_WHITESPACE token, if it already exists.
162
-                    $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
163
-                    $this->tokens[$i + 1][2]--;
164
-                } else {
165
-                    // Otherwise, we need to create a new T_WHITESPACE token.
166
-                    array_splice($this->tokens, $i + 1, 0, [
167
-                        [\T_WHITESPACE, $trailingNewline, $line],
168
-                    ]);
169
-                    $numTokens++;
170
-                }
171
-            }
172
-
173
-            // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
174
-            // into a single token.
175
-            if (\is_array($token)
176
-                    && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) {
177
-                $lastWasSeparator = $token[0] === \T_NS_SEPARATOR;
178
-                $text = $token[1];
179
-                for ($j = $i + 1; isset($this->tokens[$j]); $j++) {
180
-                    if ($lastWasSeparator) {
181
-                        if (!isset($this->identifierTokens[$this->tokens[$j][0]])) {
182
-                            break;
183
-                        }
184
-                        $lastWasSeparator = false;
185
-                    } else {
186
-                        if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) {
187
-                            break;
188
-                        }
189
-                        $lastWasSeparator = true;
190
-                    }
191
-                    $text .= $this->tokens[$j][1];
192
-                }
193
-                if ($lastWasSeparator) {
194
-                    // Trailing separator is not part of the name.
195
-                    $j--;
196
-                    $text = substr($text, 0, -1);
197
-                }
198
-                if ($j > $i + 1) {
199
-                    if ($token[0] === \T_NS_SEPARATOR) {
200
-                        $type = \T_NAME_FULLY_QUALIFIED;
201
-                    } else if ($token[0] === \T_NAMESPACE) {
202
-                        $type = \T_NAME_RELATIVE;
203
-                    } else {
204
-                        $type = \T_NAME_QUALIFIED;
205
-                    }
206
-                    $token = [$type, $text, $line];
207
-                    array_splice($this->tokens, $i, $j - $i, [$token]);
208
-                    $numTokens -= $j - $i - 1;
209
-                }
210
-            }
211
-
212
-            if ($token === '&') {
213
-                $next = $i + 1;
214
-                while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) {
215
-                    $next++;
216
-                }
217
-                $followedByVarOrVarArg = isset($this->tokens[$next]) &&
218
-                    ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS);
219
-                $this->tokens[$i] = $token = [
220
-                    $followedByVarOrVarArg
221
-                        ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
222
-                        : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
223
-                    '&',
224
-                    $line,
225
-                ];
226
-            }
227
-
228
-            $tokenValue = \is_string($token) ? $token : $token[1];
229
-            $tokenLen = \strlen($tokenValue);
230
-
231
-            if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
232
-                // Something is missing, must be an invalid character
233
-                $nextFilePos = strpos($this->code, $tokenValue, $filePos);
234
-                $badCharTokens = $this->handleInvalidCharacterRange(
235
-                    $filePos, $nextFilePos, $line, $errorHandler);
236
-                $filePos = (int) $nextFilePos;
237
-
238
-                array_splice($this->tokens, $i, 0, $badCharTokens);
239
-                $numTokens += \count($badCharTokens);
240
-                $i += \count($badCharTokens);
241
-            }
242
-
243
-            $filePos += $tokenLen;
244
-            $line += substr_count($tokenValue, "\n");
245
-        }
246
-
247
-        if ($filePos !== \strlen($this->code)) {
248
-            if (substr($this->code, $filePos, 2) === '/*') {
249
-                // Unlike PHP, HHVM will drop unterminated comments entirely
250
-                $comment = substr($this->code, $filePos);
251
-                $errorHandler->handleError(new Error('Unterminated comment', [
252
-                    'startLine' => $line,
253
-                    'endLine' => $line + substr_count($comment, "\n"),
254
-                    'startFilePos' => $filePos,
255
-                    'endFilePos' => $filePos + \strlen($comment),
256
-                ]));
257
-
258
-                // Emulate the PHP behavior
259
-                $isDocComment = isset($comment[3]) && $comment[3] === '*';
260
-                $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
261
-            } else {
262
-                // Invalid characters at the end of the input
263
-                $badCharTokens = $this->handleInvalidCharacterRange(
264
-                    $filePos, \strlen($this->code), $line, $errorHandler);
265
-                $this->tokens = array_merge($this->tokens, $badCharTokens);
266
-            }
267
-            return;
268
-        }
269
-
270
-        if (count($this->tokens) > 0) {
271
-            // Check for unterminated comment
272
-            $lastToken = $this->tokens[count($this->tokens) - 1];
273
-            if ($this->isUnterminatedComment($lastToken)) {
274
-                $errorHandler->handleError(new Error('Unterminated comment', [
275
-                    'startLine' => $line - substr_count($lastToken[1], "\n"),
276
-                    'endLine' => $line,
277
-                    'startFilePos' => $filePos - \strlen($lastToken[1]),
278
-                    'endFilePos' => $filePos,
279
-                ]));
280
-            }
281
-        }
282
-    }
283
-
284
-    /**
285
-     * Fetches the next token.
286
-     *
287
-     * The available attributes are determined by the 'usedAttributes' option, which can
288
-     * be specified in the constructor. The following attributes are supported:
289
-     *
290
-     *  * 'comments'      => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
291
-     *                       representing all comments that occurred between the previous
292
-     *                       non-discarded token and the current one.
293
-     *  * 'startLine'     => Line in which the node starts.
294
-     *  * 'endLine'       => Line in which the node ends.
295
-     *  * 'startTokenPos' => Offset into the token array of the first token in the node.
296
-     *  * 'endTokenPos'   => Offset into the token array of the last token in the node.
297
-     *  * 'startFilePos'  => Offset into the code string of the first character that is part of the node.
298
-     *  * 'endFilePos'    => Offset into the code string of the last character that is part of the node.
299
-     *
300
-     * @param mixed $value           Variable to store token content in
301
-     * @param mixed $startAttributes Variable to store start attributes in
302
-     * @param mixed $endAttributes   Variable to store end attributes in
303
-     *
304
-     * @return int Token id
305
-     */
306
-    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int {
307
-        $startAttributes = [];
308
-        $endAttributes   = [];
309
-
310
-        while (1) {
311
-            if (isset($this->tokens[++$this->pos])) {
312
-                $token = $this->tokens[$this->pos];
313
-            } else {
314
-                // EOF token with ID 0
315
-                $token = "\0";
316
-            }
317
-
318
-            if ($this->attributeStartLineUsed) {
319
-                $startAttributes['startLine'] = $this->line;
320
-            }
321
-            if ($this->attributeStartTokenPosUsed) {
322
-                $startAttributes['startTokenPos'] = $this->pos;
323
-            }
324
-            if ($this->attributeStartFilePosUsed) {
325
-                $startAttributes['startFilePos'] = $this->filePos;
326
-            }
327
-
328
-            if (\is_string($token)) {
329
-                $value = $token;
330
-                if (isset($token[1])) {
331
-                    // bug in token_get_all
332
-                    $this->filePos += 2;
333
-                    $id = ord('"');
334
-                } else {
335
-                    $this->filePos += 1;
336
-                    $id = ord($token);
337
-                }
338
-            } elseif (!isset($this->dropTokens[$token[0]])) {
339
-                $value = $token[1];
340
-                $id = $this->tokenMap[$token[0]];
341
-                if (\T_CLOSE_TAG === $token[0]) {
342
-                    $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n")
343
-                        || false !== strpos($token[1], "\r");
344
-                } elseif (\T_INLINE_HTML === $token[0]) {
345
-                    $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline;
346
-                }
347
-
348
-                $this->line += substr_count($value, "\n");
349
-                $this->filePos += \strlen($value);
350
-            } else {
351
-                $origLine = $this->line;
352
-                $origFilePos = $this->filePos;
353
-                $this->line += substr_count($token[1], "\n");
354
-                $this->filePos += \strlen($token[1]);
355
-
356
-                if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
357
-                    if ($this->attributeCommentsUsed) {
358
-                        $comment = \T_DOC_COMMENT === $token[0]
359
-                            ? new Comment\Doc($token[1],
360
-                                $origLine, $origFilePos, $this->pos,
361
-                                $this->line, $this->filePos - 1, $this->pos)
362
-                            : new Comment($token[1],
363
-                                $origLine, $origFilePos, $this->pos,
364
-                                $this->line, $this->filePos - 1, $this->pos);
365
-                        $startAttributes['comments'][] = $comment;
366
-                    }
367
-                }
368
-                continue;
369
-            }
370
-
371
-            if ($this->attributeEndLineUsed) {
372
-                $endAttributes['endLine'] = $this->line;
373
-            }
374
-            if ($this->attributeEndTokenPosUsed) {
375
-                $endAttributes['endTokenPos'] = $this->pos;
376
-            }
377
-            if ($this->attributeEndFilePosUsed) {
378
-                $endAttributes['endFilePos'] = $this->filePos - 1;
379
-            }
380
-
381
-            return $id;
382
-        }
383
-
384
-        throw new \RuntimeException('Reached end of lexer loop');
385
-    }
386
-
387
-    /**
388
-     * Returns the token array for current code.
389
-     *
390
-     * The token array is in the same format as provided by the
391
-     * token_get_all() function and does not discard tokens (i.e.
392
-     * whitespace and comments are included). The token position
393
-     * attributes are against this token array.
394
-     *
395
-     * @return array Array of tokens in token_get_all() format
396
-     */
397
-    public function getTokens() : array {
398
-        return $this->tokens;
399
-    }
400
-
401
-    /**
402
-     * Handles __halt_compiler() by returning the text after it.
403
-     *
404
-     * @return string Remaining text
405
-     */
406
-    public function handleHaltCompiler() : string {
407
-        // text after T_HALT_COMPILER, still including ();
408
-        $textAfter = substr($this->code, $this->filePos);
409
-
410
-        // ensure that it is followed by ();
411
-        // this simplifies the situation, by not allowing any comments
412
-        // in between of the tokens.
413
-        if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
414
-            throw new Error('__HALT_COMPILER must be followed by "();"');
415
-        }
416
-
417
-        // prevent the lexer from returning any further tokens
418
-        $this->pos = count($this->tokens);
419
-
420
-        // return with (); removed
421
-        return substr($textAfter, strlen($matches[0]));
422
-    }
423
-
424
-    private function defineCompatibilityTokens() {
425
-        static $compatTokensDefined = false;
426
-        if ($compatTokensDefined) {
427
-            return;
428
-        }
429
-
430
-        $compatTokens = [
431
-            // PHP 7.4
432
-            'T_BAD_CHARACTER',
433
-            'T_FN',
434
-            'T_COALESCE_EQUAL',
435
-            // PHP 8.0
436
-            'T_NAME_QUALIFIED',
437
-            'T_NAME_FULLY_QUALIFIED',
438
-            'T_NAME_RELATIVE',
439
-            'T_MATCH',
440
-            'T_NULLSAFE_OBJECT_OPERATOR',
441
-            'T_ATTRIBUTE',
442
-            // PHP 8.1
443
-            'T_ENUM',
444
-            'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
445
-            'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
446
-            'T_READONLY',
447
-        ];
448
-
449
-        // PHP-Parser might be used together with another library that also emulates some or all
450
-        // of these tokens. Perform a sanity-check that all already defined tokens have been
451
-        // assigned a unique ID.
452
-        $usedTokenIds = [];
453
-        foreach ($compatTokens as $token) {
454
-            if (\defined($token)) {
455
-                $tokenId = \constant($token);
456
-                $clashingToken = $usedTokenIds[$tokenId] ?? null;
457
-                if ($clashingToken !== null) {
458
-                    throw new \Error(sprintf(
459
-                        'Token %s has same ID as token %s, ' .
460
-                        'you may be using a library with broken token emulation',
461
-                        $token, $clashingToken
462
-                    ));
463
-                }
464
-                $usedTokenIds[$tokenId] = $token;
465
-            }
466
-        }
467
-
468
-        // Now define any tokens that have not yet been emulated. Try to assign IDs from -1
469
-        // downwards, but skip any IDs that may already be in use.
470
-        $newTokenId = -1;
471
-        foreach ($compatTokens as $token) {
472
-            if (!\defined($token)) {
473
-                while (isset($usedTokenIds[$newTokenId])) {
474
-                    $newTokenId--;
475
-                }
476
-                \define($token, $newTokenId);
477
-                $newTokenId--;
478
-            }
479
-        }
480
-
481
-        $compatTokensDefined = true;
482
-    }
483
-
484
-    /**
485
-     * Creates the token map.
486
-     *
487
-     * The token map maps the PHP internal token identifiers
488
-     * to the identifiers used by the Parser. Additionally it
489
-     * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
490
-     *
491
-     * @return array The token map
492
-     */
493
-    protected function createTokenMap() : array {
494
-        $tokenMap = [];
495
-
496
-        // 256 is the minimum possible token number, as everything below
497
-        // it is an ASCII value
498
-        for ($i = 256; $i < 1000; ++$i) {
499
-            if (\T_DOUBLE_COLON === $i) {
500
-                // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
501
-                $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
502
-            } elseif(\T_OPEN_TAG_WITH_ECHO === $i) {
503
-                // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
504
-                $tokenMap[$i] = Tokens::T_ECHO;
505
-            } elseif(\T_CLOSE_TAG === $i) {
506
-                // T_CLOSE_TAG is equivalent to ';'
507
-                $tokenMap[$i] = ord(';');
508
-            } elseif ('UNKNOWN' !== $name = token_name($i)) {
509
-                if ('T_HASHBANG' === $name) {
510
-                    // HHVM uses a special token for #! hashbang lines
511
-                    $tokenMap[$i] = Tokens::T_INLINE_HTML;
512
-                } elseif (defined($name = Tokens::class . '::' . $name)) {
513
-                    // Other tokens can be mapped directly
514
-                    $tokenMap[$i] = constant($name);
515
-                }
516
-            }
517
-        }
518
-
519
-        // HHVM uses a special token for numbers that overflow to double
520
-        if (defined('T_ONUMBER')) {
521
-            $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER;
522
-        }
523
-        // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
524
-        if (defined('T_COMPILER_HALT_OFFSET')) {
525
-            $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
526
-        }
527
-
528
-        // Assign tokens for which we define compatibility constants, as token_name() does not know them.
529
-        $tokenMap[\T_FN] = Tokens::T_FN;
530
-        $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
531
-        $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED;
532
-        $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
533
-        $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
534
-        $tokenMap[\T_MATCH] = Tokens::T_MATCH;
535
-        $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
536
-        $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE;
537
-        $tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
538
-        $tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG;
539
-        $tokenMap[\T_ENUM] = Tokens::T_ENUM;
540
-        $tokenMap[\T_READONLY] = Tokens::T_READONLY;
541
-
542
-        return $tokenMap;
543
-    }
544
-
545
-    private function createIdentifierTokenMap(): array {
546
-        // Based on semi_reserved production.
547
-        return array_fill_keys([
548
-            \T_STRING,
549
-            \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY,
550
-            \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
551
-            \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
552
-            \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
553
-            \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
554
-            \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
555
-            \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
556
-            \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
557
-            \T_MATCH,
558
-        ], true);
559
-    }
9
+	protected $code;
10
+	protected $tokens;
11
+	protected $pos;
12
+	protected $line;
13
+	protected $filePos;
14
+	protected $prevCloseTagHasNewline;
15
+
16
+	protected $tokenMap;
17
+	protected $dropTokens;
18
+	protected $identifierTokens;
19
+
20
+	private $attributeStartLineUsed;
21
+	private $attributeEndLineUsed;
22
+	private $attributeStartTokenPosUsed;
23
+	private $attributeEndTokenPosUsed;
24
+	private $attributeStartFilePosUsed;
25
+	private $attributeEndFilePosUsed;
26
+	private $attributeCommentsUsed;
27
+
28
+	/**
29
+	 * Creates a Lexer.
30
+	 *
31
+	 * @param array $options Options array. Currently only the 'usedAttributes' option is supported,
32
+	 *                       which is an array of attributes to add to the AST nodes. Possible
33
+	 *                       attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos',
34
+	 *                       'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the
35
+	 *                       first three. For more info see getNextToken() docs.
36
+	 */
37
+	public function __construct(array $options = []) {
38
+		// Create Map from internal tokens to PhpParser tokens.
39
+		$this->defineCompatibilityTokens();
40
+		$this->tokenMap = $this->createTokenMap();
41
+		$this->identifierTokens = $this->createIdentifierTokenMap();
42
+
43
+		// map of tokens to drop while lexing (the map is only used for isset lookup,
44
+		// that's why the value is simply set to 1; the value is never actually used.)
45
+		$this->dropTokens = array_fill_keys(
46
+			[\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1
47
+		);
48
+
49
+		$defaultAttributes = ['comments', 'startLine', 'endLine'];
50
+		$usedAttributes = array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, true);
51
+
52
+		// Create individual boolean properties to make these checks faster.
53
+		$this->attributeStartLineUsed = isset($usedAttributes['startLine']);
54
+		$this->attributeEndLineUsed = isset($usedAttributes['endLine']);
55
+		$this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
56
+		$this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
57
+		$this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
58
+		$this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
59
+		$this->attributeCommentsUsed = isset($usedAttributes['comments']);
60
+	}
61
+
62
+	/**
63
+	 * Initializes the lexer for lexing the provided source code.
64
+	 *
65
+	 * This function does not throw if lexing errors occur. Instead, errors may be retrieved using
66
+	 * the getErrors() method.
67
+	 *
68
+	 * @param string $code The source code to lex
69
+	 * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to
70
+	 *                                        ErrorHandler\Throwing
71
+	 */
72
+	public function startLexing(string $code, ?ErrorHandler $errorHandler = null) {
73
+		if (null === $errorHandler) {
74
+			$errorHandler = new ErrorHandler\Throwing();
75
+		}
76
+
77
+		$this->code = $code; // keep the code around for __halt_compiler() handling
78
+		$this->pos  = -1;
79
+		$this->line =  1;
80
+		$this->filePos = 0;
81
+
82
+		// If inline HTML occurs without preceding code, treat it as if it had a leading newline.
83
+		// This ensures proper composability, because having a newline is the "safe" assumption.
84
+		$this->prevCloseTagHasNewline = true;
85
+
86
+		$scream = ini_set('xdebug.scream', '0');
87
+
88
+		$this->tokens = @token_get_all($code);
89
+		$this->postprocessTokens($errorHandler);
90
+
91
+		if (false !== $scream) {
92
+			ini_set('xdebug.scream', $scream);
93
+		}
94
+	}
95
+
96
+	private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) {
97
+		$tokens = [];
98
+		for ($i = $start; $i < $end; $i++) {
99
+			$chr = $this->code[$i];
100
+			if ($chr === "\0") {
101
+				// PHP cuts error message after null byte, so need special case
102
+				$errorMsg = 'Unexpected null byte';
103
+			} else {
104
+				$errorMsg = sprintf(
105
+					'Unexpected character "%s" (ASCII %d)', $chr, ord($chr)
106
+				);
107
+			}
108
+
109
+			$tokens[] = [\T_BAD_CHARACTER, $chr, $line];
110
+			$errorHandler->handleError(new Error($errorMsg, [
111
+				'startLine' => $line,
112
+				'endLine' => $line,
113
+				'startFilePos' => $i,
114
+				'endFilePos' => $i,
115
+			]));
116
+		}
117
+		return $tokens;
118
+	}
119
+
120
+	/**
121
+	 * Check whether comment token is unterminated.
122
+	 *
123
+	 * @return bool
124
+	 */
125
+	private function isUnterminatedComment($token) : bool {
126
+		return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT)
127
+			&& substr($token[1], 0, 2) === '/*'
128
+			&& substr($token[1], -2) !== '*/';
129
+	}
130
+
131
+	protected function postprocessTokens(ErrorHandler $errorHandler) {
132
+		// PHP's error handling for token_get_all() is rather bad, so if we want detailed
133
+		// error information we need to compute it ourselves. Invalid character errors are
134
+		// detected by finding "gaps" in the token array. Unterminated comments are detected
135
+		// by checking if a trailing comment has a "*/" at the end.
136
+		//
137
+		// Additionally, we perform a number of canonicalizations here:
138
+		//  * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore.
139
+		//  * Use PHP 8.0 T_NAME_* tokens.
140
+		//  * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and
141
+		//    T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types.
142
+
143
+		$filePos = 0;
144
+		$line = 1;
145
+		$numTokens = \count($this->tokens);
146
+		for ($i = 0; $i < $numTokens; $i++) {
147
+			$token = $this->tokens[$i];
148
+
149
+			// Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
150
+			// In this case we only need to emit an error.
151
+			if ($token[0] === \T_BAD_CHARACTER) {
152
+				$this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
153
+			}
154
+
155
+			if ($token[0] === \T_COMMENT && substr($token[1], 0, 2) !== '/*'
156
+					&& preg_match('/(\r\n|\n|\r)$/D', $token[1], $matches)) {
157
+				$trailingNewline = $matches[0];
158
+				$token[1] = substr($token[1], 0, -strlen($trailingNewline));
159
+				$this->tokens[$i] = $token;
160
+				if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
161
+					// Move trailing newline into following T_WHITESPACE token, if it already exists.
162
+					$this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
163
+					$this->tokens[$i + 1][2]--;
164
+				} else {
165
+					// Otherwise, we need to create a new T_WHITESPACE token.
166
+					array_splice($this->tokens, $i + 1, 0, [
167
+						[\T_WHITESPACE, $trailingNewline, $line],
168
+					]);
169
+					$numTokens++;
170
+				}
171
+			}
172
+
173
+			// Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
174
+			// into a single token.
175
+			if (\is_array($token)
176
+					&& ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) {
177
+				$lastWasSeparator = $token[0] === \T_NS_SEPARATOR;
178
+				$text = $token[1];
179
+				for ($j = $i + 1; isset($this->tokens[$j]); $j++) {
180
+					if ($lastWasSeparator) {
181
+						if (!isset($this->identifierTokens[$this->tokens[$j][0]])) {
182
+							break;
183
+						}
184
+						$lastWasSeparator = false;
185
+					} else {
186
+						if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) {
187
+							break;
188
+						}
189
+						$lastWasSeparator = true;
190
+					}
191
+					$text .= $this->tokens[$j][1];
192
+				}
193
+				if ($lastWasSeparator) {
194
+					// Trailing separator is not part of the name.
195
+					$j--;
196
+					$text = substr($text, 0, -1);
197
+				}
198
+				if ($j > $i + 1) {
199
+					if ($token[0] === \T_NS_SEPARATOR) {
200
+						$type = \T_NAME_FULLY_QUALIFIED;
201
+					} else if ($token[0] === \T_NAMESPACE) {
202
+						$type = \T_NAME_RELATIVE;
203
+					} else {
204
+						$type = \T_NAME_QUALIFIED;
205
+					}
206
+					$token = [$type, $text, $line];
207
+					array_splice($this->tokens, $i, $j - $i, [$token]);
208
+					$numTokens -= $j - $i - 1;
209
+				}
210
+			}
211
+
212
+			if ($token === '&') {
213
+				$next = $i + 1;
214
+				while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) {
215
+					$next++;
216
+				}
217
+				$followedByVarOrVarArg = isset($this->tokens[$next]) &&
218
+					($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS);
219
+				$this->tokens[$i] = $token = [
220
+					$followedByVarOrVarArg
221
+						? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
222
+						: \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG,
223
+					'&',
224
+					$line,
225
+				];
226
+			}
227
+
228
+			$tokenValue = \is_string($token) ? $token : $token[1];
229
+			$tokenLen = \strlen($tokenValue);
230
+
231
+			if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
232
+				// Something is missing, must be an invalid character
233
+				$nextFilePos = strpos($this->code, $tokenValue, $filePos);
234
+				$badCharTokens = $this->handleInvalidCharacterRange(
235
+					$filePos, $nextFilePos, $line, $errorHandler);
236
+				$filePos = (int) $nextFilePos;
237
+
238
+				array_splice($this->tokens, $i, 0, $badCharTokens);
239
+				$numTokens += \count($badCharTokens);
240
+				$i += \count($badCharTokens);
241
+			}
242
+
243
+			$filePos += $tokenLen;
244
+			$line += substr_count($tokenValue, "\n");
245
+		}
246
+
247
+		if ($filePos !== \strlen($this->code)) {
248
+			if (substr($this->code, $filePos, 2) === '/*') {
249
+				// Unlike PHP, HHVM will drop unterminated comments entirely
250
+				$comment = substr($this->code, $filePos);
251
+				$errorHandler->handleError(new Error('Unterminated comment', [
252
+					'startLine' => $line,
253
+					'endLine' => $line + substr_count($comment, "\n"),
254
+					'startFilePos' => $filePos,
255
+					'endFilePos' => $filePos + \strlen($comment),
256
+				]));
257
+
258
+				// Emulate the PHP behavior
259
+				$isDocComment = isset($comment[3]) && $comment[3] === '*';
260
+				$this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
261
+			} else {
262
+				// Invalid characters at the end of the input
263
+				$badCharTokens = $this->handleInvalidCharacterRange(
264
+					$filePos, \strlen($this->code), $line, $errorHandler);
265
+				$this->tokens = array_merge($this->tokens, $badCharTokens);
266
+			}
267
+			return;
268
+		}
269
+
270
+		if (count($this->tokens) > 0) {
271
+			// Check for unterminated comment
272
+			$lastToken = $this->tokens[count($this->tokens) - 1];
273
+			if ($this->isUnterminatedComment($lastToken)) {
274
+				$errorHandler->handleError(new Error('Unterminated comment', [
275
+					'startLine' => $line - substr_count($lastToken[1], "\n"),
276
+					'endLine' => $line,
277
+					'startFilePos' => $filePos - \strlen($lastToken[1]),
278
+					'endFilePos' => $filePos,
279
+				]));
280
+			}
281
+		}
282
+	}
283
+
284
+	/**
285
+	 * Fetches the next token.
286
+	 *
287
+	 * The available attributes are determined by the 'usedAttributes' option, which can
288
+	 * be specified in the constructor. The following attributes are supported:
289
+	 *
290
+	 *  * 'comments'      => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
291
+	 *                       representing all comments that occurred between the previous
292
+	 *                       non-discarded token and the current one.
293
+	 *  * 'startLine'     => Line in which the node starts.
294
+	 *  * 'endLine'       => Line in which the node ends.
295
+	 *  * 'startTokenPos' => Offset into the token array of the first token in the node.
296
+	 *  * 'endTokenPos'   => Offset into the token array of the last token in the node.
297
+	 *  * 'startFilePos'  => Offset into the code string of the first character that is part of the node.
298
+	 *  * 'endFilePos'    => Offset into the code string of the last character that is part of the node.
299
+	 *
300
+	 * @param mixed $value           Variable to store token content in
301
+	 * @param mixed $startAttributes Variable to store start attributes in
302
+	 * @param mixed $endAttributes   Variable to store end attributes in
303
+	 *
304
+	 * @return int Token id
305
+	 */
306
+	public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int {
307
+		$startAttributes = [];
308
+		$endAttributes   = [];
309
+
310
+		while (1) {
311
+			if (isset($this->tokens[++$this->pos])) {
312
+				$token = $this->tokens[$this->pos];
313
+			} else {
314
+				// EOF token with ID 0
315
+				$token = "\0";
316
+			}
317
+
318
+			if ($this->attributeStartLineUsed) {
319
+				$startAttributes['startLine'] = $this->line;
320
+			}
321
+			if ($this->attributeStartTokenPosUsed) {
322
+				$startAttributes['startTokenPos'] = $this->pos;
323
+			}
324
+			if ($this->attributeStartFilePosUsed) {
325
+				$startAttributes['startFilePos'] = $this->filePos;
326
+			}
327
+
328
+			if (\is_string($token)) {
329
+				$value = $token;
330
+				if (isset($token[1])) {
331
+					// bug in token_get_all
332
+					$this->filePos += 2;
333
+					$id = ord('"');
334
+				} else {
335
+					$this->filePos += 1;
336
+					$id = ord($token);
337
+				}
338
+			} elseif (!isset($this->dropTokens[$token[0]])) {
339
+				$value = $token[1];
340
+				$id = $this->tokenMap[$token[0]];
341
+				if (\T_CLOSE_TAG === $token[0]) {
342
+					$this->prevCloseTagHasNewline = false !== strpos($token[1], "\n")
343
+						|| false !== strpos($token[1], "\r");
344
+				} elseif (\T_INLINE_HTML === $token[0]) {
345
+					$startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline;
346
+				}
347
+
348
+				$this->line += substr_count($value, "\n");
349
+				$this->filePos += \strlen($value);
350
+			} else {
351
+				$origLine = $this->line;
352
+				$origFilePos = $this->filePos;
353
+				$this->line += substr_count($token[1], "\n");
354
+				$this->filePos += \strlen($token[1]);
355
+
356
+				if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
357
+					if ($this->attributeCommentsUsed) {
358
+						$comment = \T_DOC_COMMENT === $token[0]
359
+							? new Comment\Doc($token[1],
360
+								$origLine, $origFilePos, $this->pos,
361
+								$this->line, $this->filePos - 1, $this->pos)
362
+							: new Comment($token[1],
363
+								$origLine, $origFilePos, $this->pos,
364
+								$this->line, $this->filePos - 1, $this->pos);
365
+						$startAttributes['comments'][] = $comment;
366
+					}
367
+				}
368
+				continue;
369
+			}
370
+
371
+			if ($this->attributeEndLineUsed) {
372
+				$endAttributes['endLine'] = $this->line;
373
+			}
374
+			if ($this->attributeEndTokenPosUsed) {
375
+				$endAttributes['endTokenPos'] = $this->pos;
376
+			}
377
+			if ($this->attributeEndFilePosUsed) {
378
+				$endAttributes['endFilePos'] = $this->filePos - 1;
379
+			}
380
+
381
+			return $id;
382
+		}
383
+
384
+		throw new \RuntimeException('Reached end of lexer loop');
385
+	}
386
+
387
+	/**
388
+	 * Returns the token array for current code.
389
+	 *
390
+	 * The token array is in the same format as provided by the
391
+	 * token_get_all() function and does not discard tokens (i.e.
392
+	 * whitespace and comments are included). The token position
393
+	 * attributes are against this token array.
394
+	 *
395
+	 * @return array Array of tokens in token_get_all() format
396
+	 */
397
+	public function getTokens() : array {
398
+		return $this->tokens;
399
+	}
400
+
401
+	/**
402
+	 * Handles __halt_compiler() by returning the text after it.
403
+	 *
404
+	 * @return string Remaining text
405
+	 */
406
+	public function handleHaltCompiler() : string {
407
+		// text after T_HALT_COMPILER, still including ();
408
+		$textAfter = substr($this->code, $this->filePos);
409
+
410
+		// ensure that it is followed by ();
411
+		// this simplifies the situation, by not allowing any comments
412
+		// in between of the tokens.
413
+		if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) {
414
+			throw new Error('__HALT_COMPILER must be followed by "();"');
415
+		}
416
+
417
+		// prevent the lexer from returning any further tokens
418
+		$this->pos = count($this->tokens);
419
+
420
+		// return with (); removed
421
+		return substr($textAfter, strlen($matches[0]));
422
+	}
423
+
424
+	private function defineCompatibilityTokens() {
425
+		static $compatTokensDefined = false;
426
+		if ($compatTokensDefined) {
427
+			return;
428
+		}
429
+
430
+		$compatTokens = [
431
+			// PHP 7.4
432
+			'T_BAD_CHARACTER',
433
+			'T_FN',
434
+			'T_COALESCE_EQUAL',
435
+			// PHP 8.0
436
+			'T_NAME_QUALIFIED',
437
+			'T_NAME_FULLY_QUALIFIED',
438
+			'T_NAME_RELATIVE',
439
+			'T_MATCH',
440
+			'T_NULLSAFE_OBJECT_OPERATOR',
441
+			'T_ATTRIBUTE',
442
+			// PHP 8.1
443
+			'T_ENUM',
444
+			'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
445
+			'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
446
+			'T_READONLY',
447
+		];
448
+
449
+		// PHP-Parser might be used together with another library that also emulates some or all
450
+		// of these tokens. Perform a sanity-check that all already defined tokens have been
451
+		// assigned a unique ID.
452
+		$usedTokenIds = [];
453
+		foreach ($compatTokens as $token) {
454
+			if (\defined($token)) {
455
+				$tokenId = \constant($token);
456
+				$clashingToken = $usedTokenIds[$tokenId] ?? null;
457
+				if ($clashingToken !== null) {
458
+					throw new \Error(sprintf(
459
+						'Token %s has same ID as token %s, ' .
460
+						'you may be using a library with broken token emulation',
461
+						$token, $clashingToken
462
+					));
463
+				}
464
+				$usedTokenIds[$tokenId] = $token;
465
+			}
466
+		}
467
+
468
+		// Now define any tokens that have not yet been emulated. Try to assign IDs from -1
469
+		// downwards, but skip any IDs that may already be in use.
470
+		$newTokenId = -1;
471
+		foreach ($compatTokens as $token) {
472
+			if (!\defined($token)) {
473
+				while (isset($usedTokenIds[$newTokenId])) {
474
+					$newTokenId--;
475
+				}
476
+				\define($token, $newTokenId);
477
+				$newTokenId--;
478
+			}
479
+		}
480
+
481
+		$compatTokensDefined = true;
482
+	}
483
+
484
+	/**
485
+	 * Creates the token map.
486
+	 *
487
+	 * The token map maps the PHP internal token identifiers
488
+	 * to the identifiers used by the Parser. Additionally it
489
+	 * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
490
+	 *
491
+	 * @return array The token map
492
+	 */
493
+	protected function createTokenMap() : array {
494
+		$tokenMap = [];
495
+
496
+		// 256 is the minimum possible token number, as everything below
497
+		// it is an ASCII value
498
+		for ($i = 256; $i < 1000; ++$i) {
499
+			if (\T_DOUBLE_COLON === $i) {
500
+				// T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
501
+				$tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
502
+			} elseif(\T_OPEN_TAG_WITH_ECHO === $i) {
503
+				// T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
504
+				$tokenMap[$i] = Tokens::T_ECHO;
505
+			} elseif(\T_CLOSE_TAG === $i) {
506
+				// T_CLOSE_TAG is equivalent to ';'
507
+				$tokenMap[$i] = ord(';');
508
+			} elseif ('UNKNOWN' !== $name = token_name($i)) {
509
+				if ('T_HASHBANG' === $name) {
510
+					// HHVM uses a special token for #! hashbang lines
511
+					$tokenMap[$i] = Tokens::T_INLINE_HTML;
512
+				} elseif (defined($name = Tokens::class . '::' . $name)) {
513
+					// Other tokens can be mapped directly
514
+					$tokenMap[$i] = constant($name);
515
+				}
516
+			}
517
+		}
518
+
519
+		// HHVM uses a special token for numbers that overflow to double
520
+		if (defined('T_ONUMBER')) {
521
+			$tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER;
522
+		}
523
+		// HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
524
+		if (defined('T_COMPILER_HALT_OFFSET')) {
525
+			$tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
526
+		}
527
+
528
+		// Assign tokens for which we define compatibility constants, as token_name() does not know them.
529
+		$tokenMap[\T_FN] = Tokens::T_FN;
530
+		$tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
531
+		$tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED;
532
+		$tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
533
+		$tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
534
+		$tokenMap[\T_MATCH] = Tokens::T_MATCH;
535
+		$tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
536
+		$tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE;
537
+		$tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
538
+		$tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG;
539
+		$tokenMap[\T_ENUM] = Tokens::T_ENUM;
540
+		$tokenMap[\T_READONLY] = Tokens::T_READONLY;
541
+
542
+		return $tokenMap;
543
+	}
544
+
545
+	private function createIdentifierTokenMap(): array {
546
+		// Based on semi_reserved production.
547
+		return array_fill_keys([
548
+			\T_STRING,
549
+			\T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY,
550
+			\T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
551
+			\T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
552
+			\T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
553
+			\T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
554
+			\T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
555
+			\T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
556
+			\T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
557
+			\T_MATCH,
558
+		], true);
559
+	}
560 560
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -76,7 +76,7 @@  discard block
 block discarded – undo
76 76
 
77 77
         $this->code = $code; // keep the code around for __halt_compiler() handling
78 78
         $this->pos  = -1;
79
-        $this->line =  1;
79
+        $this->line = 1;
80 80
         $this->filePos = 0;
81 81
 
82 82
         // If inline HTML occurs without preceding code, treat it as if it had a leading newline.
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
                 $this->tokens[$i] = $token;
160 160
                 if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
161 161
                     // Move trailing newline into following T_WHITESPACE token, if it already exists.
162
-                    $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
162
+                    $this->tokens[$i + 1][1] = $trailingNewline.$this->tokens[$i + 1][1];
163 163
                     $this->tokens[$i + 1][2]--;
164 164
                 } else {
165 165
                     // Otherwise, we need to create a new T_WHITESPACE token.
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
                 $nextFilePos = strpos($this->code, $tokenValue, $filePos);
234 234
                 $badCharTokens = $this->handleInvalidCharacterRange(
235 235
                     $filePos, $nextFilePos, $line, $errorHandler);
236
-                $filePos = (int) $nextFilePos;
236
+                $filePos = (int)$nextFilePos;
237 237
 
238 238
                 array_splice($this->tokens, $i, 0, $badCharTokens);
239 239
                 $numTokens += \count($badCharTokens);
@@ -456,7 +456,7 @@  discard block
 block discarded – undo
456 456
                 $clashingToken = $usedTokenIds[$tokenId] ?? null;
457 457
                 if ($clashingToken !== null) {
458 458
                     throw new \Error(sprintf(
459
-                        'Token %s has same ID as token %s, ' .
459
+                        'Token %s has same ID as token %s, '.
460 460
                         'you may be using a library with broken token emulation',
461 461
                         $token, $clashingToken
462 462
                     ));
@@ -499,17 +499,17 @@  discard block
 block discarded – undo
499 499
             if (\T_DOUBLE_COLON === $i) {
500 500
                 // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
501 501
                 $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
502
-            } elseif(\T_OPEN_TAG_WITH_ECHO === $i) {
502
+            } elseif (\T_OPEN_TAG_WITH_ECHO === $i) {
503 503
                 // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
504 504
                 $tokenMap[$i] = Tokens::T_ECHO;
505
-            } elseif(\T_CLOSE_TAG === $i) {
505
+            } elseif (\T_CLOSE_TAG === $i) {
506 506
                 // T_CLOSE_TAG is equivalent to ';'
507 507
                 $tokenMap[$i] = ord(';');
508 508
             } elseif ('UNKNOWN' !== $name = token_name($i)) {
509 509
                 if ('T_HASHBANG' === $name) {
510 510
                     // HHVM uses a special token for #! hashbang lines
511 511
                     $tokenMap[$i] = Tokens::T_INLINE_HTML;
512
-                } elseif (defined($name = Tokens::class . '::' . $name)) {
512
+                } elseif (defined($name = Tokens::class.'::'.$name)) {
513 513
                     // Other tokens can be mapped directly
514 514
                     $tokenMap[$i] = constant($name);
515 515
                 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -4,8 +4,7 @@
 block discarded – undo
4 4
 
5 5
 use PhpParser\Parser\Tokens;
6 6
 
7
-class Lexer
8
-{
7
+class Lexer {
9 8
     protected $code;
10 9
     protected $tokens;
11 10
     protected $pos;
Please login to merge, or discard this patch.