@@ -828,11 +828,22 @@ private function parseParameterFn() {
828828 $ parameter ->visibilityToken = $ this ->eatOptional ([TokenKind::PublicKeyword, TokenKind::ProtectedKeyword, TokenKind::PrivateKeyword]);
829829 $ parameter ->questionToken = $ this ->eatOptional1 (TokenKind::QuestionToken);
830830 $ parameter ->typeDeclarationList = $ this ->tryParseParameterTypeDeclarationList ($ parameter );
831- if ($ parameter ->questionToken && !$ parameter ->typeDeclarationList ) {
831+ if ($ parameter ->typeDeclarationList ) {
832+ $ children = $ parameter ->typeDeclarationList ->children ;
833+ if (end ($ children ) instanceof MissingToken && ($ children [count ($ children ) - 2 ]->kind ?? null ) === TokenKind::AmpersandToken) {
834+ array_pop ($ parameter ->typeDeclarationList ->children );
835+ $ parameter ->byRefToken = array_pop ($ parameter ->typeDeclarationList ->children );
836+ if (!$ parameter ->typeDeclarationList ->children ) {
837+ unset($ parameter ->typeDeclarationList );
838+ }
839+ }
840+ } elseif ($ parameter ->questionToken ) {
832841 // TODO ParameterType?
833842 $ parameter ->typeDeclarationList = new MissingToken (TokenKind::PropertyType, $ this ->token ->fullStart );
834843 }
835- $ parameter ->byRefToken = $ this ->eatOptional1 (TokenKind::AmpersandToken);
844+ if (!$ parameter ->byRefToken ) {
845+ $ parameter ->byRefToken = $ this ->eatOptional1 (TokenKind::AmpersandToken);
846+ }
836847 // TODO add post-parse rule that prevents assignment
837848 // TODO add post-parse rule that requires only last parameter be variadic
838849 $ parameter ->dotDotDotToken = $ this ->eatOptional1 (TokenKind::DotDotDotToken);
@@ -858,6 +869,11 @@ private function parseAndSetReturnTypeDeclarationList($parentNode) {
858869 $ parentNode ->returnTypeList = $ returnTypeList ;
859870 }
860871
872+ const TYPE_DELIMITER_TOKENS = [
873+ TokenKind::BarToken,
874+ TokenKind::AmpersandToken,
875+ ];
876+
861877 /**
862878 * Attempt to parse the return type after the `:` and optional `?` token.
863879 *
@@ -866,7 +882,7 @@ private function parseAndSetReturnTypeDeclarationList($parentNode) {
866882 private function parseReturnTypeDeclarationList ($ parentNode ) {
867883 $ result = $ this ->parseDelimitedList (
868884 DelimitedList \QualifiedNameList::class,
869- TokenKind::BarToken ,
885+ self :: TYPE_DELIMITER_TOKENS ,
870886 function ($ token ) {
871887 return \in_array ($ token ->kind , $ this ->returnTypeDeclarationTokens , true ) || $ this ->isQualifiedNameStart ($ token );
872888 },
@@ -878,7 +894,7 @@ function ($parentNode) {
878894
879895 // Add a MissingToken so that this will warn about `function () : T| {}`
880896 // TODO: Make this a reusable abstraction?
881- if ($ result && (end ($ result ->children )->kind ?? null ) === TokenKind::BarToken ) {
897+ if ($ result && in_array (end ($ result ->children )->kind ?? null , self :: TYPE_DELIMITER_TOKENS ) ) {
882898 $ result ->children [] = new MissingToken (TokenKind::ReturnType, $ this ->token ->fullStart );
883899 }
884900 return $ result ;
@@ -902,7 +918,7 @@ private function tryParseParameterTypeDeclaration($parentNode) {
902918 private function tryParseParameterTypeDeclarationList ($ parentNode ) {
903919 $ result = $ this ->parseDelimitedList (
904920 DelimitedList \QualifiedNameList::class,
905- TokenKind::BarToken ,
921+ self :: TYPE_DELIMITER_TOKENS ,
906922 function ($ token ) {
907923 return \in_array ($ token ->kind , $ this ->parameterTypeDeclarationTokens , true ) || $ this ->isQualifiedNameStart ($ token );
908924 },
@@ -914,7 +930,7 @@ function ($parentNode) {
914930
915931 // Add a MissingToken so that this will Warn about `function (T| $x) {}`
916932 // TODO: Make this a reusable abstraction?
917- if ($ result && (end ($ result ->children )->kind ?? null ) === TokenKind::BarToken ) {
933+ if ($ result && in_array (end ($ result ->children )->kind ?? null , self :: TYPE_DELIMITER_TOKENS ) ) {
918934 $ result ->children [] = new MissingToken (TokenKind::Name, $ this ->token ->fullStart );
919935 }
920936 return $ result ;
0 commit comments