From e3447dfc16efa701d793ad8b21df008ff69ef215 Mon Sep 17 00:00:00 2001 From: i582 Date: Tue, 27 Jul 2021 22:30:27 +0300 Subject: [PATCH 1/3] php8: added property in constructor The code for creating the parameters and identifiers has been moved to the Builder.NewParameter and Builder.NewIdentifier methods. The grammar rules 'is_reference' and 'is_variadic' have been renamed to 'optional_arg_ref' and 'optional_ellipsis' as in PHP-Parser. Added a new grammar rule 'optional_visibility_modifier' to describe visibility modifiers for properties. --- internal/php8/builder.go | 67 + internal/php8/parser_php8_test.go | 553 ++++ internal/php8/php8.go | 2937 +++++++++++----------- internal/php8/php8.y | 128 +- pkg/ast/node.go | 1 + pkg/visitor/dumper/dumper.go | 1 + pkg/visitor/formatter/formatter.go | 5 + pkg/visitor/printer/printer.go | 1 + pkg/visitor/printer/printer_php8_test.go | 61 + 9 files changed, 2156 insertions(+), 1598 deletions(-) diff --git a/internal/php8/builder.go b/internal/php8/builder.go index 2456da15..19c2a4a3 100644 --- a/internal/php8/builder.go +++ b/internal/php8/builder.go @@ -75,6 +75,16 @@ func (b *Builder) NewExpressionStmt( } } +func (b *Builder) NewIdentifier( + IdentifierTkn *token.Token, +) *ast.Identifier { + return &ast.Identifier{ + Position: b.Pos.NewTokenPosition(IdentifierTkn), + IdentifierTkn: IdentifierTkn, + Value: IdentifierTkn.Value, + } +} + func (b *Builder) NewMethodCall( Expr ast.Vertex, ObjectOperatorTkn *token.Token, @@ -462,3 +472,60 @@ func (b *Builder) NewThrowExpr( Expr: Expr, } } + +func (b *Builder) NewParameter( + Visibility ast.Vertex, + Type ast.Vertex, + AmpersandTkn *token.Token, + VariadicTkn *token.Token, + VarTkn *token.Token, + EqualTkn *token.Token, + DefaultValue ast.Vertex, + WithDefault bool, +) *ast.Parameter { + var pos *position2.Position + + if WithDefault { + if Visibility != nil { + pos = b.Pos.NewNodesPosition(Visibility, DefaultValue) + } else if Type != nil { + pos = b.Pos.NewNodesPosition(Type, DefaultValue) + } else if AmpersandTkn != nil { + pos = b.Pos.NewTokenNodePosition(AmpersandTkn, DefaultValue) + } else if VariadicTkn != nil { + pos = b.Pos.NewTokenNodePosition(VariadicTkn, DefaultValue) + } else { + pos = b.Pos.NewTokenPosition(VarTkn) + } + } else { + if Visibility != nil { + pos = b.Pos.NewNodeTokenPosition(Visibility, VarTkn) + } else if Type != nil { + pos = b.Pos.NewNodeTokenPosition(Type, VarTkn) + } else if AmpersandTkn != nil { + pos = b.Pos.NewTokensPosition(AmpersandTkn, VarTkn) + } else if VariadicTkn != nil { + pos = b.Pos.NewTokensPosition(VariadicTkn, VarTkn) + } else { + pos = b.Pos.NewTokenPosition(VarTkn) + } + } + + return &ast.Parameter{ + Position: pos, + Visibility: Visibility, + Type: Type, + AmpersandTkn: AmpersandTkn, + VariadicTkn: VariadicTkn, + Var: &ast.ExprVariable{ + Position: b.Pos.NewTokenPosition(VarTkn), + Name: &ast.Identifier{ + Position: b.Pos.NewTokenPosition(VarTkn), + IdentifierTkn: VarTkn, + Value: VarTkn.Value, + }, + }, + EqualTkn: EqualTkn, + DefaultValue: DefaultValue, + } +} diff --git a/internal/php8/parser_php8_test.go b/internal/php8/parser_php8_test.go index 5042bbec..f6af58ae 100644 --- a/internal/php8/parser_php8_test.go +++ b/internal/php8/parser_php8_test.go @@ -3851,3 +3851,556 @@ func TestConcatPrecedenceWithShiftLeft(t *testing.T) { suite.Run() } + +func TestPropertiesInConstructor(t *testing.T) { + suite := tester.NewParserDumpTestSuite(t) + suite.UsePHP8() + suite.Code = ` is_reference is_variadic returns_ref +%type optional_arg_ref optional_ellipsis returns_ref %type reserved_non_modifiers %type semi_reserved @@ -273,6 +273,7 @@ import ( %type expr_list_allow_comma non_empty_expr_list %type match match_arm match_arm_list non_empty_match_arm_list %type catch_list catch +%type optional_visibility_modifier %type member_modifier %type use_type @@ -1144,7 +1145,7 @@ function_declaration_statement: } ; -is_reference: +optional_arg_ref: /* empty */ { $$ = nil @@ -1155,7 +1156,7 @@ is_reference: } ; -is_variadic: +optional_ellipsis: /* empty */ { $$ = nil @@ -1676,61 +1677,20 @@ non_empty_parameter_list: | non_empty_parameter_list ',' parameter { $$ = yylex.(*Parser).builder.AppendToSeparatedList($1, $2, $3) } ; -parameter: - optional_type_without_static is_reference is_variadic plain_variable - { - pos := yylex.(*Parser).builder.Pos.NewTokenPosition($4) - if $1 != nil { - pos = yylex.(*Parser).builder.Pos.NewNodeTokenPosition($1, $4) - } else if $2 != nil { - pos = yylex.(*Parser).builder.Pos.NewTokensPosition($2, $4) - } else if $3 != nil { - pos = yylex.(*Parser).builder.Pos.NewTokensPosition($3, $4) - } - - $$ = &ast.Parameter{ - Position: pos, - Type: $1, - AmpersandTkn: $2, - VariadicTkn: $3, - Var: &ast.ExprVariable{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($4), - Name: &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($4), - IdentifierTkn: $4, - Value: $4.Value, - }, - }, - } - } - | optional_type_without_static is_reference is_variadic plain_variable '=' expr - { - pos := yylex.(*Parser).builder.Pos.NewTokenNodePosition($4, $6) - if $1 != nil { - pos = yylex.(*Parser).builder.Pos.NewNodesPosition($1, $6) - } else if $2 != nil { - pos = yylex.(*Parser).builder.Pos.NewTokenNodePosition($2, $6) - } else if $3 != nil { - pos = yylex.(*Parser).builder.Pos.NewTokenNodePosition($3, $6) - } +optional_visibility_modifier: + /* empty */ { $$ = nil; } + | T_PUBLIC { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_PROTECTED { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_PRIVATE { $$ = yylex.(*Parser).builder.NewIdentifier($1) } +; - $$ = &ast.Parameter{ - Position: pos, - Type: $1, - AmpersandTkn: $2, - VariadicTkn: $3, - Var: &ast.ExprVariable{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($4), - Name: &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($4), - IdentifierTkn: $4, - Value: $4.Value, - }, - }, - EqualTkn: $5, - DefaultValue: $6, - } - } +parameter: + optional_visibility_modifier optional_type_without_static + optional_arg_ref optional_ellipsis plain_variable + { $$ = yylex.(*Parser).builder.NewParameter($1, $2, $3, $4, $5, nil, nil, false) } + | optional_visibility_modifier optional_type_without_static + optional_arg_ref optional_ellipsis plain_variable '=' expr + { $$ = yylex.(*Parser).builder.NewParameter($1, $2, $3, $4, $5, $6, $7, true) } ; type_expr: @@ -2224,54 +2184,12 @@ non_empty_member_modifiers: ; member_modifier: - T_PUBLIC - { - $$ = &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - } - } - | T_PROTECTED - { - $$ = &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - } - } - | T_PRIVATE - { - $$ = &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - } - } - | T_STATIC - { - $$ = &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - } - } - | T_ABSTRACT - { - $$ = &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - } - } - | T_FINAL - { - $$ = &ast.Identifier{ - Position: yylex.(*Parser).builder.Pos.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - } - } + T_PUBLIC { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_PROTECTED { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_PRIVATE { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_STATIC { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_ABSTRACT { $$ = yylex.(*Parser).builder.NewIdentifier($1) } + | T_FINAL { $$ = yylex.(*Parser).builder.NewIdentifier($1) } ; property_list: diff --git a/pkg/ast/node.go b/pkg/ast/node.go index e48c0808..256b42d2 100644 --- a/pkg/ast/node.go +++ b/pkg/ast/node.go @@ -53,6 +53,7 @@ func (n *Union) GetPosition() *position.Position { // Parameter node type Parameter struct { Position *position.Position + Visibility Vertex Type Vertex AmpersandTkn *token.Token VariadicTkn *token.Token diff --git a/pkg/visitor/dumper/dumper.go b/pkg/visitor/dumper/dumper.go index f8861a9a..ee4bdaff 100644 --- a/pkg/visitor/dumper/dumper.go +++ b/pkg/visitor/dumper/dumper.go @@ -193,6 +193,7 @@ func (v *Dumper) Parameter(n *ast.Parameter) { v.indent++ v.dumpPosition(n.Position) + v.dumpVertex("Visibility", n.Visibility) v.dumpVertex("Type", n.Type) v.dumpToken("AmpersandTkn", n.AmpersandTkn) v.dumpToken("VariadicTkn", n.VariadicTkn) diff --git a/pkg/visitor/formatter/formatter.go b/pkg/visitor/formatter/formatter.go index c01eb736..007c6915 100644 --- a/pkg/visitor/formatter/formatter.go +++ b/pkg/visitor/formatter/formatter.go @@ -154,6 +154,11 @@ func (f *formatter) Nullable(n *ast.Nullable) { } func (f *formatter) Parameter(n *ast.Parameter) { + if n.Visibility != nil { + n.Visibility.Accept(f) + f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) + } + if n.Type != nil { n.Type.Accept(f) f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) diff --git a/pkg/visitor/printer/printer.go b/pkg/visitor/printer/printer.go index e80768cf..8c5eb1a0 100644 --- a/pkg/visitor/printer/printer.go +++ b/pkg/visitor/printer/printer.go @@ -146,6 +146,7 @@ func (p *printer) Nullable(n *ast.Nullable) { } func (p *printer) Parameter(n *ast.Parameter) { + p.printNode(n.Visibility) p.printNode(n.Type) p.printToken(n.AmpersandTkn, nil) p.printToken(n.VariadicTkn, nil) diff --git a/pkg/visitor/printer/printer_php8_test.go b/pkg/visitor/printer/printer_php8_test.go index fffae1bf..e3c6392b 100644 --- a/pkg/visitor/printer/printer_php8_test.go +++ b/pkg/visitor/printer/printer_php8_test.go @@ -1920,3 +1920,64 @@ throw new InvalidArgumentException(); assert.Equal(t, src, actual) } + +func TestParseAndPrintPropertyInConstructorPHP8(t *testing.T) { + src := ` Date: Tue, 27 Jul 2021 22:37:21 +0300 Subject: [PATCH 2/3] php8: fixed position in Builder.NewParameter --- internal/php8/builder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/php8/builder.go b/internal/php8/builder.go index 19c2a4a3..2b1015b1 100644 --- a/internal/php8/builder.go +++ b/internal/php8/builder.go @@ -495,7 +495,7 @@ func (b *Builder) NewParameter( } else if VariadicTkn != nil { pos = b.Pos.NewTokenNodePosition(VariadicTkn, DefaultValue) } else { - pos = b.Pos.NewTokenPosition(VarTkn) + pos = b.Pos.NewTokenNodePosition(VarTkn, DefaultValue) } } else { if Visibility != nil { From d547fce007c21d920fc1dc46aa003880689e3ca6 Mon Sep 17 00:00:00 2001 From: i582 Date: Tue, 27 Jul 2021 22:40:09 +0300 Subject: [PATCH 3/3] php8: added variability of access modifier in TestParseAndPrintPropertyInConstructorPHP8 test --- pkg/visitor/printer/printer_php8_test.go | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/visitor/printer/printer_php8_test.go b/pkg/visitor/printer/printer_php8_test.go index e3c6392b..f376a661 100644 --- a/pkg/visitor/printer/printer_php8_test.go +++ b/pkg/visitor/printer/printer_php8_test.go @@ -1925,24 +1925,24 @@ func TestParseAndPrintPropertyInConstructorPHP8(t *testing.T) { src := `