Skip to content

Commit 74854c6

Browse files
authored
Merge pull request microsoft#151 from Microsoft/nullableTypes
Support nullable types
2 parents 96fca76 + 2cc3701 commit 74854c6

File tree

95 files changed

+447
-21
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

95 files changed

+447
-21
lines changed

src/Node/Expression/AnonymousFunctionCreationExpression.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class AnonymousFunctionCreationExpression extends Expression {
3535

3636
// FunctionReturnType
3737
'colonToken',
38+
'questionToken',
3839
'returnType',
3940

4041
// FunctionBody

src/Node/FunctionReturnType.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
trait FunctionReturnType {
1212
/** @var Token */
1313
public $colonToken;
14+
/** @var Token|null */
15+
public $questionToken;
1416
/** @var Token | QualifiedName */
1517
public $returnType;
1618
}

src/Node/MethodDeclaration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class MethodDeclaration extends Node {
2929

3030
// FunctionReturnType
3131
'colonToken',
32+
'questionToken',
3233
'returnType',
3334

3435
// FunctionBody

src/Node/Parameter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@
1010
use Microsoft\PhpParser\Token;
1111

1212
class Parameter extends Node {
13+
/** @var Token|null */
14+
public $questionToken;
1315
/** @var QualifiedName | Token | null */
1416
public $typeDeclaration;
1517
/** @var Token | null */
1618
public $byRefToken;
1719
/** @var Token | null */
1820
public $dotDotDotToken;
19-
2021
/** @var Token */
2122
public $variableName;
22-
2323
/** @var Token | null */
2424
public $equalsToken;
25-
2625
/** @var null | Expression */
2726
public $default;
2827

2928
const CHILD_NAMES = [
29+
'questionToken',
3030
'typeDeclaration',
3131
'byRefToken',
3232
'dotDotDotToken',

src/Node/Statement/FunctionDeclaration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class FunctionDeclaration extends StatementNode implements NamespacedNameInterfa
2828

2929
// FunctionReturnType
3030
'colonToken',
31+
'questionToken',
3132
'returnType',
3233

3334
// FunctionBody

src/Parser.php

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,7 @@ private function parseParameterFn() {
598598
return function ($parentNode) {
599599
$parameter = new Parameter();
600600
$parameter->parent = $parentNode;
601+
$parameter->questionToken = $this->eatOptional(TokenKind::QuestionToken);
601602
$parameter->typeDeclaration = $this->tryParseParameterTypeDeclaration($parameter);
602603
$parameter->byRefToken = $this->eatOptional(TokenKind::AmpersandToken);
603604
// TODO add post-parse rule that prevents assignment
@@ -1086,6 +1087,10 @@ private function isParameterStartFn() {
10861087

10871088
case TokenKind::VariableName:
10881089
return true;
1090+
1091+
// nullable-type
1092+
case TokenKind::QuestionToken:
1093+
return true;
10891094
}
10901095

10911096
// scalar-type
@@ -1195,45 +1200,46 @@ private function parseRelativeSpecifier($parentNode) {
11951200
return null;
11961201
}
11971202

1198-
private function parseFunctionType(Node $functionDefinition, $canBeAbstract = false, $isAnonymous = false) {
1199-
$functionDefinition->functionKeyword = $this->eat(TokenKind::FunctionKeyword);
1200-
$functionDefinition->byRefToken = $this->eatOptional(TokenKind::AmpersandToken);
1201-
$functionDefinition->name = $isAnonymous
1203+
private function parseFunctionType(Node $functionDeclaration, $canBeAbstract = false, $isAnonymous = false) {
1204+
$functionDeclaration->functionKeyword = $this->eat(TokenKind::FunctionKeyword);
1205+
$functionDeclaration->byRefToken = $this->eatOptional(TokenKind::AmpersandToken);
1206+
$functionDeclaration->name = $isAnonymous
12021207
? $this->eatOptional($this->nameOrKeywordOrReservedWordTokens)
12031208
: $this->eat($this->nameOrKeywordOrReservedWordTokens);
12041209

1205-
if (isset($functionDefinition->name)) {
1206-
$functionDefinition->name->kind = TokenKind::Name;
1210+
if (isset($functionDeclaration->name)) {
1211+
$functionDeclaration->name->kind = TokenKind::Name;
12071212
}
12081213

1209-
if ($isAnonymous && isset($functionDefinition->name)) {
1214+
if ($isAnonymous && isset($functionDeclaration->name)) {
12101215
// Anonymous functions should not have names
1211-
$functionDefinition->name = new SkippedToken($functionDefinition->name); // TODO instaed handle this during post-walk
1216+
$functionDeclaration->name = new SkippedToken($functionDeclaration->name); // TODO instaed handle this during post-walk
12121217
}
12131218

1214-
$functionDefinition->openParen = $this->eat(TokenKind::OpenParenToken);
1215-
$functionDefinition->parameters = $this->parseDelimitedList(
1219+
$functionDeclaration->openParen = $this->eat(TokenKind::OpenParenToken);
1220+
$functionDeclaration->parameters = $this->parseDelimitedList(
12161221
DelimitedList\ParameterDeclarationList::class,
12171222
TokenKind::CommaToken,
12181223
$this->isParameterStartFn(),
12191224
$this->parseParameterFn(),
1220-
$functionDefinition);
1221-
$functionDefinition->closeParen = $this->eat(TokenKind::CloseParenToken);
1225+
$functionDeclaration);
1226+
$functionDeclaration->closeParen = $this->eat(TokenKind::CloseParenToken);
12221227
if ($isAnonymous) {
1223-
$functionDefinition->anonymousFunctionUseClause = $this->parseAnonymousFunctionUseClause($functionDefinition);
1228+
$functionDeclaration->anonymousFunctionUseClause = $this->parseAnonymousFunctionUseClause($functionDeclaration);
12241229
}
12251230

12261231
if ($this->checkToken(TokenKind::ColonToken)) {
1227-
$functionDefinition->colonToken = $this->eat(TokenKind::ColonToken);
1228-
$functionDefinition->returnType = $this->parseReturnTypeDeclaration($functionDefinition);
1232+
$functionDeclaration->colonToken = $this->eat(TokenKind::ColonToken);
1233+
$functionDeclaration->questionToken = $this->eatOptional(TokenKind::QuestionToken);
1234+
$functionDeclaration->returnType = $this->parseReturnTypeDeclaration($functionDeclaration);
12291235
}
12301236

12311237
if ($canBeAbstract) {
1232-
$functionDefinition->compoundStatementOrSemicolon = $this->eatOptional(TokenKind::SemicolonToken);
1238+
$functionDeclaration->compoundStatementOrSemicolon = $this->eatOptional(TokenKind::SemicolonToken);
12331239
}
12341240

1235-
if (!isset($functionDefinition->compoundStatementOrSemicolon)) {
1236-
$functionDefinition->compoundStatementOrSemicolon = $this->parseCompoundStatement($functionDefinition);
1241+
if (!isset($functionDeclaration->compoundStatementOrSemicolon)) {
1242+
$functionDeclaration->compoundStatementOrSemicolon = $this->parseCompoundStatement($functionDeclaration);
12371243
}
12381244
}
12391245

tests/cases/parser/abstractMethodDeclaration1.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"textLength": 1
6666
},
6767
"colonToken": null,
68+
"questionToken": null,
6869
"returnType": null,
6970
"compoundStatementOrSemicolon": {
7071
"kind": "SemicolonToken",

tests/cases/parser/abstractMethodDeclaration2.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
"textLength": 1
6363
},
6464
"colonToken": null,
65+
"questionToken": null,
6566
"returnType": null,
6667
"compoundStatementOrSemicolon": {
6768
"kind": "SemicolonToken",

tests/cases/parser/abstractMethodDeclaration3.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"textLength": 1
6666
},
6767
"colonToken": null,
68+
"questionToken": null,
6869
"returnType": null,
6970
"compoundStatementOrSemicolon": {
7071
"CompoundStatementNode": {

tests/cases/parser/abstractMethodDeclaration4.php.tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"textLength": 1
3333
},
3434
"colonToken": null,
35+
"questionToken": null,
3536
"returnType": null,
3637
"compoundStatementOrSemicolon": {
3738
"CompoundStatementNode": {

0 commit comments

Comments
 (0)