php8.1: added readonly modifier (#6)

This commit is contained in:
Makhnev Petr 2021-07-31 18:00:21 +03:00 committed by GitHub
parent 4d0bfa25aa
commit 8c35b0aef1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 7656 additions and 7049 deletions

BIN
internal/php5/php5.go generated

Binary file not shown.

BIN
internal/php7/php7.go generated

Binary file not shown.

View File

@ -899,7 +899,7 @@ func (b *Builder) NewThrowExpr(
func (b *Builder) NewParameter(
AttrGroups []ast.Vertex,
Visibility ast.Vertex,
Modifiers []ast.Vertex,
Type ast.Vertex,
AmpersandTkn *token.Token,
VariadicTkn *token.Token,
@ -913,8 +913,8 @@ func (b *Builder) NewParameter(
if WithDefault {
if AttrGroups != nil {
pos = b.Pos.NewNodeListNodePosition(AttrGroups, DefaultValue)
} else if Visibility != nil {
pos = b.Pos.NewNodesPosition(Visibility, DefaultValue)
} else if Modifiers != nil {
pos = b.Pos.NewNodeListNodePosition(Modifiers, DefaultValue)
} else if Type != nil {
pos = b.Pos.NewNodesPosition(Type, DefaultValue)
} else if AmpersandTkn != nil {
@ -927,8 +927,8 @@ func (b *Builder) NewParameter(
} else {
if AttrGroups != nil {
pos = b.Pos.NewNodeListTokenPosition(AttrGroups, VarTkn)
} else if Visibility != nil {
pos = b.Pos.NewNodeTokenPosition(Visibility, VarTkn)
} else if Modifiers != nil {
pos = b.Pos.NewNodeListTokenPosition(Modifiers, VarTkn)
} else if Type != nil {
pos = b.Pos.NewNodeTokenPosition(Type, VarTkn)
} else if AmpersandTkn != nil {
@ -943,7 +943,7 @@ func (b *Builder) NewParameter(
return &ast.Parameter{
Position: pos,
AttrGroups: AttrGroups,
Visibility: Visibility,
Modifiers: Modifiers,
Type: Type,
AmpersandTkn: AmpersandTkn,
VariadicTkn: VariadicTkn,

View File

@ -0,0 +1,228 @@
package php8_test
import (
"testing"
"github.com/VKCOM/php-parser/internal/tester"
)
func TestReadonlyModifier(t *testing.T) {
suite := tester.NewParserDumpTestSuite(t)
suite.UsePHP8()
suite.Code = `<?php
class Foo {
readonly string $a;
private readonly string $a;
private string $a;
private readonly $a = 100;
public function __construct(
readonly string $a,
private readonly string $a,
private string $a,
private readonly $a = 100,
) {}
}
`
suite.Expected = `&ast.Root{
Stmts: []ast.Vertex{
&ast.StmtClass{
Name: &ast.Identifier{
Val: []byte("Foo"),
},
Stmts: []ast.Vertex{
&ast.StmtPropertyList{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("readonly"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
Val: []byte("string"),
},
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
},
},
},
&ast.StmtPropertyList{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("private"),
},
&ast.Identifier{
Val: []byte("readonly"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
Val: []byte("string"),
},
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
},
},
},
&ast.StmtPropertyList{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("private"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
Val: []byte("string"),
},
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
},
},
},
&ast.StmtPropertyList{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("private"),
},
&ast.Identifier{
Val: []byte("readonly"),
},
},
Props: []ast.Vertex{
&ast.StmtProperty{
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
Expr: &ast.ScalarLnumber{
Val: []byte("100"),
},
},
},
},
&ast.StmtClassMethod{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("public"),
},
},
Name: &ast.Identifier{
Val: []byte("__construct"),
},
Params: []ast.Vertex{
&ast.Parameter{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("readonly"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
Val: []byte("string"),
},
},
},
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
},
&ast.Parameter{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("private"),
},
&ast.Identifier{
Val: []byte("readonly"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
Val: []byte("string"),
},
},
},
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
},
&ast.Parameter{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("private"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
Val: []byte("string"),
},
},
},
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
},
&ast.Parameter{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("private"),
},
&ast.Identifier{
Val: []byte("readonly"),
},
},
Var: &ast.ExprVariable{
Name: &ast.Identifier{
Val: []byte("$a"),
},
},
DefaultValue: &ast.ScalarLnumber{
Val: []byte("100"),
},
},
},
Stmt: &ast.StmtStmtList{
Stmts: []ast.Vertex{},
},
},
},
},
},
},`
suite.Run()
}

View File

@ -3883,9 +3883,11 @@ class Point {
},
Params: []ast.Vertex{
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
@ -3903,9 +3905,11 @@ class Point {
},
},
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
@ -3923,9 +3927,11 @@ class Point {
},
},
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
@ -4057,7 +4063,8 @@ class Point {
},
Params: []ast.Vertex{
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Val: []byte("public"),
@ -4070,6 +4077,7 @@ class Point {
},
Val: []byte("public"),
},
},
Var: &ast.ExprVariable{
Name: &ast.Identifier{
IdentifierTkn: &token.Token{
@ -4087,7 +4095,8 @@ class Point {
},
},
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Val: []byte("public"),
@ -4100,6 +4109,7 @@ class Point {
},
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
@ -4134,7 +4144,8 @@ class Point {
},
},
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Val: []byte("public"),
@ -4147,6 +4158,7 @@ class Point {
},
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
@ -4185,7 +4197,8 @@ class Point {
},
},
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Val: []byte("public"),
@ -4198,6 +4211,7 @@ class Point {
},
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{
@ -4255,7 +4269,8 @@ class Point {
},
},
&ast.Parameter{
Visibility: &ast.Identifier{
Modifiers: []ast.Vertex{
&ast.Identifier{
IdentifierTkn: &token.Token{
ID: token.T_PUBLIC,
Val: []byte("public"),
@ -4268,6 +4283,7 @@ class Point {
},
Val: []byte("public"),
},
},
Type: &ast.Name{
Parts: []ast.Vertex{
&ast.NamePart{

File diff suppressed because it is too large Load Diff

View File

@ -160,6 +160,7 @@ import (
%token <token> T_NAME_RELATIVE
%token <token> T_NAME_QUALIFIED
%token <token> T_NAME_FULLY_QUALIFIED
%token <token> T_READONLY
%token <token> '"'
%token <token> '`'
%token <token> '{'
@ -223,7 +224,7 @@ import (
%left T_ELSEIF
%left T_ELSE
%left T_ENDIF
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_READONLY
%type <token> optional_arg_ref optional_ellipsis returns_ref
@ -281,7 +282,7 @@ import (
%type <node> expr_list_allow_comma non_empty_expr_list
%type <node> match match_arm match_arm_list non_empty_match_arm_list
%type <node> catch_list catch
%type <node> optional_visibility_modifier
%type <node> property_modifier
%type <node> attribute_decl attribute_group attribute
%type <node> member_modifier
@ -293,6 +294,7 @@ import (
%type <list> top_statement_list
%type <list> inner_statement_list class_statement_list
%type <list> method_modifiers variable_modifiers
%type <list> optional_property_modifiers
%type <list> non_empty_member_modifiers class_modifiers optional_class_modifiers
%type <list> optional_attributes attributes
@ -328,7 +330,8 @@ semi_reserved:
{
$$ = $1
}
| T_STATIC {$$=$1} | T_ABSTRACT {$$=$1} | T_FINAL {$$=$1} | T_PRIVATE {$$=$1} | T_PROTECTED {$$=$1} | T_PUBLIC {$$=$1}
| T_STATIC {$$=$1} | T_ABSTRACT {$$=$1} | T_FINAL {$$=$1} | T_PRIVATE {$$=$1}
| T_PROTECTED {$$=$1} | T_PUBLIC {$$=$1} | T_READONLY {$$=$1}
;
identifier:
@ -1253,18 +1256,23 @@ non_empty_parameter_list:
| non_empty_parameter_list ',' parameter { $$ = yylex.(*Parser).builder.AppendToSeparatedList($1, $2, $3) }
;
optional_visibility_modifier:
/* empty */ { $$ = nil; }
| T_PUBLIC { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
optional_property_modifiers:
/* empty */ { $$ = nil }
| optional_property_modifiers property_modifier { $$ = append($1, $2) }
;
property_modifier:
T_PUBLIC { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
| T_PROTECTED { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
| T_PRIVATE { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
| T_READONLY { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
;
parameter:
optional_attributes optional_visibility_modifier optional_type_without_static
optional_attributes optional_property_modifiers optional_type_without_static
optional_arg_ref optional_ellipsis plain_variable
{ $$ = yylex.(*Parser).builder.NewParameter($1, $2, $3, $4, $5, $6, nil, nil, false) }
| optional_attributes optional_visibility_modifier optional_type_without_static
| optional_attributes optional_property_modifiers optional_type_without_static
optional_arg_ref optional_ellipsis plain_variable '=' expr
{ $$ = yylex.(*Parser).builder.NewParameter($1, $2, $3, $4, $5, $6, $7, $8, true) }
;
@ -1664,6 +1672,7 @@ member_modifier:
| T_STATIC { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
| T_ABSTRACT { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
| T_FINAL { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
| T_READONLY { $$ = yylex.(*Parser).builder.NewIdentifier($1) }
;
property_list:

File diff suppressed because it is too large Load Diff

View File

@ -252,6 +252,7 @@ func (lex *Lexer) Lex() *token.Token {
'print'i => {lex.setTokenPosition(tkn); tok = token.T_PRINT; fbreak;};
'protected'i => {lex.setTokenPosition(tkn); tok = token.T_PROTECTED; fbreak;};
'return'i => {lex.setTokenPosition(tkn); tok = token.T_RETURN; fbreak;};
'readonly'i => {lex.setTokenPosition(tkn); tok = token.T_READONLY; fbreak;};
'static'i => {lex.setTokenPosition(tkn); tok = token.T_STATIC; fbreak;};
'switch'i => {lex.setTokenPosition(tkn); tok = token.T_SWITCH; fbreak;};
'match'i => {lex.setTokenPosition(tkn); tok = token.T_MATCH; fbreak;};

View File

@ -0,0 +1,33 @@
package php8_test
import (
"testing"
"github.com/VKCOM/php-parser/internal/tester"
"github.com/VKCOM/php-parser/pkg/token"
)
func TestReadonlyTokens(t *testing.T) {
suite := tester.NewLexerTokenStructTestSuite(t)
suite.UsePHP8()
suite.Code = "<?php readonly public $a;"
suite.Expected = []*token.Token{
{
ID: token.T_READONLY,
Value: []byte("readonly"),
},
{
ID: token.T_PUBLIC,
Value: []byte("public"),
},
{
ID: token.T_VARIABLE,
Value: []byte("$a"),
},
{
ID: ';',
Value: []byte(";"),
},
}
suite.Run()
}

View File

@ -54,7 +54,7 @@ func (n *Union) GetPosition() *position.Position {
type Parameter struct {
Position *position.Position
AttrGroups []Vertex
Visibility Vertex
Modifiers []Vertex
Type Vertex
AmpersandTkn *token.Token
VariadicTkn *token.Token

View File

@ -150,6 +150,7 @@ const (
T_NAME_RELATIVE
T_NAME_QUALIFIED
T_NAME_FULLY_QUALIFIED
T_READONLY
)
type Token struct {

View File

@ -152,11 +152,12 @@ func _() {
_ = x[T_NAME_RELATIVE-57487]
_ = x[T_NAME_QUALIFIED-57488]
_ = x[T_NAME_FULLY_QUALIFIED-57489]
_ = x[T_READONLY-57490]
}
const _ID_name = "T_INCLUDET_INCLUDE_ONCET_EXITT_IFT_LNUMBERT_DNUMBERT_STRINGT_STRING_VARNAMET_VARIABLET_NUM_STRINGT_INLINE_HTMLT_CHARACTERT_BAD_CHARACTERT_ENCAPSED_AND_WHITESPACET_CONSTANT_ENCAPSED_STRINGT_ECHOT_DOT_WHILET_ENDWHILET_FORT_ENDFORT_FOREACHT_ENDFOREACHT_DECLARET_ENDDECLARET_AST_SWITCHT_ENDSWITCHT_CASET_DEFAULTT_BREAKT_CONTINUET_GOTOT_FUNCTIONT_FNT_CONSTT_RETURNT_TRYT_CATCHT_FINALLYT_THROWT_USET_INSTEADOFT_GLOBALT_VART_UNSETT_ISSETT_EMPTYT_HALT_COMPILERT_CLASST_TRAITT_INTERFACET_EXTENDST_IMPLEMENTST_OBJECT_OPERATORT_DOUBLE_ARROWT_LISTT_ARRAYT_CALLABLET_CLASS_CT_TRAIT_CT_METHOD_CT_FUNC_CT_LINET_FILET_COMMENTT_DOC_COMMENTT_OPEN_TAGT_OPEN_TAG_WITH_ECHOT_CLOSE_TAGT_WHITESPACET_START_HEREDOCT_END_HEREDOCT_DOLLAR_OPEN_CURLY_BRACEST_CURLY_OPENT_PAAMAYIM_NEKUDOTAYIMT_NAMESPACET_NS_CT_DIRT_NS_SEPARATORT_ELLIPSIST_EVALT_REQUIRET_REQUIRE_ONCET_LOGICAL_ORT_LOGICAL_XORT_LOGICAL_ANDT_INSTANCEOFT_NEWT_CLONET_ELSEIFT_ELSET_ENDIFT_PRINTT_YIELDT_STATICT_ABSTRACTT_FINALT_PRIVATET_PROTECTEDT_PUBLICT_INCT_DECT_YIELD_FROMT_INT_CASTT_DOUBLE_CASTT_STRING_CASTT_ARRAY_CASTT_OBJECT_CASTT_BOOL_CASTT_UNSET_CASTT_COALESCET_SPACESHIPT_NOELSET_PLUS_EQUALT_MINUS_EQUALT_MUL_EQUALT_POW_EQUALT_DIV_EQUALT_CONCAT_EQUALT_MOD_EQUALT_AND_EQUALT_OR_EQUALT_XOR_EQUALT_SL_EQUALT_SR_EQUALT_COALESCE_EQUALT_BOOLEAN_ORT_BOOLEAN_ANDT_POWT_SLT_SRT_IS_IDENTICALT_IS_NOT_IDENTICALT_IS_EQUALT_IS_NOT_EQUALT_IS_SMALLER_OR_EQUALT_IS_GREATER_OR_EQUALT_NULLSAFE_OBJECT_OPERATORT_MATCHT_ATTRIBUTET_NAME_RELATIVET_NAME_QUALIFIEDT_NAME_FULLY_QUALIFIED"
const _ID_name = "T_INCLUDET_INCLUDE_ONCET_EXITT_IFT_LNUMBERT_DNUMBERT_STRINGT_STRING_VARNAMET_VARIABLET_NUM_STRINGT_INLINE_HTMLT_CHARACTERT_BAD_CHARACTERT_ENCAPSED_AND_WHITESPACET_CONSTANT_ENCAPSED_STRINGT_ECHOT_DOT_WHILET_ENDWHILET_FORT_ENDFORT_FOREACHT_ENDFOREACHT_DECLARET_ENDDECLARET_AST_SWITCHT_ENDSWITCHT_CASET_DEFAULTT_BREAKT_CONTINUET_GOTOT_FUNCTIONT_FNT_CONSTT_RETURNT_TRYT_CATCHT_FINALLYT_THROWT_USET_INSTEADOFT_GLOBALT_VART_UNSETT_ISSETT_EMPTYT_HALT_COMPILERT_CLASST_TRAITT_INTERFACET_EXTENDST_IMPLEMENTST_OBJECT_OPERATORT_DOUBLE_ARROWT_LISTT_ARRAYT_CALLABLET_CLASS_CT_TRAIT_CT_METHOD_CT_FUNC_CT_LINET_FILET_COMMENTT_DOC_COMMENTT_OPEN_TAGT_OPEN_TAG_WITH_ECHOT_CLOSE_TAGT_WHITESPACET_START_HEREDOCT_END_HEREDOCT_DOLLAR_OPEN_CURLY_BRACEST_CURLY_OPENT_PAAMAYIM_NEKUDOTAYIMT_NAMESPACET_NS_CT_DIRT_NS_SEPARATORT_ELLIPSIST_EVALT_REQUIRET_REQUIRE_ONCET_LOGICAL_ORT_LOGICAL_XORT_LOGICAL_ANDT_INSTANCEOFT_NEWT_CLONET_ELSEIFT_ELSET_ENDIFT_PRINTT_YIELDT_STATICT_ABSTRACTT_FINALT_PRIVATET_PROTECTEDT_PUBLICT_INCT_DECT_YIELD_FROMT_INT_CASTT_DOUBLE_CASTT_STRING_CASTT_ARRAY_CASTT_OBJECT_CASTT_BOOL_CASTT_UNSET_CASTT_COALESCET_SPACESHIPT_NOELSET_PLUS_EQUALT_MINUS_EQUALT_MUL_EQUALT_POW_EQUALT_DIV_EQUALT_CONCAT_EQUALT_MOD_EQUALT_AND_EQUALT_OR_EQUALT_XOR_EQUALT_SL_EQUALT_SR_EQUALT_COALESCE_EQUALT_BOOLEAN_ORT_BOOLEAN_ANDT_POWT_SLT_SRT_IS_IDENTICALT_IS_NOT_IDENTICALT_IS_EQUALT_IS_NOT_EQUALT_IS_SMALLER_OR_EQUALT_IS_GREATER_OR_EQUALT_NULLSAFE_OBJECT_OPERATORT_MATCHT_ATTRIBUTET_NAME_RELATIVET_NAME_QUALIFIEDT_NAME_FULLY_QUALIFIEDT_READONLY"
var _ID_index = [...]uint16{0, 9, 23, 29, 33, 42, 51, 59, 75, 85, 97, 110, 121, 136, 161, 187, 193, 197, 204, 214, 219, 227, 236, 248, 257, 269, 273, 281, 292, 298, 307, 314, 324, 330, 340, 344, 351, 359, 364, 371, 380, 387, 392, 403, 411, 416, 423, 430, 437, 452, 459, 466, 477, 486, 498, 515, 529, 535, 542, 552, 561, 570, 580, 588, 594, 600, 609, 622, 632, 652, 663, 675, 690, 703, 729, 741, 763, 774, 780, 785, 799, 809, 815, 824, 838, 850, 863, 876, 888, 893, 900, 908, 914, 921, 928, 935, 943, 953, 960, 969, 980, 988, 993, 998, 1010, 1020, 1033, 1046, 1058, 1071, 1082, 1094, 1104, 1115, 1123, 1135, 1148, 1159, 1170, 1181, 1195, 1206, 1217, 1227, 1238, 1248, 1258, 1274, 1286, 1299, 1304, 1308, 1312, 1326, 1344, 1354, 1368, 1389, 1410, 1436, 1443, 1454, 1469, 1485, 1507}
var _ID_index = [...]uint16{0, 9, 23, 29, 33, 42, 51, 59, 75, 85, 97, 110, 121, 136, 161, 187, 193, 197, 204, 214, 219, 227, 236, 248, 257, 269, 273, 281, 292, 298, 307, 314, 324, 330, 340, 344, 351, 359, 364, 371, 380, 387, 392, 403, 411, 416, 423, 430, 437, 452, 459, 466, 477, 486, 498, 515, 529, 535, 542, 552, 561, 570, 580, 588, 594, 600, 609, 622, 632, 652, 663, 675, 690, 703, 729, 741, 763, 774, 780, 785, 799, 809, 815, 824, 838, 850, 863, 876, 888, 893, 900, 908, 914, 921, 928, 935, 943, 953, 960, 969, 980, 988, 993, 998, 1010, 1020, 1033, 1046, 1058, 1071, 1082, 1094, 1104, 1115, 1123, 1135, 1148, 1159, 1170, 1181, 1195, 1206, 1217, 1227, 1238, 1248, 1258, 1274, 1286, 1299, 1304, 1308, 1312, 1326, 1344, 1354, 1368, 1389, 1410, 1436, 1443, 1454, 1469, 1485, 1507, 1517}
func (i ID) String() string {
i -= 57346

View File

@ -194,7 +194,7 @@ func (v *Dumper) Parameter(n *ast.Parameter) {
v.dumpPosition(n.Position)
v.dumpVertexList("AttrGroups", n.AttrGroups)
v.dumpVertex("Visibility", n.Visibility)
v.dumpVertexList("Modifiers", n.Modifiers)
v.dumpVertex("Type", n.Type)
v.dumpToken("AmpersandTkn", n.AmpersandTkn)
v.dumpToken("VariadicTkn", n.VariadicTkn)

View File

@ -161,8 +161,8 @@ func (f *formatter) Parameter(n *ast.Parameter) {
f.addFreeFloating(token.T_WHITESPACE, []byte(" "))
}
if n.Visibility != nil {
n.Visibility.Accept(f)
for _, modifier := range n.Modifiers {
modifier.Accept(f)
f.addFreeFloating(token.T_WHITESPACE, []byte(" "))
}

View File

@ -147,7 +147,7 @@ func (p *printer) Nullable(n *ast.Nullable) {
func (p *printer) Parameter(n *ast.Parameter) {
p.printList(n.AttrGroups)
p.printNode(n.Visibility)
p.printList(n.Modifiers)
p.printNode(n.Type)
p.printToken(n.AmpersandTkn, nil)
p.printToken(n.VariadicTkn, nil)

View File

@ -0,0 +1,25 @@
package printer_test
import (
"testing"
"github.com/VKCOM/php-parser/internal/tester"
)
func TestParseAndPrintReadonlyModifierPHP81(t *testing.T) {
tester.NewParserPrintTestSuite(t).UsePHP8().Run(`<?php
class Foo {
readonly string $a;
private readonly string $a;
private string $a;
private readonly $a = 100;
public function __construct(
readonly string $a,
private readonly string $a,
private string $a,
private readonly $a = 100,
) {}
}
`)
}

View File

@ -41,7 +41,10 @@ func (t *Traverser) Parameter(n *ast.Parameter) {
nn.Accept(t)
}
t.Traverse(n.Visibility)
for _, nn := range n.Modifiers {
nn.Accept(t)
}
t.Traverse(n.Type)
t.Traverse(n.Var)
t.Traverse(n.DefaultValue)