mirror of
https://github.com/standardebooks/web.git
synced 2025-07-16 11:26:37 -04:00
Add Composer autoloading functions and PHPStan for testing
This commit is contained in:
parent
e198c4db65
commit
f5d7d4e02a
1518 changed files with 169063 additions and 30 deletions
25
vendor/phpstan/phpdoc-parser/build-abnfgen.sh
vendored
Executable file
25
vendor/phpstan/phpdoc-parser/build-abnfgen.sh
vendored
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
ROOT_DIR="$DIR"
|
||||
|
||||
if [[ ! -d "$ROOT_DIR/tools/abnfgen" ]]; then
|
||||
rm -rf "$ROOT_DIR/temp/abnfgen"
|
||||
mkdir -p "$ROOT_DIR/temp/abnfgen"
|
||||
|
||||
wget http://www.quut.com/abnfgen/abnfgen-0.20.tar.gz \
|
||||
--output-document "$ROOT_DIR/temp/abnfgen.tar.gz"
|
||||
|
||||
tar xf "$ROOT_DIR/temp/abnfgen.tar.gz" \
|
||||
--directory "$ROOT_DIR/temp/abnfgen" \
|
||||
--strip-components 1
|
||||
|
||||
cd "$ROOT_DIR/temp/abnfgen"
|
||||
./configure
|
||||
make
|
||||
|
||||
mkdir -p "$ROOT_DIR/tools/abnfgen"
|
||||
mv abnfgen "$ROOT_DIR/tools/abnfgen"
|
||||
rm -rf "$ROOT_DIR/temp/abnfgen" "$ROOT_DIR/temp/abnfgen.tar.gz"
|
||||
fi
|
28
vendor/phpstan/phpdoc-parser/composer.json
vendored
Normal file
28
vendor/phpstan/phpdoc-parser/composer.json
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "phpstan/phpdoc-parser",
|
||||
"description": "PHPDoc parser with support for nullable, intersection and generic types",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "~7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"consistence/coding-standard": "^2.0.0",
|
||||
"jakub-onderka/php-parallel-lint": "^0.9.2",
|
||||
"phing/phing": "^2.16.0",
|
||||
"phpstan/phpstan": "^0.10",
|
||||
"phpunit/phpunit": "^6.3",
|
||||
"slevomat/coding-standard": "^3.3.0",
|
||||
"symfony/process": "^3.4 || ^4.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {"PHPStan\\PhpDocParser\\": ["src/"]}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {"PHPStan\\PhpDocParser\\": ["tests/PHPStan"]}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.3-dev"
|
||||
}
|
||||
}
|
||||
}
|
41
vendor/phpstan/phpdoc-parser/doc/grammars/phpdoc-method.peg
vendored
Normal file
41
vendor/phpstan/phpdoc-parser/doc/grammars/phpdoc-method.peg
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
PhpDocMethod
|
||||
= AnnotationName IsStatic? MethodReturnType? MethodName MethodParameters? Description?
|
||||
|
||||
AnnotationName
|
||||
= '@method'
|
||||
|
||||
IsStatic
|
||||
= 'static'
|
||||
|
||||
MethodReturnType
|
||||
= Type
|
||||
|
||||
MethodName
|
||||
= [a-zA-Z_\127-\255][a-zA-Z0-9_\127-\255]*
|
||||
|
||||
MethodParameters
|
||||
= '(' MethodParametersInner? ')'
|
||||
|
||||
MethodParametersInner
|
||||
= MethodParameter (',' MethodParameter)*
|
||||
|
||||
MethodParameter
|
||||
= MethodParameterType? IsReference? IsVariaric? MethodParameterName MethodParameterDefaultValue?
|
||||
|
||||
MethodParameterType
|
||||
= Type
|
||||
|
||||
IsReference
|
||||
= '&'
|
||||
|
||||
IsVariaric
|
||||
= '...'
|
||||
|
||||
MethodParameterName
|
||||
= '$' [a-zA-Z_\127-\255][a-zA-Z0-9_\127-\255]*
|
||||
|
||||
MethodParameterDefaultValue
|
||||
= '=' PhpConstantExpr
|
||||
|
||||
Description
|
||||
= .+ # TODO: exclude EOL or another PhpDocTag start
|
14
vendor/phpstan/phpdoc-parser/doc/grammars/phpdoc-param.peg
vendored
Normal file
14
vendor/phpstan/phpdoc-parser/doc/grammars/phpdoc-param.peg
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
PhpDocParam
|
||||
= AnnotationName Type IsVariadic? ParameterName Description?
|
||||
|
||||
AnnotationName
|
||||
= '@param'
|
||||
|
||||
IsVariaric
|
||||
= '...'
|
||||
|
||||
ParameterName
|
||||
= '$' [a-zA-Z_\127-\255][a-zA-Z0-9_\127-\255]*
|
||||
|
||||
Description
|
||||
= .+ # TODO: exclude EOL or another PhpDocTag start
|
231
vendor/phpstan/phpdoc-parser/doc/grammars/type.abnf
vendored
Normal file
231
vendor/phpstan/phpdoc-parser/doc/grammars/type.abnf
vendored
Normal file
|
@ -0,0 +1,231 @@
|
|||
; ---------------------------------------------------------------------------- ;
|
||||
; Type ;
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
|
||||
Type
|
||||
= Atomic [Union / Intersection]
|
||||
/ Nullable
|
||||
|
||||
Union
|
||||
= 1*(TokenUnion Atomic)
|
||||
|
||||
Intersection
|
||||
= 1*(TokenIntersection Atomic)
|
||||
|
||||
Nullable
|
||||
= TokenNullable TokenIdentifier [Generic]
|
||||
|
||||
Atomic
|
||||
= TokenIdentifier [Generic / Callable / Array]
|
||||
/ TokenThisVariable
|
||||
/ TokenParenthesesOpen Type TokenParenthesesClose [Array]
|
||||
|
||||
Generic
|
||||
= TokenAngleBracketOpen Type *(TokenComma Type) TokenAngleBracketClose
|
||||
|
||||
Callable
|
||||
= TokenParenthesesOpen [CallableParameters] TokenParenthesesClose TokenColon CallableReturnType
|
||||
|
||||
CallableParameters
|
||||
= CallableParameter *(TokenComma CallableParameter)
|
||||
|
||||
CallableParameter
|
||||
= Type [CallableParameterIsReference] [CallableParameterIsVariadic] [CallableParameterName] [CallableParameterIsOptional]
|
||||
|
||||
CallableParameterIsReference
|
||||
= TokenIntersection
|
||||
|
||||
CallableParameterIsVariadic
|
||||
= TokenVariadic
|
||||
|
||||
CallableParameterName
|
||||
= TokenVariable
|
||||
|
||||
CallableParameterIsOptional
|
||||
= TokenEqualSign
|
||||
|
||||
CallableReturnType
|
||||
= TokenIdentifier [Generic]
|
||||
/ Nullable
|
||||
/ TokenParenthesesOpen Type TokenParenthesesClose
|
||||
|
||||
Array
|
||||
= 1*(TokenSquareBracketOpen TokenSquareBracketClose)
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; ConstantExpr ;
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
|
||||
ConstantExpr
|
||||
= ConstantFloat *ByteHorizontalWs
|
||||
/ ConstantInt *ByteHorizontalWs
|
||||
/ ConstantTrue *ByteHorizontalWs
|
||||
/ ConstantFalse *ByteHorizontalWs
|
||||
/ ConstantNull *ByteHorizontalWs
|
||||
/ ConstantString *ByteHorizontalWs
|
||||
/ ConstantArray *ByteHorizontalWs
|
||||
/ ConstantFetch *ByteHorizontalWs
|
||||
|
||||
ConstantFloat
|
||||
= ["-"] 1*ByteDecDigit "." *ByteDecDigit [ConstantFloatExp]
|
||||
/ ["-"] 1*ByteDecDigit ConstantFloatExp
|
||||
/ ["-"] "." 1*ByteDecDigit [ConstantFloatExp]
|
||||
|
||||
ConstantFloatExp
|
||||
= "e" ["-"] 1*ByteDecDigit
|
||||
|
||||
ConstantInt
|
||||
= ["-"] "0b" 1*ByteBinDigit
|
||||
/ ["-"] "0o" 1*ByteOctDigit
|
||||
/ ["-"] "0x" 1*ByteHexDigit
|
||||
/ ["-"] 1*ByteDecDigit
|
||||
|
||||
ConstantTrue
|
||||
= "true"
|
||||
|
||||
ConstantFalse
|
||||
= "false"
|
||||
|
||||
ConstantNull
|
||||
= "null"
|
||||
|
||||
ConstantString
|
||||
= ByteSingleQuote *(ByteBackslash ByteNotEol / ByteNotEolAndNotBackslashAndNotSingleQuote) ByteSingleQuote
|
||||
/ ByteDoubleQuote *(ByteBackslash ByteNotEol / ByteNotEolAndNotBackslashAndNotDoubleQuote) ByteDoubleQuote
|
||||
|
||||
ConstantArray
|
||||
= TokenSquareBracketOpen [ConstantArrayItems] TokenSquareBracketClose
|
||||
/ "array" TokenParenthesesOpen [ConstantArrayItems] TokenParenthesesClose
|
||||
|
||||
ConstantArrayItems
|
||||
= ConstantArrayItem *(TokenComma ConstantArrayItem) [TokenComma]
|
||||
|
||||
ConstantArrayItem
|
||||
= ConstantExpr [TokenDoubleArrow ConstantExpr]
|
||||
|
||||
ConstantFetch
|
||||
= TokenIdentifier [TokenDoubleColon ByteIdentifierFirst *ByteIdentifierSecond *ByteHorizontalWs]
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Tokens ;
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
|
||||
TokenUnion
|
||||
= "|" *ByteHorizontalWs
|
||||
|
||||
TokenIntersection
|
||||
= "&" *ByteHorizontalWs
|
||||
|
||||
TokenNullable
|
||||
= "?" *ByteHorizontalWs
|
||||
|
||||
TokenParenthesesOpen
|
||||
= "(" *ByteHorizontalWs
|
||||
|
||||
TokenParenthesesClose
|
||||
= ")" *ByteHorizontalWs
|
||||
|
||||
TokenAngleBracketOpen
|
||||
= "<" *ByteHorizontalWs
|
||||
|
||||
TokenAngleBracketClose
|
||||
= ">" *ByteHorizontalWs
|
||||
|
||||
TokenSquareBracketOpen
|
||||
= "[" *ByteHorizontalWs
|
||||
|
||||
TokenSquareBracketClose
|
||||
= "]" *ByteHorizontalWs
|
||||
|
||||
TokenComma
|
||||
= "," *ByteHorizontalWs
|
||||
|
||||
TokenColon
|
||||
= ":" *ByteHorizontalWs
|
||||
|
||||
TokenVariadic
|
||||
= "..." *ByteHorizontalWs
|
||||
|
||||
TokenEqualSign
|
||||
= "=" *ByteHorizontalWs
|
||||
|
||||
TokenVariable
|
||||
= "$" ByteIdentifierFirst *ByteIdentifierSecond *ByteHorizontalWs
|
||||
|
||||
TokenDoubleArrow
|
||||
= "=>" *ByteHorizontalWs
|
||||
|
||||
TokenDoubleColon
|
||||
= "::" *ByteHorizontalWs
|
||||
|
||||
TokenThisVariable
|
||||
= %x24.74.68.69.73 *ByteHorizontalWs
|
||||
|
||||
TokenIdentifier
|
||||
= [ByteBackslash] ByteIdentifierFirst *ByteIdentifierSecond *(ByteBackslash ByteIdentifierFirst *ByteIdentifierSecond) *ByteHorizontalWs
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
; Bytes ;
|
||||
; ---------------------------------------------------------------------------- ;
|
||||
|
||||
ByteHorizontalWs
|
||||
= %x09 ; horizontal tab
|
||||
/ %x20 ; space
|
||||
|
||||
ByteBinDigit
|
||||
= %x30-31 ; 0-1
|
||||
|
||||
ByteOctDigit
|
||||
= %x30-37 ; 0-7
|
||||
|
||||
ByteDecDigit
|
||||
= %x30-39 ; 0-9
|
||||
|
||||
ByteHexDigit
|
||||
= %x30-39 ; 0-9
|
||||
/ %x41-46 ; A-F
|
||||
/ %x61-66 ; a-f
|
||||
|
||||
ByteIdentifierFirst
|
||||
= %x41-5A ; A-Z
|
||||
/ %x5F ; _
|
||||
/ %x61-7A ; a-z
|
||||
/ %x80-FF
|
||||
|
||||
ByteIdentifierSecond
|
||||
= %x30-39 ; 0-9
|
||||
/ %x41-5A ; A-Z
|
||||
/ %x5F ; _
|
||||
/ %x61-7A ; a-z
|
||||
/ %x80-FF
|
||||
|
||||
ByteSingleQuote
|
||||
= %x27 ; '
|
||||
|
||||
ByteDoubleQuote
|
||||
= %x22 ; "
|
||||
|
||||
ByteBackslash
|
||||
= %x5C ; \
|
||||
|
||||
ByteNotEol
|
||||
= %x00-09 ; skip LF
|
||||
/ %x0B-0C ; skip CR
|
||||
/ %x0E-FF
|
||||
|
||||
ByteNotEolAndNotBackslashAndNotSingleQuote
|
||||
= %x00-09 ; skip LF
|
||||
/ %x0B-0C ; skip CR
|
||||
/ %x0E-26 ; skip single quote
|
||||
/ %x28-5B ; skip backslash
|
||||
/ %x5D-FF
|
||||
|
||||
ByteNotEolAndNotBackslashAndNotDoubleQuote
|
||||
= %x00-09 ; skip LF
|
||||
/ %x0B-0C ; skip CR
|
||||
/ %x0E-21 ; skip double quote
|
||||
/ %x23-5B ; skip backslash
|
||||
/ %x5D-FF
|
31
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php
vendored
Normal file
31
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprArrayItemNode implements ConstExprNode
|
||||
{
|
||||
|
||||
/** @var null|ConstExprNode */
|
||||
public $key;
|
||||
|
||||
/** @var ConstExprNode */
|
||||
public $value;
|
||||
|
||||
public function __construct(?ConstExprNode $key, ConstExprNode $value)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->key !== null) {
|
||||
return "{$this->key} => {$this->value}";
|
||||
|
||||
} else {
|
||||
return "{$this->value}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
25
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php
vendored
Normal file
25
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprArrayNode implements ConstExprNode
|
||||
{
|
||||
|
||||
/** @var ConstExprArrayItemNode[] */
|
||||
public $items;
|
||||
|
||||
/**
|
||||
* @param ConstExprArrayItemNode[] $items
|
||||
*/
|
||||
public function __construct(array $items)
|
||||
{
|
||||
$this->items = $items;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '[' . implode(', ', $this->items) . ']';
|
||||
}
|
||||
|
||||
}
|
13
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php
vendored
Normal file
13
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprFalseNode implements ConstExprNode
|
||||
{
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'false';
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprFloatNode implements ConstExprNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $value;
|
||||
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprIntegerNode implements ConstExprNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $value;
|
||||
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
10
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php
vendored
Normal file
10
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
interface ConstExprNode extends Node
|
||||
{
|
||||
|
||||
}
|
13
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php
vendored
Normal file
13
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprNullNode implements ConstExprNode
|
||||
{
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'null';
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprStringNode implements ConstExprNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $value;
|
||||
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
13
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php
vendored
Normal file
13
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstExprTrueNode implements ConstExprNode
|
||||
{
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return 'true';
|
||||
}
|
||||
|
||||
}
|
31
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php
vendored
Normal file
31
vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
|
||||
|
||||
class ConstFetchNode implements ConstExprNode
|
||||
{
|
||||
|
||||
/** @var string class name for class constants or empty string for non-class constants */
|
||||
public $className;
|
||||
|
||||
/** @var string */
|
||||
public $name;
|
||||
|
||||
public function __construct(string $className, string $name)
|
||||
{
|
||||
$this->className = $className;
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->className === '') {
|
||||
return $this->name;
|
||||
|
||||
} else {
|
||||
return "{$this->className}::{$this->name}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
10
vendor/phpstan/phpdoc-parser/src/Ast/Node.php
vendored
Normal file
10
vendor/phpstan/phpdoc-parser/src/Ast/Node.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast;
|
||||
|
||||
interface Node
|
||||
{
|
||||
|
||||
public function __toString(): string;
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
class GenericTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $value;
|
||||
|
||||
public function __construct(string $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
26
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php
vendored
Normal file
26
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
class InvalidTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $value;
|
||||
|
||||
/** @var \PHPStan\PhpDocParser\Parser\ParserException */
|
||||
public $exception;
|
||||
|
||||
public function __construct(string $value, \PHPStan\PhpDocParser\Parser\ParserException $exception)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
44
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php
vendored
Normal file
44
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class MethodTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var bool */
|
||||
public $isStatic;
|
||||
|
||||
/** @var null|TypeNode */
|
||||
public $returnType;
|
||||
|
||||
/** @var string */
|
||||
public $methodName;
|
||||
|
||||
/** @var MethodTagValueParameterNode[] */
|
||||
public $parameters;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
|
||||
public function __construct(bool $isStatic, ?TypeNode $returnType, string $methodName, array $parameters, string $description)
|
||||
{
|
||||
$this->isStatic = $isStatic;
|
||||
$this->returnType = $returnType;
|
||||
$this->methodName = $methodName;
|
||||
$this->parameters = $parameters;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$static = $this->isStatic ? 'static ' : '';
|
||||
$returnType = $this->returnType ? "{$this->returnType} " : '';
|
||||
$parameters = implode(', ', $this->parameters);
|
||||
$description = $this->description !== '' ? " {$this->description}" : '';
|
||||
return "{$static}{$returnType}{$this->methodName}({$parameters}){$description}";
|
||||
}
|
||||
|
||||
}
|
46
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php
vendored
Normal file
46
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class MethodTagValueParameterNode implements Node
|
||||
{
|
||||
|
||||
/** @var null|TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var bool */
|
||||
public $isReference;
|
||||
|
||||
/** @var bool */
|
||||
public $isVariadic;
|
||||
|
||||
/** @var string */
|
||||
public $parameterName;
|
||||
|
||||
/** @var null|ConstExprNode */
|
||||
public $defaultValue;
|
||||
|
||||
public function __construct(?TypeNode $type, bool $isReference, bool $isVariadic, string $parameterName, ?ConstExprNode $defaultValue)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->isReference = $isReference;
|
||||
$this->isVariadic = $isVariadic;
|
||||
$this->parameterName = $parameterName;
|
||||
$this->defaultValue = $defaultValue;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$type = $this->type ? "{$this->type} " : '';
|
||||
$isReference = $this->isReference ? '&' : '';
|
||||
$isVariadic = $this->isVariadic ? '...' : '';
|
||||
$default = $this->defaultValue ? " = {$this->defaultValue}" : '';
|
||||
return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}";
|
||||
}
|
||||
|
||||
}
|
37
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php
vendored
Normal file
37
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class ParamTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var bool */
|
||||
public $isVariadic;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $parameterName;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
|
||||
public function __construct(TypeNode $type, bool $isVariadic, string $parameterName, string $description)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->isVariadic = $isVariadic;
|
||||
$this->parameterName = $parameterName;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$variadic = $this->isVariadic ? '...' : '';
|
||||
return trim("{$this->type} {$variadic}{$this->parameterName} {$this->description}");
|
||||
}
|
||||
|
||||
}
|
10
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php
vendored
Normal file
10
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
interface PhpDocChildNode extends Node
|
||||
{
|
||||
|
||||
}
|
162
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php
vendored
Normal file
162
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
class PhpDocNode implements Node
|
||||
{
|
||||
|
||||
/** @var PhpDocChildNode[] */
|
||||
public $children;
|
||||
|
||||
/**
|
||||
* @param PhpDocChildNode[] $children
|
||||
*/
|
||||
public function __construct(array $children)
|
||||
{
|
||||
$this->children = $children;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PhpDocTagNode[]
|
||||
*/
|
||||
public function getTags(): array
|
||||
{
|
||||
return array_filter($this->children, function (PhpDocChildNode $child): bool {
|
||||
return $child instanceof PhpDocTagNode;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $tagName
|
||||
* @return PhpDocTagNode[]
|
||||
*/
|
||||
public function getTagsByName(string $tagName): array
|
||||
{
|
||||
return array_filter($this->getTags(), function (PhpDocTagNode $tag) use ($tagName): bool {
|
||||
return $tag->name === $tagName;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return VarTagValueNode[]
|
||||
*/
|
||||
public function getVarTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@var'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof VarTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ParamTagValueNode[]
|
||||
*/
|
||||
public function getParamTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@param'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof ParamTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ReturnTagValueNode[]
|
||||
*/
|
||||
public function getReturnTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@return'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof ReturnTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ThrowsTagValueNode[]
|
||||
*/
|
||||
public function getThrowsTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@throws'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof ThrowsTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PropertyTagValueNode[]
|
||||
*/
|
||||
public function getPropertyTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@property'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof PropertyTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PropertyTagValueNode[]
|
||||
*/
|
||||
public function getPropertyReadTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@property-read'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof PropertyTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return PropertyTagValueNode[]
|
||||
*/
|
||||
public function getPropertyWriteTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@property-write'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof PropertyTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return MethodTagValueNode[]
|
||||
*/
|
||||
public function getMethodTagValues(): array
|
||||
{
|
||||
return array_column(
|
||||
array_filter($this->getTagsByName('@method'), function (PhpDocTagNode $tag): bool {
|
||||
return $tag->value instanceof MethodTagValueNode;
|
||||
}),
|
||||
'value'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "/**\n * " . implode("\n * ", $this->children) . '*/';
|
||||
}
|
||||
|
||||
}
|
26
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php
vendored
Normal file
26
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
class PhpDocTagNode implements PhpDocChildNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $name;
|
||||
|
||||
/** @var PhpDocTagValueNode */
|
||||
public $value;
|
||||
|
||||
public function __construct(string $name, PhpDocTagValueNode $value)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return trim("{$this->name} {$this->value}");
|
||||
}
|
||||
|
||||
}
|
10
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php
vendored
Normal file
10
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
interface PhpDocTagValueNode extends Node
|
||||
{
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
class PhpDocTextNode implements PhpDocChildNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $text;
|
||||
|
||||
public function __construct(string $text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
}
|
32
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php
vendored
Normal file
32
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class PropertyTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var string */
|
||||
public $propertyName;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
|
||||
public function __construct(TypeNode $type, string $propertyName, string $description)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->propertyName = $propertyName;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return trim("{$this->type} {$this->propertyName} {$this->description}");
|
||||
}
|
||||
|
||||
}
|
28
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php
vendored
Normal file
28
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class ReturnTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
|
||||
public function __construct(TypeNode $type, string $description)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return trim("{$this->type} {$this->description}");
|
||||
}
|
||||
|
||||
}
|
28
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php
vendored
Normal file
28
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class ThrowsTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
|
||||
public function __construct(TypeNode $type, string $description)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return trim("{$this->type} {$this->description}");
|
||||
}
|
||||
|
||||
}
|
32
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php
vendored
Normal file
32
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
|
||||
class VarTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $variableName;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
|
||||
public function __construct(TypeNode $type, string $variableName, string $description)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->variableName = $variableName;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return trim("$this->type " . trim("{$this->variableName} {$this->description}"));
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class ArrayTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
public function __construct(TypeNode $type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->type . '[]';
|
||||
}
|
||||
|
||||
}
|
31
vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php
vendored
Normal file
31
vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class CallableTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var IdentifierTypeNode */
|
||||
public $identifier;
|
||||
|
||||
/** @var CallableTypeParameterNode[] */
|
||||
public $parameters;
|
||||
|
||||
/** @var TypeNode */
|
||||
public $returnType;
|
||||
|
||||
public function __construct(IdentifierTypeNode $identifier, array $parameters, TypeNode $returnType)
|
||||
{
|
||||
$this->identifier = $identifier;
|
||||
$this->parameters = $parameters;
|
||||
$this->returnType = $returnType;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$parameters = implode(', ', $this->parameters);
|
||||
return "{$this->identifier}({$parameters}): {$this->returnType}";
|
||||
}
|
||||
|
||||
}
|
44
vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php
vendored
Normal file
44
vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
class CallableTypeParameterNode implements Node
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var bool */
|
||||
public $isReference;
|
||||
|
||||
/** @var bool */
|
||||
public $isVariadic;
|
||||
|
||||
/** @var string (may be empty) */
|
||||
public $parameterName;
|
||||
|
||||
/** @var bool */
|
||||
public $isOptional;
|
||||
|
||||
public function __construct(TypeNode $type, bool $isReference, bool $isVariadic, string $parameterName, bool $isOptional)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->isReference = $isReference;
|
||||
$this->isVariadic = $isVariadic;
|
||||
$this->parameterName = $parameterName;
|
||||
$this->isOptional = $isOptional;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$type = "{$this->type} ";
|
||||
$isReference = $this->isReference ? '&' : '';
|
||||
$isVariadic = $this->isVariadic ? '...' : '';
|
||||
$default = $this->isOptional ? ' = default' : '';
|
||||
return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}";
|
||||
}
|
||||
|
||||
}
|
26
vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php
vendored
Normal file
26
vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class GenericTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var IdentifierTypeNode */
|
||||
public $type;
|
||||
|
||||
/** @var TypeNode[] */
|
||||
public $genericTypes;
|
||||
|
||||
public function __construct(IdentifierTypeNode $type, array $genericTypes)
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->genericTypes = $genericTypes;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->type . '<' . implode(', ', $this->genericTypes) . '>';
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class IdentifierTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
public $name;
|
||||
|
||||
public function __construct(string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class IntersectionTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var TypeNode[] */
|
||||
public $types;
|
||||
|
||||
public function __construct(array $types)
|
||||
{
|
||||
$this->types = $types;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '(' . implode(' & ', $this->types) . ')';
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class NullableTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var TypeNode */
|
||||
public $type;
|
||||
|
||||
public function __construct(TypeNode $type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '?' . $this->type;
|
||||
}
|
||||
|
||||
}
|
13
vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php
vendored
Normal file
13
vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class ThisTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '$this';
|
||||
}
|
||||
|
||||
}
|
10
vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php
vendored
Normal file
10
vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
interface TypeNode extends Node
|
||||
{
|
||||
|
||||
}
|
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php
vendored
Normal file
22
vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Ast\Type;
|
||||
|
||||
class UnionTypeNode implements TypeNode
|
||||
{
|
||||
|
||||
/** @var TypeNode[] */
|
||||
public $types;
|
||||
|
||||
public function __construct(array $types)
|
||||
{
|
||||
$this->types = $types;
|
||||
}
|
||||
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return '(' . implode(' | ', $this->types) . ')';
|
||||
}
|
||||
|
||||
}
|
158
vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php
vendored
Normal file
158
vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php
vendored
Normal file
|
@ -0,0 +1,158 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Lexer;
|
||||
|
||||
/**
|
||||
* Implementation based on Nette Tokenizer (New BSD License; https://github.com/nette/tokenizer)
|
||||
*/
|
||||
class Lexer
|
||||
{
|
||||
|
||||
public const TOKEN_REFERENCE = 0;
|
||||
public const TOKEN_UNION = 1;
|
||||
public const TOKEN_INTERSECTION = 2;
|
||||
public const TOKEN_NULLABLE = 3;
|
||||
public const TOKEN_OPEN_PARENTHESES = 4;
|
||||
public const TOKEN_CLOSE_PARENTHESES = 5;
|
||||
public const TOKEN_OPEN_ANGLE_BRACKET = 6;
|
||||
public const TOKEN_CLOSE_ANGLE_BRACKET = 7;
|
||||
public const TOKEN_OPEN_SQUARE_BRACKET = 8;
|
||||
public const TOKEN_CLOSE_SQUARE_BRACKET = 9;
|
||||
public const TOKEN_COMMA = 10;
|
||||
public const TOKEN_COLON = 29;
|
||||
public const TOKEN_VARIADIC = 11;
|
||||
public const TOKEN_DOUBLE_COLON = 12;
|
||||
public const TOKEN_DOUBLE_ARROW = 13;
|
||||
public const TOKEN_EQUAL = 14;
|
||||
public const TOKEN_OPEN_PHPDOC = 15;
|
||||
public const TOKEN_CLOSE_PHPDOC = 16;
|
||||
public const TOKEN_PHPDOC_TAG = 17;
|
||||
public const TOKEN_PHPDOC_EOL = 26;
|
||||
public const TOKEN_FLOAT = 18;
|
||||
public const TOKEN_INTEGER = 19;
|
||||
public const TOKEN_SINGLE_QUOTED_STRING = 20;
|
||||
public const TOKEN_DOUBLE_QUOTED_STRING = 21;
|
||||
public const TOKEN_IDENTIFIER = 22;
|
||||
public const TOKEN_THIS_VARIABLE = 23;
|
||||
public const TOKEN_VARIABLE = 24;
|
||||
public const TOKEN_HORIZONTAL_WS = 25;
|
||||
public const TOKEN_OTHER = 27;
|
||||
public const TOKEN_END = 28;
|
||||
|
||||
public const TOKEN_LABELS = [
|
||||
self::TOKEN_REFERENCE => '\'&\'',
|
||||
self::TOKEN_UNION => '\'|\'',
|
||||
self::TOKEN_INTERSECTION => '\'&\'',
|
||||
self::TOKEN_NULLABLE => '\'?\'',
|
||||
self::TOKEN_OPEN_PARENTHESES => '\'(\'',
|
||||
self::TOKEN_CLOSE_PARENTHESES => '\')\'',
|
||||
self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'',
|
||||
self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'',
|
||||
self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'',
|
||||
self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'',
|
||||
self::TOKEN_COMMA => '\',\'',
|
||||
self::TOKEN_COLON => '\':\'',
|
||||
self::TOKEN_VARIADIC => '\'...\'',
|
||||
self::TOKEN_DOUBLE_COLON => '\'::\'',
|
||||
self::TOKEN_DOUBLE_ARROW => '\'=>\'',
|
||||
self::TOKEN_EQUAL => '\'=\'',
|
||||
self::TOKEN_OPEN_PHPDOC => '\'/**\'',
|
||||
self::TOKEN_CLOSE_PHPDOC => '\'*/\'',
|
||||
self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG',
|
||||
self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL',
|
||||
self::TOKEN_FLOAT => 'TOKEN_FLOAT',
|
||||
self::TOKEN_INTEGER => 'TOKEN_INTEGER',
|
||||
self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING',
|
||||
self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING',
|
||||
self::TOKEN_IDENTIFIER => 'TOKEN_IDENTIFIER',
|
||||
self::TOKEN_THIS_VARIABLE => '\'$this\'',
|
||||
self::TOKEN_VARIABLE => 'TOKEN_VARIABLE',
|
||||
self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS',
|
||||
self::TOKEN_OTHER => 'TOKEN_OTHER',
|
||||
self::TOKEN_END => 'TOKEN_END',
|
||||
];
|
||||
|
||||
public const VALUE_OFFSET = 0;
|
||||
public const TYPE_OFFSET = 1;
|
||||
|
||||
/** @var null|string */
|
||||
private $regexp;
|
||||
|
||||
/** @var null|int[] */
|
||||
private $types;
|
||||
|
||||
public function tokenize(string $s): array
|
||||
{
|
||||
if ($this->regexp === null || $this->types === null) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
assert($this->regexp !== null);
|
||||
assert($this->types !== null);
|
||||
|
||||
preg_match_all($this->regexp, $s, $tokens, PREG_SET_ORDER);
|
||||
|
||||
$count = count($this->types);
|
||||
foreach ($tokens as &$match) {
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
if ($match[$i] !== null && $match[$i] !== '') {
|
||||
$match = [$match[0], $this->types[$i - 1]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tokens[] = ['', self::TOKEN_END];
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
|
||||
private function initialize()
|
||||
{
|
||||
$patterns = [
|
||||
// '&' followed by TOKEN_VARIADIC, TOKEN_VARIABLE, TOKEN_EQUAL, TOKEN_EQUAL or TOKEN_CLOSE_PARENTHESES
|
||||
self::TOKEN_REFERENCE => '&(?=\\s*+(?:[.,=)]|(?:\\$(?!this(?![0-9a-z_\\x80-\\xFF])))))',
|
||||
self::TOKEN_UNION => '\\|',
|
||||
self::TOKEN_INTERSECTION => '&',
|
||||
self::TOKEN_NULLABLE => '\\?',
|
||||
|
||||
self::TOKEN_OPEN_PARENTHESES => '\\(',
|
||||
self::TOKEN_CLOSE_PARENTHESES => '\\)',
|
||||
self::TOKEN_OPEN_ANGLE_BRACKET => '<',
|
||||
self::TOKEN_CLOSE_ANGLE_BRACKET => '>',
|
||||
self::TOKEN_OPEN_SQUARE_BRACKET => '\\[',
|
||||
self::TOKEN_CLOSE_SQUARE_BRACKET => '\\]',
|
||||
|
||||
self::TOKEN_COMMA => ',',
|
||||
self::TOKEN_VARIADIC => '\\.\\.\\.',
|
||||
self::TOKEN_DOUBLE_COLON => '::',
|
||||
self::TOKEN_DOUBLE_ARROW => '=>',
|
||||
self::TOKEN_EQUAL => '=',
|
||||
self::TOKEN_COLON => ':',
|
||||
|
||||
self::TOKEN_OPEN_PHPDOC => '/\\*\\*(?=\\s)',
|
||||
self::TOKEN_CLOSE_PHPDOC => '\\*/',
|
||||
self::TOKEN_PHPDOC_TAG => '@[a-z-]++',
|
||||
self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/))?',
|
||||
|
||||
self::TOKEN_FLOAT => '(?:-?[0-9]++\\.[0-9]*+(?:e-?[0-9]++)?)|(?:-?[0-9]*+\\.[0-9]++(?:e-?[0-9]++)?)|(?:-?[0-9]++e-?[0-9]++)',
|
||||
self::TOKEN_INTEGER => '-?(?:(?:0b[0-1]++)|(?:0o[0-7]++)|(?:0x[0-9a-f]++)|(?:[0-9]++))',
|
||||
self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'',
|
||||
self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"',
|
||||
|
||||
self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF]*+)++',
|
||||
self::TOKEN_THIS_VARIABLE => '\\$this(?![0-9a-z_\\x80-\\xFF])',
|
||||
self::TOKEN_VARIABLE => '\\$[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF]*+',
|
||||
|
||||
self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++',
|
||||
|
||||
// anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
|
||||
self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++',
|
||||
];
|
||||
|
||||
$this->regexp = '~(' . implode(')|(', $patterns) . ')~Asi';
|
||||
$this->types = array_keys($patterns);
|
||||
}
|
||||
|
||||
}
|
97
vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php
vendored
Normal file
97
vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Parser;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
|
||||
class ConstExprParser
|
||||
{
|
||||
|
||||
public function parse(TokenIterator $tokens): Ast\ConstExpr\ConstExprNode
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) {
|
||||
$value = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
return new Ast\ConstExpr\ConstExprFloatNode($value);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
|
||||
$value = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
return new Ast\ConstExpr\ConstExprIntegerNode($value);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
|
||||
$value = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
return new Ast\ConstExpr\ConstExprStringNode($value);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
|
||||
$value = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
return new Ast\ConstExpr\ConstExprStringNode($value);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
|
||||
$identifier = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
|
||||
switch (strtolower($identifier)) {
|
||||
case 'true':
|
||||
return new Ast\ConstExpr\ConstExprTrueNode();
|
||||
case 'false':
|
||||
return new Ast\ConstExpr\ConstExprFalseNode();
|
||||
case 'null':
|
||||
return new Ast\ConstExpr\ConstExprNullNode();
|
||||
case 'array':
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
|
||||
return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES);
|
||||
}
|
||||
|
||||
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
|
||||
$classConstantName = $tokens->currentTokenValue();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||
return new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName);
|
||||
|
||||
} else {
|
||||
return new Ast\ConstExpr\ConstFetchNode('', $identifier);
|
||||
}
|
||||
|
||||
} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
|
||||
return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
|
||||
}
|
||||
|
||||
throw new \LogicException($tokens->currentTokenValue());
|
||||
}
|
||||
|
||||
|
||||
private function parseArray(TokenIterator $tokens, int $endToken): Ast\ConstExpr\ConstExprArrayNode
|
||||
{
|
||||
$items = [];
|
||||
|
||||
if (!$tokens->tryConsumeTokenType($endToken)) {
|
||||
do {
|
||||
$items[] = $this->parseArrayItem($tokens);
|
||||
} while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA) && !$tokens->isCurrentTokenType($endToken));
|
||||
$tokens->consumeTokenType($endToken);
|
||||
}
|
||||
|
||||
return new Ast\ConstExpr\ConstExprArrayNode($items);
|
||||
}
|
||||
|
||||
|
||||
private function parseArrayItem(TokenIterator $tokens): Ast\ConstExpr\ConstExprArrayItemNode
|
||||
{
|
||||
$expr = $this->parse($tokens);
|
||||
|
||||
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) {
|
||||
$key = $expr;
|
||||
$value = $this->parse($tokens);
|
||||
|
||||
} else {
|
||||
$key = null;
|
||||
$value = $expr;
|
||||
}
|
||||
|
||||
return new Ast\ConstExpr\ConstExprArrayItemNode($key, $value);
|
||||
}
|
||||
|
||||
}
|
69
vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php
vendored
Normal file
69
vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Parser;
|
||||
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
|
||||
class ParserException extends \Exception
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $currentTokenValue;
|
||||
|
||||
/** @var int */
|
||||
private $currentTokenType;
|
||||
|
||||
/** @var int */
|
||||
private $currentOffset;
|
||||
|
||||
/** @var int */
|
||||
private $expectedTokenType;
|
||||
|
||||
public function __construct(
|
||||
string $currentTokenValue,
|
||||
int $currentTokenType,
|
||||
int $currentOffset,
|
||||
int $expectedTokenType
|
||||
)
|
||||
{
|
||||
$this->currentTokenValue = $currentTokenValue;
|
||||
$this->currentTokenType = $currentTokenType;
|
||||
$this->currentOffset = $currentOffset;
|
||||
$this->expectedTokenType = $expectedTokenType;
|
||||
|
||||
$json = json_encode($currentTokenValue, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
assert($json !== false);
|
||||
|
||||
parent::__construct(sprintf(
|
||||
'Unexpected token %s, expected %s at offset %d',
|
||||
$json,
|
||||
Lexer::TOKEN_LABELS[$expectedTokenType],
|
||||
$currentOffset
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
public function getCurrentTokenValue(): string
|
||||
{
|
||||
return $this->currentTokenValue;
|
||||
}
|
||||
|
||||
|
||||
public function getCurrentTokenType(): int
|
||||
{
|
||||
return $this->currentTokenType;
|
||||
}
|
||||
|
||||
|
||||
public function getCurrentOffset(): int
|
||||
{
|
||||
return $this->currentOffset;
|
||||
}
|
||||
|
||||
|
||||
public function getExpectedTokenType(): int
|
||||
{
|
||||
return $this->expectedTokenType;
|
||||
}
|
||||
|
||||
}
|
273
vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php
vendored
Normal file
273
vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php
vendored
Normal file
|
@ -0,0 +1,273 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Parser;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
|
||||
class PhpDocParser
|
||||
{
|
||||
|
||||
private const DISALLOWED_DESCRIPTION_START_TOKENS = [
|
||||
Lexer::TOKEN_UNION,
|
||||
Lexer::TOKEN_INTERSECTION,
|
||||
Lexer::TOKEN_OPEN_ANGLE_BRACKET,
|
||||
];
|
||||
|
||||
/** @var TypeParser */
|
||||
private $typeParser;
|
||||
|
||||
/** @var ConstExprParser */
|
||||
private $constantExprParser;
|
||||
|
||||
public function __construct(TypeParser $typeParser, ConstExprParser $constantExprParser)
|
||||
{
|
||||
$this->typeParser = $typeParser;
|
||||
$this->constantExprParser = $constantExprParser;
|
||||
}
|
||||
|
||||
|
||||
public function parse(TokenIterator $tokens): Ast\PhpDoc\PhpDocNode
|
||||
{
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC);
|
||||
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
||||
|
||||
$children = [];
|
||||
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
$children[] = $this->parseChild($tokens);
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL) && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
$children[] = $this->parseChild($tokens);
|
||||
}
|
||||
}
|
||||
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC);
|
||||
|
||||
return new Ast\PhpDoc\PhpDocNode(array_values($children));
|
||||
}
|
||||
|
||||
|
||||
private function parseChild(TokenIterator $tokens): Ast\PhpDoc\PhpDocChildNode
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
|
||||
return $this->parseTag($tokens);
|
||||
|
||||
} else {
|
||||
return $this->parseText($tokens);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function parseText(TokenIterator $tokens): Ast\PhpDoc\PhpDocTextNode
|
||||
{
|
||||
$text = $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END);
|
||||
$text = rtrim($text, " \t"); // the trimmed characters MUST match Lexer::TOKEN_HORIZONTAL_WS
|
||||
|
||||
return new Ast\PhpDoc\PhpDocTextNode($text);
|
||||
}
|
||||
|
||||
|
||||
public function parseTag(TokenIterator $tokens): Ast\PhpDoc\PhpDocTagNode
|
||||
{
|
||||
$tag = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
$value = $this->parseTagValue($tokens, $tag);
|
||||
|
||||
return new Ast\PhpDoc\PhpDocTagNode($tag, $value);
|
||||
}
|
||||
|
||||
|
||||
public function parseTagValue(TokenIterator $tokens, string $tag): Ast\PhpDoc\PhpDocTagValueNode
|
||||
{
|
||||
try {
|
||||
$tokens->pushSavePoint();
|
||||
|
||||
switch ($tag) {
|
||||
case '@param':
|
||||
$tagValue = $this->parseParamTagValue($tokens);
|
||||
break;
|
||||
|
||||
case '@var':
|
||||
$tagValue = $this->parseVarTagValue($tokens);
|
||||
break;
|
||||
|
||||
case '@return':
|
||||
$tagValue = $this->parseReturnTagValue($tokens);
|
||||
break;
|
||||
|
||||
case '@throws':
|
||||
$tagValue = $this->parseThrowsTagValue($tokens);
|
||||
break;
|
||||
|
||||
case '@property':
|
||||
case '@property-read':
|
||||
case '@property-write':
|
||||
$tagValue = $this->parsePropertyTagValue($tokens);
|
||||
break;
|
||||
|
||||
case '@method':
|
||||
$tagValue = $this->parseMethodTagValue($tokens);
|
||||
break;
|
||||
|
||||
default:
|
||||
$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
|
||||
break;
|
||||
}
|
||||
|
||||
$tokens->dropSavePoint();
|
||||
|
||||
} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
|
||||
$tokens->rollback();
|
||||
$tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens), $e);
|
||||
}
|
||||
|
||||
return $tagValue;
|
||||
}
|
||||
|
||||
|
||||
private function parseParamTagValue(TokenIterator $tokens): Ast\PhpDoc\ParamTagValueNode
|
||||
{
|
||||
$type = $this->typeParser->parse($tokens);
|
||||
$isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
|
||||
$parameterName = $this->parseRequiredVariableName($tokens);
|
||||
$description = $this->parseOptionalDescription($tokens);
|
||||
return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description);
|
||||
}
|
||||
|
||||
|
||||
private function parseVarTagValue(TokenIterator $tokens): Ast\PhpDoc\VarTagValueNode
|
||||
{
|
||||
$type = $this->typeParser->parse($tokens);
|
||||
$variableName = $this->parseOptionalVariableName($tokens);
|
||||
$description = $this->parseOptionalDescription($tokens, $variableName === '');
|
||||
return new Ast\PhpDoc\VarTagValueNode($type, $variableName, $description);
|
||||
}
|
||||
|
||||
|
||||
private function parseReturnTagValue(TokenIterator $tokens): Ast\PhpDoc\ReturnTagValueNode
|
||||
{
|
||||
$type = $this->typeParser->parse($tokens);
|
||||
$description = $this->parseOptionalDescription($tokens, true);
|
||||
return new Ast\PhpDoc\ReturnTagValueNode($type, $description);
|
||||
}
|
||||
|
||||
|
||||
private function parseThrowsTagValue(TokenIterator $tokens): Ast\PhpDoc\ThrowsTagValueNode
|
||||
{
|
||||
$type = $this->typeParser->parse($tokens);
|
||||
$description = $this->parseOptionalDescription($tokens, true);
|
||||
return new Ast\PhpDoc\ThrowsTagValueNode($type, $description);
|
||||
}
|
||||
|
||||
|
||||
private function parsePropertyTagValue(TokenIterator $tokens): Ast\PhpDoc\PropertyTagValueNode
|
||||
{
|
||||
$type = $this->typeParser->parse($tokens);
|
||||
$parameterName = $this->parseRequiredVariableName($tokens);
|
||||
$description = $this->parseOptionalDescription($tokens);
|
||||
return new Ast\PhpDoc\PropertyTagValueNode($type, $parameterName, $description);
|
||||
}
|
||||
|
||||
|
||||
private function parseMethodTagValue(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueNode
|
||||
{
|
||||
$isStatic = $tokens->tryConsumeTokenValue('static');
|
||||
$returnTypeOrMethodName = $this->typeParser->parse($tokens);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
|
||||
$returnType = $returnTypeOrMethodName;
|
||||
$methodName = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
|
||||
} elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) {
|
||||
$returnType = $isStatic ? new Ast\Type\IdentifierTypeNode('static') : null;
|
||||
$methodName = $returnTypeOrMethodName->name;
|
||||
$isStatic = false;
|
||||
|
||||
} else {
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER); // will throw exception
|
||||
exit;
|
||||
}
|
||||
|
||||
$parameters = [];
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
|
||||
$parameters[] = $this->parseMethodTagValueParameter($tokens);
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
|
||||
$parameters[] = $this->parseMethodTagValueParameter($tokens);
|
||||
}
|
||||
}
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
|
||||
|
||||
$description = $this->parseOptionalDescription($tokens);
|
||||
return new Ast\PhpDoc\MethodTagValueNode($isStatic, $returnType, $methodName, $parameters, $description);
|
||||
}
|
||||
|
||||
|
||||
private function parseMethodTagValueParameter(TokenIterator $tokens): Ast\PhpDoc\MethodTagValueParameterNode
|
||||
{
|
||||
switch ($tokens->currentTokenType()) {
|
||||
case Lexer::TOKEN_IDENTIFIER:
|
||||
case Lexer::TOKEN_OPEN_PARENTHESES:
|
||||
case Lexer::TOKEN_NULLABLE:
|
||||
$parameterType = $this->typeParser->parse($tokens);
|
||||
break;
|
||||
|
||||
default:
|
||||
$parameterType = null;
|
||||
}
|
||||
|
||||
$isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
|
||||
$isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
|
||||
|
||||
$parameterName = $tokens->currentTokenValue();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
|
||||
|
||||
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) {
|
||||
$defaultValue = $this->constantExprParser->parse($tokens);
|
||||
|
||||
} else {
|
||||
$defaultValue = null;
|
||||
}
|
||||
|
||||
return new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue);
|
||||
}
|
||||
|
||||
|
||||
private function parseOptionalVariableName(TokenIterator $tokens): string
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
|
||||
$parameterName = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
|
||||
} else {
|
||||
$parameterName = '';
|
||||
}
|
||||
|
||||
return $parameterName;
|
||||
}
|
||||
|
||||
|
||||
private function parseRequiredVariableName(TokenIterator $tokens): string
|
||||
{
|
||||
$parameterName = $tokens->currentTokenValue();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
|
||||
|
||||
return $parameterName;
|
||||
}
|
||||
|
||||
|
||||
private function parseOptionalDescription(TokenIterator $tokens, bool $limitStartToken = false): string
|
||||
{
|
||||
if ($limitStartToken) {
|
||||
foreach (self::DISALLOWED_DESCRIPTION_START_TOKENS as $disallowedStartToken) {
|
||||
if ($tokens->isCurrentTokenType($disallowedStartToken)) {
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OTHER); // will throw exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->parseText($tokens)->text;
|
||||
}
|
||||
|
||||
}
|
179
vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php
vendored
Normal file
179
vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php
vendored
Normal file
|
@ -0,0 +1,179 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Parser;
|
||||
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
|
||||
class TokenIterator
|
||||
{
|
||||
|
||||
/** @var mixed[][] */
|
||||
private $tokens;
|
||||
|
||||
/** @var int */
|
||||
private $index;
|
||||
|
||||
/** @var int[] */
|
||||
private $savePoints = [];
|
||||
|
||||
public function __construct(array $tokens, int $index = 0)
|
||||
{
|
||||
$this->tokens = $tokens;
|
||||
$this->index = $index;
|
||||
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function currentTokenValue(): string
|
||||
{
|
||||
return $this->tokens[$this->index][Lexer::VALUE_OFFSET];
|
||||
}
|
||||
|
||||
|
||||
public function currentTokenType(): int
|
||||
{
|
||||
return $this->tokens[$this->index][Lexer::TYPE_OFFSET];
|
||||
}
|
||||
|
||||
|
||||
public function currentTokenOffset(): int
|
||||
{
|
||||
$offset = 0;
|
||||
for ($i = 0; $i < $this->index; $i++) {
|
||||
$offset += strlen($this->tokens[$i][Lexer::VALUE_OFFSET]);
|
||||
}
|
||||
|
||||
return $offset;
|
||||
}
|
||||
|
||||
|
||||
public function isCurrentTokenValue(string $tokenValue): bool
|
||||
{
|
||||
return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue;
|
||||
}
|
||||
|
||||
|
||||
public function isCurrentTokenType(int $tokenType): bool
|
||||
{
|
||||
return $this->tokens[$this->index][Lexer::TYPE_OFFSET] === $tokenType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $tokenType
|
||||
* @throws \PHPStan\PhpDocParser\Parser\ParserException
|
||||
*/
|
||||
public function consumeTokenType(int $tokenType)
|
||||
{
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
|
||||
$this->throwError($tokenType);
|
||||
}
|
||||
|
||||
$this->index++;
|
||||
|
||||
if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function tryConsumeTokenValue(string $tokenValue): bool
|
||||
{
|
||||
if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->index++;
|
||||
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function tryConsumeTokenType(int $tokenType): bool
|
||||
{
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->index++;
|
||||
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function getSkippedHorizontalWhiteSpaceIfAny(): string
|
||||
{
|
||||
if ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
return $this->tokens[$this->index - 1][Lexer::VALUE_OFFSET];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function joinUntil(int ...$tokenType): string
|
||||
{
|
||||
$s = '';
|
||||
while (!in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, true)) {
|
||||
$s .= $this->tokens[$this->index++][Lexer::VALUE_OFFSET];
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
|
||||
|
||||
public function next()
|
||||
{
|
||||
$this->index++;
|
||||
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function pushSavePoint()
|
||||
{
|
||||
$this->savePoints[] = $this->index;
|
||||
}
|
||||
|
||||
|
||||
public function dropSavePoint()
|
||||
{
|
||||
array_pop($this->savePoints);
|
||||
}
|
||||
|
||||
|
||||
public function rollback()
|
||||
{
|
||||
$index = array_pop($this->savePoints);
|
||||
assert($index !== null);
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $expectedTokenType
|
||||
* @throws \PHPStan\PhpDocParser\Parser\ParserException
|
||||
*/
|
||||
private function throwError(int $expectedTokenType)
|
||||
{
|
||||
throw new \PHPStan\PhpDocParser\Parser\ParserException(
|
||||
$this->currentTokenValue(),
|
||||
$this->currentTokenType(),
|
||||
$this->currentTokenOffset(),
|
||||
$expectedTokenType
|
||||
);
|
||||
}
|
||||
|
||||
}
|
211
vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php
vendored
Normal file
211
vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php
vendored
Normal file
|
@ -0,0 +1,211 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\PhpDocParser\Parser;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
|
||||
class TypeParser
|
||||
{
|
||||
|
||||
public function parse(TokenIterator $tokens): Ast\Type\TypeNode
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
|
||||
$type = $this->parseNullable($tokens);
|
||||
|
||||
} else {
|
||||
$type = $this->parseAtomic($tokens);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) {
|
||||
$type = $this->parseUnion($tokens, $type);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
|
||||
$type = $this->parseIntersection($tokens, $type);
|
||||
}
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
private function parseAtomic(TokenIterator $tokens): Ast\Type\TypeNode
|
||||
{
|
||||
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
|
||||
$type = $this->parse($tokens);
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
|
||||
$type = $this->tryParseArray($tokens, $type);
|
||||
}
|
||||
|
||||
} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
|
||||
return new Ast\Type\ThisTypeNode();
|
||||
|
||||
} else {
|
||||
$type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
|
||||
$type = $this->parseGeneric($tokens, $type);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
|
||||
$type = $this->tryParseCallable($tokens, $type);
|
||||
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
|
||||
$type = $this->tryParseArray($tokens, $type);
|
||||
}
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
private function parseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
|
||||
{
|
||||
$types = [$type];
|
||||
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
|
||||
$types[] = $this->parseAtomic($tokens);
|
||||
}
|
||||
|
||||
return new Ast\Type\UnionTypeNode($types);
|
||||
}
|
||||
|
||||
|
||||
private function parseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
|
||||
{
|
||||
$types = [$type];
|
||||
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
|
||||
$types[] = $this->parseAtomic($tokens);
|
||||
}
|
||||
|
||||
return new Ast\Type\IntersectionTypeNode($types);
|
||||
}
|
||||
|
||||
|
||||
private function parseNullable(TokenIterator $tokens): Ast\Type\TypeNode
|
||||
{
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_NULLABLE);
|
||||
|
||||
$type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
|
||||
$type = $this->parseGeneric($tokens, $type);
|
||||
}
|
||||
|
||||
return new Ast\Type\NullableTypeNode($type);
|
||||
}
|
||||
|
||||
|
||||
private function parseGeneric(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $baseType): Ast\Type\TypeNode
|
||||
{
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
|
||||
$genericTypes[] = $this->parse($tokens);
|
||||
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
|
||||
$genericTypes[] = $this->parse($tokens);
|
||||
}
|
||||
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
|
||||
return new Ast\Type\GenericTypeNode($baseType, $genericTypes);
|
||||
}
|
||||
|
||||
|
||||
private function parseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier): Ast\Type\TypeNode
|
||||
{
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
|
||||
|
||||
$parameters = [];
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
|
||||
$parameters[] = $this->parseCallableParameter($tokens);
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
|
||||
$parameters[] = $this->parseCallableParameter($tokens);
|
||||
}
|
||||
}
|
||||
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_COLON);
|
||||
$returnType = $this->parseCallableReturnType($tokens);
|
||||
|
||||
return new Ast\Type\CallableTypeNode($identifier, $parameters, $returnType);
|
||||
}
|
||||
|
||||
|
||||
private function parseCallableParameter(TokenIterator $tokens): Ast\Type\CallableTypeParameterNode
|
||||
{
|
||||
$type = $this->parse($tokens);
|
||||
$isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
|
||||
$isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
|
||||
$parameterName = $tokens->currentTokenValue();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
|
||||
|
||||
} else {
|
||||
$parameterName = '';
|
||||
}
|
||||
|
||||
$isOptional = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
|
||||
return new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional);
|
||||
}
|
||||
|
||||
|
||||
private function parseCallableReturnType(TokenIterator $tokens): Ast\Type\TypeNode
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
|
||||
$type = $this->parseNullable($tokens);
|
||||
|
||||
} elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
|
||||
$type = $this->parse($tokens);
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
|
||||
|
||||
} else {
|
||||
$type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
|
||||
$type = $this->parseGeneric($tokens, $type);
|
||||
}
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
private function tryParseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier): Ast\Type\TypeNode
|
||||
{
|
||||
try {
|
||||
$tokens->pushSavePoint();
|
||||
$type = $this->parseCallable($tokens, $identifier);
|
||||
$tokens->dropSavePoint();
|
||||
|
||||
} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
|
||||
$tokens->rollback();
|
||||
$type = $identifier;
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
|
||||
private function tryParseArray(TokenIterator $tokens, Ast\Type\TypeNode $type): Ast\Type\TypeNode
|
||||
{
|
||||
try {
|
||||
while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
|
||||
$tokens->pushSavePoint();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET);
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
|
||||
$tokens->dropSavePoint();
|
||||
$type = new Ast\Type\ArrayTypeNode($type);
|
||||
}
|
||||
|
||||
} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
|
||||
$tokens->rollback();
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
}
|
27
vendor/phpstan/phpstan/.editorconfig
vendored
Normal file
27
vendor/phpstan/phpstan/.editorconfig
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{php,phpt}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.xml]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.neon]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.{yaml,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[composer.json]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
2
vendor/phpstan/phpstan/.gitattributes
vendored
Normal file
2
vendor/phpstan/phpstan/.gitattributes
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/build export-ignore
|
||||
/tests export-ignore
|
15
vendor/phpstan/phpstan/.github/ISSUE_TEMPLATE.md
vendored
Normal file
15
vendor/phpstan/phpstan/.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
<!-- Before reporting an issue please check that you are using the latest PHPStan version! -->
|
||||
|
||||
### Summary of a problem or a feature request
|
||||
|
||||
<!-- Please describe your problem/feature request here. -->
|
||||
|
||||
|
||||
### Code snippet that reproduces the problem
|
||||
|
||||
<!-- Try to reproduce the issue you are facing using https://phpstan.org/ (click Preview, check result, and then "Analyze & Persist" to get a unique URL) -->
|
||||
|
||||
|
||||
### Expected output
|
||||
|
||||
<!-- Was the issue reported incorrectly? Or should PHPStan detect an issue with the code but doesn't? -->
|
61
vendor/phpstan/phpstan/.travis.yml
vendored
Normal file
61
vendor/phpstan/phpstan/.travis.yml
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
dist: xenial
|
||||
language: php
|
||||
|
||||
stages:
|
||||
- test
|
||||
- name: phar-test
|
||||
if: branch = master && type = push
|
||||
- name: phar-push
|
||||
if: branch = master && type = push
|
||||
|
||||
php:
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
- master
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- dependencies=lowest
|
||||
- dependencies=highest
|
||||
global:
|
||||
secure: Wxs9IuFkyacKk/Cu4qxFkkSldob6AhJtx3MDS6Nehz/VF4M88awmI/GcVzfcXjFIA2+EJlkA+X0ymxP9xY5sp+vvmF4mkBIOvSvQdIOLsy73Ixpji3nqc8+epuvtBUGA4Y2xlLmBxSPYZlpVc/DRR2mIlzqDfOQc+gUmJ1aOZPUvs533cl4k0V23hU7L3LxgAnNY7j5vfNgYUhLqBHnqZ0yHt+m0x56wTOBHIBXH+LVNdgsl07fZnuC9HBb3lZKhtCtJiMyC0SsFQLljESaedTHRzptcOuvO+3dmt9R+AP/WxbdmleBaozCrwpdCK3Lqwrt9DXkxtn9ERjtVg0uT2KV5Mm5y4W0w9EXzX/8iUexlJaYOP7OYBtaV0R65w+oiC9dupKiFFvQtJkWcMg+4FCqEjNVM/smXin7+4dLgXiioLtqbjyQQqVwy/U+UmkQ5KIcWjJZGWkL79j1z1e29esNudieXqrX/yvGUW7Ng+4U3G2IHdWH3nMmjwx5/oBuOlc+6vu5aXdDRZVE12CJZ2X/uyJW2Ls5YLJsThAJ9roxsZ29MNZRihUOGk2lLDy/Q5TS6VcsaUmRaZHngM7Xt7v7pJLLbPIomgqGshPKxEXFO3vowZ7nXT1gJX0/FaBBqOahW0scGnxfZlJRZPWbvTg8gxhIGRxhNNYaX5Bb2hw8=
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: master
|
||||
|
||||
before_script:
|
||||
- if php --ri xdebug >/dev/null; then phpenv config-rm xdebug.ini; fi
|
||||
|
||||
install:
|
||||
- if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest --no-interaction; fi
|
||||
- if [ "$dependencies" = "highest" ]; then composer update --no-interaction; fi
|
||||
|
||||
script:
|
||||
- vendor/bin/phing
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: phar-test
|
||||
script:
|
||||
- git clone https://github.com/phpstan/phpstan-compiler && cd phpstan-compiler && ./run-e2e-tests.sh $TRAVIS_COMMIT
|
||||
- stage: phar-push
|
||||
script:
|
||||
- |
|
||||
git clone https://github.com/phpstan/phpstan-compiler && \
|
||||
composer install --working-dir=phpstan-compiler && \
|
||||
php phpstan-compiler/bin/compile $TRAVIS_COMMIT && \
|
||||
git clone https://${GITHUB_TOKEN}@github.com/phpstan/phpstan-shim.git > /dev/null 2>&1 && \
|
||||
cp phpstan-compiler/tmp/phpstan.phar phpstan-shim/phpstan.phar && \
|
||||
cp phpstan-compiler/tmp/phpstan.phar phpstan-shim/phpstan && \
|
||||
cd phpstan-shim && \
|
||||
git config user.email "travis@travis-ci.org" && \
|
||||
git config user.name "Travis CI" && \
|
||||
git add phpstan phpstan.phar && \
|
||||
git commit -m "Updated PHPStan to commit ${TRAVIS_COMMIT}" && \
|
||||
git push --quiet origin master
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
- tmp
|
65
vendor/phpstan/phpstan/BACKERS.md
vendored
Normal file
65
vendor/phpstan/phpstan/BACKERS.md
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
# Backers
|
||||
|
||||
Development of PHPStan is made possible thanks to these awesome backers!
|
||||
You can become one of them by [pledging on Patreon](https://www.patreon.com/phpstan).
|
||||
|
||||
Check out all the tiers - higher ones include additional goodies like placing
|
||||
the logo of your company in PHPStan's README.
|
||||
|
||||
# $50+
|
||||
|
||||
* MessageBird
|
||||
|
||||
# $10+
|
||||
|
||||
* Adam Lundrigan
|
||||
* Scott Arciszewski
|
||||
|
||||
# $5+
|
||||
|
||||
* Adam Žurek
|
||||
* Bart Reunes
|
||||
* Carlos C Soto
|
||||
* Craig Mayhew
|
||||
* David Šolc
|
||||
* Dennis Haarbrink
|
||||
* Haralan Dobrev
|
||||
* Ilija Tovilo
|
||||
* Jake B
|
||||
* Jakub Chábek
|
||||
* Jakub Červený
|
||||
* Jan Endel
|
||||
* Jan Kuchař
|
||||
* Lars Roettig
|
||||
* Lukas Unger
|
||||
* Masaru Yamagishi
|
||||
* Michael Moll
|
||||
* Pavel Vondrášek
|
||||
* René Kliment
|
||||
* Rudolph Gottesheim
|
||||
* seagoj
|
||||
* Stefan Zielke
|
||||
* Thomas Daugaard
|
||||
* Tomasz
|
||||
* Tommy Muehle
|
||||
* Vašek Brychta
|
||||
* Woda Digital
|
||||
|
||||
# $1+
|
||||
|
||||
* Andrew Barlow
|
||||
* Broken Bialek
|
||||
* Christian Sjöström
|
||||
* Craig Duncan
|
||||
* Honza Cerny
|
||||
* Ian Den Hartog
|
||||
* Ivan Kvasnica
|
||||
* korchasa
|
||||
* Lucas Dos Santos Abreu
|
||||
* Martin Lukeš
|
||||
* Matej Drame
|
||||
* Michal Mleczko
|
||||
* Michał Włodarczyk
|
||||
* Oliver Klee
|
||||
* Ondrej Vodacek
|
||||
* Wouter Admiraal
|
74
vendor/phpstan/phpstan/CODE_OF_CONDUCT.md
vendored
Normal file
74
vendor/phpstan/phpstan/CODE_OF_CONDUCT.md
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project maintainer at <ondrej@mirtes.cz>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
21
vendor/phpstan/phpstan/LICENSE
vendored
Normal file
21
vendor/phpstan/phpstan/LICENSE
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 Ondřej Mirtes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
714
vendor/phpstan/phpstan/README.md
vendored
Normal file
714
vendor/phpstan/phpstan/README.md
vendored
Normal file
|
@ -0,0 +1,714 @@
|
|||
<h1 align="center">PHPStan - PHP Static Analysis Tool</h1>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://i.imgur.com/MOt7taM.png" alt="PHPStan" width="300" height="300">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/phpstan/phpstan"><img src="https://travis-ci.org/phpstan/phpstan.svg" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/phpstan/phpstan"><img src="https://poser.pugx.org/phpstan/phpstan/v/stable" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/phpstan/phpstan/stats"><img src="https://poser.pugx.org/phpstan/phpstan/downloads" alt="Total Downloads"></a>
|
||||
<a href="https://choosealicense.com/licenses/mit/"><img src="https://poser.pugx.org/phpstan/phpstan/license" alt="License"></a>
|
||||
<a href="https://github.com/phpstan/phpstan"><img src="https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat" alt="PHPStan Enabled"></a>
|
||||
</p>
|
||||
|
||||
------
|
||||
|
||||
PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs
|
||||
even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code
|
||||
can be checked before you run the actual line.
|
||||
|
||||
**[Read more about PHPStan on Medium.com »](https://medium.com/@ondrejmirtes/phpstan-2939cd0ad0e3)**
|
||||
|
||||
**[Try out PHPStan on the on-line playground! »](https://phpstan.org/)**
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://mike-pretzlaw.de/"><img src="https://i.imgur.com/TW2US6H.png" alt="Mike Pretzlaw" width="247" height="64"></a>
|
||||
|
||||
<a href="https://coders.thecodingmachine.com/phpstan"><img src="https://i.imgur.com/kQhNOTP.png" alt="TheCodingMachine" width="247" height="64"></a>
|
||||
|
||||
<a href="https://www.wispay.io/t/JdL" target="_blank"><img src="https://assets.wispay.io/wgt2_d_o.png" width="247" height="78"></a>
|
||||
|
||||
Check out [PHPStan's Patreon](https://www.patreon.com/phpstan) for sponsoring options. One-time donations [through PayPal](https://paypal.me/phpstan) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
PHPStan requires PHP >= 7.1. You have to run it in environment with PHP 7.x but the actual code does not have to use
|
||||
PHP 7.x features. (Code written for PHP 5.6 and earlier can run on 7.x mostly unmodified.)
|
||||
|
||||
PHPStan works best with modern object-oriented code. The more strongly-typed your code is, the more information
|
||||
you give PHPStan to work with.
|
||||
|
||||
Properly annotated and typehinted code (class properties, function and method arguments, return types) helps
|
||||
not only static analysis tools but also other people that work with the code to understand it.
|
||||
|
||||
## Installation
|
||||
|
||||
To start performing analysis on your code, require PHPStan in [Composer](https://getcomposer.org/):
|
||||
|
||||
```
|
||||
composer require --dev phpstan/phpstan
|
||||
```
|
||||
|
||||
Composer will install PHPStan's executable in its `bin-dir` which defaults to `vendor/bin`.
|
||||
|
||||
If you have conflicting dependencies or you want to install PHPStan globally, the best way is via a PHAR archive. You will always find the latest stable PHAR archive below the [release notes](https://github.com/phpstan/phpstan/releases). You can also use the [phpstan/phpstan-shim](https://packagist.org/packages/phpstan/phpstan-shim) package to install PHPStan via Composer without the risk of conflicting dependencies.
|
||||
|
||||
You can also use [PHPStan via Docker](https://github.com/phpstan/docker-image).
|
||||
|
||||
## First run
|
||||
|
||||
To let PHPStan analyse your codebase, you have to use the `analyse` command and point it to the right directories.
|
||||
|
||||
So, for example if you have your classes in directories `src` and `tests`, you can run PHPStan like this:
|
||||
|
||||
```bash
|
||||
vendor/bin/phpstan analyse src tests
|
||||
```
|
||||
|
||||
PHPStan will probably find some errors, but don't worry, your code might be just fine. Errors found
|
||||
on the first run tend to be:
|
||||
|
||||
* Extra arguments passed to functions (e. g. function requires two arguments, the code passes three)
|
||||
* Extra arguments passed to print/sprintf functions (e. g. format string contains one placeholder, the code passes two values to replace)
|
||||
* Obvious errors in dead code
|
||||
* Magic behaviour that needs to be defined. See [Extensibility](#extensibility).
|
||||
|
||||
After fixing the obvious mistakes in the code, look to the following section
|
||||
for all the configuration options that will bring the number of reported errors to zero
|
||||
making PHPStan suitable to run as part of your continuous integration script.
|
||||
|
||||
## Rule levels
|
||||
|
||||
If you want to use PHPStan but your codebase isn't up to speed with strong typing
|
||||
and PHPStan's strict checks, you can choose from currently 8 levels
|
||||
(0 is the loosest and 7 is the strictest) by passing `--level` to `analyse` command. Default level is `0`.
|
||||
|
||||
This feature enables incremental adoption of PHPStan checks. You can start using PHPStan
|
||||
with a lower rule level and increase it when you feel like it.
|
||||
|
||||
You can also use `--level max` as an alias for the highest level. This will ensure that you will always use the highest level when upgrading to new versions of PHPStan. Please note that this can create a significant obstacle when upgrading to a newer version because you might have to fix a lot of code to bring the number of errors down to zero.
|
||||
|
||||
## Extensibility
|
||||
|
||||
Unique feature of PHPStan is the ability to define and statically check "magic" behaviour of classes -
|
||||
accessing properties that are not defined in the class but are created in `__get` and `__set`
|
||||
and invoking methods using `__call`.
|
||||
|
||||
See [Class reflection extensions](#class-reflection-extensions), [Dynamic return type extensions](#dynamic-return-type-extensions) and [Type-specifying extensions](#type-specifying-extensions).
|
||||
|
||||
You can also install official framework-specific extensions:
|
||||
|
||||
* [Doctrine](https://github.com/phpstan/phpstan-doctrine)
|
||||
* [PHPUnit](https://github.com/phpstan/phpstan-phpunit)
|
||||
* [Nette Framework](https://github.com/phpstan/phpstan-nette)
|
||||
* [Dibi - Database Abstraction Library](https://github.com/phpstan/phpstan-dibi)
|
||||
* [PHP-Parser](https://github.com/phpstan/phpstan-php-parser)
|
||||
* [beberlei/assert](https://github.com/phpstan/phpstan-beberlei-assert)
|
||||
* [webmozart/assert](https://github.com/phpstan/phpstan-webmozart-assert)
|
||||
* [Symfony Framework](https://github.com/phpstan/phpstan-symfony)
|
||||
* [Mockery](https://github.com/phpstan/phpstan-mockery)
|
||||
|
||||
Unofficial extensions for other frameworks and libraries are also available:
|
||||
|
||||
* [Phony](https://github.com/eloquent/phpstan-phony)
|
||||
* [Prophecy](https://github.com/Jan0707/phpstan-prophecy)
|
||||
* [Laravel](https://github.com/nunomaduro/larastan)
|
||||
* [myclabs/php-enum](https://github.com/timeweb/phpstan-enum)
|
||||
* [Yii2](https://github.com/proget-hq/phpstan-yii2)
|
||||
* [PhpSpec](https://github.com/proget-hq/phpstan-phpspec)
|
||||
* [TYPO3](https://github.com/sascha-egerer/phpstan-typo3)
|
||||
|
||||
New extensions are becoming available on a regular basis!
|
||||
|
||||
## Configuration
|
||||
|
||||
Config file is passed to the `phpstan` executable with `-c` option:
|
||||
|
||||
```bash
|
||||
vendor/bin/phpstan analyse -l 4 -c phpstan.neon src tests
|
||||
```
|
||||
|
||||
When using a custom project config file, you have to pass the `--level` (`-l`)
|
||||
option to `analyse` command (default value does not apply here).
|
||||
|
||||
If you do not provide config file explicitly, PHPStan will look for
|
||||
files named `phpstan.neon` or `phpstan.neon.dist` in current directory.
|
||||
|
||||
The resolution priority is as such:
|
||||
1. If config file is provided on command line, it is used.
|
||||
2. If config file `phpstan.neon` exists in current directory, it will be used.
|
||||
3. If config file `phpstan.neon.dist` exists in current directory, it will be used.
|
||||
4. If none of the above is true, no config will be used.
|
||||
|
||||
[NEON file format](https://ne-on.org/) is very similar to YAML.
|
||||
All the following options are part of the `parameters` section.
|
||||
|
||||
#### Configuration variables
|
||||
- `%rootDir%` - root directory where PHPStan resides (i.e. `vendor/phpstan/phpstan` in Composer installation)
|
||||
- `%currentWorkingDirectory%` - current working directory where PHPStan was executed
|
||||
|
||||
#### Configuration options
|
||||
|
||||
- `tmpDir` - specifies the temporary directory used by PHPStan cache (defaults to `sys_get_temp_dir() . '/phpstan'`)
|
||||
- `level` - specifies analysis level - if specified, `-l` option is not required
|
||||
- `paths` - specifies analysed paths - if specified, paths are not required to be passed as arguments
|
||||
|
||||
### Autoloading
|
||||
|
||||
PHPStan uses Composer autoloader so the easiest way how to autoload classes
|
||||
is through the `autoload`/`autoload-dev` sections in composer.json.
|
||||
|
||||
#### Specify paths to scan
|
||||
|
||||
If PHPStan complains about some non-existent classes and you're sure the classes
|
||||
exist in the codebase AND you don't want to use Composer autoloader for some reason,
|
||||
you can specify directories to scan and concrete files to include using
|
||||
`autoload_directories` and `autoload_files` array parameters:
|
||||
|
||||
```
|
||||
parameters:
|
||||
autoload_directories:
|
||||
- %rootDir%/../../../build
|
||||
autoload_files:
|
||||
- %rootDir%/../../../generated/routes/GeneratedRouteList.php
|
||||
```
|
||||
|
||||
`%rootDir%` is expanded to the root directory where PHPStan resides.
|
||||
|
||||
#### Autoloading for global installation
|
||||
|
||||
PHPStan supports global installation using [`composer global`](https://getcomposer.org/doc/03-cli.md#global) or via a [PHAR archive](#installation).
|
||||
In this case, it's not part of the project autoloader, but it supports autodiscovery of the Composer autoloader
|
||||
from current working directory residing in `vendor/`:
|
||||
|
||||
```bash
|
||||
cd /path/to/project
|
||||
phpstan analyse src tests # looks for autoloader at /path/to/project/vendor/autoload.php
|
||||
```
|
||||
|
||||
If you have your dependencies installed at a different path
|
||||
or you're running PHPStan from a different directory,
|
||||
you can specify the path to the autoloader with the `--autoload-file|-a` option:
|
||||
|
||||
```bash
|
||||
phpstan analyse --autoload-file=/path/to/autoload.php src tests
|
||||
```
|
||||
|
||||
### Exclude files from analysis
|
||||
|
||||
If your codebase contains some files that are broken on purpose
|
||||
(e. g. to test behaviour of your application on files with invalid PHP code),
|
||||
you can exclude them using the `excludes_analyse` array parameter. String at each line
|
||||
is used as a pattern for the [`fnmatch`](https://secure.php.net/manual/en/function.fnmatch.php) function.
|
||||
|
||||
```
|
||||
parameters:
|
||||
excludes_analyse:
|
||||
- %rootDir%/../../../tests/*/data/*
|
||||
```
|
||||
|
||||
### Include custom extensions
|
||||
|
||||
If your codebase contains php files with extensions other than the standard .php extension then you can add them
|
||||
to the `fileExtensions` array parameter:
|
||||
|
||||
```
|
||||
parameters:
|
||||
fileExtensions:
|
||||
- php
|
||||
- module
|
||||
- inc
|
||||
```
|
||||
|
||||
### Universal object crates
|
||||
|
||||
Classes without predefined structure are common in PHP applications.
|
||||
They are used as universal holders of data - any property can be set and read on them. Notable examples
|
||||
include `stdClass`, `SimpleXMLElement` (these are enabled by default), objects with results of database queries etc.
|
||||
Use `universalObjectCratesClasses` array parameter to let PHPStan know which classes
|
||||
with these characteristics are used in your codebase:
|
||||
|
||||
```
|
||||
parameters:
|
||||
universalObjectCratesClasses:
|
||||
- Dibi\Row
|
||||
- Ratchet\ConnectionInterface
|
||||
```
|
||||
|
||||
### Add non-obviously assigned variables to scope
|
||||
|
||||
If you use some variables from a try block in your catch blocks, set `polluteCatchScopeWithTryAssignments` boolean parameter to `true`.
|
||||
|
||||
```php
|
||||
try {
|
||||
$author = $this->getLoggedInUser();
|
||||
$post = $this->postRepository->getById($id);
|
||||
} catch (PostNotFoundException $e) {
|
||||
// $author is probably defined here
|
||||
throw new ArticleByAuthorCannotBePublished($author);
|
||||
}
|
||||
```
|
||||
|
||||
If you are enumerating over all possible situations in if-elseif branches
|
||||
and PHPStan complains about undefined variables after the conditions, you can write
|
||||
an else branch with throwing an exception:
|
||||
|
||||
```php
|
||||
if (somethingIsTrue()) {
|
||||
$foo = true;
|
||||
} elseif (orSomethingElseIsTrue()) {
|
||||
$foo = false;
|
||||
} else {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
doFoo($foo);
|
||||
```
|
||||
|
||||
I recommend leaving `polluteCatchScopeWithTryAssignments` set to `false` because it leads to a clearer and more maintainable code.
|
||||
|
||||
### Custom early terminating method calls
|
||||
|
||||
Previous example showed that if a condition branches end with throwing an exception, that branch does not have
|
||||
to define a variable used after the condition branches end.
|
||||
|
||||
But exceptions are not the only way how to terminate execution of a method early. Some specific method calls
|
||||
can be perceived by project developers also as early terminating - like a `redirect()` that stops execution
|
||||
by throwing an internal exception.
|
||||
|
||||
```php
|
||||
if (somethingIsTrue()) {
|
||||
$foo = true;
|
||||
} elseif (orSomethingElseIsTrue()) {
|
||||
$foo = false;
|
||||
} else {
|
||||
$this->redirect('homepage');
|
||||
}
|
||||
|
||||
doFoo($foo);
|
||||
```
|
||||
|
||||
These methods can be configured by specifying a class on whose instance they are called like this:
|
||||
|
||||
```
|
||||
parameters:
|
||||
earlyTerminatingMethodCalls:
|
||||
Nette\Application\UI\Presenter:
|
||||
- redirect
|
||||
- redirectUrl
|
||||
- sendJson
|
||||
- sendResponse
|
||||
```
|
||||
|
||||
### Ignore error messages with regular expressions
|
||||
|
||||
If some issue in your code base is not easy to fix or just simply want to deal with it later,
|
||||
you can exclude error messages from the analysis result with regular expressions:
|
||||
|
||||
```
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
- '#Call to an undefined method [a-zA-Z0-9\\_]+::method\(\)#'
|
||||
- '#Call to an undefined method [a-zA-Z0-9\\_]+::expects\(\)#'
|
||||
- '#Access to an undefined property PHPUnit_Framework_MockObject_MockObject::\$[a-zA-Z0-9_]+#'
|
||||
- '#Call to an undefined method PHPUnit_Framework_MockObject_MockObject::[a-zA-Z0-9_]+\(\)#'
|
||||
```
|
||||
|
||||
To exclude an error in a specific directory or file, specify a `path` along with the `message`:
|
||||
|
||||
```
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: '#Call to an undefined method [a-zA-Z0-9\\_]+::method\(\)#'
|
||||
path: %currentWorkingDirectory%/some/dir/SomeFile.php
|
||||
-
|
||||
message: '#Call to an undefined method [a-zA-Z0-9\\_]+::method\(\)#'
|
||||
path: %currentWorkingDirectory%/other/dir/*
|
||||
- '#Other error to catch anywhere#'
|
||||
```
|
||||
|
||||
If some of the patterns do not occur in the result anymore, PHPStan will let you know
|
||||
and you will have to remove the pattern from the configuration. You can turn off
|
||||
this behaviour by setting `reportUnmatchedIgnoredErrors` to `false` in PHPStan configuration.
|
||||
|
||||
### Bootstrap file
|
||||
|
||||
If you need to initialize something in PHP runtime before PHPStan runs (like your own autoloader),
|
||||
you can provide your own bootstrap file:
|
||||
|
||||
```
|
||||
parameters:
|
||||
bootstrap: %rootDir%/../../../phpstan-bootstrap.php
|
||||
```
|
||||
|
||||
### Custom rules
|
||||
|
||||
PHPStan allows writing custom rules to check for specific situations in your own codebase. Your rule class
|
||||
needs to implement the `PHPStan\Rules\Rule` interface and registered as a service in the configuration file:
|
||||
|
||||
```
|
||||
services:
|
||||
-
|
||||
class: MyApp\PHPStan\Rules\DefaultValueTypesAssignedToPropertiesRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
```
|
||||
|
||||
For inspiration on how to implement a rule turn to [src/Rules](https://github.com/phpstan/phpstan/tree/master/src/Rules)
|
||||
to see a lot of built-in rules.
|
||||
|
||||
Check out also [phpstan-strict-rules](https://github.com/phpstan/phpstan-strict-rules) repository for extra strict and opinionated rules for PHPStan!
|
||||
|
||||
### Custom error formatters
|
||||
|
||||
PHPStan outputs errors via formatters. You can customize the output by implementing the `ErrorFormatter` interface in a new class and add it to the configuration. For existing formatters, see next chapter.
|
||||
|
||||
```php
|
||||
interface ErrorFormatter
|
||||
{
|
||||
|
||||
/**
|
||||
* Formats the errors and outputs them to the console.
|
||||
*
|
||||
* @param \PHPStan\Command\AnalysisResult $analysisResult
|
||||
* @param \Symfony\Component\Console\Style\OutputStyle $style
|
||||
* @return int Error code.
|
||||
*/
|
||||
public function formatErrors(
|
||||
AnalysisResult $analysisResult,
|
||||
\Symfony\Component\Console\Style\OutputStyle $style
|
||||
): int;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Register the formatter in your `phpstan.neon`:
|
||||
|
||||
```
|
||||
services:
|
||||
errorFormatter.awesome:
|
||||
class: App\PHPStan\AwesomeErrorFormatter
|
||||
```
|
||||
|
||||
Use the name part after `errorFormatter.` as the CLI option value:
|
||||
|
||||
```bash
|
||||
vendor/bin/phpstan analyse -c phpstan.neon -l 4 --error-format awesome src tests
|
||||
```
|
||||
|
||||
### Existing error formatters to be used
|
||||
|
||||
You can pass the following keywords to the `--error-format=X` parameter in order to affect the output:
|
||||
|
||||
- `table`: Default. Grouped errors by file, colorized. For human consumption.
|
||||
- `raw`: Contains one error per line, with path to file, line number, and error description
|
||||
- `checkstyle`: Creates a checkstyle.xml compatible output. Note that you'd have to redirect output into a file in order to capture the results for later processing.
|
||||
|
||||
## Class reflection extensions
|
||||
|
||||
Classes in PHP can expose "magical" properties and methods decided in run-time using
|
||||
class methods like `__get`, `__set` and `__call`. Because PHPStan is all about static analysis
|
||||
(testing code for errors without running it), it has to know about those properties and methods beforehand.
|
||||
|
||||
When PHPStan stumbles upon a property or a method that is unknown to built-in class reflection, it iterates
|
||||
over all registered class reflection extensions until it finds one that defines the property or method.
|
||||
|
||||
Class reflection extension cannot have `PHPStan\Broker\Broker` (service for obtaining class reflections) injected in the constructor due to circular reference issue, but the extensions can implement `PHPStan\Reflection\BrokerAwareExtension` interface to obtain Broker via a setter.
|
||||
|
||||
### Properties class reflection extensions
|
||||
|
||||
This extension type must implement the following interface:
|
||||
|
||||
```php
|
||||
namespace PHPStan\Reflection;
|
||||
|
||||
interface PropertiesClassReflectionExtension
|
||||
{
|
||||
|
||||
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool;
|
||||
|
||||
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Most likely you will also have to implement a new `PropertyReflection` class:
|
||||
|
||||
```php
|
||||
namespace PHPStan\Reflection;
|
||||
|
||||
interface PropertyReflection
|
||||
{
|
||||
|
||||
public function getType(): Type;
|
||||
|
||||
public function getDeclaringClass(): ClassReflection;
|
||||
|
||||
public function isStatic(): bool;
|
||||
|
||||
public function isPrivate(): bool;
|
||||
|
||||
public function isPublic(): bool;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
This is how you register the extension in project's PHPStan config file:
|
||||
|
||||
```
|
||||
services:
|
||||
-
|
||||
class: App\PHPStan\PropertiesFromAnnotationsClassReflectionExtension
|
||||
tags:
|
||||
- phpstan.broker.propertiesClassReflectionExtension
|
||||
```
|
||||
|
||||
### Methods class reflection extensions
|
||||
|
||||
This extension type must implement the following interface:
|
||||
|
||||
```php
|
||||
namespace PHPStan\Reflection;
|
||||
|
||||
interface MethodsClassReflectionExtension
|
||||
{
|
||||
|
||||
public function hasMethod(ClassReflection $classReflection, string $methodName): bool;
|
||||
|
||||
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Most likely you will also have to implement a new `MethodReflection` class:
|
||||
|
||||
```php
|
||||
namespace PHPStan\Reflection;
|
||||
|
||||
interface MethodReflection
|
||||
{
|
||||
|
||||
public function getDeclaringClass(): ClassReflection;
|
||||
|
||||
public function getPrototype(): self;
|
||||
|
||||
public function isStatic(): bool;
|
||||
|
||||
public function isPrivate(): bool;
|
||||
|
||||
public function isPublic(): bool;
|
||||
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* @return \PHPStan\Reflection\ParameterReflection[]
|
||||
*/
|
||||
public function getParameters(): array;
|
||||
|
||||
public function isVariadic(): bool;
|
||||
|
||||
public function getReturnType(): Type;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
This is how you register the extension in project's PHPStan config file:
|
||||
|
||||
```
|
||||
services:
|
||||
-
|
||||
class: App\PHPStan\EnumMethodsClassReflectionExtension
|
||||
tags:
|
||||
- phpstan.broker.methodsClassReflectionExtension
|
||||
```
|
||||
|
||||
## Dynamic return type extensions
|
||||
|
||||
If the return type of a method is not always the same, but depends on an argument passed to the method,
|
||||
you can specify the return type by writing and registering an extension.
|
||||
|
||||
Because you have to write the code with the type-resolving logic, it can be as complex as you want.
|
||||
|
||||
After writing the sample extension, the variable `$mergedArticle` will have the correct type:
|
||||
|
||||
```php
|
||||
$mergedArticle = $this->entityManager->merge($article);
|
||||
// $mergedArticle will have the same type as $article
|
||||
```
|
||||
|
||||
This is the interface for dynamic return type extension:
|
||||
|
||||
```php
|
||||
namespace PHPStan\Type;
|
||||
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\MethodReflection;
|
||||
|
||||
interface DynamicMethodReturnTypeExtension
|
||||
{
|
||||
|
||||
public function getClass(): string;
|
||||
|
||||
public function isMethodSupported(MethodReflection $methodReflection): bool;
|
||||
|
||||
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
And this is how you'd write the extension that correctly resolves the EntityManager::merge() return type:
|
||||
|
||||
```php
|
||||
public function getClass(): string
|
||||
{
|
||||
return \Doctrine\ORM\EntityManager::class;
|
||||
}
|
||||
|
||||
public function isMethodSupported(MethodReflection $methodReflection): bool
|
||||
{
|
||||
return $methodReflection->getName() === 'merge';
|
||||
}
|
||||
|
||||
public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
|
||||
{
|
||||
if (count($methodCall->args) === 0) {
|
||||
return \PHPStan\Reflection\ParametersAcceptorSelector::selectFromArgs(
|
||||
$scope,
|
||||
$methodCall->args,
|
||||
$methodReflection->getVariants()
|
||||
)->getReturnType();
|
||||
}
|
||||
$arg = $methodCall->args[0]->value;
|
||||
|
||||
return $scope->getType($arg);
|
||||
}
|
||||
```
|
||||
|
||||
And finally, register the extension to PHPStan in the project's config file:
|
||||
|
||||
```
|
||||
services:
|
||||
-
|
||||
class: App\PHPStan\EntityManagerDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||
```
|
||||
|
||||
There's also an analogous functionality for:
|
||||
|
||||
* **static methods** using `DynamicStaticMethodReturnTypeExtension` interface
|
||||
and `phpstan.broker.dynamicStaticMethodReturnTypeExtension` service tag.
|
||||
* **functions** using `DynamicFunctionReturnTypeExtension` interface and `phpstan.broker.dynamicFunctionReturnTypeExtension` service tag.
|
||||
|
||||
## Type-specifying extensions
|
||||
|
||||
These extensions allow you to specify types of expressions based on certain pre-existing conditions. This is best illustrated with couple examples:
|
||||
|
||||
```php
|
||||
if (is_int($variable)) {
|
||||
// here we can be sure that $variable is integer
|
||||
}
|
||||
```
|
||||
|
||||
```php
|
||||
// using PHPUnit's asserts
|
||||
|
||||
self::assertNotNull($variable);
|
||||
// here we can be sure that $variable is not null
|
||||
```
|
||||
|
||||
Type-specifying extension cannot have `PHPStan\Analyser\TypeSpecifier` injected in the constructor due to circular reference issue, but the extensions can implement `PHPStan\Analyser\TypeSpecifierAwareExtension` interface to obtain TypeSpecifier via a setter.
|
||||
|
||||
This is the interface for type-specifying extension:
|
||||
|
||||
```php
|
||||
namespace PHPStan\Type;
|
||||
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Analyser\SpecifiedTypes;
|
||||
use PHPStan\Analyser\TypeSpecifierContext;
|
||||
use PHPStan\Reflection\MethodReflection;
|
||||
|
||||
interface StaticMethodTypeSpecifyingExtension
|
||||
{
|
||||
|
||||
public function getClass(): string;
|
||||
|
||||
public function isStaticMethodSupported(MethodReflection $staticMethodReflection, StaticCall $node, TypeSpecifierContext $context): bool;
|
||||
|
||||
public function specifyTypes(MethodReflection $staticMethodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
And this is how you'd write the extension for the second example above:
|
||||
|
||||
```php
|
||||
public function getClass(): string
|
||||
{
|
||||
return \PHPUnit\Framework\Assert::class;
|
||||
}
|
||||
|
||||
public function isStaticMethodSupported(MethodReflection $staticMethodReflection, StaticCall $node, TypeSpecifierContext $context): bool;
|
||||
{
|
||||
// The $context argument tells us if we're in an if condition or not (as in this case).
|
||||
return $staticMethodReflection->getName() === 'assertNotNull' && $context->null();
|
||||
}
|
||||
|
||||
public function specifyTypes(MethodReflection $staticMethodReflection, StaticCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
|
||||
{
|
||||
// Assuming extension implements \PHPStan\Analyser\TypeSpecifierAwareExtension.
|
||||
return $this->typeSpecifier->create($node->var, \PHPStan\Type\TypeCombinator::removeNull($scope->getType($node->var)), $context);
|
||||
}
|
||||
```
|
||||
|
||||
And finally, register the extension to PHPStan in the project's config file:
|
||||
|
||||
```
|
||||
services:
|
||||
-
|
||||
class: App\PHPStan\AssertNotNullTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension
|
||||
```
|
||||
|
||||
There's also an analogous functionality for:
|
||||
|
||||
* **dynamic methods** using `MethodTypeSpecifyingExtension` interface
|
||||
and `phpstan.typeSpecifier.methodTypeSpecifyingExtension` service tag.
|
||||
* **functions** using `FunctionTypeSpecifyingExtension` interface and `phpstan.typeSpecifier.functionTypeSpecifyingExtension` service tag.
|
||||
|
||||
## Known issues
|
||||
|
||||
* If `include` or `require` are used in the analysed code (instead of `include_once` or `require_once`),
|
||||
PHPStan will throw `Cannot redeclare class` error. Use the `_once` variants to avoid this error.
|
||||
* If PHPStan crashes without outputting any error, it's quite possible that it's
|
||||
because of a low memory limit set on your system. **Run PHPStan again** to read a couple of hints
|
||||
what you can do to prevent the crashes.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project adheres to a [Contributor Code of Conduct](https://github.com/phpstan/phpstan/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.
|
||||
|
||||
## Contributing
|
||||
|
||||
Any contributions are welcome.
|
||||
|
||||
### Building
|
||||
|
||||
You can either run the whole build including linting and coding standards using
|
||||
|
||||
```bash
|
||||
vendor/bin/phing
|
||||
```
|
||||
|
||||
or run only tests using
|
||||
|
||||
```bash
|
||||
vendor/bin/phing tests
|
||||
```
|
70
vendor/phpstan/phpstan/appveyor.yml
vendored
Normal file
70
vendor/phpstan/phpstan/appveyor.yml
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
build: false
|
||||
clone_folder: c:\projects\phpstan
|
||||
clone_depth: 1
|
||||
platform:
|
||||
- x64
|
||||
environment:
|
||||
matrix:
|
||||
- dependencies: lowest
|
||||
php_version: 7.1
|
||||
- dependencies: highest
|
||||
php_version: 7.1
|
||||
- dependencies: lowest
|
||||
php_version: 7.2
|
||||
- dependencies: highest
|
||||
php_version: 7.2
|
||||
- dependencies: lowest
|
||||
php_version: 7.3
|
||||
- dependencies: highest
|
||||
php_version: 7.3
|
||||
|
||||
project_directory: c:\projects\phpstan
|
||||
composer_directory: c:\tools\composer
|
||||
composer_executable: c:\tools\composer\composer.phar
|
||||
composer_installer: c:\tools\composer\installer.php
|
||||
php_root_directory: c:\tools\php
|
||||
cache:
|
||||
- c:\ProgramData\chocolatey\bin -> appveyor.yml
|
||||
- c:\ProgramData\chocolatey\lib -> appveyor.yml
|
||||
- c:\tools\composer -> appveyor.yml
|
||||
- '%LOCALAPPDATA%\Composer -> appveyor.yml'
|
||||
- c:\tools\php -> appveyor.yml
|
||||
init:
|
||||
- ps: $Env:php_directory = $Env:php_root_directory + '\' + $Env:php_version
|
||||
- ps: $Env:exact_php_version = (((choco search php --exact --all-versions --limit-output | Select-String -pattern $Env:php_version) -replace '[php|]', '') | %{ New-Object System.Version $_ } | Sort-Object | Select-Object -Last 1).ToString()
|
||||
- ps: $Env:PATH = $Env:php_directory + ';' + $Env:composer_directory + ';' + $Env:PATH
|
||||
- ps: $Env:COMPOSER_NO_INTERACTION = 1
|
||||
- ps: $Env:ANSICON = '121x90 (121x90)'
|
||||
install:
|
||||
# Install PHP
|
||||
- ps: If ((Test-Path $Env:php_directory) -eq $False) { New-Item -Path $Env:php_directory -ItemType 'directory' }
|
||||
- ps: $php_install_parameters = '"/DontAddToPath /InstallDir:' + $Env:php_directory + '"'
|
||||
- ps: appveyor-retry choco upgrade php --yes --version=$Env:exact_php_version --params=$php_install_parameters
|
||||
|
||||
# Prepare PHP
|
||||
- ps: cd $Env:php_directory
|
||||
- ps: Copy-Item php.ini-production -Destination php.ini
|
||||
- ps: Add-Content -Path php.ini -Value 'memory_limit=1G'
|
||||
- ps: Add-Content -Path php.ini -Value 'date.timezone="UTC"'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension_dir=ext'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension=php_curl.dll'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension=php_mbstring.dll'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension=php_openssl.dll'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension=php_soap.dll'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension=php_mysqli.dll'
|
||||
- ps: Add-Content -Path php.ini -Value 'extension=php_intl.dll'
|
||||
- ps: php --version
|
||||
|
||||
# Prepare composer
|
||||
- ps: If ((Test-Path $Env:composer_directory) -eq $False) { New-Item -Path $Env:composer_directory -ItemType 'directory' }
|
||||
- ps: If ((Test-Path $Env:composer_installer) -eq $False) { appveyor-retry appveyor DownloadFile https://getcomposer.org/installer -FileName $Env:composer_installer }
|
||||
- ps: If ((Test-Path $Env:composer_executable) -eq $False) { php $Env:composer_installer --install-dir=$Env:composer_directory }
|
||||
- ps: Set-Content -Path ($Env:composer_directory + '\composer.bat') -Value ('@php ' + $Env:composer_executable + ' %*')
|
||||
|
||||
# Install dependencies
|
||||
- ps: cd $Env:project_directory
|
||||
- IF %dependencies%==lowest composer update --prefer-dist --prefer-lowest --prefer-stable --no-progress
|
||||
- IF %dependencies%==highest composer update --prefer-dist --no-progress
|
||||
test_script:
|
||||
- ps: cd $Env:project_directory
|
||||
- vendor\bin\phing
|
41
vendor/phpstan/phpstan/bin/phpstan
vendored
Executable file
41
vendor/phpstan/phpstan/bin/phpstan
vendored
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env php
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
use Composer\XdebugHandler\XdebugHandler;
|
||||
use PHPStan\Command\AnalyseCommand;
|
||||
use PHPStan\Command\DumpDependenciesCommand;
|
||||
|
||||
gc_disable(); // performance boost
|
||||
|
||||
define('__PHPSTAN_RUNNING__', true);
|
||||
|
||||
$autoloaderInWorkingDirectory = getcwd() . '/vendor/autoload.php';
|
||||
if (is_file($autoloaderInWorkingDirectory)) {
|
||||
require_once $autoloaderInWorkingDirectory;
|
||||
}
|
||||
|
||||
$composerAutoloadFile = __DIR__ . '/../vendor/autoload.php';
|
||||
if (!is_file($composerAutoloadFile)) {
|
||||
$composerAutoloadFile = __DIR__ . '/../../../autoload.php';
|
||||
}
|
||||
|
||||
require_once $composerAutoloadFile;
|
||||
|
||||
$xdebug = new XdebugHandler('phpstan', '--ansi');
|
||||
$xdebug->check();
|
||||
unset($xdebug);
|
||||
|
||||
$version = 'Version unknown';
|
||||
try {
|
||||
$version = \Jean85\PrettyVersions::getVersion('phpstan/phpstan')->getPrettyVersion();
|
||||
} catch (\OutOfBoundsException $e) {
|
||||
|
||||
}
|
||||
|
||||
$application = new \Symfony\Component\Console\Application(
|
||||
'PHPStan - PHP Static Analysis Tool',
|
||||
$version
|
||||
);
|
||||
$application->add(new AnalyseCommand());
|
||||
$application->add(new DumpDependenciesCommand());
|
||||
$application->run();
|
244
vendor/phpstan/phpstan/build.xml
vendored
Normal file
244
vendor/phpstan/phpstan/build.xml
vendored
Normal file
|
@ -0,0 +1,244 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project name="PHPStan" default="check">
|
||||
<property name="path.composer-require-checker"
|
||||
value="tmp/composer-require-checker-1.1.0.phar"/>
|
||||
<property name="url.composer-require-checker"
|
||||
value="https://github.com/maglnet/ComposerRequireChecker/releases/download/1.1.0/composer-require-checker.phar"/>
|
||||
<target name="check" depends="
|
||||
composer-validate,
|
||||
composer-install,
|
||||
lint,
|
||||
cs,
|
||||
composer-normalize-check,
|
||||
composer-require-checker,
|
||||
test-configuration-validate,
|
||||
tests,
|
||||
phpstan
|
||||
"/>
|
||||
|
||||
<target name="composer-validate">
|
||||
<exec
|
||||
executable="composer"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="validate"/>
|
||||
<arg value="--ansi"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="composer-install">
|
||||
<exec
|
||||
executable="composer"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="install"/>
|
||||
<arg value="--ansi"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="composer-normalize-check">
|
||||
<exec
|
||||
executable="composer"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="normalize"/>
|
||||
<arg value="--ansi"/>
|
||||
<arg value="--dry-run"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="composer-normalize-fix">
|
||||
<exec
|
||||
executable="composer"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="normalize"/>
|
||||
<arg value="--ansi"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="composer-require-checker">
|
||||
<if>
|
||||
<and>
|
||||
<not>
|
||||
<available file="${path.composer-require-checker}"/>
|
||||
</not>
|
||||
<not><os family="windows"/></not>
|
||||
</and>
|
||||
<then>
|
||||
<exec
|
||||
executable="wget"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="-O"/>
|
||||
<arg path="${path.composer-require-checker}"/>
|
||||
<arg value="${url.composer-require-checker}"/>
|
||||
</exec>
|
||||
</then>
|
||||
</if>
|
||||
<if>
|
||||
<available file="${path.composer-require-checker}"/>
|
||||
<then>
|
||||
<exec
|
||||
executable="php"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg path="${path.composer-require-checker}"/>
|
||||
<arg value="check"/>
|
||||
<arg value="--config-file"/>
|
||||
<arg path="${project.basedir}/build/composer-require-checker.json"/>
|
||||
<arg path="composer.json"/>
|
||||
</exec>
|
||||
</then>
|
||||
</if>
|
||||
</target>
|
||||
|
||||
<target name="lint">
|
||||
<exec
|
||||
executable="vendor/bin/parallel-lint"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="--colors"/>
|
||||
<arg value="--exclude"/>
|
||||
<arg path="tests/PHPStan/Analyser/data"/>
|
||||
<arg value="--exclude"/>
|
||||
<arg path="tests/PHPStan/Rules/Methods/data"/>
|
||||
<arg value="--exclude"/>
|
||||
<arg path="tests/PHPStan/Rules/Functions/data"/>
|
||||
<arg value="--exclude"/>
|
||||
<arg path="tests/PHPStan/Rules/Operators/data/invalid-inc-dec.php"/>
|
||||
<arg value="--exclude"/>
|
||||
<arg path="tests/PHPStan/Rules/Arrays/data/offset-access-without-dim-for-reading.php"/>
|
||||
<arg path="src" />
|
||||
<arg path="tests" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="cs">
|
||||
<exec
|
||||
executable="vendor/bin/phpcs"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="--colors"/>
|
||||
<arg value="--extensions=php"/>
|
||||
<arg value="--encoding=utf-8"/>
|
||||
<arg value="--tab-width=4"/>
|
||||
<arg value="--cache=tmp/cache/phpcs"/>
|
||||
<arg value="--ignore=tests/*/data,tests/*/traits,tests/notAutoloaded,src/Reflection/SignatureMap/functionMap.php"/>
|
||||
<arg value="-sp"/>
|
||||
<arg path="src"/>
|
||||
<arg path="tests"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="cs-fix">
|
||||
<exec
|
||||
executable="vendor/bin/phpcbf"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="--colors"/>
|
||||
<arg value="--extensions=php"/>
|
||||
<arg value="--encoding=utf-8"/>
|
||||
<arg value="--tab-width=4"/>
|
||||
<arg value="-sp"/>
|
||||
<arg path="src"/>
|
||||
<arg path="tests"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="test-configuration-validate" depends="composer-install">
|
||||
<xmllint schema="vendor/phpunit/phpunit/phpunit.xsd" file="tests/phpunit.xml"/>
|
||||
</target>
|
||||
|
||||
<target name="tests">
|
||||
<if>
|
||||
<os family="windows"/>
|
||||
<then>
|
||||
<property name="phpunit.executable" value="vendor/bin/phpunit"/>
|
||||
</then>
|
||||
<else>
|
||||
<property name="phpunit.executable" value="vendor/bin/paratest"/>
|
||||
</else>
|
||||
</if>
|
||||
<exec
|
||||
executable="${phpunit.executable}"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="-c"/>
|
||||
<arg value="tests/phpunit.xml"/>
|
||||
<arg path="tests"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="phpstan">
|
||||
<property name="phpstan.config" value="build/phpstan-generated.neon"/>
|
||||
<php expression="PHP_VERSION_ID >= 70300 ?'true':'false'" returnProperty="isPHP73" level="verbose" />
|
||||
<touch file="${phpstan.config}"/>
|
||||
<append
|
||||
destFile="${phpstan.config}"
|
||||
text="includes: [ phpstan.neon"
|
||||
append="false"
|
||||
></append>
|
||||
<if>
|
||||
<os family="windows" />
|
||||
<then>
|
||||
<append
|
||||
destFile="${phpstan.config}"
|
||||
text=", ignore-windows-errors.neon"
|
||||
></append>
|
||||
</then>
|
||||
</if>
|
||||
<if>
|
||||
<equals arg1="${isPHP73}" arg2="false" />
|
||||
<then>
|
||||
<append
|
||||
destFile="${phpstan.config}"
|
||||
text=", ignore-lt-php7.3-errors.neon"
|
||||
></append>
|
||||
</then>
|
||||
</if>
|
||||
<append
|
||||
destFile="${phpstan.config}"
|
||||
text=" ]"
|
||||
></append>
|
||||
<exec
|
||||
executable="php"
|
||||
logoutput="true"
|
||||
passthru="true"
|
||||
checkreturn="true"
|
||||
>
|
||||
<arg value="-d"/>
|
||||
<arg value="memory_limit=512M"/>
|
||||
<arg path="bin/phpstan"/>
|
||||
<arg value="analyse"/>
|
||||
<arg value="-c"/>
|
||||
<arg path="${phpstan.config}"/>
|
||||
<arg value="-l"/>
|
||||
<arg value="7"/>
|
||||
<arg path="build/PHPStan"/>
|
||||
<arg path="src"/>
|
||||
<arg path="tests"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
</project>
|
68
vendor/phpstan/phpstan/composer.json
vendored
Normal file
68
vendor/phpstan/phpstan/composer.json
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"require": {
|
||||
"php": "~7.1",
|
||||
"composer/xdebug-handler": "^1.3.0",
|
||||
"jean85/pretty-package-versions": "^1.0.3",
|
||||
"nette/bootstrap": "^2.4 || ^3.0",
|
||||
"nette/di": "^2.4.7 || ^3.0",
|
||||
"nette/robot-loader": "^3.0.1",
|
||||
"nette/utils": "^2.4.5 || ^3.0",
|
||||
"nikic/php-parser": "^4.0.2",
|
||||
"phpstan/phpdoc-parser": "^0.3",
|
||||
"symfony/console": "~3.2 || ~4.0",
|
||||
"symfony/finder": "~3.2 || ~4.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "3.4.16 || 4.1.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-intl": "*",
|
||||
"ext-mysqli": "*",
|
||||
"ext-soap": "*",
|
||||
"ext-zip": "*",
|
||||
"brianium/paratest": "^2.0",
|
||||
"consistence/coding-standard": "^3.5",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.4",
|
||||
"jakub-onderka/php-parallel-lint": "^1.0",
|
||||
"localheinz/composer-normalize": "^1.1.0",
|
||||
"phing/phing": "^2.16.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.11",
|
||||
"phpstan/phpstan-php-parser": "^0.11",
|
||||
"phpstan/phpstan-phpunit": "^0.11",
|
||||
"phpstan/phpstan-strict-rules": "^0.11",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"slevomat/coding-standard": "^4.7.2",
|
||||
"squizlabs/php_codesniffer": "^3.3.2"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.11-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PHPStan\\": [
|
||||
"src/",
|
||||
"build/PHPStan"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"classmap": [
|
||||
"tests/PHPStan"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"bin": [
|
||||
"bin/phpstan"
|
||||
]
|
||||
}
|
132
vendor/phpstan/phpstan/conf/config.level0.neon
vendored
Normal file
132
vendor/phpstan/phpstan/conf/config.level0.neon
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
parameters:
|
||||
customRulesetUsed: false
|
||||
|
||||
rules:
|
||||
- PHPStan\Rules\Arrays\DuplicateKeysInLiteralArraysRule
|
||||
- PHPStan\Rules\Arrays\OffsetAccessWithoutDimForReadingRule
|
||||
- PHPStan\Rules\Classes\ClassConstantDeclarationRule
|
||||
- PHPStan\Rules\Classes\ClassConstantRule
|
||||
- PHPStan\Rules\Classes\ExistingClassesInClassImplementsRule
|
||||
- PHPStan\Rules\Classes\ExistingClassesInInterfaceExtendsRule
|
||||
- PHPStan\Rules\Classes\ExistingClassInClassExtendsRule
|
||||
- PHPStan\Rules\Classes\ExistingClassInTraitUseRule
|
||||
- PHPStan\Rules\Classes\InstantiationRule
|
||||
- PHPStan\Rules\Classes\RequireParentConstructCallRule
|
||||
- PHPStan\Rules\Classes\UnusedConstructorParametersRule
|
||||
- PHPStan\Rules\Functions\CallToFunctionParametersRule
|
||||
- PHPStan\Rules\Functions\ExistingClassesInClosureTypehintsRule
|
||||
- PHPStan\Rules\Functions\ExistingClassesInTypehintsRule
|
||||
- PHPStan\Rules\Functions\InnerFunctionRule
|
||||
- PHPStan\Rules\Functions\NonExistentDefinedFunctionRule
|
||||
- PHPStan\Rules\Functions\PrintfParametersRule
|
||||
- PHPStan\Rules\Functions\UnusedClosureUsesRule
|
||||
- PHPStan\Rules\Methods\ExistingClassesInTypehintsRule
|
||||
- PHPStan\Rules\Properties\AccessStaticPropertiesRule
|
||||
- PHPStan\Rules\Variables\ThisVariableRule
|
||||
|
||||
services:
|
||||
-
|
||||
class: PHPStan\Rules\Classes\ExistingClassInInstanceOfRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkClassCaseSensitivity: %checkClassCaseSensitivity%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Exceptions\CaughtExceptionExistenceRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkClassCaseSensitivity: %checkClassCaseSensitivity%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Functions\CallToNonExistentFunctionRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkFunctionNameCase: %checkFunctionNameCase%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Methods\CallMethodsRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkFunctionNameCase: %checkFunctionNameCase%
|
||||
reportMagicMethods: %reportMagicMethods%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Methods\CallStaticMethodsRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkFunctionNameCase: %checkFunctionNameCase%
|
||||
reportMagicMethods: %reportMagicMethods%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Namespaces\ExistingNamesInGroupUseRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkFunctionNameCase: %checkFunctionNameCase%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Namespaces\ExistingNamesInUseRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkFunctionNameCase: %checkFunctionNameCase%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Operators\InvalidIncDecOperationRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkThisOnly: %checkThisOnly%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Properties\AccessPropertiesRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
reportMagicProperties: %reportMagicProperties%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Properties\ExistingClassesInPropertiesRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
arguments:
|
||||
checkClassCaseSensitivity: %checkClassCaseSensitivity%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Properties\WritingToReadOnlyPropertiesRule
|
||||
arguments:
|
||||
checkThisOnly: %checkThisOnly%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Properties\ReadingWriteOnlyPropertiesRule
|
||||
arguments:
|
||||
checkThisOnly: %checkThisOnly%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Variables\DefinedVariableRule
|
||||
arguments:
|
||||
cliArgumentsVariablesRegistered: %cliArgumentsVariablesRegistered%
|
||||
checkMaybeUndefinedVariables: %checkMaybeUndefinedVariables%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Variables\DefinedVariableInAnonymousFunctionUseRule
|
||||
arguments:
|
||||
checkMaybeUndefinedVariables: %checkMaybeUndefinedVariables%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Regexp\RegularExpressionPatternRule
|
||||
tags:
|
||||
- phpstan.rules.rule
|
11
vendor/phpstan/phpstan/conf/config.level1.neon
vendored
Normal file
11
vendor/phpstan/phpstan/conf/config.level1.neon
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
includes:
|
||||
- config.level0.neon
|
||||
|
||||
parameters:
|
||||
checkMaybeUndefinedVariables: true
|
||||
reportMagicMethods: true
|
||||
reportMagicProperties: true
|
||||
|
||||
rules:
|
||||
- PHPStan\Rules\Constants\ConstantRule
|
||||
- PHPStan\Rules\Variables\VariableCertaintyInIssetRule
|
29
vendor/phpstan/phpstan/conf/config.level2.neon
vendored
Normal file
29
vendor/phpstan/phpstan/conf/config.level2.neon
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
includes:
|
||||
- config.level1.neon
|
||||
|
||||
parameters:
|
||||
checkClassCaseSensitivity: true
|
||||
checkThisOnly: false
|
||||
|
||||
rules:
|
||||
- PHPStan\Rules\Cast\EchoRule
|
||||
- PHPStan\Rules\Cast\InvalidCastRule
|
||||
- PHPStan\Rules\Cast\InvalidPartOfEncapsedStringRule
|
||||
- PHPStan\Rules\Cast\PrintRule
|
||||
- PHPStan\Rules\Functions\IncompatibleDefaultParameterTypeRule
|
||||
- PHPStan\Rules\Methods\IncompatibleDefaultParameterTypeRule
|
||||
- PHPStan\Rules\Operators\InvalidBinaryOperationRule
|
||||
- PHPStan\Rules\Operators\InvalidUnaryOperationRule
|
||||
- PHPStan\Rules\Operators\InvalidComparisonOperationRule
|
||||
- PHPStan\Rules\PhpDoc\IncompatiblePhpDocTypeRule
|
||||
- PHPStan\Rules\PhpDoc\IncompatiblePropertyPhpDocTypeRule
|
||||
- PHPStan\Rules\PhpDoc\InvalidPhpDocTagValueRule
|
||||
- PHPStan\Rules\PhpDoc\InvalidThrowsPhpDocValueRule
|
||||
|
||||
services:
|
||||
-
|
||||
class: PHPStan\Rules\Functions\CallCallablesRule
|
||||
arguments:
|
||||
reportMaybes: %reportMaybes%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
52
vendor/phpstan/phpstan/conf/config.level3.neon
vendored
Normal file
52
vendor/phpstan/phpstan/conf/config.level3.neon
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
includes:
|
||||
- config.level2.neon
|
||||
|
||||
rules:
|
||||
- PHPStan\Rules\Arrays\AppendedArrayItemTypeRule
|
||||
- PHPStan\Rules\Arrays\IterableInForeachRule
|
||||
- PHPStan\Rules\Arrays\OffsetAccessAssignmentRule
|
||||
- PHPStan\Rules\Arrays\OffsetAccessAssignOpRule
|
||||
- PHPStan\Rules\Functions\ClosureReturnTypeRule
|
||||
- PHPStan\Rules\Functions\ReturnTypeRule
|
||||
- PHPStan\Rules\Methods\ReturnTypeRule
|
||||
- PHPStan\Rules\Properties\DefaultValueTypesAssignedToPropertiesRule
|
||||
- PHPStan\Rules\Properties\TypesAssignedToPropertiesRule
|
||||
- PHPStan\Rules\Variables\ThrowTypeRule
|
||||
- PHPStan\Rules\Variables\VariableCloningRule
|
||||
|
||||
services:
|
||||
-
|
||||
class: PHPStan\Rules\Arrays\AppendedArrayKeyTypeRule
|
||||
arguments:
|
||||
checkUnionTypes: %checkUnionTypes%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Arrays\InvalidKeyInArrayDimFetchRule
|
||||
arguments:
|
||||
reportMaybes: %reportMaybes%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Arrays\InvalidKeyInArrayItemRule
|
||||
arguments:
|
||||
reportMaybes: %reportMaybes%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Arrays\NonexistentOffsetInArrayDimFetchRule
|
||||
arguments:
|
||||
reportMaybes: %reportMaybes%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Methods\MethodSignatureRule
|
||||
arguments:
|
||||
reportMaybes: %reportMaybesInMethodSignatures%
|
||||
reportStatic: %reportStaticMethodSignatures%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
49
vendor/phpstan/phpstan/conf/config.level4.neon
vendored
Normal file
49
vendor/phpstan/phpstan/conf/config.level4.neon
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
includes:
|
||||
- config.level3.neon
|
||||
|
||||
rules:
|
||||
- PHPStan\Rules\Arrays\DeadForeachRule
|
||||
- PHPStan\Rules\Comparison\BooleanAndConstantConditionRule
|
||||
- PHPStan\Rules\Comparison\BooleanNotConstantConditionRule
|
||||
- PHPStan\Rules\Comparison\BooleanOrConstantConditionRule
|
||||
- PHPStan\Rules\Comparison\ElseIfConstantConditionRule
|
||||
- PHPStan\Rules\Comparison\IfConstantConditionRule
|
||||
- PHPStan\Rules\Comparison\TernaryOperatorConstantConditionRule
|
||||
- PHPStan\Rules\Comparison\UnreachableIfBranchesRule
|
||||
- PHPStan\Rules\Comparison\UnreachableTernaryElseBranchRule
|
||||
|
||||
services:
|
||||
-
|
||||
class: PHPStan\Rules\Classes\ImpossibleInstanceOfRule
|
||||
arguments:
|
||||
checkAlwaysTrueInstanceof: %checkAlwaysTrueInstanceof%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Comparison\ImpossibleCheckTypeFunctionCallRule
|
||||
arguments:
|
||||
checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Comparison\ImpossibleCheckTypeMethodCallRule
|
||||
arguments:
|
||||
checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Comparison\ImpossibleCheckTypeStaticMethodCallRule
|
||||
arguments:
|
||||
checkAlwaysTrueCheckTypeFunctionCall: %checkAlwaysTrueCheckTypeFunctionCall%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Comparison\StrictComparisonOfDifferentTypesRule
|
||||
arguments:
|
||||
checkAlwaysTrueStrictComparison: %checkAlwaysTrueStrictComparison%
|
||||
tags:
|
||||
- phpstan.rules.rule
|
6
vendor/phpstan/phpstan/conf/config.level5.neon
vendored
Normal file
6
vendor/phpstan/phpstan/conf/config.level5.neon
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
includes:
|
||||
- config.level4.neon
|
||||
|
||||
parameters:
|
||||
checkFunctionArgumentTypes: true
|
||||
checkArgumentsPassedByReference: true
|
6
vendor/phpstan/phpstan/conf/config.level6.neon
vendored
Normal file
6
vendor/phpstan/phpstan/conf/config.level6.neon
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
includes:
|
||||
- config.level5.neon
|
||||
|
||||
parameters:
|
||||
checkUnionTypes: true
|
||||
reportMaybes: true
|
5
vendor/phpstan/phpstan/conf/config.level7.neon
vendored
Normal file
5
vendor/phpstan/phpstan/conf/config.level7.neon
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
includes:
|
||||
- config.level6.neon
|
||||
|
||||
parameters:
|
||||
checkNullables: true
|
2
vendor/phpstan/phpstan/conf/config.levelmax.neon
vendored
Normal file
2
vendor/phpstan/phpstan/conf/config.levelmax.neon
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
includes:
|
||||
- config.level7.neon
|
630
vendor/phpstan/phpstan/conf/config.neon
vendored
Normal file
630
vendor/phpstan/phpstan/conf/config.neon
vendored
Normal file
|
@ -0,0 +1,630 @@
|
|||
parameters:
|
||||
bootstrap: null
|
||||
excludes_analyse: []
|
||||
autoload_directories: []
|
||||
autoload_files: []
|
||||
fileExtensions:
|
||||
- php
|
||||
checkAlwaysTrueCheckTypeFunctionCall: false
|
||||
checkAlwaysTrueInstanceof: false
|
||||
checkAlwaysTrueStrictComparison: false
|
||||
checkClassCaseSensitivity: false
|
||||
checkFunctionArgumentTypes: false
|
||||
checkFunctionNameCase: false
|
||||
checkArgumentsPassedByReference: false
|
||||
checkMaybeUndefinedVariables: false
|
||||
checkNullables: false
|
||||
checkThisOnly: true
|
||||
checkUnionTypes: false
|
||||
reportMaybes: false
|
||||
reportMaybesInMethodSignatures: false
|
||||
reportStaticMethodSignatures: false
|
||||
polluteScopeWithLoopInitialAssignments: true
|
||||
polluteScopeWithAlwaysIterableForeach: true
|
||||
polluteCatchScopeWithTryAssignments: false
|
||||
reportMagicMethods: false
|
||||
reportMagicProperties: false
|
||||
ignoreErrors: []
|
||||
internalErrorsCountLimit: 50
|
||||
cache:
|
||||
nodesByFileCountMax: 512
|
||||
nodesByStringCountMax: 512
|
||||
reportUnmatchedIgnoredErrors: true
|
||||
scopeClass: PHPStan\Analyser\Scope
|
||||
universalObjectCratesClasses:
|
||||
- stdClass
|
||||
- SimpleXMLElement
|
||||
earlyTerminatingMethodCalls: []
|
||||
memoryLimitFile: %tmpDir%/.memory_limit
|
||||
benchmarkFile: null
|
||||
dynamicConstantNames:
|
||||
- ICONV_IMPL
|
||||
- PHP_VERSION
|
||||
- PHP_MAJOR_VERSION
|
||||
- PHP_MINOR_VERSION
|
||||
- PHP_RELEASE_VERSION
|
||||
- PHP_VERSION_ID
|
||||
- PHP_EXTRA_VERSION
|
||||
- PHP_ZTS
|
||||
- PHP_DEBUG
|
||||
- PHP_MAXPATHLEN
|
||||
- PHP_OS
|
||||
- PHP_OS_FAMILY
|
||||
- PHP_SAPI
|
||||
- PHP_EOL
|
||||
- PHP_INT_MAX
|
||||
- PHP_INT_MIN
|
||||
- PHP_INT_SIZE
|
||||
- PHP_FLOAT_DIG
|
||||
- PHP_FLOAT_EPSILON
|
||||
- PHP_FLOAT_MIN
|
||||
- PHP_FLOAT_MAX
|
||||
- DEFAULT_INCLUDE_PATH
|
||||
- PEAR_INSTALL_DIR
|
||||
- PEAR_EXTENSION_DIR
|
||||
- PHP_EXTENSION_DIR
|
||||
- PHP_PREFIX
|
||||
- PHP_BINDIR
|
||||
- PHP_BINARY
|
||||
- PHP_MANDIR
|
||||
- PHP_LIBDIR
|
||||
- PHP_DATADIR
|
||||
- PHP_SYSCONFDIR
|
||||
- PHP_LOCALSTATEDIR
|
||||
- PHP_CONFIG_FILE_PATH
|
||||
- PHP_CONFIG_FILE_SCAN_DIR
|
||||
- PHP_SHLIB_SUFFIX
|
||||
- PHP_FD_SETSIZE
|
||||
|
||||
extensions:
|
||||
rules: PHPStan\DependencyInjection\RulesExtension
|
||||
conditionalTags: PHPStan\DependencyInjection\ConditionalTagsExtension
|
||||
|
||||
services:
|
||||
-
|
||||
class: PhpParser\BuilderFactory
|
||||
|
||||
-
|
||||
class: PhpParser\Lexer
|
||||
|
||||
-
|
||||
class: PhpParser\NodeTraverser
|
||||
setup:
|
||||
- addVisitor(@PhpParser\NodeVisitor\NameResolver)
|
||||
|
||||
-
|
||||
class: PhpParser\NodeVisitor\NameResolver
|
||||
|
||||
-
|
||||
class: PhpParser\Parser\Php7
|
||||
|
||||
-
|
||||
class: PhpParser\PrettyPrinter\Standard
|
||||
|
||||
-
|
||||
class: PHPStan\Broker\AnonymousClassNameHelper
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDocParser\Lexer\Lexer
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDocParser\Parser\TypeParser
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDocParser\Parser\ConstExprParser
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDocParser\Parser\PhpDocParser
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDoc\PhpDocNodeResolver
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDoc\PhpDocStringResolver
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDoc\TypeNodeResolver
|
||||
factory: @typeNodeResolverFactory::create
|
||||
|
||||
-
|
||||
class: PHPStan\PhpDoc\TypeStringResolver
|
||||
|
||||
-
|
||||
class: PHPStan\Analyser\Analyser
|
||||
arguments:
|
||||
ignoreErrors: %ignoreErrors%
|
||||
reportUnmatchedIgnoredErrors: %reportUnmatchedIgnoredErrors%
|
||||
internalErrorsCountLimit: %internalErrorsCountLimit%
|
||||
benchmarkFile: %benchmarkFile%
|
||||
|
||||
-
|
||||
class: PHPStan\Analyser\ScopeFactory
|
||||
arguments:
|
||||
scopeClass: %scopeClass%
|
||||
|
||||
-
|
||||
class: PHPStan\Analyser\NodeScopeResolver
|
||||
arguments:
|
||||
polluteScopeWithLoopInitialAssignments: %polluteScopeWithLoopInitialAssignments%
|
||||
polluteCatchScopeWithTryAssignments: %polluteCatchScopeWithTryAssignments%
|
||||
polluteScopeWithAlwaysIterableForeach: %polluteScopeWithAlwaysIterableForeach%
|
||||
earlyTerminatingMethodCalls: %earlyTerminatingMethodCalls%
|
||||
|
||||
-
|
||||
class: PHPStan\Cache\Cache
|
||||
arguments:
|
||||
storage: @cacheStorage
|
||||
|
||||
-
|
||||
class: PHPStan\Command\AnalyseApplication
|
||||
arguments:
|
||||
memoryLimitFile: %memoryLimitFile%
|
||||
currentWorkingDirectory: %currentWorkingDirectory%
|
||||
|
||||
-
|
||||
class: PHPStan\Dependency\DependencyDumper
|
||||
|
||||
-
|
||||
class: PHPStan\Dependency\DependencyResolver
|
||||
|
||||
-
|
||||
class: PHPStan\File\FileHelper
|
||||
arguments:
|
||||
workingDirectory: %currentWorkingDirectory%
|
||||
|
||||
-
|
||||
class: PHPStan\File\FileExcluder
|
||||
arguments:
|
||||
analyseExcludes: %excludes_analyse%
|
||||
|
||||
-
|
||||
class: PHPStan\File\FileFinder
|
||||
arguments:
|
||||
fileExtensions: %fileExtensions%
|
||||
|
||||
-
|
||||
class: PHPStan\Parser\CachedParser
|
||||
arguments:
|
||||
originalParser: @directParser
|
||||
cachedNodesByFileCountMax: %cache.nodesByFileCountMax%
|
||||
cachedNodesByStringCountMax: %cache.nodesByStringCountMax%
|
||||
|
||||
-
|
||||
class: PHPStan\Parser\FunctionCallStatementFinder
|
||||
|
||||
-
|
||||
implement: PHPStan\Reflection\FunctionReflectionFactory
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\Php\PhpClassReflectionExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension
|
||||
|
||||
-
|
||||
implement: PHPStan\Reflection\Php\PhpMethodReflectionFactory
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension
|
||||
tags:
|
||||
- phpstan.broker.propertiesClassReflectionExtension
|
||||
arguments:
|
||||
classes: %universalObjectCratesClasses%
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\SignatureMap\SignatureMapParser
|
||||
|
||||
-
|
||||
class: PHPStan\Reflection\SignatureMap\SignatureMapProvider
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\ClassCaseSensitivityCheck
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Comparison\ConstantConditionRuleHelper
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Comparison\ImpossibleCheckTypeHelper
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\FunctionCallParametersCheck
|
||||
arguments:
|
||||
checkArgumentTypes: %checkFunctionArgumentTypes%
|
||||
checkArgumentsPassedByReference: %checkArgumentsPassedByReference%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\FunctionDefinitionCheck
|
||||
arguments:
|
||||
checkClassCaseSensitivity: %checkClassCaseSensitivity%
|
||||
checkThisOnly: %checkThisOnly%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\FunctionReturnTypeCheck
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Properties\PropertyDescriptor
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\Properties\PropertyReflectionFinder
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\RegistryFactory
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\RuleLevelHelper
|
||||
arguments:
|
||||
checkNullables: %checkNullables%
|
||||
checkThisOnly: %checkThisOnly%
|
||||
checkUnionTypes: %checkUnionTypes%
|
||||
|
||||
-
|
||||
class: PHPStan\Rules\UnusedFunctionParametersCheck
|
||||
|
||||
-
|
||||
class: PHPStan\Type\FileTypeMapper
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArgumentBasedFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayFillFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayFillKeysFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayFilterFunctionReturnTypeReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayKeyDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayKeyExistsFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayKeyFirstDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayKeyLastDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayKeysFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayMapFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayMergeFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayPopFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayReduceFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayShiftFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArraySliceFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArraySearchFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayValuesFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\CountFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\CountFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\CurlInitReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\DioStatDynamicFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ExplodeFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\GetParentClassDynamicFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\GettimeofdayDynamicFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\StatDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\MethodExistsTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\PropertyExistsTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\MinMaxFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\PathinfoFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ReplaceFunctionsDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ArrayPointerFunctionsDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\VarExportFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\MbFunctionsReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\MicrotimeFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\HrtimeFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\ParseUrlFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\VersionCompareFunctionDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\StrtotimeFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\RangeFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\AssertFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\DefineConstantTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\DefinedConstantTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\InArrayFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsIntFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsFloatFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsNullFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsArrayFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsBoolFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsCallableFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsCountableFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsResourceFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsIterableFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsStringFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsSubclassOfFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsObjectFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsNumericFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsScalarFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\IsAFunctionTypeSpecifyingExtension
|
||||
tags:
|
||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\JsonThrowOnErrorDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\TypeSpecifyingFunctionsDynamicReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
-
|
||||
class: PHPStan\Type\Php\StrSplitFunctionReturnTypeExtension
|
||||
tags:
|
||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||
|
||||
typeSpecifier:
|
||||
class: PHPStan\Analyser\TypeSpecifier
|
||||
factory: @typeSpecifierFactory::create
|
||||
|
||||
typeSpecifierFactory:
|
||||
class: PHPStan\Analyser\TypeSpecifierFactory
|
||||
|
||||
relativePathHelper:
|
||||
class: PHPStan\File\RelativePathHelper
|
||||
dynamic: true
|
||||
|
||||
broker:
|
||||
class: PHPStan\Broker\Broker
|
||||
factory: @brokerFactory::create
|
||||
|
||||
brokerFactory:
|
||||
class: PHPStan\Broker\BrokerFactory
|
||||
|
||||
cacheStorage:
|
||||
class: PHPStan\Cache\FileCacheStorage
|
||||
arguments:
|
||||
directory: %tmpDir%/cache/PHPStan
|
||||
autowired: no
|
||||
|
||||
directParser:
|
||||
class: PHPStan\Parser\DirectParser
|
||||
autowired: no
|
||||
|
||||
registry:
|
||||
class: PHPStan\Rules\Registry
|
||||
factory: @PHPStan\Rules\RegistryFactory::create
|
||||
|
||||
typeNodeResolverFactory:
|
||||
class: PHPStan\PhpDoc\TypeNodeResolverFactory
|
||||
|
||||
errorFormatter.raw:
|
||||
class: PHPStan\Command\ErrorFormatter\RawErrorFormatter
|
||||
|
||||
errorFormatter.table:
|
||||
class: PHPStan\Command\ErrorFormatter\TableErrorFormatter
|
||||
|
||||
errorFormatter.checkstyle:
|
||||
class: PHPStan\Command\ErrorFormatter\CheckstyleErrorFormatter
|
||||
|
||||
errorFormatter.json:
|
||||
class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter
|
||||
arguments:
|
||||
pretty: false
|
||||
|
||||
errorFormatter.prettyJson:
|
||||
class: PHPStan\Command\ErrorFormatter\JsonErrorFormatter
|
||||
arguments:
|
||||
pretty: true
|
62
vendor/phpstan/phpstan/phpcs.xml
vendored
Normal file
62
vendor/phpstan/phpstan/phpcs.xml
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0"?>
|
||||
<ruleset name="PHPStan">
|
||||
<rule ref="vendor/consistence/coding-standard/Consistence/ruleset.xml">
|
||||
<exclude name="SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.InvalidFormat"/>
|
||||
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameAfterKeyword"/>
|
||||
<exclude name="SlevomatCodingStandard.Namespaces.FullyQualifiedClassNameInAnnotation"/>
|
||||
<exclude name="SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly"/>
|
||||
<exclude name="Consistence.Exceptions.ExceptionDeclaration"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.MissingParamTag"/>
|
||||
<exclude name="Squiz.Commenting.FunctionComment.ParamNameNoMatch"/>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses">
|
||||
<properties>
|
||||
<property name="caseSensitive" value="false"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
|
||||
<properties>
|
||||
<property name="newlinesCountBetweenOpenTagAndDeclare" value="0"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration">
|
||||
<properties>
|
||||
<property name="usefulAnnotations" type="array" value="
|
||||
@dataProvider,
|
||||
@requires
|
||||
"/>
|
||||
<property name="enableObjectTypeHint" value="false"/>
|
||||
</properties>
|
||||
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableParameterTypeHintSpecification"/>
|
||||
<exclude name="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingTraversableReturnTypeHintSpecification"/>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.ControlStructures.AssignmentInCondition"/>
|
||||
<rule ref="SlevomatCodingStandard.ControlStructures.DisallowEqualOperators"/>
|
||||
<rule ref="SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator"/>
|
||||
<rule ref="SlevomatCodingStandard.ControlStructures.EarlyExit"/>
|
||||
<rule ref="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming"/>
|
||||
<rule ref="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming"/>
|
||||
<rule ref="SlevomatCodingStandard.ControlStructures.DisallowShortTernaryOperator"/>
|
||||
<rule ref="SlevomatCodingStandard.Files.TypeNameMatchesFileName">
|
||||
<properties>
|
||||
<property name="rootNamespaces" type="array" value="src=>PHPStan,tests/PHPStan=>PHPStan"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="SlevomatCodingStandard.Classes.ModernClassNameReference"/>
|
||||
<rule ref="SlevomatCodingStandard.Functions.StaticClosure"/>
|
||||
<rule ref="SlevomatCodingStandard.Operators.RequireCombinedAssignmentOperator"/>
|
||||
<rule ref="SlevomatCodingStandard.TypeHints.NullTypeHintOnLastPosition"/>
|
||||
<rule ref="SlevomatCodingStandard.Classes.TraitUseDeclaration"/>
|
||||
<rule ref="SlevomatCodingStandard.Classes.TraitUseSpacing"/>
|
||||
<rule ref="SlevomatCodingStandard.Variables.UnusedVariable"/>
|
||||
<rule ref="SlevomatCodingStandard.Variables.UselessVariable"/>
|
||||
<!--<rule ref="SlevomatCodingStandard.Functions.UnusedParameter"/>-->
|
||||
<rule ref="SlevomatCodingStandard.Functions.UnusedInheritedVariablePassedToClosure"/>
|
||||
<rule ref="SlevomatCodingStandard.Namespaces.UselessAlias"/>
|
||||
<rule ref="SlevomatCodingStandard.PHP.UselessSemicolon"/>
|
||||
<rule ref="SlevomatCodingStandard.PHP.UselessParentheses"/>
|
||||
<exclude-pattern>tests/*/data</exclude-pattern>
|
||||
<exclude-pattern>tests/*/traits</exclude-pattern>
|
||||
<exclude-pattern>tests/notAutoloaded</exclude-pattern>
|
||||
<exclude-pattern>src/Reflection/SignatureMap/functionMap.php</exclude-pattern>
|
||||
</ruleset>
|
8
vendor/phpstan/phpstan/src/AnalysedCodeException.php
vendored
Normal file
8
vendor/phpstan/phpstan/src/AnalysedCodeException.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan;
|
||||
|
||||
abstract class AnalysedCodeException extends \Exception
|
||||
{
|
||||
|
||||
}
|
302
vendor/phpstan/phpstan/src/Analyser/Analyser.php
vendored
Normal file
302
vendor/phpstan/phpstan/src/Analyser/Analyser.php
vendored
Normal file
|
@ -0,0 +1,302 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use Nette\Utils\Json;
|
||||
use PHPStan\File\FileHelper;
|
||||
use PHPStan\Parser\Parser;
|
||||
use PHPStan\Rules\FileRuleError;
|
||||
use PHPStan\Rules\LineRuleError;
|
||||
use PHPStan\Rules\Registry;
|
||||
|
||||
class Analyser
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Analyser\ScopeFactory */
|
||||
private $scopeFactory;
|
||||
|
||||
/** @var \PHPStan\Parser\Parser */
|
||||
private $parser;
|
||||
|
||||
/** @var \PHPStan\Rules\Registry */
|
||||
private $registry;
|
||||
|
||||
/** @var \PHPStan\Analyser\NodeScopeResolver */
|
||||
private $nodeScopeResolver;
|
||||
|
||||
/** @var \PHPStan\File\FileHelper */
|
||||
private $fileHelper;
|
||||
|
||||
/** @var (string|array<string, string>)[] */
|
||||
private $ignoreErrors;
|
||||
|
||||
/** @var bool */
|
||||
private $reportUnmatchedIgnoredErrors;
|
||||
|
||||
/** @var int */
|
||||
private $internalErrorsCountLimit;
|
||||
|
||||
/** @var string|null */
|
||||
private $benchmarkFile;
|
||||
|
||||
/** @var float[] */
|
||||
private $benchmarkData = [];
|
||||
|
||||
/**
|
||||
* @param \PHPStan\Analyser\ScopeFactory $scopeFactory
|
||||
* @param \PHPStan\Parser\Parser $parser
|
||||
* @param \PHPStan\Rules\Registry $registry
|
||||
* @param \PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver
|
||||
* @param \PHPStan\File\FileHelper $fileHelper
|
||||
* @param (string|array<string, string>)[] $ignoreErrors
|
||||
* @param bool $reportUnmatchedIgnoredErrors
|
||||
* @param int $internalErrorsCountLimit
|
||||
* @param string|null $benchmarkFile
|
||||
*/
|
||||
public function __construct(
|
||||
ScopeFactory $scopeFactory,
|
||||
Parser $parser,
|
||||
Registry $registry,
|
||||
NodeScopeResolver $nodeScopeResolver,
|
||||
FileHelper $fileHelper,
|
||||
array $ignoreErrors,
|
||||
bool $reportUnmatchedIgnoredErrors,
|
||||
int $internalErrorsCountLimit,
|
||||
?string $benchmarkFile = null
|
||||
)
|
||||
{
|
||||
$this->scopeFactory = $scopeFactory;
|
||||
$this->parser = $parser;
|
||||
$this->registry = $registry;
|
||||
$this->nodeScopeResolver = $nodeScopeResolver;
|
||||
$this->fileHelper = $fileHelper;
|
||||
$this->ignoreErrors = $ignoreErrors;
|
||||
$this->reportUnmatchedIgnoredErrors = $reportUnmatchedIgnoredErrors;
|
||||
$this->internalErrorsCountLimit = $internalErrorsCountLimit;
|
||||
$this->benchmarkFile = $benchmarkFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $files
|
||||
* @param bool $onlyFiles
|
||||
* @param \Closure(string $file): void|null $preFileCallback
|
||||
* @param \Closure(string $file): void|null $postFileCallback
|
||||
* @param bool $debug
|
||||
* @return string[]|\PHPStan\Analyser\Error[] errors
|
||||
*/
|
||||
public function analyse(
|
||||
array $files,
|
||||
bool $onlyFiles,
|
||||
?\Closure $preFileCallback = null,
|
||||
?\Closure $postFileCallback = null,
|
||||
bool $debug = false
|
||||
): array
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
foreach ($this->ignoreErrors as $ignoreError) {
|
||||
try {
|
||||
if (is_array($ignoreError)) {
|
||||
if (!isset($ignoreError['message'])) {
|
||||
$errors[] = sprintf(
|
||||
'Ignored error %s is missing a message.',
|
||||
Json::encode($ignoreError)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!isset($ignoreError['path'])) {
|
||||
$errors[] = sprintf(
|
||||
'Ignored error %s is missing a path.',
|
||||
Json::encode($ignoreError)
|
||||
);
|
||||
}
|
||||
|
||||
$ignoreMessage = $ignoreError['message'];
|
||||
} else {
|
||||
$ignoreMessage = $ignoreError;
|
||||
}
|
||||
|
||||
\Nette\Utils\Strings::match('', $ignoreMessage);
|
||||
} catch (\Nette\Utils\RegexpException $e) {
|
||||
$errors[] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
if (count($errors) > 0) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
$this->nodeScopeResolver->setAnalysedFiles($files);
|
||||
$internalErrorsCount = 0;
|
||||
$reachedInternalErrorsCountLimit = false;
|
||||
foreach ($files as $file) {
|
||||
try {
|
||||
$fileErrors = [];
|
||||
if ($preFileCallback !== null) {
|
||||
$preFileCallback($file);
|
||||
}
|
||||
|
||||
if (is_file($file)) {
|
||||
$parserBenchmarkTime = $this->benchmarkStart();
|
||||
$parserNodes = $this->parser->parseFile($file);
|
||||
$this->benchmarkEnd($parserBenchmarkTime, 'parser');
|
||||
|
||||
$scopeBenchmarkTime = $this->benchmarkStart();
|
||||
$this->nodeScopeResolver->processNodes(
|
||||
$parserNodes,
|
||||
$this->scopeFactory->create(ScopeContext::create($file)),
|
||||
function (\PhpParser\Node $node, Scope $scope) use (&$fileErrors, $file, &$scopeBenchmarkTime): void {
|
||||
$this->benchmarkEnd($scopeBenchmarkTime, 'scope');
|
||||
$uniquedAnalysedCodeExceptionMessages = [];
|
||||
foreach ($this->registry->getRules(get_class($node)) as $rule) {
|
||||
try {
|
||||
$ruleBenchmarkTime = $this->benchmarkStart();
|
||||
$ruleErrors = $rule->processNode($node, $scope);
|
||||
$this->benchmarkEnd($ruleBenchmarkTime, sprintf('rule-%s', get_class($rule)));
|
||||
} catch (\PHPStan\AnalysedCodeException $e) {
|
||||
if (isset($uniquedAnalysedCodeExceptionMessages[$e->getMessage()])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$uniquedAnalysedCodeExceptionMessages[$e->getMessage()] = true;
|
||||
$fileErrors[] = new Error($e->getMessage(), $file, $node->getLine(), false);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($ruleErrors as $ruleError) {
|
||||
$line = $node->getLine();
|
||||
$fileName = $scope->getFileDescription();
|
||||
if (is_string($ruleError)) {
|
||||
$message = $ruleError;
|
||||
} else {
|
||||
$message = $ruleError->getMessage();
|
||||
if (
|
||||
$ruleError instanceof LineRuleError
|
||||
&& $ruleError->getLine() !== -1
|
||||
) {
|
||||
$line = $ruleError->getLine();
|
||||
}
|
||||
if (
|
||||
$ruleError instanceof FileRuleError
|
||||
&& $ruleError->getFile() !== ''
|
||||
) {
|
||||
$fileName = $ruleError->getFile();
|
||||
}
|
||||
}
|
||||
$fileErrors[] = new Error($message, $fileName, $line);
|
||||
}
|
||||
}
|
||||
|
||||
$scopeBenchmarkTime = $this->benchmarkStart();
|
||||
}
|
||||
);
|
||||
} elseif (is_dir($file)) {
|
||||
$fileErrors[] = new Error(sprintf('File %s is a directory.', $file), $file, null, false);
|
||||
} else {
|
||||
$fileErrors[] = new Error(sprintf('File %s does not exist.', $file), $file, null, false);
|
||||
}
|
||||
if ($postFileCallback !== null) {
|
||||
$postFileCallback($file);
|
||||
}
|
||||
|
||||
$errors = array_merge($errors, $fileErrors);
|
||||
} catch (\PhpParser\Error $e) {
|
||||
$errors[] = new Error($e->getMessage(), $file, $e->getStartLine() !== -1 ? $e->getStartLine() : null, false);
|
||||
} catch (\PHPStan\Parser\ParserErrorsException $e) {
|
||||
foreach ($e->getErrors() as $error) {
|
||||
$errors[] = new Error($error->getMessage(), $file, $error->getStartLine() !== -1 ? $error->getStartLine() : null, false);
|
||||
}
|
||||
} catch (\PHPStan\AnalysedCodeException $e) {
|
||||
$errors[] = new Error($e->getMessage(), $file, null, false);
|
||||
} catch (\Throwable $t) {
|
||||
if ($debug) {
|
||||
throw $t;
|
||||
}
|
||||
$internalErrorsCount++;
|
||||
$internalErrorMessage = sprintf('Internal error: %s', $t->getMessage());
|
||||
$internalErrorMessage .= sprintf(
|
||||
'%sRun PHPStan with --debug option and post the stack trace to:%s%s',
|
||||
"\n",
|
||||
"\n",
|
||||
'https://github.com/phpstan/phpstan/issues/new'
|
||||
);
|
||||
$errors[] = new Error($internalErrorMessage, $file);
|
||||
if ($internalErrorsCount >= $this->internalErrorsCountLimit) {
|
||||
$reachedInternalErrorsCountLimit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->benchmarkFile !== null) {
|
||||
uasort($this->benchmarkData, static function (float $a, float $b): int {
|
||||
return $b <=> $a;
|
||||
});
|
||||
file_put_contents($this->benchmarkFile, Json::encode($this->benchmarkData, Json::PRETTY));
|
||||
}
|
||||
|
||||
$unmatchedIgnoredErrors = $this->ignoreErrors;
|
||||
$addErrors = [];
|
||||
$errors = array_values(array_filter($errors, function (Error $error) use (&$unmatchedIgnoredErrors, &$addErrors): bool {
|
||||
foreach ($this->ignoreErrors as $i => $ignore) {
|
||||
if (IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore)) {
|
||||
unset($unmatchedIgnoredErrors[$i]);
|
||||
if (!$error->canBeIgnored()) {
|
||||
$addErrors[] = sprintf(
|
||||
'Error message "%s" cannot be ignored, use excludes_analyse instead.',
|
||||
$error->getMessage()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}));
|
||||
|
||||
$errors = array_merge($errors, $addErrors);
|
||||
|
||||
if (!$onlyFiles && $this->reportUnmatchedIgnoredErrors && !$reachedInternalErrorsCountLimit) {
|
||||
foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) {
|
||||
$errors[] = sprintf(
|
||||
'Ignored error pattern %s was not matched in reported errors.',
|
||||
IgnoredError::stringifyPattern($unmatchedIgnoredError)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ($reachedInternalErrorsCountLimit) {
|
||||
$errors[] = sprintf('Reached internal errors count limit of %d, exiting...', $this->internalErrorsCountLimit);
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
private function benchmarkStart(): ?float
|
||||
{
|
||||
if ($this->benchmarkFile === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return microtime(true);
|
||||
}
|
||||
|
||||
private function benchmarkEnd(?float $startTime, string $description): void
|
||||
{
|
||||
if ($this->benchmarkFile === null) {
|
||||
return;
|
||||
}
|
||||
if ($startTime === null) {
|
||||
return;
|
||||
}
|
||||
$elapsedTime = microtime(true) - $startTime;
|
||||
if (!isset($this->benchmarkData[$description])) {
|
||||
$this->benchmarkData[$description] = $elapsedTime;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->benchmarkData[$description] += $elapsedTime;
|
||||
}
|
||||
|
||||
}
|
48
vendor/phpstan/phpstan/src/Analyser/Error.php
vendored
Normal file
48
vendor/phpstan/phpstan/src/Analyser/Error.php
vendored
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
class Error
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $message;
|
||||
|
||||
/** @var string */
|
||||
private $file;
|
||||
|
||||
/** @var int|NULL */
|
||||
private $line;
|
||||
|
||||
/** @var bool */
|
||||
private $canBeIgnored;
|
||||
|
||||
public function __construct(string $message, string $file, ?int $line = null, bool $canBeIgnored = true)
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->file = $file;
|
||||
$this->line = $line;
|
||||
$this->canBeIgnored = $canBeIgnored;
|
||||
}
|
||||
|
||||
public function getMessage(): string
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
public function getFile(): string
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getLine(): ?int
|
||||
{
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
public function canBeIgnored(): bool
|
||||
{
|
||||
return $this->canBeIgnored;
|
||||
}
|
||||
|
||||
}
|
58
vendor/phpstan/phpstan/src/Analyser/IgnoredError.php
vendored
Normal file
58
vendor/phpstan/phpstan/src/Analyser/IgnoredError.php
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PHPStan\File\FileExcluder;
|
||||
use PHPStan\File\FileHelper;
|
||||
|
||||
class IgnoredError
|
||||
{
|
||||
|
||||
/**
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
|
||||
* @param array<string, string>|string $ignoredError
|
||||
* @return string Representation of the ignored error
|
||||
*/
|
||||
public static function stringifyPattern($ignoredError): string
|
||||
{
|
||||
if (!is_array($ignoredError)) {
|
||||
return $ignoredError;
|
||||
}
|
||||
|
||||
// ignore by path
|
||||
if (isset($ignoredError['path'])) {
|
||||
return sprintf('%s in path %s', $ignoredError['message'], $ignoredError['path']);
|
||||
}
|
||||
|
||||
return $ignoredError['message'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
|
||||
* @param FileHelper $fileHelper
|
||||
* @param Error $error
|
||||
* @param array<string, string>|string $ignoredError
|
||||
* @return bool To ignore or not to ignore?
|
||||
*/
|
||||
public static function shouldIgnore(
|
||||
FileHelper $fileHelper,
|
||||
Error $error,
|
||||
$ignoredError
|
||||
): bool
|
||||
{
|
||||
if (is_array($ignoredError)) {
|
||||
// ignore by path
|
||||
if (isset($ignoredError['path'])) {
|
||||
$fileExcluder = new FileExcluder($fileHelper, [$ignoredError['path']]);
|
||||
|
||||
return \Nette\Utils\Strings::match($error->getMessage(), $ignoredError['message']) !== null
|
||||
&& $fileExcluder->isExcludedFromAnalysing($error->getFile());
|
||||
}
|
||||
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return \Nette\Utils\Strings::match($error->getMessage(), $ignoredError) !== null;
|
||||
}
|
||||
|
||||
}
|
119
vendor/phpstan/phpstan/src/Analyser/LookForAssignsSettings.php
vendored
Normal file
119
vendor/phpstan/phpstan/src/Analyser/LookForAssignsSettings.php
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PhpParser\Node\Stmt\Break_;
|
||||
use PhpParser\Node\Stmt\Continue_;
|
||||
|
||||
class LookForAssignsSettings
|
||||
{
|
||||
|
||||
private const EARLY_TERMINATION_CONTINUE = 1;
|
||||
private const EARLY_TERMINATION_BREAK = 2;
|
||||
private const EARLY_TERMINATION_STOP = 4;
|
||||
private const EARLY_TERMINATION_ALL = self::EARLY_TERMINATION_CONTINUE
|
||||
+ self::EARLY_TERMINATION_BREAK
|
||||
+ self::EARLY_TERMINATION_STOP;
|
||||
private const EARLY_TERMINATION_CLOSURE = 8;
|
||||
private const REPEAT_ANALYSIS = 16;
|
||||
|
||||
/** @var int */
|
||||
private $respectEarlyTermination;
|
||||
|
||||
/** @var self[] */
|
||||
private static $registry = [];
|
||||
|
||||
private function __construct(
|
||||
int $respectEarlyTermination
|
||||
)
|
||||
{
|
||||
$this->respectEarlyTermination = $respectEarlyTermination;
|
||||
}
|
||||
|
||||
public static function default(): self
|
||||
{
|
||||
return self::create(self::EARLY_TERMINATION_ALL);
|
||||
}
|
||||
|
||||
public static function insideLoop(): self
|
||||
{
|
||||
return self::create(self::EARLY_TERMINATION_STOP + self::EARLY_TERMINATION_BREAK + self::REPEAT_ANALYSIS);
|
||||
}
|
||||
|
||||
public static function afterLoop(): self
|
||||
{
|
||||
return self::create(self::EARLY_TERMINATION_STOP + self::REPEAT_ANALYSIS);
|
||||
}
|
||||
|
||||
public static function afterSwitch(): self
|
||||
{
|
||||
return self::create(self::EARLY_TERMINATION_STOP);
|
||||
}
|
||||
|
||||
public static function insideFinally(): self
|
||||
{
|
||||
return self::create(0);
|
||||
}
|
||||
|
||||
public static function insideClosure(): self
|
||||
{
|
||||
return self::create(self::EARLY_TERMINATION_CLOSURE);
|
||||
}
|
||||
|
||||
private static function create(int $value): self
|
||||
{
|
||||
self::$registry[$value] = self::$registry[$value] ?? new self($value);
|
||||
return self::$registry[$value];
|
||||
}
|
||||
|
||||
public function shouldRepeatAnalysis(): bool
|
||||
{
|
||||
return ($this->respectEarlyTermination & self::REPEAT_ANALYSIS) === self::REPEAT_ANALYSIS;
|
||||
}
|
||||
|
||||
public function shouldSkipBranch(\PhpParser\Node $earlyTerminationStatement): bool
|
||||
{
|
||||
return $this->isRespected($earlyTerminationStatement);
|
||||
}
|
||||
|
||||
private function isRespected(\PhpParser\Node $earlyTerminationStatement): bool
|
||||
{
|
||||
if (
|
||||
$earlyTerminationStatement instanceof Break_
|
||||
) {
|
||||
return ($this->respectEarlyTermination & self::EARLY_TERMINATION_BREAK) === self::EARLY_TERMINATION_BREAK;
|
||||
}
|
||||
|
||||
if (
|
||||
$earlyTerminationStatement instanceof Continue_
|
||||
) {
|
||||
return ($this->respectEarlyTermination & self::EARLY_TERMINATION_CONTINUE) === self::EARLY_TERMINATION_CONTINUE;
|
||||
}
|
||||
|
||||
return ($this->respectEarlyTermination & self::EARLY_TERMINATION_STOP) === self::EARLY_TERMINATION_STOP;
|
||||
}
|
||||
|
||||
public function shouldIntersectVariables(?\PhpParser\Node $earlyTerminationStatement): bool
|
||||
{
|
||||
if ($earlyTerminationStatement === null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->shouldSkipBranch($earlyTerminationStatement)) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return $earlyTerminationStatement instanceof Break_
|
||||
|| $earlyTerminationStatement instanceof Continue_
|
||||
|| ($this->respectEarlyTermination & self::EARLY_TERMINATION_STOP) === 0;
|
||||
}
|
||||
|
||||
public function shouldGeneralizeConstantTypesOfNonIdempotentOperations(): bool
|
||||
{
|
||||
return (
|
||||
($this->respectEarlyTermination & self::EARLY_TERMINATION_STOP) === self::EARLY_TERMINATION_STOP
|
||||
&& $this->respectEarlyTermination !== self::EARLY_TERMINATION_ALL
|
||||
) || $this->respectEarlyTermination === self::EARLY_TERMINATION_CLOSURE;
|
||||
}
|
||||
|
||||
}
|
57
vendor/phpstan/phpstan/src/Analyser/NameScope.php
vendored
Normal file
57
vendor/phpstan/phpstan/src/Analyser/NameScope.php
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
class NameScope
|
||||
{
|
||||
|
||||
/** @var string|null */
|
||||
private $namespace;
|
||||
|
||||
/** @var string[] alias(string) => fullName(string) */
|
||||
private $uses;
|
||||
|
||||
/** @var string|null */
|
||||
private $className;
|
||||
|
||||
/**
|
||||
* @param string|null $namespace
|
||||
* @param string[] $uses alias(string) => fullName(string)
|
||||
* @param string|null $className
|
||||
*/
|
||||
public function __construct(?string $namespace, array $uses, ?string $className = null)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->uses = $uses;
|
||||
$this->className = $className;
|
||||
}
|
||||
|
||||
public function getClassName(): ?string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
public function resolveStringName(string $name): string
|
||||
{
|
||||
if (strpos($name, '\\') === 0) {
|
||||
return ltrim($name, '\\');
|
||||
}
|
||||
|
||||
$nameParts = explode('\\', $name);
|
||||
$firstNamePart = strtolower($nameParts[0]);
|
||||
if (isset($this->uses[$firstNamePart])) {
|
||||
if (count($nameParts) === 1) {
|
||||
return $this->uses[$firstNamePart];
|
||||
}
|
||||
array_shift($nameParts);
|
||||
return sprintf('%s\\%s', $this->uses[$firstNamePart], implode('\\', $nameParts));
|
||||
}
|
||||
|
||||
if ($this->namespace !== null) {
|
||||
return sprintf('%s\\%s', $this->namespace, $name);
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
}
|
2064
vendor/phpstan/phpstan/src/Analyser/NodeScopeResolver.php
vendored
Normal file
2064
vendor/phpstan/phpstan/src/Analyser/NodeScopeResolver.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
39
vendor/phpstan/phpstan/src/Analyser/OutOfClassScope.php
vendored
Normal file
39
vendor/phpstan/phpstan/src/Analyser/OutOfClassScope.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PHPStan\Reflection\ClassMemberAccessAnswerer;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use PHPStan\Reflection\ConstantReflection;
|
||||
use PHPStan\Reflection\MethodReflection;
|
||||
use PHPStan\Reflection\PropertyReflection;
|
||||
|
||||
class OutOfClassScope implements ClassMemberAccessAnswerer
|
||||
{
|
||||
|
||||
public function isInClass(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getClassReflection(): ?ClassReflection
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function canAccessProperty(PropertyReflection $propertyReflection): bool
|
||||
{
|
||||
return $propertyReflection->isPublic();
|
||||
}
|
||||
|
||||
public function canCallMethod(MethodReflection $methodReflection): bool
|
||||
{
|
||||
return $methodReflection->isPublic();
|
||||
}
|
||||
|
||||
public function canAccessConstant(ConstantReflection $constantReflection): bool
|
||||
{
|
||||
return $constantReflection->isPublic();
|
||||
}
|
||||
|
||||
}
|
2806
vendor/phpstan/phpstan/src/Analyser/Scope.php
vendored
Normal file
2806
vendor/phpstan/phpstan/src/Analyser/Scope.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
78
vendor/phpstan/phpstan/src/Analyser/ScopeContext.php
vendored
Normal file
78
vendor/phpstan/phpstan/src/Analyser/ScopeContext.php
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
|
||||
class ScopeContext
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $file;
|
||||
|
||||
/** @var ClassReflection|null */
|
||||
private $classReflection;
|
||||
|
||||
/** @var ClassReflection|null */
|
||||
private $traitReflection;
|
||||
|
||||
private function __construct(
|
||||
string $file,
|
||||
?ClassReflection $classReflection,
|
||||
?ClassReflection $traitReflection
|
||||
)
|
||||
{
|
||||
$this->file = $file;
|
||||
$this->classReflection = $classReflection;
|
||||
$this->traitReflection = $traitReflection;
|
||||
}
|
||||
|
||||
public static function create(string $file): self
|
||||
{
|
||||
return new self($file, null, null);
|
||||
}
|
||||
|
||||
public function beginFile(): self
|
||||
{
|
||||
return new self($this->file, null, null);
|
||||
}
|
||||
|
||||
public function enterClass(ClassReflection $classReflection): self
|
||||
{
|
||||
if ($this->classReflection !== null && !$classReflection->isAnonymous()) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
if ($classReflection->isTrait()) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
return new self($this->file, $classReflection, null);
|
||||
}
|
||||
|
||||
public function enterTrait(ClassReflection $traitReflection): self
|
||||
{
|
||||
if ($this->classReflection === null) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
if (!$traitReflection->isTrait()) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return new self($this->file, $this->classReflection, $traitReflection);
|
||||
}
|
||||
|
||||
public function getFile(): string
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
public function getClassReflection(): ?ClassReflection
|
||||
{
|
||||
return $this->classReflection;
|
||||
}
|
||||
|
||||
public function getTraitReflection(): ?ClassReflection
|
||||
{
|
||||
return $this->traitReflection;
|
||||
}
|
||||
|
||||
}
|
99
vendor/phpstan/phpstan/src/Analyser/ScopeFactory.php
vendored
Normal file
99
vendor/phpstan/phpstan/src/Analyser/ScopeFactory.php
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use PHPStan\Broker\Broker;
|
||||
use PHPStan\Type\Type;
|
||||
|
||||
class ScopeFactory
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $scopeClass;
|
||||
|
||||
/** @var \PHPStan\Broker\Broker */
|
||||
private $broker;
|
||||
|
||||
/** @var \PhpParser\PrettyPrinter\Standard */
|
||||
private $printer;
|
||||
|
||||
/** @var \PHPStan\Analyser\TypeSpecifier */
|
||||
private $typeSpecifier;
|
||||
|
||||
/** @var string[] */
|
||||
private $dynamicConstantNames;
|
||||
|
||||
public function __construct(
|
||||
string $scopeClass,
|
||||
Broker $broker,
|
||||
\PhpParser\PrettyPrinter\Standard $printer,
|
||||
TypeSpecifier $typeSpecifier,
|
||||
\Nette\DI\Container $container
|
||||
)
|
||||
{
|
||||
$this->scopeClass = $scopeClass;
|
||||
$this->broker = $broker;
|
||||
$this->printer = $printer;
|
||||
$this->typeSpecifier = $typeSpecifier;
|
||||
$this->dynamicConstantNames = $container->parameters['dynamicConstantNames'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \PHPStan\Analyser\ScopeContext $context
|
||||
* @param bool $declareStrictTypes
|
||||
* @param \PHPStan\Reflection\FunctionReflection|\PHPStan\Reflection\MethodReflection|null $function
|
||||
* @param string|null $namespace
|
||||
* @param \PHPStan\Analyser\VariableTypeHolder[] $variablesTypes
|
||||
* @param \PHPStan\Analyser\VariableTypeHolder[] $moreSpecificTypes
|
||||
* @param string|null $inClosureBindScopeClass
|
||||
* @param \PHPStan\Type\Type|null $inAnonymousFunctionReturnType
|
||||
* @param \PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|null $inFunctionCall
|
||||
* @param bool $negated
|
||||
* @param bool $inFirstLevelStatement
|
||||
* @param string[] $currentlyAssignedExpressions
|
||||
*
|
||||
* @return Scope
|
||||
*/
|
||||
public function create(
|
||||
ScopeContext $context,
|
||||
bool $declareStrictTypes = false,
|
||||
$function = null,
|
||||
?string $namespace = null,
|
||||
array $variablesTypes = [],
|
||||
array $moreSpecificTypes = [],
|
||||
?string $inClosureBindScopeClass = null,
|
||||
?Type $inAnonymousFunctionReturnType = null,
|
||||
?Expr $inFunctionCall = null,
|
||||
bool $negated = false,
|
||||
bool $inFirstLevelStatement = true,
|
||||
array $currentlyAssignedExpressions = []
|
||||
): Scope
|
||||
{
|
||||
$scopeClass = $this->scopeClass;
|
||||
if (!is_a($scopeClass, Scope::class, true)) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return new $scopeClass(
|
||||
$this,
|
||||
$this->broker,
|
||||
$this->printer,
|
||||
$this->typeSpecifier,
|
||||
$context,
|
||||
$declareStrictTypes,
|
||||
$function,
|
||||
$namespace,
|
||||
$variablesTypes,
|
||||
$moreSpecificTypes,
|
||||
$inClosureBindScopeClass,
|
||||
$inAnonymousFunctionReturnType,
|
||||
$inFunctionCall,
|
||||
$negated,
|
||||
$inFirstLevelStatement,
|
||||
$currentlyAssignedExpressions,
|
||||
$this->dynamicConstantNames
|
||||
);
|
||||
}
|
||||
|
||||
}
|
103
vendor/phpstan/phpstan/src/Analyser/SpecifiedTypes.php
vendored
Normal file
103
vendor/phpstan/phpstan/src/Analyser/SpecifiedTypes.php
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PHPStan\Type\TypeCombinator;
|
||||
|
||||
class SpecifiedTypes
|
||||
{
|
||||
|
||||
/** @var mixed[] */
|
||||
private $sureTypes;
|
||||
|
||||
/** @var mixed[] */
|
||||
private $sureNotTypes;
|
||||
|
||||
/**
|
||||
* @param mixed[] $sureTypes
|
||||
* @param mixed[] $sureNotTypes
|
||||
*/
|
||||
public function __construct(array $sureTypes = [], array $sureNotTypes = [])
|
||||
{
|
||||
$this->sureTypes = $sureTypes;
|
||||
$this->sureNotTypes = $sureNotTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getSureTypes(): array
|
||||
{
|
||||
return $this->sureTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getSureNotTypes(): array
|
||||
{
|
||||
return $this->sureNotTypes;
|
||||
}
|
||||
|
||||
public function intersectWith(SpecifiedTypes $other): self
|
||||
{
|
||||
$sureTypeUnion = [];
|
||||
$sureNotTypeUnion = [];
|
||||
|
||||
foreach ($this->sureTypes as $exprString => [$exprNode, $type]) {
|
||||
if (!isset($other->sureTypes[$exprString])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sureTypeUnion[$exprString] = [
|
||||
$exprNode,
|
||||
TypeCombinator::union($type, $other->sureTypes[$exprString][1]),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->sureNotTypes as $exprString => [$exprNode, $type]) {
|
||||
if (!isset($other->sureNotTypes[$exprString])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sureNotTypeUnion[$exprString] = [
|
||||
$exprNode,
|
||||
TypeCombinator::intersect($type, $other->sureNotTypes[$exprString][1]),
|
||||
];
|
||||
}
|
||||
|
||||
return new self($sureTypeUnion, $sureNotTypeUnion);
|
||||
}
|
||||
|
||||
|
||||
public function unionWith(SpecifiedTypes $other): self
|
||||
{
|
||||
$sureTypeUnion = $this->sureTypes + $other->sureTypes;
|
||||
$sureNotTypeUnion = $this->sureNotTypes + $other->sureNotTypes;
|
||||
|
||||
foreach ($this->sureTypes as $exprString => [$exprNode, $type]) {
|
||||
if (!isset($other->sureTypes[$exprString])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sureTypeUnion[$exprString] = [
|
||||
$exprNode,
|
||||
TypeCombinator::intersect($type, $other->sureTypes[$exprString][1]),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($this->sureNotTypes as $exprString => [$exprNode, $type]) {
|
||||
if (!isset($other->sureNotTypes[$exprString])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sureNotTypeUnion[$exprString] = [
|
||||
$exprNode,
|
||||
TypeCombinator::union($type, $other->sureNotTypes[$exprString][1]),
|
||||
];
|
||||
}
|
||||
|
||||
return new self($sureTypeUnion, $sureNotTypeUnion);
|
||||
}
|
||||
|
||||
}
|
73
vendor/phpstan/phpstan/src/Analyser/StatementList.php
vendored
Normal file
73
vendor/phpstan/phpstan/src/Analyser/StatementList.php
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
class StatementList
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Analyser\Scope */
|
||||
private $scope;
|
||||
|
||||
/** @var \PhpParser\Node[] */
|
||||
private $statements;
|
||||
|
||||
/** @var bool */
|
||||
private $filterByTruthyValue;
|
||||
|
||||
/** @var callable(Scope $scope): Scope|null */
|
||||
private $processScope;
|
||||
|
||||
/**
|
||||
* @param Scope $scope
|
||||
* @param \PhpParser\Node[] $statements
|
||||
* @param bool $filterByTruthyValue
|
||||
* @param callable(Scope $scope): Scope|null $processScope
|
||||
*/
|
||||
public function __construct(
|
||||
Scope $scope,
|
||||
array $statements,
|
||||
bool $filterByTruthyValue = false,
|
||||
?callable $processScope = null
|
||||
)
|
||||
{
|
||||
$this->scope = $scope;
|
||||
$this->statements = $statements;
|
||||
$this->filterByTruthyValue = $filterByTruthyValue;
|
||||
$this->processScope = $processScope;
|
||||
}
|
||||
|
||||
public static function fromList(Scope $scope, self $list): self
|
||||
{
|
||||
return new self(
|
||||
$scope,
|
||||
$list->statements,
|
||||
$list->filterByTruthyValue,
|
||||
$list->processScope
|
||||
);
|
||||
}
|
||||
|
||||
public function getScope(): Scope
|
||||
{
|
||||
$scope = $this->scope;
|
||||
if ($this->processScope !== null) {
|
||||
$callback = $this->processScope;
|
||||
$scope = $callback($scope);
|
||||
}
|
||||
|
||||
return $scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PhpParser\Node[]
|
||||
*/
|
||||
public function getStatements(): array
|
||||
{
|
||||
return $this->statements;
|
||||
}
|
||||
|
||||
public function shouldFilterByTruthyValue(): bool
|
||||
{
|
||||
return $this->filterByTruthyValue;
|
||||
}
|
||||
|
||||
}
|
562
vendor/phpstan/phpstan/src/Analyser/TypeSpecifier.php
vendored
Normal file
562
vendor/phpstan/phpstan/src/Analyser/TypeSpecifier.php
vendored
Normal file
|
@ -0,0 +1,562 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanOr;
|
||||
use PhpParser\Node\Expr\BinaryOp\LogicalAnd;
|
||||
use PhpParser\Node\Expr\BinaryOp\LogicalOr;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\Instanceof_;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\New_;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Expr\StaticPropertyFetch;
|
||||
use PhpParser\Node\Name;
|
||||
use PHPStan\Broker\Broker;
|
||||
use PHPStan\Type\Accessory\HasOffsetType;
|
||||
use PHPStan\Type\Accessory\NonEmptyArrayType;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use PHPStan\Type\Constant\ConstantArrayType;
|
||||
use PHPStan\Type\Constant\ConstantBooleanType;
|
||||
use PHPStan\Type\Constant\ConstantFloatType;
|
||||
use PHPStan\Type\Constant\ConstantIntegerType;
|
||||
use PHPStan\Type\Constant\ConstantStringType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\NeverType;
|
||||
use PHPStan\Type\NonexistentParentClassType;
|
||||
use PHPStan\Type\NullType;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\ObjectWithoutClassType;
|
||||
use PHPStan\Type\StaticType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeCombinator;
|
||||
use PHPStan\Type\TypeUtils;
|
||||
use PHPStan\Type\UnionType;
|
||||
|
||||
class TypeSpecifier
|
||||
{
|
||||
|
||||
/** @var \PhpParser\PrettyPrinter\Standard */
|
||||
private $printer;
|
||||
|
||||
/** @var \PHPStan\Broker\Broker */
|
||||
private $broker;
|
||||
|
||||
/** @var \PHPStan\Type\FunctionTypeSpecifyingExtension[] */
|
||||
private $functionTypeSpecifyingExtensions = [];
|
||||
|
||||
/** @var \PHPStan\Type\MethodTypeSpecifyingExtension[] */
|
||||
private $methodTypeSpecifyingExtensions = [];
|
||||
|
||||
/** @var \PHPStan\Type\StaticMethodTypeSpecifyingExtension[] */
|
||||
private $staticMethodTypeSpecifyingExtensions = [];
|
||||
|
||||
/** @var \PHPStan\Type\MethodTypeSpecifyingExtension[][]|null */
|
||||
private $methodTypeSpecifyingExtensionsByClass;
|
||||
|
||||
/** @var \PHPStan\Type\StaticMethodTypeSpecifyingExtension[][]|null */
|
||||
private $staticMethodTypeSpecifyingExtensionsByClass;
|
||||
|
||||
/**
|
||||
* @param \PhpParser\PrettyPrinter\Standard $printer
|
||||
* @param \PHPStan\Broker\Broker $broker
|
||||
* @param \PHPStan\Type\FunctionTypeSpecifyingExtension[] $functionTypeSpecifyingExtensions
|
||||
* @param \PHPStan\Type\MethodTypeSpecifyingExtension[] $methodTypeSpecifyingExtensions
|
||||
* @param \PHPStan\Type\StaticMethodTypeSpecifyingExtension[] $staticMethodTypeSpecifyingExtensions
|
||||
*/
|
||||
public function __construct(
|
||||
\PhpParser\PrettyPrinter\Standard $printer,
|
||||
Broker $broker,
|
||||
array $functionTypeSpecifyingExtensions,
|
||||
array $methodTypeSpecifyingExtensions,
|
||||
array $staticMethodTypeSpecifyingExtensions
|
||||
)
|
||||
{
|
||||
$this->printer = $printer;
|
||||
$this->broker = $broker;
|
||||
|
||||
foreach (array_merge($functionTypeSpecifyingExtensions, $methodTypeSpecifyingExtensions, $staticMethodTypeSpecifyingExtensions) as $extension) {
|
||||
if (!($extension instanceof TypeSpecifierAwareExtension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension->setTypeSpecifier($this);
|
||||
}
|
||||
|
||||
$this->functionTypeSpecifyingExtensions = $functionTypeSpecifyingExtensions;
|
||||
$this->methodTypeSpecifyingExtensions = $methodTypeSpecifyingExtensions;
|
||||
$this->staticMethodTypeSpecifyingExtensions = $staticMethodTypeSpecifyingExtensions;
|
||||
}
|
||||
|
||||
public function specifyTypesInCondition(
|
||||
Scope $scope,
|
||||
Expr $expr,
|
||||
TypeSpecifierContext $context,
|
||||
bool $defaultHandleFunctions = false
|
||||
): SpecifiedTypes
|
||||
{
|
||||
if ($expr instanceof Instanceof_) {
|
||||
if ($expr->class instanceof Name) {
|
||||
$className = (string) $expr->class;
|
||||
$lowercasedClassName = strtolower($className);
|
||||
if ($lowercasedClassName === 'self' && $scope->isInClass()) {
|
||||
$type = new ObjectType($scope->getClassReflection()->getName());
|
||||
} elseif ($lowercasedClassName === 'static' && $scope->isInClass()) {
|
||||
$type = new StaticType($scope->getClassReflection()->getName());
|
||||
} elseif ($lowercasedClassName === 'parent') {
|
||||
if (
|
||||
$scope->isInClass()
|
||||
&& $scope->getClassReflection()->getParentClass() !== false
|
||||
) {
|
||||
$type = new ObjectType($scope->getClassReflection()->getParentClass()->getName());
|
||||
} else {
|
||||
$type = new NonexistentParentClassType();
|
||||
}
|
||||
} else {
|
||||
$type = new ObjectType($className);
|
||||
}
|
||||
return $this->create($expr->expr, $type, $context);
|
||||
}
|
||||
|
||||
if ($context->true()) {
|
||||
return $this->create($expr->expr, new ObjectWithoutClassType(), $context);
|
||||
}
|
||||
} elseif ($expr instanceof Node\Expr\BinaryOp\Identical) {
|
||||
$expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr);
|
||||
if ($expressions !== null) {
|
||||
/** @var Expr $exprNode */
|
||||
$exprNode = $expressions[0];
|
||||
/** @var \PHPStan\Type\ConstantScalarType $constantType */
|
||||
$constantType = $expressions[1];
|
||||
if ($constantType->getValue() === false) {
|
||||
$types = $this->create($exprNode, $constantType, $context);
|
||||
return $types->unionWith($this->specifyTypesInCondition(
|
||||
$scope,
|
||||
$exprNode,
|
||||
$context->true() ? TypeSpecifierContext::createFalse() : TypeSpecifierContext::createFalse()->negate()
|
||||
));
|
||||
}
|
||||
|
||||
if ($constantType->getValue() === true) {
|
||||
$types = $this->create($exprNode, $constantType, $context);
|
||||
return $types->unionWith($this->specifyTypesInCondition(
|
||||
$scope,
|
||||
$exprNode,
|
||||
$context->true() ? TypeSpecifierContext::createTrue() : TypeSpecifierContext::createTrue()->negate()
|
||||
));
|
||||
}
|
||||
|
||||
if ($constantType->getValue() === null) {
|
||||
return $this->create($exprNode, $constantType, $context);
|
||||
}
|
||||
|
||||
if (
|
||||
!$context->null()
|
||||
&& $exprNode instanceof FuncCall
|
||||
&& count($exprNode->args) === 1
|
||||
&& $exprNode->name instanceof Name
|
||||
&& strtolower((string) $exprNode->name) === 'count'
|
||||
&& $constantType instanceof ConstantIntegerType
|
||||
) {
|
||||
if ($context->truthy() || $constantType->getValue() === 0) {
|
||||
$newContext = $context;
|
||||
if ($constantType->getValue() === 0) {
|
||||
$newContext = $newContext->negate();
|
||||
}
|
||||
$argType = $scope->getType($exprNode->args[0]->value);
|
||||
if ((new ArrayType(new MixedType(), new MixedType()))->isSuperTypeOf($argType)->yes()) {
|
||||
return $this->create($exprNode->args[0]->value, new NonEmptyArrayType(), $newContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($context->true()) {
|
||||
$type = TypeCombinator::intersect($scope->getType($expr->right), $scope->getType($expr->left));
|
||||
$leftTypes = $this->create($expr->left, $type, $context);
|
||||
$rightTypes = $this->create($expr->right, $type, $context);
|
||||
return $leftTypes->unionWith($rightTypes);
|
||||
|
||||
} elseif ($context->false()) {
|
||||
$identicalType = $scope->getType($expr);
|
||||
if ($identicalType instanceof ConstantBooleanType) {
|
||||
$never = new NeverType();
|
||||
$contextForTypes = $identicalType->getValue() ? $context->negate() : $context;
|
||||
$leftTypes = $this->create($expr->left, $never, $contextForTypes);
|
||||
$rightTypes = $this->create($expr->right, $never, $contextForTypes);
|
||||
return $leftTypes->unionWith($rightTypes);
|
||||
}
|
||||
|
||||
if (
|
||||
(
|
||||
$expr->left instanceof Node\Scalar
|
||||
|| $expr->left instanceof Expr\Array_
|
||||
)
|
||||
&& !$expr->right instanceof Node\Scalar
|
||||
) {
|
||||
return $this->create(
|
||||
$expr->right,
|
||||
$scope->getType($expr->left),
|
||||
$context
|
||||
);
|
||||
}
|
||||
if (
|
||||
(
|
||||
$expr->right instanceof Node\Scalar
|
||||
|| $expr->right instanceof Expr\Array_
|
||||
)
|
||||
&& !$expr->left instanceof Node\Scalar
|
||||
) {
|
||||
return $this->create(
|
||||
$expr->left,
|
||||
$scope->getType($expr->right),
|
||||
$context
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($expr instanceof Node\Expr\BinaryOp\NotIdentical) {
|
||||
return $this->specifyTypesInCondition(
|
||||
$scope,
|
||||
new Node\Expr\BooleanNot(new Node\Expr\BinaryOp\Identical($expr->left, $expr->right)),
|
||||
$context
|
||||
);
|
||||
} elseif ($expr instanceof Node\Expr\BinaryOp\Equal) {
|
||||
$expressions = $this->findTypeExpressionsFromBinaryOperation($scope, $expr);
|
||||
if ($expressions !== null) {
|
||||
/** @var Expr $exprNode */
|
||||
$exprNode = $expressions[0];
|
||||
/** @var \PHPStan\Type\ConstantScalarType $constantType */
|
||||
$constantType = $expressions[1];
|
||||
if ($constantType->getValue() === false || $constantType->getValue() === null) {
|
||||
return $this->specifyTypesInCondition(
|
||||
$scope,
|
||||
$exprNode,
|
||||
$context->true() ? TypeSpecifierContext::createFalsey() : TypeSpecifierContext::createFalsey()->negate()
|
||||
);
|
||||
}
|
||||
|
||||
if ($constantType->getValue() === true) {
|
||||
return $this->specifyTypesInCondition(
|
||||
$scope,
|
||||
$exprNode,
|
||||
$context->true() ? TypeSpecifierContext::createTruthy() : TypeSpecifierContext::createTruthy()->negate()
|
||||
);
|
||||
}
|
||||
}
|
||||
} elseif ($expr instanceof Node\Expr\BinaryOp\NotEqual) {
|
||||
return $this->specifyTypesInCondition(
|
||||
$scope,
|
||||
new Node\Expr\BooleanNot(new Node\Expr\BinaryOp\Equal($expr->left, $expr->right)),
|
||||
$context
|
||||
);
|
||||
} elseif ($expr instanceof FuncCall && $expr->name instanceof Name) {
|
||||
if ($this->broker->hasFunction($expr->name, $scope)) {
|
||||
$functionReflection = $this->broker->getFunction($expr->name, $scope);
|
||||
foreach ($this->getFunctionTypeSpecifyingExtensions() as $extension) {
|
||||
if (!$extension->isFunctionSupported($functionReflection, $expr, $context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $extension->specifyTypes($functionReflection, $expr, $scope, $context);
|
||||
}
|
||||
}
|
||||
|
||||
if ($defaultHandleFunctions) {
|
||||
return $this->handleDefaultTruthyOrFalseyContext($context, $expr);
|
||||
}
|
||||
} elseif ($expr instanceof MethodCall && $expr->name instanceof Node\Identifier) {
|
||||
$methodCalledOnType = $scope->getType($expr->var);
|
||||
$referencedClasses = TypeUtils::getDirectClassNames($methodCalledOnType);
|
||||
if (
|
||||
count($referencedClasses) === 1
|
||||
&& $this->broker->hasClass($referencedClasses[0])
|
||||
) {
|
||||
$methodClassReflection = $this->broker->getClass($referencedClasses[0]);
|
||||
if ($methodClassReflection->hasMethod($expr->name->name)) {
|
||||
$methodReflection = $methodClassReflection->getMethod($expr->name->name, $scope);
|
||||
foreach ($this->getMethodTypeSpecifyingExtensionsForClass($methodClassReflection->getName()) as $extension) {
|
||||
if (!$extension->isMethodSupported($methodReflection, $expr, $context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $extension->specifyTypes($methodReflection, $expr, $scope, $context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($defaultHandleFunctions) {
|
||||
return $this->handleDefaultTruthyOrFalseyContext($context, $expr);
|
||||
}
|
||||
} elseif ($expr instanceof StaticCall && $expr->name instanceof Node\Identifier) {
|
||||
if ($expr->class instanceof Name) {
|
||||
$calleeType = new ObjectType($scope->resolveName($expr->class));
|
||||
} else {
|
||||
$calleeType = $scope->getType($expr->class);
|
||||
}
|
||||
|
||||
if ($calleeType->hasMethod($expr->name->name)->yes()) {
|
||||
$staticMethodReflection = $calleeType->getMethod($expr->name->name, $scope);
|
||||
$referencedClasses = TypeUtils::getDirectClassNames($calleeType);
|
||||
if (
|
||||
count($referencedClasses) === 1
|
||||
&& $this->broker->hasClass($referencedClasses[0])
|
||||
) {
|
||||
$staticMethodClassReflection = $this->broker->getClass($referencedClasses[0]);
|
||||
foreach ($this->getStaticMethodTypeSpecifyingExtensionsForClass($staticMethodClassReflection->getName()) as $extension) {
|
||||
if (!$extension->isStaticMethodSupported($staticMethodReflection, $expr, $context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $extension->specifyTypes($staticMethodReflection, $expr, $scope, $context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($defaultHandleFunctions) {
|
||||
return $this->handleDefaultTruthyOrFalseyContext($context, $expr);
|
||||
}
|
||||
} elseif ($expr instanceof BooleanAnd || $expr instanceof LogicalAnd) {
|
||||
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context);
|
||||
$rightTypes = $this->specifyTypesInCondition($scope, $expr->right, $context);
|
||||
return $context->true() ? $leftTypes->unionWith($rightTypes) : $leftTypes->intersectWith($rightTypes);
|
||||
} elseif ($expr instanceof BooleanOr || $expr instanceof LogicalOr) {
|
||||
$leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context);
|
||||
$rightTypes = $this->specifyTypesInCondition($scope, $expr->right, $context);
|
||||
return $context->true() ? $leftTypes->intersectWith($rightTypes) : $leftTypes->unionWith($rightTypes);
|
||||
} elseif ($expr instanceof Node\Expr\BooleanNot && !$context->null()) {
|
||||
return $this->specifyTypesInCondition($scope, $expr->expr, $context->negate());
|
||||
} elseif ($expr instanceof Node\Expr\Assign) {
|
||||
if ($context->null()) {
|
||||
return $this->specifyTypesInCondition($scope, $expr->expr, $context);
|
||||
}
|
||||
|
||||
return $this->specifyTypesInCondition($scope, $expr->var, $context);
|
||||
} elseif (
|
||||
(
|
||||
$expr instanceof Expr\Isset_
|
||||
&& count($expr->vars) > 0
|
||||
&& $context->truthy()
|
||||
)
|
||||
|| ($expr instanceof Expr\Empty_ && $context->falsey())
|
||||
) {
|
||||
$vars = [];
|
||||
if ($expr instanceof Expr\Isset_) {
|
||||
$varsToIterate = $expr->vars;
|
||||
} else {
|
||||
$varsToIterate = [$expr->expr];
|
||||
}
|
||||
foreach ($varsToIterate as $var) {
|
||||
$vars[] = $var;
|
||||
|
||||
while (
|
||||
$var instanceof ArrayDimFetch
|
||||
|| $var instanceof PropertyFetch
|
||||
|| (
|
||||
$var instanceof StaticPropertyFetch
|
||||
&& $var->class instanceof Expr
|
||||
)
|
||||
) {
|
||||
if ($var instanceof StaticPropertyFetch) {
|
||||
/** @var Expr $var */
|
||||
$var = $var->class;
|
||||
} else {
|
||||
$var = $var->var;
|
||||
}
|
||||
$vars[] = $var;
|
||||
}
|
||||
}
|
||||
|
||||
$types = null;
|
||||
foreach ($vars as $var) {
|
||||
if ($expr instanceof Expr\Isset_) {
|
||||
if (
|
||||
$var instanceof ArrayDimFetch
|
||||
&& $var->dim !== null
|
||||
&& !$scope->getType($var->var) instanceof MixedType
|
||||
) {
|
||||
$type = $this->create(
|
||||
$var->var,
|
||||
new HasOffsetType($scope->getType($var->dim)),
|
||||
$context
|
||||
)->unionWith(
|
||||
$this->create($var, new NullType(), TypeSpecifierContext::createFalse())
|
||||
);
|
||||
} else {
|
||||
$type = $this->create($var, new NullType(), TypeSpecifierContext::createFalse());
|
||||
}
|
||||
} else {
|
||||
$type = $this->create(
|
||||
$var,
|
||||
new UnionType([
|
||||
new NullType(),
|
||||
new ConstantBooleanType(false),
|
||||
]),
|
||||
TypeSpecifierContext::createFalse()
|
||||
);
|
||||
}
|
||||
if ($types === null) {
|
||||
$types = $type;
|
||||
} else {
|
||||
$types = $types->unionWith($type);
|
||||
}
|
||||
}
|
||||
|
||||
/** @var SpecifiedTypes $types */
|
||||
$types = $types;
|
||||
|
||||
if (
|
||||
$expr instanceof Expr\Empty_
|
||||
&& (new ArrayType(new MixedType(), new MixedType()))->isSuperTypeOf($scope->getType($expr->expr))->yes()) {
|
||||
$types = $types->unionWith(
|
||||
$this->create($expr->expr, new NonEmptyArrayType(), $context->negate())
|
||||
);
|
||||
}
|
||||
|
||||
return $types;
|
||||
} elseif (
|
||||
$expr instanceof Expr\Empty_ && $context->truthy()
|
||||
&& (new ArrayType(new MixedType(), new MixedType()))->isSuperTypeOf($scope->getType($expr->expr))->yes()
|
||||
) {
|
||||
return $this->create($expr->expr, new NonEmptyArrayType(), $context->negate());
|
||||
} elseif (!$context->null()) {
|
||||
return $this->handleDefaultTruthyOrFalseyContext($context, $expr);
|
||||
}
|
||||
|
||||
return new SpecifiedTypes();
|
||||
}
|
||||
|
||||
private function handleDefaultTruthyOrFalseyContext(TypeSpecifierContext $context, Expr $expr): SpecifiedTypes
|
||||
{
|
||||
if (!$context->truthy()) {
|
||||
$type = new UnionType([new ObjectWithoutClassType(), new NonEmptyArrayType()]);
|
||||
return $this->create($expr, $type, TypeSpecifierContext::createFalse());
|
||||
} elseif (!$context->falsey()) {
|
||||
$type = new UnionType([
|
||||
new NullType(),
|
||||
new ConstantBooleanType(false),
|
||||
new ConstantIntegerType(0),
|
||||
new ConstantFloatType(0.0),
|
||||
new ConstantStringType(''),
|
||||
new ConstantArrayType([], []),
|
||||
]);
|
||||
return $this->create($expr, $type, TypeSpecifierContext::createFalse());
|
||||
}
|
||||
|
||||
return new SpecifiedTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \PHPStan\Analyser\Scope $scope
|
||||
* @param \PhpParser\Node\Expr\BinaryOp $binaryOperation
|
||||
* @return (Expr|\PHPStan\Type\ConstantScalarType)[]|null
|
||||
*/
|
||||
private function findTypeExpressionsFromBinaryOperation(Scope $scope, Node\Expr\BinaryOp $binaryOperation): ?array
|
||||
{
|
||||
$leftType = $scope->getType($binaryOperation->left);
|
||||
$rightType = $scope->getType($binaryOperation->right);
|
||||
if (
|
||||
$leftType instanceof \PHPStan\Type\ConstantScalarType
|
||||
&& !$binaryOperation->right instanceof ConstFetch
|
||||
&& !$binaryOperation->right instanceof Expr\ClassConstFetch
|
||||
) {
|
||||
return [$binaryOperation->right, $leftType];
|
||||
} elseif (
|
||||
$rightType instanceof \PHPStan\Type\ConstantScalarType
|
||||
&& !$binaryOperation->left instanceof ConstFetch
|
||||
&& !$binaryOperation->left instanceof Expr\ClassConstFetch
|
||||
) {
|
||||
return [$binaryOperation->left, $rightType];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function create(Expr $expr, Type $type, TypeSpecifierContext $context): SpecifiedTypes
|
||||
{
|
||||
if ($expr instanceof New_) {
|
||||
return new SpecifiedTypes();
|
||||
}
|
||||
|
||||
$sureTypes = [];
|
||||
$sureNotTypes = [];
|
||||
|
||||
$exprString = $this->printer->prettyPrintExpr($expr);
|
||||
if ($context->false()) {
|
||||
$sureNotTypes[$exprString] = [$expr, $type];
|
||||
} elseif ($context->true()) {
|
||||
$sureTypes[$exprString] = [$expr, $type];
|
||||
}
|
||||
|
||||
return new SpecifiedTypes($sureTypes, $sureNotTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PHPStan\Type\FunctionTypeSpecifyingExtension[]
|
||||
*/
|
||||
public function getFunctionTypeSpecifyingExtensions(): array
|
||||
{
|
||||
return $this->functionTypeSpecifyingExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return \PHPStan\Type\MethodTypeSpecifyingExtension[]
|
||||
*/
|
||||
public function getMethodTypeSpecifyingExtensionsForClass(string $className): array
|
||||
{
|
||||
if ($this->methodTypeSpecifyingExtensionsByClass === null) {
|
||||
$byClass = [];
|
||||
foreach ($this->methodTypeSpecifyingExtensions as $extension) {
|
||||
$byClass[$extension->getClass()][] = $extension;
|
||||
}
|
||||
|
||||
$this->methodTypeSpecifyingExtensionsByClass = $byClass;
|
||||
}
|
||||
return $this->getTypeSpecifyingExtensionsForType($this->methodTypeSpecifyingExtensionsByClass, $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return \PHPStan\Type\StaticMethodTypeSpecifyingExtension[]
|
||||
*/
|
||||
public function getStaticMethodTypeSpecifyingExtensionsForClass(string $className): array
|
||||
{
|
||||
if ($this->staticMethodTypeSpecifyingExtensionsByClass === null) {
|
||||
$byClass = [];
|
||||
foreach ($this->staticMethodTypeSpecifyingExtensions as $extension) {
|
||||
$byClass[$extension->getClass()][] = $extension;
|
||||
}
|
||||
|
||||
$this->staticMethodTypeSpecifyingExtensionsByClass = $byClass;
|
||||
}
|
||||
return $this->getTypeSpecifyingExtensionsForType($this->staticMethodTypeSpecifyingExtensionsByClass, $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \PHPStan\Type\MethodTypeSpecifyingExtension[][]|\PHPStan\Type\StaticMethodTypeSpecifyingExtension[][] $extensions
|
||||
* @param string $className
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function getTypeSpecifyingExtensionsForType(array $extensions, string $className): array
|
||||
{
|
||||
$extensionsForClass = [];
|
||||
$class = $this->broker->getClass($className);
|
||||
foreach (array_merge([$className], $class->getParentClassesNames(), $class->getNativeReflection()->getInterfaceNames()) as $extensionClassName) {
|
||||
if (!isset($extensions[$extensionClassName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extensionsForClass = array_merge($extensionsForClass, $extensions[$extensionClassName]);
|
||||
}
|
||||
|
||||
return $extensionsForClass;
|
||||
}
|
||||
|
||||
}
|
10
vendor/phpstan/phpstan/src/Analyser/TypeSpecifierAwareExtension.php
vendored
Normal file
10
vendor/phpstan/phpstan/src/Analyser/TypeSpecifierAwareExtension.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
interface TypeSpecifierAwareExtension
|
||||
{
|
||||
|
||||
public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void;
|
||||
|
||||
}
|
90
vendor/phpstan/phpstan/src/Analyser/TypeSpecifierContext.php
vendored
Normal file
90
vendor/phpstan/phpstan/src/Analyser/TypeSpecifierContext.php
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
class TypeSpecifierContext
|
||||
{
|
||||
|
||||
public const CONTEXT_TRUE = 0b0001;
|
||||
public const CONTEXT_TRUTHY_BUT_NOT_TRUE = 0b0010;
|
||||
public const CONTEXT_TRUTHY = self::CONTEXT_TRUE | self::CONTEXT_TRUTHY_BUT_NOT_TRUE;
|
||||
public const CONTEXT_FALSE = 0b0100;
|
||||
public const CONTEXT_FALSEY_BUT_NOT_FALSE = 0b1000;
|
||||
public const CONTEXT_FALSEY = self::CONTEXT_FALSE | self::CONTEXT_FALSEY_BUT_NOT_FALSE;
|
||||
|
||||
/** @var int|null */
|
||||
private $value;
|
||||
|
||||
/** @var self[] */
|
||||
private static $registry;
|
||||
|
||||
private function __construct(?int $value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
private static function create(?int $value): self
|
||||
{
|
||||
self::$registry[$value] = self::$registry[$value] ?? new self($value);
|
||||
return self::$registry[$value];
|
||||
}
|
||||
|
||||
public static function createTrue(): self
|
||||
{
|
||||
return self::create(self::CONTEXT_TRUE);
|
||||
}
|
||||
|
||||
public static function createTruthy(): self
|
||||
{
|
||||
return self::create(self::CONTEXT_TRUTHY);
|
||||
}
|
||||
|
||||
public static function createFalse(): self
|
||||
{
|
||||
return self::create(self::CONTEXT_FALSE);
|
||||
}
|
||||
|
||||
public static function createFalsey(): self
|
||||
{
|
||||
return self::create(self::CONTEXT_FALSEY);
|
||||
}
|
||||
|
||||
public static function createNull(): self
|
||||
{
|
||||
return self::create(null);
|
||||
}
|
||||
|
||||
public function negate(): self
|
||||
{
|
||||
if ($this->value === null) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
return self::create(~$this->value);
|
||||
}
|
||||
|
||||
public function true(): bool
|
||||
{
|
||||
return $this->value !== null && (bool) ($this->value & self::CONTEXT_TRUE);
|
||||
}
|
||||
|
||||
public function truthy(): bool
|
||||
{
|
||||
return $this->value !== null && (bool) ($this->value & self::CONTEXT_TRUTHY);
|
||||
}
|
||||
|
||||
public function false(): bool
|
||||
{
|
||||
return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSE);
|
||||
}
|
||||
|
||||
public function falsey(): bool
|
||||
{
|
||||
return $this->value !== null && (bool) ($this->value & self::CONTEXT_FALSEY);
|
||||
}
|
||||
|
||||
public function null(): bool
|
||||
{
|
||||
return $this->value === null;
|
||||
}
|
||||
|
||||
}
|
58
vendor/phpstan/phpstan/src/Analyser/TypeSpecifierFactory.php
vendored
Normal file
58
vendor/phpstan/phpstan/src/Analyser/TypeSpecifierFactory.php
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use Nette\DI\Container;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use PHPStan\Broker\Broker;
|
||||
use PHPStan\Broker\BrokerFactory;
|
||||
|
||||
class TypeSpecifierFactory
|
||||
{
|
||||
|
||||
public const FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG = 'phpstan.typeSpecifier.functionTypeSpecifyingExtension';
|
||||
public const METHOD_TYPE_SPECIFYING_EXTENSION_TAG = 'phpstan.typeSpecifier.methodTypeSpecifyingExtension';
|
||||
public const STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG = 'phpstan.typeSpecifier.staticMethodTypeSpecifyingExtension';
|
||||
|
||||
/** @var \Nette\DI\Container */
|
||||
private $container;
|
||||
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function create(): TypeSpecifier
|
||||
{
|
||||
$tagToService = function (array $tags) {
|
||||
return array_map(function (string $serviceName) {
|
||||
return $this->container->getService($serviceName);
|
||||
}, array_keys($tags));
|
||||
};
|
||||
|
||||
$typeSpecifier = new TypeSpecifier(
|
||||
$this->container->getByType(Standard::class),
|
||||
$this->container->getByType(Broker::class),
|
||||
$tagToService($this->container->findByTag(self::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(self::METHOD_TYPE_SPECIFYING_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(self::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG))
|
||||
);
|
||||
|
||||
foreach (array_merge(
|
||||
$tagToService($this->container->findByTag(BrokerFactory::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(BrokerFactory::METHODS_CLASS_REFLECTION_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(BrokerFactory::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(BrokerFactory::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(BrokerFactory::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG))
|
||||
) as $extension) {
|
||||
if (!($extension instanceof TypeSpecifierAwareExtension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension->setTypeSpecifier($typeSpecifier);
|
||||
}
|
||||
|
||||
return $typeSpecifier;
|
||||
}
|
||||
|
||||
}
|
31
vendor/phpstan/phpstan/src/Analyser/UndefinedVariableException.php
vendored
Normal file
31
vendor/phpstan/phpstan/src/Analyser/UndefinedVariableException.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
class UndefinedVariableException extends \PHPStan\AnalysedCodeException
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Analyser\Scope */
|
||||
private $scope;
|
||||
|
||||
/** @var string */
|
||||
private $variableName;
|
||||
|
||||
public function __construct(Scope $scope, string $variableName)
|
||||
{
|
||||
parent::__construct(sprintf('Undefined variable: $%s', $variableName));
|
||||
$this->scope = $scope;
|
||||
$this->variableName = $variableName;
|
||||
}
|
||||
|
||||
public function getScope(): Scope
|
||||
{
|
||||
return $this->scope;
|
||||
}
|
||||
|
||||
public function getVariableName(): string
|
||||
{
|
||||
return $this->variableName;
|
||||
}
|
||||
|
||||
}
|
55
vendor/phpstan/phpstan/src/Analyser/VariableTypeHolder.php
vendored
Normal file
55
vendor/phpstan/phpstan/src/Analyser/VariableTypeHolder.php
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Analyser;
|
||||
|
||||
use PHPStan\TrinaryLogic;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeCombinator;
|
||||
|
||||
class VariableTypeHolder
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Type\Type */
|
||||
private $type;
|
||||
|
||||
/** @var \PHPStan\TrinaryLogic */
|
||||
private $certainty;
|
||||
|
||||
public function __construct(Type $type, TrinaryLogic $certainty)
|
||||
{
|
||||
if ($certainty->no()) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
$this->type = $type;
|
||||
$this->certainty = $certainty;
|
||||
}
|
||||
|
||||
public static function createYes(Type $type): self
|
||||
{
|
||||
return new self($type, TrinaryLogic::createYes());
|
||||
}
|
||||
|
||||
public static function createMaybe(Type $type): self
|
||||
{
|
||||
return new self($type, TrinaryLogic::createMaybe());
|
||||
}
|
||||
|
||||
public function and(self $other): self
|
||||
{
|
||||
return new self(
|
||||
TypeCombinator::union($this->getType(), $other->getType()),
|
||||
$this->getCertainty()->and($other->getCertainty())
|
||||
);
|
||||
}
|
||||
|
||||
public function getType(): Type
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function getCertainty(): TrinaryLogic
|
||||
{
|
||||
return $this->certainty;
|
||||
}
|
||||
|
||||
}
|
45
vendor/phpstan/phpstan/src/Broker/AnonymousClassNameHelper.php
vendored
Normal file
45
vendor/phpstan/phpstan/src/Broker/AnonymousClassNameHelper.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Broker;
|
||||
|
||||
use PHPStan\File\FileHelper;
|
||||
use PHPStan\File\RelativePathHelper;
|
||||
|
||||
class AnonymousClassNameHelper
|
||||
{
|
||||
|
||||
/** @var FileHelper */
|
||||
private $fileHelper;
|
||||
|
||||
/** @var RelativePathHelper */
|
||||
private $relativePathHelper;
|
||||
|
||||
public function __construct(
|
||||
FileHelper $fileHelper,
|
||||
RelativePathHelper $relativePathHelper
|
||||
)
|
||||
{
|
||||
$this->fileHelper = $fileHelper;
|
||||
$this->relativePathHelper = $relativePathHelper;
|
||||
}
|
||||
|
||||
public function getAnonymousClassName(
|
||||
\PhpParser\Node\Expr\New_ $node,
|
||||
string $filename
|
||||
): string
|
||||
{
|
||||
if (!$node->class instanceof \PhpParser\Node\Stmt\Class_) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$filename = $this->relativePathHelper->getRelativePath(
|
||||
$this->fileHelper->normalizePath($filename)
|
||||
);
|
||||
|
||||
return sprintf(
|
||||
'AnonymousClass%s',
|
||||
md5(sprintf('%s:%s', $filename, $node->class->getLine()))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
592
vendor/phpstan/phpstan/src/Broker/Broker.php
vendored
Normal file
592
vendor/phpstan/phpstan/src/Broker/Broker.php
vendored
Normal file
|
@ -0,0 +1,592 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Broker;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\File\RelativePathHelper;
|
||||
use PHPStan\Parser\Parser;
|
||||
use PHPStan\PhpDoc\Tag\ParamTag;
|
||||
use PHPStan\Reflection\BrokerAwareExtension;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use PHPStan\Reflection\FunctionReflectionFactory;
|
||||
use PHPStan\Reflection\FunctionVariant;
|
||||
use PHPStan\Reflection\Native\NativeFunctionReflection;
|
||||
use PHPStan\Reflection\Native\NativeParameterReflection;
|
||||
use PHPStan\Reflection\SignatureMap\ParameterSignature;
|
||||
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
|
||||
use PHPStan\Type\BooleanType;
|
||||
use PHPStan\Type\FileTypeMapper;
|
||||
use PHPStan\Type\FloatType;
|
||||
use PHPStan\Type\IntegerType;
|
||||
use PHPStan\Type\NullType;
|
||||
use PHPStan\Type\StringAlwaysAcceptingObjectWithToStringType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeUtils;
|
||||
use PHPStan\Type\UnionType;
|
||||
use ReflectionClass;
|
||||
|
||||
class Broker
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Reflection\PropertiesClassReflectionExtension[] */
|
||||
private $propertiesClassReflectionExtensions;
|
||||
|
||||
/** @var \PHPStan\Reflection\MethodsClassReflectionExtension[] */
|
||||
private $methodsClassReflectionExtensions;
|
||||
|
||||
/** @var \PHPStan\Type\DynamicMethodReturnTypeExtension[] */
|
||||
private $dynamicMethodReturnTypeExtensions = [];
|
||||
|
||||
/** @var \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] */
|
||||
private $dynamicStaticMethodReturnTypeExtensions = [];
|
||||
|
||||
/** @var \PHPStan\Type\DynamicMethodReturnTypeExtension[][]|null */
|
||||
private $dynamicMethodReturnTypeExtensionsByClass;
|
||||
|
||||
/** @var \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[][]|null */
|
||||
private $dynamicStaticMethodReturnTypeExtensionsByClass;
|
||||
|
||||
/** @var \PHPStan\Type\DynamicFunctionReturnTypeExtension[] */
|
||||
private $dynamicFunctionReturnTypeExtensions = [];
|
||||
|
||||
/** @var \PHPStan\Reflection\ClassReflection[] */
|
||||
private $classReflections = [];
|
||||
|
||||
/** @var \PHPStan\Reflection\FunctionReflectionFactory */
|
||||
private $functionReflectionFactory;
|
||||
|
||||
/** @var \PHPStan\Type\FileTypeMapper */
|
||||
private $fileTypeMapper;
|
||||
|
||||
/** @var \PHPStan\Reflection\SignatureMap\SignatureMapProvider */
|
||||
private $signatureMapProvider;
|
||||
|
||||
/** @var \PhpParser\PrettyPrinter\Standard */
|
||||
private $printer;
|
||||
|
||||
/** @var AnonymousClassNameHelper */
|
||||
private $anonymousClassNameHelper;
|
||||
|
||||
/** @var Parser */
|
||||
private $parser;
|
||||
|
||||
/** @var RelativePathHelper */
|
||||
private $relativePathHelper;
|
||||
|
||||
/** @var string[] */
|
||||
private $universalObjectCratesClasses;
|
||||
|
||||
/** @var \PHPStan\Reflection\FunctionReflection[] */
|
||||
private $functionReflections = [];
|
||||
|
||||
/** @var \PHPStan\Reflection\Php\PhpFunctionReflection[] */
|
||||
private $customFunctionReflections = [];
|
||||
|
||||
/** @var self|null */
|
||||
private static $instance;
|
||||
|
||||
/** @var bool[] */
|
||||
private $hasClassCache;
|
||||
|
||||
/** @var NativeFunctionReflection[] */
|
||||
private static $functionMap = [];
|
||||
|
||||
/** @var \PHPStan\Reflection\ClassReflection[] */
|
||||
private static $anonymousClasses = [];
|
||||
|
||||
/**
|
||||
* @param \PHPStan\Reflection\PropertiesClassReflectionExtension[] $propertiesClassReflectionExtensions
|
||||
* @param \PHPStan\Reflection\MethodsClassReflectionExtension[] $methodsClassReflectionExtensions
|
||||
* @param \PHPStan\Type\DynamicMethodReturnTypeExtension[] $dynamicMethodReturnTypeExtensions
|
||||
* @param \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[] $dynamicStaticMethodReturnTypeExtensions
|
||||
* @param \PHPStan\Type\DynamicFunctionReturnTypeExtension[] $dynamicFunctionReturnTypeExtensions
|
||||
* @param \PHPStan\Reflection\FunctionReflectionFactory $functionReflectionFactory
|
||||
* @param \PHPStan\Type\FileTypeMapper $fileTypeMapper
|
||||
* @param \PHPStan\Reflection\SignatureMap\SignatureMapProvider $signatureMapProvider
|
||||
* @param \PhpParser\PrettyPrinter\Standard $printer
|
||||
* @param AnonymousClassNameHelper $anonymousClassNameHelper
|
||||
* @param Parser $parser
|
||||
* @param RelativePathHelper $relativePathHelper
|
||||
* @param string[] $universalObjectCratesClasses
|
||||
*/
|
||||
public function __construct(
|
||||
array $propertiesClassReflectionExtensions,
|
||||
array $methodsClassReflectionExtensions,
|
||||
array $dynamicMethodReturnTypeExtensions,
|
||||
array $dynamicStaticMethodReturnTypeExtensions,
|
||||
array $dynamicFunctionReturnTypeExtensions,
|
||||
FunctionReflectionFactory $functionReflectionFactory,
|
||||
FileTypeMapper $fileTypeMapper,
|
||||
SignatureMapProvider $signatureMapProvider,
|
||||
\PhpParser\PrettyPrinter\Standard $printer,
|
||||
AnonymousClassNameHelper $anonymousClassNameHelper,
|
||||
Parser $parser,
|
||||
RelativePathHelper $relativePathHelper,
|
||||
array $universalObjectCratesClasses
|
||||
)
|
||||
{
|
||||
$this->propertiesClassReflectionExtensions = $propertiesClassReflectionExtensions;
|
||||
$this->methodsClassReflectionExtensions = $methodsClassReflectionExtensions;
|
||||
foreach (array_merge($propertiesClassReflectionExtensions, $methodsClassReflectionExtensions, $dynamicMethodReturnTypeExtensions, $dynamicStaticMethodReturnTypeExtensions, $dynamicFunctionReturnTypeExtensions) as $extension) {
|
||||
if (!($extension instanceof BrokerAwareExtension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extension->setBroker($this);
|
||||
}
|
||||
|
||||
$this->dynamicMethodReturnTypeExtensions = $dynamicMethodReturnTypeExtensions;
|
||||
$this->dynamicStaticMethodReturnTypeExtensions = $dynamicStaticMethodReturnTypeExtensions;
|
||||
|
||||
foreach ($dynamicFunctionReturnTypeExtensions as $functionReturnTypeExtension) {
|
||||
$this->dynamicFunctionReturnTypeExtensions[] = $functionReturnTypeExtension;
|
||||
}
|
||||
|
||||
$this->functionReflectionFactory = $functionReflectionFactory;
|
||||
$this->fileTypeMapper = $fileTypeMapper;
|
||||
$this->signatureMapProvider = $signatureMapProvider;
|
||||
$this->printer = $printer;
|
||||
$this->anonymousClassNameHelper = $anonymousClassNameHelper;
|
||||
$this->parser = $parser;
|
||||
$this->relativePathHelper = $relativePathHelper;
|
||||
$this->universalObjectCratesClasses = $universalObjectCratesClasses;
|
||||
}
|
||||
|
||||
public static function registerInstance(Broker $broker): void
|
||||
{
|
||||
self::$instance = $broker;
|
||||
}
|
||||
|
||||
public static function getInstance(): self
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getUniversalObjectCratesClasses(): array
|
||||
{
|
||||
return $this->universalObjectCratesClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return \PHPStan\Type\DynamicMethodReturnTypeExtension[]
|
||||
*/
|
||||
public function getDynamicMethodReturnTypeExtensionsForClass(string $className): array
|
||||
{
|
||||
if ($this->dynamicMethodReturnTypeExtensionsByClass === null) {
|
||||
$byClass = [];
|
||||
foreach ($this->dynamicMethodReturnTypeExtensions as $extension) {
|
||||
$byClass[$extension->getClass()][] = $extension;
|
||||
}
|
||||
|
||||
$this->dynamicMethodReturnTypeExtensionsByClass = $byClass;
|
||||
}
|
||||
return $this->getDynamicExtensionsForType($this->dynamicMethodReturnTypeExtensionsByClass, $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return \PHPStan\Type\DynamicStaticMethodReturnTypeExtension[]
|
||||
*/
|
||||
public function getDynamicStaticMethodReturnTypeExtensionsForClass(string $className): array
|
||||
{
|
||||
if ($this->dynamicStaticMethodReturnTypeExtensionsByClass === null) {
|
||||
$byClass = [];
|
||||
foreach ($this->dynamicStaticMethodReturnTypeExtensions as $extension) {
|
||||
$byClass[$extension->getClass()][] = $extension;
|
||||
}
|
||||
|
||||
$this->dynamicStaticMethodReturnTypeExtensionsByClass = $byClass;
|
||||
}
|
||||
return $this->getDynamicExtensionsForType($this->dynamicStaticMethodReturnTypeExtensionsByClass, $className);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PHPStan\Type\DynamicFunctionReturnTypeExtension[]
|
||||
*/
|
||||
public function getDynamicFunctionReturnTypeExtensions(): array
|
||||
{
|
||||
return $this->dynamicFunctionReturnTypeExtensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \PHPStan\Type\DynamicMethodReturnTypeExtension[][]|\PHPStan\Type\DynamicStaticMethodReturnTypeExtension[][] $extensions
|
||||
* @param string $className
|
||||
* @return mixed[]
|
||||
*/
|
||||
private function getDynamicExtensionsForType(array $extensions, string $className): array
|
||||
{
|
||||
$extensionsForClass = [];
|
||||
$class = $this->getClass($className);
|
||||
foreach (array_merge([$className], $class->getParentClassesNames(), $class->getNativeReflection()->getInterfaceNames()) as $extensionClassName) {
|
||||
if (!isset($extensions[$extensionClassName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$extensionsForClass = array_merge($extensionsForClass, $extensions[$extensionClassName]);
|
||||
}
|
||||
|
||||
return $extensionsForClass;
|
||||
}
|
||||
|
||||
public function getClass(string $className): \PHPStan\Reflection\ClassReflection
|
||||
{
|
||||
if (!$this->hasClass($className)) {
|
||||
throw new \PHPStan\Broker\ClassNotFoundException($className);
|
||||
}
|
||||
|
||||
if (isset(self::$anonymousClasses[$className])) {
|
||||
return self::$anonymousClasses[$className];
|
||||
}
|
||||
|
||||
if (!isset($this->classReflections[$className])) {
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
$filename = null;
|
||||
if ($reflectionClass->getFileName() !== false) {
|
||||
$filename = $reflectionClass->getFileName();
|
||||
}
|
||||
|
||||
$classReflection = $this->getClassFromReflection(
|
||||
$reflectionClass,
|
||||
$reflectionClass->getName(),
|
||||
$reflectionClass->isAnonymous() ? $filename : null
|
||||
);
|
||||
$this->classReflections[$className] = $classReflection;
|
||||
if ($className !== $reflectionClass->getName()) {
|
||||
// class alias optimization
|
||||
$this->classReflections[$reflectionClass->getName()] = $classReflection;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->classReflections[$className];
|
||||
}
|
||||
|
||||
public function getAnonymousClassReflection(
|
||||
\PhpParser\Node\Expr\New_ $node,
|
||||
Scope $scope
|
||||
): ClassReflection
|
||||
{
|
||||
if (!$node->class instanceof \PhpParser\Node\Stmt\Class_) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
if (!$scope->isInTrait()) {
|
||||
$scopeFile = $scope->getFile();
|
||||
} else {
|
||||
$scopeFile = $scope->getTraitReflection()->getFileName();
|
||||
if ($scopeFile === false) {
|
||||
$scopeFile = $scope->getFile();
|
||||
}
|
||||
}
|
||||
|
||||
$filename = $this->relativePathHelper->getRelativePath($scopeFile);
|
||||
|
||||
$className = $this->anonymousClassNameHelper->getAnonymousClassName(
|
||||
$node,
|
||||
$filename
|
||||
);
|
||||
|
||||
if (isset(self::$anonymousClasses[$className])) {
|
||||
return self::$anonymousClasses[$className];
|
||||
}
|
||||
|
||||
$classNode = $node->class;
|
||||
$classNode->name = new \PhpParser\Node\Identifier($className);
|
||||
eval($this->printer->prettyPrint([$classNode]));
|
||||
unset($classNode);
|
||||
|
||||
self::$anonymousClasses[$className] = $this->getClassFromReflection(
|
||||
new \ReflectionClass('\\' . $className),
|
||||
sprintf('class@anonymous/%s:%s', $filename, $node->getLine()),
|
||||
$scopeFile
|
||||
);
|
||||
$this->classReflections[$className] = self::$anonymousClasses[$className];
|
||||
|
||||
return self::$anonymousClasses[$className];
|
||||
}
|
||||
|
||||
public function getClassFromReflection(\ReflectionClass $reflectionClass, string $displayName, ?string $anonymousFilename): ClassReflection
|
||||
{
|
||||
$className = $reflectionClass->getName();
|
||||
if (!isset($this->classReflections[$className])) {
|
||||
$classReflection = new ClassReflection(
|
||||
$this,
|
||||
$this->fileTypeMapper,
|
||||
$this->propertiesClassReflectionExtensions,
|
||||
$this->methodsClassReflectionExtensions,
|
||||
$displayName,
|
||||
$reflectionClass,
|
||||
$anonymousFilename
|
||||
);
|
||||
$this->classReflections[$className] = $classReflection;
|
||||
}
|
||||
|
||||
return $this->classReflections[$className];
|
||||
}
|
||||
|
||||
public function hasClass(string $className): bool
|
||||
{
|
||||
if (isset($this->hasClassCache[$className])) {
|
||||
return $this->hasClassCache[$className];
|
||||
}
|
||||
|
||||
spl_autoload_register($autoloader = function (string $autoloadedClassName) use ($className): void {
|
||||
if ($autoloadedClassName !== $className && !$this->isExistsCheckCall()) {
|
||||
throw new \PHPStan\Broker\ClassAutoloadingException($autoloadedClassName);
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return $this->hasClassCache[$className] = class_exists($className) || interface_exists($className) || trait_exists($className);
|
||||
} catch (\PHPStan\Broker\ClassAutoloadingException $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $t) {
|
||||
throw new \PHPStan\Broker\ClassAutoloadingException(
|
||||
$className,
|
||||
$t
|
||||
);
|
||||
} finally {
|
||||
spl_autoload_unregister($autoloader);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFunction(\PhpParser\Node\Name $nameNode, ?Scope $scope): \PHPStan\Reflection\FunctionReflection
|
||||
{
|
||||
$functionName = $this->resolveFunctionName($nameNode, $scope);
|
||||
if ($functionName === null) {
|
||||
throw new \PHPStan\Broker\FunctionNotFoundException((string) $nameNode);
|
||||
}
|
||||
|
||||
$lowerCasedFunctionName = strtolower($functionName);
|
||||
if (!isset($this->functionReflections[$lowerCasedFunctionName])) {
|
||||
if (isset(self::$functionMap[$lowerCasedFunctionName])) {
|
||||
return $this->functionReflections[$lowerCasedFunctionName] = self::$functionMap[$lowerCasedFunctionName];
|
||||
}
|
||||
|
||||
if ($this->signatureMapProvider->hasFunctionSignature($lowerCasedFunctionName)) {
|
||||
$variantName = $lowerCasedFunctionName;
|
||||
$variants = [];
|
||||
$i = 0;
|
||||
while ($this->signatureMapProvider->hasFunctionSignature($variantName)) {
|
||||
$functionSignature = $this->signatureMapProvider->getFunctionSignature($variantName, null);
|
||||
$returnType = $functionSignature->getReturnType();
|
||||
if ($lowerCasedFunctionName === 'pow') {
|
||||
$returnType = TypeUtils::toBenevolentUnion($returnType);
|
||||
}
|
||||
$variants[] = new FunctionVariant(
|
||||
array_map(static function (ParameterSignature $parameterSignature) use ($lowerCasedFunctionName): NativeParameterReflection {
|
||||
$type = $parameterSignature->getType();
|
||||
if (
|
||||
$parameterSignature->getName() === 'args'
|
||||
&& (
|
||||
$lowerCasedFunctionName === 'printf'
|
||||
|| $lowerCasedFunctionName === 'sprintf'
|
||||
)
|
||||
) {
|
||||
$type = new UnionType([
|
||||
new StringAlwaysAcceptingObjectWithToStringType(),
|
||||
new IntegerType(),
|
||||
new FloatType(),
|
||||
new NullType(),
|
||||
new BooleanType(),
|
||||
]);
|
||||
}
|
||||
return new NativeParameterReflection(
|
||||
$parameterSignature->getName(),
|
||||
$parameterSignature->isOptional(),
|
||||
$type,
|
||||
$parameterSignature->passedByReference(),
|
||||
$parameterSignature->isVariadic()
|
||||
);
|
||||
}, $functionSignature->getParameters()),
|
||||
$functionSignature->isVariadic(),
|
||||
$returnType
|
||||
);
|
||||
|
||||
$i++;
|
||||
$variantName = sprintf($lowerCasedFunctionName . '\'' . $i);
|
||||
}
|
||||
$functionReflection = new NativeFunctionReflection(
|
||||
$lowerCasedFunctionName,
|
||||
$variants,
|
||||
null
|
||||
);
|
||||
self::$functionMap[$lowerCasedFunctionName] = $functionReflection;
|
||||
$this->functionReflections[$lowerCasedFunctionName] = $functionReflection;
|
||||
} else {
|
||||
$this->functionReflections[$lowerCasedFunctionName] = $this->getCustomFunction($nameNode, $scope);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->functionReflections[$lowerCasedFunctionName];
|
||||
}
|
||||
|
||||
public function hasFunction(\PhpParser\Node\Name $nameNode, ?Scope $scope): bool
|
||||
{
|
||||
return $this->resolveFunctionName($nameNode, $scope) !== null;
|
||||
}
|
||||
|
||||
public function hasCustomFunction(\PhpParser\Node\Name $nameNode, ?Scope $scope): bool
|
||||
{
|
||||
$functionName = $this->resolveFunctionName($nameNode, $scope);
|
||||
if ($functionName === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lowerCasedFunctionName = strtolower($functionName);
|
||||
|
||||
return !$this->signatureMapProvider->hasFunctionSignature($lowerCasedFunctionName);
|
||||
}
|
||||
|
||||
public function getCustomFunction(\PhpParser\Node\Name $nameNode, ?Scope $scope): \PHPStan\Reflection\Php\PhpFunctionReflection
|
||||
{
|
||||
if (!$this->hasCustomFunction($nameNode, $scope)) {
|
||||
throw new \PHPStan\Broker\FunctionNotFoundException((string) $nameNode);
|
||||
}
|
||||
|
||||
/** @var string $functionName */
|
||||
$functionName = $this->resolveFunctionName($nameNode, $scope);
|
||||
if (!function_exists($functionName)) {
|
||||
throw new \PHPStan\Broker\FunctionNotFoundException($functionName);
|
||||
}
|
||||
$lowerCasedFunctionName = strtolower($functionName);
|
||||
if (isset($this->customFunctionReflections[$lowerCasedFunctionName])) {
|
||||
return $this->customFunctionReflections[$lowerCasedFunctionName];
|
||||
}
|
||||
|
||||
$reflectionFunction = new \ReflectionFunction($functionName);
|
||||
$phpDocParameterTags = [];
|
||||
$phpDocReturnTag = null;
|
||||
$phpDocThrowsTag = null;
|
||||
$isDeprecated = false;
|
||||
$isInternal = false;
|
||||
$isFinal = false;
|
||||
if ($reflectionFunction->getFileName() !== false && $reflectionFunction->getDocComment() !== false) {
|
||||
$fileName = $reflectionFunction->getFileName();
|
||||
$docComment = $reflectionFunction->getDocComment();
|
||||
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc($fileName, null, null, $docComment);
|
||||
$phpDocParameterTags = $resolvedPhpDoc->getParamTags();
|
||||
$phpDocReturnTag = $resolvedPhpDoc->getReturnTag();
|
||||
$phpDocThrowsTag = $resolvedPhpDoc->getThrowsTag();
|
||||
$isDeprecated = $resolvedPhpDoc->isDeprecated();
|
||||
$isInternal = $resolvedPhpDoc->isInternal();
|
||||
$isFinal = $resolvedPhpDoc->isFinal();
|
||||
}
|
||||
|
||||
$functionReflection = $this->functionReflectionFactory->create(
|
||||
$reflectionFunction,
|
||||
array_map(static function (ParamTag $paramTag): Type {
|
||||
return $paramTag->getType();
|
||||
}, $phpDocParameterTags),
|
||||
$phpDocReturnTag !== null ? $phpDocReturnTag->getType() : null,
|
||||
$phpDocThrowsTag !== null ? $phpDocThrowsTag->getType() : null,
|
||||
$isDeprecated,
|
||||
$isInternal,
|
||||
$isFinal,
|
||||
$reflectionFunction->getFileName()
|
||||
);
|
||||
$this->customFunctionReflections[$lowerCasedFunctionName] = $functionReflection;
|
||||
|
||||
return $functionReflection;
|
||||
}
|
||||
|
||||
public function resolveFunctionName(\PhpParser\Node\Name $nameNode, ?Scope $scope): ?string
|
||||
{
|
||||
return $this->resolveName($nameNode, function (string $name): bool {
|
||||
$exists = function_exists($name);
|
||||
if ($exists) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$lowercased = strtolower($name);
|
||||
|
||||
return $this->signatureMapProvider->hasFunctionSignature($lowercased);
|
||||
}, $scope);
|
||||
}
|
||||
|
||||
public function hasConstant(\PhpParser\Node\Name $nameNode, ?Scope $scope): bool
|
||||
{
|
||||
return $this->resolveConstantName($nameNode, $scope) !== null;
|
||||
}
|
||||
|
||||
public function resolveConstantName(\PhpParser\Node\Name $nameNode, ?Scope $scope): ?string
|
||||
{
|
||||
return $this->resolveName($nameNode, function (string $name) use ($scope): bool {
|
||||
$isCompilerHaltOffset = $name === '__COMPILER_HALT_OFFSET__';
|
||||
if ($isCompilerHaltOffset && $scope !== null && $this->fileHasCompilerHaltStatementCalls($scope->getFile())) {
|
||||
return true;
|
||||
}
|
||||
return defined($name);
|
||||
}, $scope);
|
||||
}
|
||||
|
||||
private function fileHasCompilerHaltStatementCalls(string $pathToFile): bool
|
||||
{
|
||||
$nodes = $this->parser->parseFile($pathToFile);
|
||||
foreach ($nodes as $node) {
|
||||
if ($node instanceof Node\Stmt\HaltCompiler) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node\Name $nameNode
|
||||
* @param \Closure(string $name): bool $existsCallback
|
||||
* @param Scope|null $scope
|
||||
* @return string|null
|
||||
*/
|
||||
private function resolveName(
|
||||
\PhpParser\Node\Name $nameNode,
|
||||
\Closure $existsCallback,
|
||||
?Scope $scope
|
||||
): ?string
|
||||
{
|
||||
$name = (string) $nameNode;
|
||||
if ($scope !== null && $scope->getNamespace() !== null && !$nameNode->isFullyQualified()) {
|
||||
$namespacedName = sprintf('%s\\%s', $scope->getNamespace(), $name);
|
||||
if ($existsCallback($namespacedName)) {
|
||||
return $namespacedName;
|
||||
}
|
||||
}
|
||||
|
||||
if ($existsCallback($name)) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function isExistsCheckCall(): bool
|
||||
{
|
||||
$debugBacktrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
|
||||
$existsCallTypes = [
|
||||
'class_exists' => true,
|
||||
'interface_exists' => true,
|
||||
'trait_exists' => true,
|
||||
];
|
||||
|
||||
foreach ($debugBacktrace as $traceStep) {
|
||||
if (
|
||||
isset($traceStep['function'])
|
||||
&& isset($existsCallTypes[$traceStep['function']])
|
||||
// We must ignore the self::hasClass calls
|
||||
&& (!isset($traceStep['file']) || $traceStep['file'] !== __FILE__)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
65
vendor/phpstan/phpstan/src/Broker/BrokerFactory.php
vendored
Normal file
65
vendor/phpstan/phpstan/src/Broker/BrokerFactory.php
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Broker;
|
||||
|
||||
use PHPStan\File\RelativePathHelper;
|
||||
use PHPStan\Parser\Parser;
|
||||
use PHPStan\Reflection\Annotations\AnnotationsMethodsClassReflectionExtension;
|
||||
use PHPStan\Reflection\Annotations\AnnotationsPropertiesClassReflectionExtension;
|
||||
use PHPStan\Reflection\FunctionReflectionFactory;
|
||||
use PHPStan\Reflection\Php\PhpClassReflectionExtension;
|
||||
use PHPStan\Reflection\PhpDefect\PhpDefectClassReflectionExtension;
|
||||
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
|
||||
use PHPStan\Type\FileTypeMapper;
|
||||
|
||||
class BrokerFactory
|
||||
{
|
||||
|
||||
public const PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG = 'phpstan.broker.propertiesClassReflectionExtension';
|
||||
public const METHODS_CLASS_REFLECTION_EXTENSION_TAG = 'phpstan.broker.methodsClassReflectionExtension';
|
||||
public const DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG = 'phpstan.broker.dynamicMethodReturnTypeExtension';
|
||||
public const DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG = 'phpstan.broker.dynamicStaticMethodReturnTypeExtension';
|
||||
public const DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG = 'phpstan.broker.dynamicFunctionReturnTypeExtension';
|
||||
|
||||
/** @var \Nette\DI\Container */
|
||||
private $container;
|
||||
|
||||
public function __construct(\Nette\DI\Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function create(): Broker
|
||||
{
|
||||
$tagToService = function (array $tags) {
|
||||
return array_map(function (string $serviceName) {
|
||||
return $this->container->getService($serviceName);
|
||||
}, array_keys($tags));
|
||||
};
|
||||
|
||||
$phpClassReflectionExtension = $this->container->getByType(PhpClassReflectionExtension::class);
|
||||
$annotationsMethodsClassReflectionExtension = $this->container->getByType(AnnotationsMethodsClassReflectionExtension::class);
|
||||
$annotationsPropertiesClassReflectionExtension = $this->container->getByType(AnnotationsPropertiesClassReflectionExtension::class);
|
||||
$phpDefectClassReflectionExtension = $this->container->getByType(PhpDefectClassReflectionExtension::class);
|
||||
|
||||
/** @var RelativePathHelper $relativePathHelper */
|
||||
$relativePathHelper = $this->container->getService('relativePathHelper');
|
||||
|
||||
return new Broker(
|
||||
array_merge([$phpClassReflectionExtension, $phpDefectClassReflectionExtension], $tagToService($this->container->findByTag(self::PROPERTIES_CLASS_REFLECTION_EXTENSION_TAG)), [$annotationsPropertiesClassReflectionExtension]),
|
||||
array_merge([$phpClassReflectionExtension], $tagToService($this->container->findByTag(self::METHODS_CLASS_REFLECTION_EXTENSION_TAG)), [$annotationsMethodsClassReflectionExtension]),
|
||||
$tagToService($this->container->findByTag(self::DYNAMIC_METHOD_RETURN_TYPE_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(self::DYNAMIC_STATIC_METHOD_RETURN_TYPE_EXTENSION_TAG)),
|
||||
$tagToService($this->container->findByTag(self::DYNAMIC_FUNCTION_RETURN_TYPE_EXTENSION_TAG)),
|
||||
$this->container->getByType(FunctionReflectionFactory::class),
|
||||
$this->container->getByType(FileTypeMapper::class),
|
||||
$this->container->getByType(SignatureMapProvider::class),
|
||||
$this->container->getByType(\PhpParser\PrettyPrinter\Standard::class),
|
||||
$this->container->getByType(AnonymousClassNameHelper::class),
|
||||
$this->container->getByType(Parser::class),
|
||||
$relativePathHelper,
|
||||
$this->container->parameters['universalObjectCratesClasses']
|
||||
);
|
||||
}
|
||||
|
||||
}
|
38
vendor/phpstan/phpstan/src/Broker/ClassAutoloadingException.php
vendored
Normal file
38
vendor/phpstan/phpstan/src/Broker/ClassAutoloadingException.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Broker;
|
||||
|
||||
class ClassAutoloadingException extends \PHPStan\AnalysedCodeException
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $className;
|
||||
|
||||
public function __construct(
|
||||
string $functionName,
|
||||
?\Throwable $previous = null
|
||||
)
|
||||
{
|
||||
if ($previous !== null) {
|
||||
parent::__construct(sprintf(
|
||||
'%s (%s) thrown while autoloading class %s.',
|
||||
get_class($previous),
|
||||
$previous->getMessage(),
|
||||
$functionName
|
||||
), 0, $previous);
|
||||
} else {
|
||||
parent::__construct(sprintf(
|
||||
'Class %s not found and could not be autoloaded.',
|
||||
$functionName
|
||||
), 0);
|
||||
}
|
||||
|
||||
$this->className = $functionName;
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpstan/src/Broker/ClassNotFoundException.php
vendored
Normal file
22
vendor/phpstan/phpstan/src/Broker/ClassNotFoundException.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Broker;
|
||||
|
||||
class ClassNotFoundException extends \PHPStan\AnalysedCodeException
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $className;
|
||||
|
||||
public function __construct(string $functionName)
|
||||
{
|
||||
parent::__construct(sprintf('Class %s was not found while trying to analyse it - autoloading is probably not configured properly.', $functionName));
|
||||
$this->className = $functionName;
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
}
|
22
vendor/phpstan/phpstan/src/Broker/FunctionNotFoundException.php
vendored
Normal file
22
vendor/phpstan/phpstan/src/Broker/FunctionNotFoundException.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Broker;
|
||||
|
||||
class FunctionNotFoundException extends \PHPStan\AnalysedCodeException
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $functionName;
|
||||
|
||||
public function __construct(string $functionName)
|
||||
{
|
||||
parent::__construct(sprintf('Function %s not found while trying to analyse it - autoloading is probably not configured properly.', $functionName));
|
||||
$this->functionName = $functionName;
|
||||
}
|
||||
|
||||
public function getFunctionName(): string
|
||||
{
|
||||
return $this->functionName;
|
||||
}
|
||||
|
||||
}
|
35
vendor/phpstan/phpstan/src/Cache/Cache.php
vendored
Normal file
35
vendor/phpstan/phpstan/src/Cache/Cache.php
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Cache;
|
||||
|
||||
class Cache
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Cache\CacheStorage */
|
||||
private $storage;
|
||||
|
||||
public function __construct(CacheStorage $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function load(string $key)
|
||||
{
|
||||
return $this->storage->load($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function save(string $key, $data): bool
|
||||
{
|
||||
return $this->storage->save($key, $data);
|
||||
}
|
||||
|
||||
}
|
21
vendor/phpstan/phpstan/src/Cache/CacheStorage.php
vendored
Normal file
21
vendor/phpstan/phpstan/src/Cache/CacheStorage.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Cache;
|
||||
|
||||
interface CacheStorage
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function load(string $key);
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function save(string $key, $data): bool;
|
||||
|
||||
}
|
51
vendor/phpstan/phpstan/src/Cache/FileCacheStorage.php
vendored
Normal file
51
vendor/phpstan/phpstan/src/Cache/FileCacheStorage.php
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Cache;
|
||||
|
||||
class FileCacheStorage implements CacheStorage
|
||||
{
|
||||
|
||||
/** @var string */
|
||||
private $directory;
|
||||
|
||||
public function __construct(string $directory)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
|
||||
if (@mkdir($this->directory) && !is_dir($this->directory)) {
|
||||
throw new \InvalidArgumentException(sprintf('Directory "%s" doesn\'t exist.', $this->directory));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function load(string $key)
|
||||
{
|
||||
return (function (string $key) {
|
||||
$filePath = $this->getFilePath($key);
|
||||
return is_file($filePath) ? require $this->getFilePath($key) : null;
|
||||
})($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function save(string $key, $data): bool
|
||||
{
|
||||
$writtenBytes = @file_put_contents(
|
||||
$this->getFilePath($key),
|
||||
sprintf("<?php declare(strict_types = 1);\n\nreturn %s;", var_export($data, true))
|
||||
);
|
||||
return $writtenBytes !== false;
|
||||
}
|
||||
|
||||
private function getFilePath(string $key): string
|
||||
{
|
||||
return sprintf('%s/%s.php', $this->directory, preg_replace('~[^-\\w]~', '_', $key));
|
||||
}
|
||||
|
||||
}
|
31
vendor/phpstan/phpstan/src/Cache/MemoryCacheStorage.php
vendored
Normal file
31
vendor/phpstan/phpstan/src/Cache/MemoryCacheStorage.php
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Cache;
|
||||
|
||||
class MemoryCacheStorage implements CacheStorage
|
||||
{
|
||||
|
||||
/** @var mixed[] */
|
||||
private $storage = [];
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function load(string $key)
|
||||
{
|
||||
return $this->storage[$key] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
public function save(string $key, $data): bool
|
||||
{
|
||||
$this->storage[$key] = $data;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
127
vendor/phpstan/phpstan/src/Command/AnalyseApplication.php
vendored
Normal file
127
vendor/phpstan/phpstan/src/Command/AnalyseApplication.php
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Command;
|
||||
|
||||
use PHPStan\Analyser\Analyser;
|
||||
use PHPStan\Command\ErrorFormatter\ErrorFormatter;
|
||||
use PHPStan\File\FileHelper;
|
||||
use Symfony\Component\Console\Style\OutputStyle;
|
||||
|
||||
class AnalyseApplication
|
||||
{
|
||||
|
||||
/** @var \PHPStan\Analyser\Analyser */
|
||||
private $analyser;
|
||||
|
||||
/** @var string */
|
||||
private $memoryLimitFile;
|
||||
|
||||
/** @var \PHPStan\File\FileHelper */
|
||||
private $fileHelper;
|
||||
|
||||
/** @var string */
|
||||
private $currentWorkingDirectory;
|
||||
|
||||
public function __construct(
|
||||
Analyser $analyser,
|
||||
string $memoryLimitFile,
|
||||
FileHelper $fileHelper,
|
||||
string $currentWorkingDirectory
|
||||
)
|
||||
{
|
||||
$this->analyser = $analyser;
|
||||
$this->memoryLimitFile = $memoryLimitFile;
|
||||
$this->fileHelper = $fileHelper;
|
||||
$this->currentWorkingDirectory = $currentWorkingDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $files
|
||||
* @param bool $onlyFiles
|
||||
* @param \Symfony\Component\Console\Style\OutputStyle $style
|
||||
* @param \PHPStan\Command\ErrorFormatter\ErrorFormatter $errorFormatter
|
||||
* @param bool $defaultLevelUsed
|
||||
* @param bool $debug
|
||||
* @return int Error code.
|
||||
*/
|
||||
public function analyse(
|
||||
array $files,
|
||||
bool $onlyFiles,
|
||||
OutputStyle $style,
|
||||
ErrorFormatter $errorFormatter,
|
||||
bool $defaultLevelUsed,
|
||||
bool $debug
|
||||
): int
|
||||
{
|
||||
$this->updateMemoryLimitFile();
|
||||
$errors = [];
|
||||
|
||||
if (!$debug) {
|
||||
$progressStarted = false;
|
||||
$fileOrder = 0;
|
||||
$preFileCallback = null;
|
||||
$postFileCallback = function () use ($style, &$progressStarted, $files, &$fileOrder): void {
|
||||
if (!$progressStarted) {
|
||||
$style->progressStart(count($files));
|
||||
$progressStarted = true;
|
||||
}
|
||||
$style->progressAdvance();
|
||||
if ($fileOrder % 100 === 0) {
|
||||
$this->updateMemoryLimitFile();
|
||||
}
|
||||
$fileOrder++;
|
||||
};
|
||||
} else {
|
||||
$preFileCallback = static function (string $file) use ($style): void {
|
||||
$style->writeln($file);
|
||||
};
|
||||
$postFileCallback = null;
|
||||
}
|
||||
|
||||
$errors = array_merge($errors, $this->analyser->analyse(
|
||||
$files,
|
||||
$onlyFiles,
|
||||
$preFileCallback,
|
||||
$postFileCallback,
|
||||
$debug
|
||||
));
|
||||
|
||||
if (isset($progressStarted) && $progressStarted) {
|
||||
$style->progressFinish();
|
||||
}
|
||||
|
||||
$fileSpecificErrors = [];
|
||||
$notFileSpecificErrors = [];
|
||||
foreach ($errors as $error) {
|
||||
if (is_string($error)) {
|
||||
$notFileSpecificErrors[] = $error;
|
||||
} else {
|
||||
$fileSpecificErrors[] = $error;
|
||||
}
|
||||
}
|
||||
|
||||
return $errorFormatter->formatErrors(
|
||||
new AnalysisResult(
|
||||
$fileSpecificErrors,
|
||||
$notFileSpecificErrors,
|
||||
$defaultLevelUsed,
|
||||
$this->fileHelper->normalizePath($this->currentWorkingDirectory)
|
||||
),
|
||||
$style
|
||||
);
|
||||
}
|
||||
|
||||
private function updateMemoryLimitFile(): void
|
||||
{
|
||||
$bytes = memory_get_peak_usage(true);
|
||||
$megabytes = ceil($bytes / 1024 / 1024);
|
||||
file_put_contents($this->memoryLimitFile, sprintf('%d MB', $megabytes));
|
||||
|
||||
if (!function_exists('pcntl_signal_dispatch')) {
|
||||
return;
|
||||
}
|
||||
|
||||
pcntl_signal_dispatch();
|
||||
}
|
||||
|
||||
}
|
131
vendor/phpstan/phpstan/src/Command/AnalyseCommand.php
vendored
Normal file
131
vendor/phpstan/phpstan/src/Command/AnalyseCommand.php
vendored
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace PHPStan\Command;
|
||||
|
||||
use PHPStan\Command\ErrorFormatter\ErrorFormatter;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class AnalyseCommand extends \Symfony\Component\Console\Command\Command
|
||||
{
|
||||
|
||||
private const NAME = 'analyse';
|
||||
|
||||
public const OPTION_LEVEL = 'level';
|
||||
|
||||
public const DEFAULT_LEVEL = CommandHelper::DEFAULT_LEVEL;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName(self::NAME)
|
||||
->setDescription('Analyses source code')
|
||||
->setDefinition([
|
||||
new InputArgument('paths', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'Paths with source code to run analysis on'),
|
||||
new InputOption('paths-file', null, InputOption::VALUE_REQUIRED, 'Path to a file with a list of paths to run analysis on'),
|
||||
new InputOption('configuration', 'c', InputOption::VALUE_REQUIRED, 'Path to project configuration file'),
|
||||
new InputOption(self::OPTION_LEVEL, 'l', InputOption::VALUE_REQUIRED, 'Level of rule options - the higher the stricter'),
|
||||
new InputOption(ErrorsConsoleStyle::OPTION_NO_PROGRESS, null, InputOption::VALUE_NONE, 'Do not show progress bar, only results'),
|
||||
new InputOption('debug', null, InputOption::VALUE_NONE, 'Show debug information - which file is analysed, do not catch internal errors'),
|
||||
new InputOption('autoload-file', 'a', InputOption::VALUE_REQUIRED, 'Project\'s additional autoload file path'),
|
||||
new InputOption('error-format', null, InputOption::VALUE_REQUIRED, 'Format in which to print the result of the analysis', 'table'),
|
||||
new InputOption('memory-limit', null, InputOption::VALUE_REQUIRED, 'Memory limit for analysis'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getAliases(): array
|
||||
{
|
||||
return ['analyze'];
|
||||
}
|
||||
|
||||
protected function initialize(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
if ((bool) $input->getOption('debug')) {
|
||||
$this->getApplication()->setCatchExceptions(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$paths = $input->getArgument('paths');
|
||||
$memoryLimit = $input->getOption('memory-limit');
|
||||
$autoloadFile = $input->getOption('autoload-file');
|
||||
$configuration = $input->getOption('configuration');
|
||||
$level = $input->getOption(self::OPTION_LEVEL);
|
||||
$pathsFile = $input->getOption('paths-file');
|
||||
|
||||
if (
|
||||
!is_array($paths)
|
||||
|| (!is_string($memoryLimit) && $memoryLimit !== null)
|
||||
|| (!is_string($autoloadFile) && $autoloadFile !== null)
|
||||
|| (!is_string($configuration) && $configuration !== null)
|
||||
|| (!is_string($level) && $level !== null)
|
||||
|| (!is_string($pathsFile) && $pathsFile !== null)
|
||||
) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
try {
|
||||
$inceptionResult = CommandHelper::begin(
|
||||
$input,
|
||||
$output,
|
||||
$paths,
|
||||
$pathsFile,
|
||||
$memoryLimit,
|
||||
$autoloadFile,
|
||||
$configuration,
|
||||
$level
|
||||
);
|
||||
} catch (\PHPStan\Command\InceptionNotSuccessfulException $e) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$errorOutput = $inceptionResult->getErrorOutput();
|
||||
$errorFormat = $input->getOption('error-format');
|
||||
|
||||
if (!is_string($errorFormat) && $errorFormat !== null) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$container = $inceptionResult->getContainer();
|
||||
$errorFormatterServiceName = sprintf('errorFormatter.%s', $errorFormat);
|
||||
if (!$container->hasService($errorFormatterServiceName)) {
|
||||
$errorOutput->writeln(sprintf(
|
||||
'Error formatter "%s" not found. Available error formatters are: %s',
|
||||
$errorFormat,
|
||||
implode(', ', array_map(static function (string $name) {
|
||||
return substr($name, strlen('errorFormatter.'));
|
||||
}, $container->findByType(ErrorFormatter::class)))
|
||||
));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @var ErrorFormatter $errorFormatter */
|
||||
$errorFormatter = $container->getService($errorFormatterServiceName);
|
||||
|
||||
/** @var AnalyseApplication $application */
|
||||
$application = $container->getByType(AnalyseApplication::class);
|
||||
|
||||
$debug = $input->getOption('debug');
|
||||
if (!is_bool($debug)) {
|
||||
throw new \PHPStan\ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return $inceptionResult->handleReturn(
|
||||
$application->analyse(
|
||||
$inceptionResult->getFiles(),
|
||||
$inceptionResult->isOnlyFiles(),
|
||||
$inceptionResult->getConsoleStyle(),
|
||||
$errorFormatter,
|
||||
$inceptionResult->isDefaultLevelUsed(),
|
||||
$debug
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue