Коммит
6bd3e3ba00
|
@ -25,7 +25,6 @@ cache:
|
|||
- validation/frameworks
|
||||
|
||||
before_script:
|
||||
- if [[ $STATIC_ANALYSIS = true ]]; then composer require phpstan/phpstan --no-update; fi
|
||||
- composer install
|
||||
- set -e # Stop on first error.
|
||||
- phpenv config-rm xdebug.ini || true
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5.15"
|
||||
"phpunit/phpunit": "^8.5.15",
|
||||
"phpstan/phpstan": "^1.8"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
parameters:
|
||||
level: 2
|
||||
level: 3
|
||||
paths:
|
||||
- src/
|
||||
ignoreErrors:
|
||||
|
|
|
@ -140,6 +140,8 @@ abstract class Node implements \JsonSerializable {
|
|||
while ($node->parent !== null) {
|
||||
$node = $node->parent;
|
||||
}
|
||||
|
||||
/** @var SourceFileNode $node */
|
||||
return $node;
|
||||
}
|
||||
|
||||
|
@ -613,6 +615,7 @@ abstract class Node implements \JsonSerializable {
|
|||
$namespaceDefinition = null;
|
||||
}
|
||||
|
||||
/** @var NamespaceDefinition|null $namespaceDefinition */
|
||||
return $namespaceDefinition;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ class EnumCaseDeclaration extends Node {
|
|||
/** @var Token */
|
||||
public $caseKeyword;
|
||||
|
||||
/** @var QualifiedName */
|
||||
/** @var Token */
|
||||
public $name;
|
||||
|
||||
/** @var Token|null */
|
||||
|
|
|
@ -11,7 +11,7 @@ use Microsoft\PhpParser\Token;
|
|||
|
||||
class AssignmentExpression extends BinaryExpression {
|
||||
|
||||
/** @var Expression */
|
||||
/** @var Expression|Token */
|
||||
public $leftOperand;
|
||||
|
||||
/** @var Token */
|
||||
|
|
|
@ -11,13 +11,13 @@ use Microsoft\PhpParser\Token;
|
|||
|
||||
class BinaryExpression extends Expression {
|
||||
|
||||
/** @var Expression */
|
||||
/** @var Expression|Token */
|
||||
public $leftOperand;
|
||||
|
||||
/** @var Token */
|
||||
public $operator;
|
||||
|
||||
/** @var Expression */
|
||||
/** @var Expression|Token */
|
||||
public $rightOperand;
|
||||
|
||||
const CHILD_NAMES = [
|
||||
|
|
|
@ -13,9 +13,6 @@ class PrefixUpdateExpression extends UnaryExpression {
|
|||
/** @var Token */
|
||||
public $incrementOrDecrementOperator;
|
||||
|
||||
/** @var Variable */
|
||||
public $operand;
|
||||
|
||||
const CHILD_NAMES = [
|
||||
'incrementOrDecrementOperator',
|
||||
'operand'
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
namespace Microsoft\PhpParser\Node\Expression;
|
||||
|
||||
use Microsoft\PhpParser\MissingToken;
|
||||
use Microsoft\PhpParser\Node\Expression;
|
||||
use Microsoft\PhpParser\Token;
|
||||
|
||||
|
@ -17,7 +18,7 @@ class SubscriptExpression extends Expression {
|
|||
/** @var Token */
|
||||
public $openBracketOrBrace;
|
||||
|
||||
/** @var Expression */
|
||||
/** @var Expression|MissingToken */
|
||||
public $accessExpression;
|
||||
|
||||
/** @var Token */
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
namespace Microsoft\PhpParser\Node\Expression;
|
||||
|
||||
use Microsoft\PhpParser\Node\Expression;
|
||||
use Microsoft\PhpParser\Token;
|
||||
|
||||
class UnaryExpression extends Expression {
|
||||
/** @var UnaryExpression|Variable */
|
||||
/** @var Expression|Variable|Token */
|
||||
public $operand;
|
||||
|
||||
const CHILD_NAMES = [
|
||||
|
|
|
@ -13,9 +13,6 @@ class UnaryOpExpression extends UnaryExpression {
|
|||
/** @var Token */
|
||||
public $operator;
|
||||
|
||||
/** @var UnaryExpression */
|
||||
public $operand;
|
||||
|
||||
const CHILD_NAMES = [
|
||||
'operator',
|
||||
'operand'
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
namespace Microsoft\PhpParser\Node;
|
||||
|
||||
use Microsoft\PhpParser\MissingToken;
|
||||
use Microsoft\PhpParser\Token;
|
||||
|
||||
trait FunctionReturnType {
|
||||
|
@ -14,6 +15,6 @@ trait FunctionReturnType {
|
|||
// TODO: This may be the wrong choice if ?type can ever be mixed with other types in union types
|
||||
/** @var Token|null */
|
||||
public $questionToken;
|
||||
/** @var DelimitedList\QualifiedNameList|null */
|
||||
/** @var DelimitedList\QualifiedNameList|null|MissingToken */
|
||||
public $returnTypeList;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
namespace Microsoft\PhpParser\Node;
|
||||
|
||||
use Microsoft\PhpParser\MissingToken;
|
||||
use Microsoft\PhpParser\ModifiedTypeInterface;
|
||||
use Microsoft\PhpParser\ModifiedTypeTrait;
|
||||
use Microsoft\PhpParser\Node;
|
||||
|
@ -20,7 +21,7 @@ class MissingMemberDeclaration extends Node implements ModifiedTypeInterface {
|
|||
/** @var Token|null needed along with typeDeclaration for what looked like typed property declarations but was missing VariableName */
|
||||
public $questionToken;
|
||||
|
||||
/** @var DelimitedList\QualifiedNameList|null */
|
||||
/** @var DelimitedList\QualifiedNameList|null|MissingToken */
|
||||
public $typeDeclarationList;
|
||||
|
||||
const CHILD_NAMES = [
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
|
||||
namespace Microsoft\PhpParser\Node;
|
||||
|
||||
use Microsoft\PhpParser\MissingToken;
|
||||
use Microsoft\PhpParser\Node;
|
||||
use Microsoft\PhpParser\Node\DelimitedList;
|
||||
use Microsoft\PhpParser\Token;
|
||||
|
||||
class NamespaceUseClause extends Node {
|
||||
/** @var QualifiedName */
|
||||
/** @var QualifiedName|MissingToken */
|
||||
public $namespaceName;
|
||||
/** @var NamespaceAliasingClause */
|
||||
public $namespaceAliasingClause;
|
||||
|
|
|
@ -20,7 +20,7 @@ class InlineHtml extends StatementNode {
|
|||
public $scriptSectionStartTag;
|
||||
|
||||
/**
|
||||
* @var ExpressionStatement|null used to represent the expression echoed by `<?=` while parsing.
|
||||
* @var EchoStatement|null used to represent the expression echoed by `<?=` while parsing.
|
||||
*
|
||||
* This should always be null in the returned AST,
|
||||
* and is deliberately excluded from CHILD_NAMES.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
namespace Microsoft\PhpParser\Node\Statement;
|
||||
|
||||
use Microsoft\PhpParser\MissingToken;
|
||||
use Microsoft\PhpParser\Node\QualifiedName;
|
||||
use Microsoft\PhpParser\Node\StatementNode;
|
||||
use Microsoft\PhpParser\Token;
|
||||
|
@ -17,7 +18,7 @@ use Microsoft\PhpParser\Node\SourceFileNode;
|
|||
class NamespaceDefinition extends StatementNode {
|
||||
/** @var Token */
|
||||
public $namespaceKeyword;
|
||||
/** @var QualifiedName|null */
|
||||
/** @var QualifiedName|null|MissingToken */
|
||||
public $name;
|
||||
/** @var CompoundStatementNode|Token */
|
||||
public $compoundStatementOrSemicolon;
|
||||
|
|
|
@ -691,7 +691,7 @@ class Parser {
|
|||
return $classNode;
|
||||
}
|
||||
|
||||
private function parseClassMembers($parentNode) : Node {
|
||||
private function parseClassMembers($parentNode) : ClassMembersNode {
|
||||
$classMembers = new ClassMembersNode();
|
||||
$classMembers->openBrace = $this->eat1(TokenKind::OpenBraceToken);
|
||||
$classMembers->classMemberDeclarations = $this->parseList($classMembers, ParseContext::ClassMembers);
|
||||
|
@ -804,7 +804,7 @@ class Parser {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return DelimitedList\AttributeElementList
|
||||
* @return DelimitedList\AttributeElementList|null
|
||||
*/
|
||||
private function parseAttributeElementList(AttributeGroup $parentNode) {
|
||||
return $this->parseDelimitedList(
|
||||
|
@ -1638,13 +1638,14 @@ class Parser {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $className (name of subclass of DelimitedList)
|
||||
* @template TDelimitedList of DelimitedList
|
||||
* @param class-string<TDelimitedList> $className (name of subclass of DelimitedList)
|
||||
* @param int|int[] $delimiter
|
||||
* @param callable $isElementStartFn
|
||||
* @param callable $parseElementFn
|
||||
* @param Node $parentNode
|
||||
* @param bool $allowEmptyElements
|
||||
* @return DelimitedList|null instance of $className
|
||||
* @return TDelimitedList|null instance of $className
|
||||
*/
|
||||
private function parseDelimitedList($className, $delimiter, $isElementStartFn, $parseElementFn, $parentNode, $allowEmptyElements = false) {
|
||||
// TODO consider allowing empty delimiter to be more tolerant
|
||||
|
@ -1994,7 +1995,7 @@ class Parser {
|
|||
/**
|
||||
* @param Node $parentNode
|
||||
* @param bool $force
|
||||
* @return Node|MissingToken|array - The expression, or a missing token, or (if $force) an array containing a missed and skipped token
|
||||
* @return Expression|MissingToken|array - The expression, or a missing token, or (if $force) an array containing a missed and skipped token
|
||||
*/
|
||||
private function parseExpression($parentNode, $force = false) {
|
||||
$token = $this->getCurrentToken();
|
||||
|
@ -2020,7 +2021,7 @@ class Parser {
|
|||
|
||||
/**
|
||||
* @param Node $parentNode
|
||||
* @return Expression
|
||||
* @return UnaryExpression|MissingToken|Variable|ThrowExpression
|
||||
*/
|
||||
private function parseUnaryExpressionOrHigher($parentNode) {
|
||||
$token = $this->getCurrentToken();
|
||||
|
@ -3212,9 +3213,16 @@ class Parser {
|
|||
private function parseScopedPropertyAccessExpression($expression, $fallbackParentNode): ScopedPropertyAccessExpression {
|
||||
$scopedPropertyAccessExpression = new ScopedPropertyAccessExpression();
|
||||
$scopedPropertyAccessExpression->parent = $expression->parent ?? $fallbackParentNode;
|
||||
|
||||
if ($expression instanceof Node) {
|
||||
$expression->parent = $scopedPropertyAccessExpression;
|
||||
$scopedPropertyAccessExpression->scopeResolutionQualifier = $expression; // TODO ensure always a Node
|
||||
|
||||
// scopeResolutionQualifier does not accept `Node` but
|
||||
// `Expression|QualifiedName|Token`. I'm not sure if we can depend
|
||||
// on that being the case.
|
||||
//
|
||||
// @phpstan-ignore-next-line
|
||||
$scopedPropertyAccessExpression->scopeResolutionQualifier = $expression;
|
||||
}
|
||||
|
||||
$scopedPropertyAccessExpression->doubleColon = $this->eat1(TokenKind::ColonColonToken);
|
||||
|
@ -3362,18 +3370,18 @@ class Parser {
|
|||
}
|
||||
|
||||
private function parseEnumCaseDeclaration($parentNode) {
|
||||
$classConstDeclaration = new EnumCaseDeclaration();
|
||||
$classConstDeclaration->parent = $parentNode;
|
||||
$classConstDeclaration->caseKeyword = $this->eat1(TokenKind::CaseKeyword);
|
||||
$classConstDeclaration->name = $this->eat($this->nameOrKeywordOrReservedWordTokens);
|
||||
$classConstDeclaration->equalsToken = $this->eatOptional1(TokenKind::EqualsToken);
|
||||
if ($classConstDeclaration->equalsToken !== null) {
|
||||
$enumCaseDeclaration = new EnumCaseDeclaration();
|
||||
$enumCaseDeclaration->parent = $parentNode;
|
||||
$enumCaseDeclaration->caseKeyword = $this->eat1(TokenKind::CaseKeyword);
|
||||
$enumCaseDeclaration->name = $this->eat($this->nameOrKeywordOrReservedWordTokens);
|
||||
$enumCaseDeclaration->equalsToken = $this->eatOptional1(TokenKind::EqualsToken);
|
||||
if ($enumCaseDeclaration->equalsToken !== null) {
|
||||
// TODO add post-parse rule that checks for invalid assignments
|
||||
$classConstDeclaration->assignment = $this->parseExpression($classConstDeclaration);
|
||||
$enumCaseDeclaration->assignment = $this->parseExpression($enumCaseDeclaration);
|
||||
}
|
||||
$classConstDeclaration->semicolon = $this->eat1(TokenKind::SemicolonToken);
|
||||
$enumCaseDeclaration->semicolon = $this->eat1(TokenKind::SemicolonToken);
|
||||
|
||||
return $classConstDeclaration;
|
||||
return $enumCaseDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3446,7 +3454,7 @@ class Parser {
|
|||
return $result;
|
||||
}
|
||||
|
||||
private function parseInterfaceDeclaration($parentNode) {
|
||||
private function parseInterfaceDeclaration($parentNode): InterfaceDeclaration {
|
||||
$interfaceDeclaration = new InterfaceDeclaration(); // TODO verify not nested
|
||||
$interfaceDeclaration->parent = $parentNode;
|
||||
$interfaceDeclaration->interfaceKeyword = $this->eat1(TokenKind::InterfaceKeyword);
|
||||
|
@ -3456,7 +3464,7 @@ class Parser {
|
|||
return $interfaceDeclaration;
|
||||
}
|
||||
|
||||
private function parseInterfaceMembers($parentNode) : Node {
|
||||
private function parseInterfaceMembers($parentNode) : InterfaceMembers {
|
||||
$interfaceMembers = new InterfaceMembers();
|
||||
$interfaceMembers->openBrace = $this->eat1(TokenKind::OpenBraceToken);
|
||||
$interfaceMembers->interfaceMemberDeclarations = $this->parseList($interfaceMembers, ParseContext::InterfaceMembers);
|
||||
|
|
Загрузка…
Ссылка в новой задаче