@@ -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
0 commit comments