From b85bae2ec11a36eb6cdd9ae08132b01ed93cecf3 Mon Sep 17 00:00:00 2001 From: Vadym Slizov Date: Sat, 26 Dec 2020 18:20:10 +0200 Subject: [PATCH] refactoring: update ast structure of "Closure" and "ClosureUse" nodes --- internal/php5/parser_test.go | 426 +++++++++++---------- internal/php5/php5.go | Bin 264939 -> 265070 bytes internal/php5/php5.y | 131 ++++--- internal/php7/parser_test.go | 426 +++++++++++---------- internal/php7/php7.go | Bin 219529 -> 219555 bytes internal/php7/php7.y | 59 +-- pkg/ast/node.go | 41 +- pkg/ast/traverser/dfs.go | 20 +- pkg/ast/visitor/dumper.go | 13 +- pkg/ast/visitor/formatter.go | 20 +- pkg/ast/visitor/formatter_test.go | 47 ++- pkg/ast/visitor/namespace_resolver_test.go | 1 - pkg/ast/visitor/printer.go | 11 +- pkg/ast/visitor/printer_test.go | 48 ++- 14 files changed, 654 insertions(+), 589 deletions(-) diff --git a/internal/php5/parser_test.go b/internal/php5/parser_test.go index a60a8fb..6ff6707 100644 --- a/internal/php5/parser_test.go +++ b/internal/php5/parser_test.go @@ -31770,7 +31770,7 @@ func TestExprClosure_Use(t *testing.T) { EndPos: 36, }, FunctionTkn: &token.Token{ - ID: token.T_FUNCTION, + ID: token.T_FUNCTION, Value: []byte("function"), Position: &position.Position{ StartLine: 1, @@ -31780,7 +31780,7 @@ func TestExprClosure_Use(t *testing.T) { }, FreeFloating: []*token.Token{ { - ID: token.T_OPEN_TAG, + ID: token.T_OPEN_TAG, Value: []byte("J|5qr%FXj$ZAUz)u{=2(25X|1XXD(Eyb)NUfC^E zlBs7YValm$D$%LwXc3~-K}WR4YH3NBRv(7>&i~(=T-we|*2-G!OI1XejE#LUDr{j?m{3t+@(*tXAjG_!D$wSO|(X3NmfAx{?+K4{8%1_b!~ z`@0m_zDzvInY)F5h=(*Lb!L7}aqjed4w@w*f?T>WgQgWsDlE#%pU59Crce)ku9Ota z$9!b_;1<&{=~;zY(~7LgeEg_%1bV2)uyu|I<19ynNjr?OGwMJWz?i zW=XVyWQh{3dzmkY8C5*37>2EL<_w-bb!t}OxWtT@skueP9(VBcKC(S0?-PL{iO>4T zux4w?b#hF*c&N_xP`CEy82I!*;uL;d2DI`x#np?%J#F0KF@wfUu`)cwBMcr<^O3(A zwLpG;wg_ytW5$hl&K8M&Zrf(W_Rki-6|vy>jF{r-d6V)z-7^BWeU1q1?Y8ra$R+)k z$Vt2H&d_Dn%h7y%J4LJddMN}yI!Z)vO_20b*H7y8j7V~=gFls-g0ru=_puHY{KjW; z7}wsw`Nr+kRdC#Cna1r_N%y+;4Ay#|u^+{aVbaPe14SICY$9(}aaNWJk;uoBC2o01 zdaHG(WjDc3os&adS8L(XbMmC%^8;Ni>t_)}{O4p9O|m+F92XmH;F)a zC)&`MqDfr(1NHI4kN#Htap@+Qw>W`a>j~M)P)P47J8{E(WMnbe5DmIP2^@VjJJbo?e$BI;+ePa){)rujF$go+n?#c_?(^1LuX4Ywi<%+;EE8@PShzP}O`b zrx>b}^sk`RnKG0cKc}{w zd4cZZ*V3gQZ`&tYam^U%@SBxYn46V7brL6Dk>hZO+iAn6R333vw&jaGWJjJb97fZ^ zYv=am6A zWlgdpArSV%IxAXiS&DQPoJ2@2H_2f2$agZ7c)|hzsb%~5Y0|ab>PLA)^1(PDa=M^F zlCy6aaXUV^S>i7!6%=CPNkbiqi=7T+)4hgUH8P&?4yoHQ)@cAc2 zI9IhIFJ%j$i2|tBKvs}^B9K}G)q0!ZREWCOjvf=-wk@T~guBjm61>s^r_4&w29^n) z-;Po_Xb-~PXd(Y*8*6pJRGx>pVm#1zBm`PZ+EY)idshZ-Rn zL;=6Kgc7+-$-X?GBjs_MWt5`uE8lo@2d)XD92pnKwHHMUx5)T+Uia zc0LnD!(>vNX?0X56|SixvUq;VAVYk#F`9ZXl(C7-*M$_jV68IKyRw$`Q2c|z7;XV znM1sz`yDn7mCt(6P|mLMIChY!Cj$Nj<0`kQgWR{5fhb_i;!Uj2OQa-DZ_=0@Ec$UuK3P=cRO&8xP8_rn z%$i%8M{!(rP55)!ck*!st&M^s6On#{DDT+r$(CB_Tb?5BHLU^XPYJdpqE^@Ury;uA zv`{-(`(?o^2EaKx>vGgB!CT!LK$``MElYaY`PBVz1c7j6@({}u1nvD4BtA0*n27bT zhgN}x8)}{ zQiSFdgBA@RhrcRM@^hn%#FL{VWgh+o|)KjC+?!3v2kFQa$Mv+Og` zh`vGF`4j135U$~JG-EZM*FFluKRprPSo$PY>*&vzj2>L@6y0tPzNYqNlgS5htrMW- zTpBF6Y>;$t_dL{k(`VAE0Oy;gtBmr<!7V92R9X?JS)zl0~;GtW+MJ^Hj~{94w?En`KhxrDMs+fQRtnT z!xVTRS#ZNZ%nw+9zz@yA1qR7Qa895{@UKhKLmcF8|sw$=5 z3mI<&-V`xJy?EY>^uBhrqxqtl^YPTg1>}19)%oz$VZIMR|2L<(Pai_&Nlb}hghe9K(_vh0q$--sVg|B((ij{y2#<#ng zR?k&h9B=lQO1+4WRhL)M(_S(uR<&JA@q%st#J9?{$ufvPSVKc8(H5^ab{J)=$Ar)S zNY{jPf^62&Lf&;2P0k8tU%Vb(-(LYQZs%c8{C+)NUAPDdo>8GQ>QwJk&`u3@^sQ*d zB;mu2ucPnGe;wVyU{@;_2&5L$0fIMebO$VBqZ>OdQ*al-UvGlhBsbN#renxwZo$Q% z3U|1-7~wYfGk2@;yYxC{VFPSmLZF+5D^nS704@pI(a9J^wqviw&LS+qq$ZcN+!nF} zVpjpXM|3z*u@mA1t?jxgyb6Lu&Rl@GZC;2TH}$NKf!CZ*%dgWXT(t{2NzES>k;=B4 zJ{A1Hi*VQW5m4IeEhre{i=8*<-wv+WEX?qC+Jj^|;uzC{jbGVAf5$`a&gTh5X{yay zO7Ki_$v%w&d-K8Nyzm_mN8tvL9%i{}-n`#%9b5yDYkc}u>&QD5uJRRRw;3pN^3wO{ zq^6pzGvX9y9u_lrdks>77LT@HORs2>H@g~_)l)xis7D<}AEYAbjOW`V%a>AhIv zBWUkm=&C{bUA4@cLl4ntgc{w?v&6R?x}(I$V^6ha#Q@%M42%Pf37m37bmkvVQ8@1` z!q-XP(^N)I8^}?QqE}8+4p!(Y7s0ayXD9`I7QKEQ4dkY?29)&Z$QT_z<_{{-Oe_ab z)T94__a6KZ<50mo>HnKxymSs~XadQ1eU<)yA5qCXc@w?B3%&r7#7%UPZ@!=(q@IC+ zqP-Vso1SIy^*qoR^xR*ofhzqgsy7fHQGSu8@Y;9q>2_oRI0YL$)RjxLM{?mQAQM2m z$@{P1m3IxYZ}N$&n&a#$vXQ2m-#Wkc$i3Go%E&6YwhZwc^mL4J8 zon*x7Krcl>0bY*(00_dMhX4Qo delta 4673 zcmaJ_dsLNG7GLM=3kWJ+Qb6Rb;1lI?feY9mXo{#y!PKTT zR$D6q17vK%;^2VSg9C&L4v=r|nuPF{~FFHii9D#|XJIdya{S9wq;wnmB8t`ajL$s2-0EB4=q&^30!$d^b(1jHB&^1Bp$g@^pY_)-umDFi>^M}AyTEIrkg(|X*0ErlvNE3+Pbb`<>XH#qf6E|wnbqzJ*0b#e$d zq{u*3vzfXJ-hIJ2W{ktRDL{sCYKn;Gj4kA*N-oMp0%~PuCrT#%}8E zC+Q8rLmMFFgWJwY#^l5`mqmN7YNQB$rCxU8lD^bO2grwaeM+7@yaRP%TP(Je_oF!W zyCTye(^?_?_|i)h#HCjt1sD3U?S$|avAk#sE=jGEQ50`?@NOH0alacfi0fyI;apHJ z+VQL3A^Oq(#pU()sW0g`&zXsEW?q$DxaM8_PUB~df zJphhjf6YV@&Xaai7FRtfa@G1w=`Q%#kMb42cn4zt7ajk?oas4*IeAla!ulrjy>k@6 zlZ#{zE;uMUa{X!OU3m`h+I2(vbM+bFt?plwgJdh$DQ=i1qj~;ynJyC?yr`O6WLr}2MK2yP1grfjTE zt}B<_z*X<;fpwEdVB!05aw1nn3oC!|jLb2=`i+&ir4O#3IaWukK`#yB2bmxmv2en%K#(>gCs8(l!grGzm@z{iG_wpwp%Ej!#x1uVGm@g zp!BBJ2|C=o4HvOdjQ7UX%{Vgiis=cX`naA>z1y1fW%rCfwAEKD1Ks(Y6p1 z-)wqjd&(31PCHCH9v^%jL zDSKYF=U+R~5SaAAX3WkG#J7#}R?}qm3!(z37qb;obz<=LAPCahX-K$p=8qJ@6?Mo9 z0I`<|gfKU0(TNzz;|2gkH(mxVz6+)yT)J30OzS>51RjkF0UCB~1|OacaY^sYm%pX6 zTs=s(;fOF}cFumX@wzaGofU=y#jODvuW)*n2Y3SO#&v7Lu{tdrx5MG?T-lx6_(3?` zfkmfkAkLWZ??QKEtb-e-BS(#y=m`3iZ|1_&sgcx9==2X{e16XMZqV;kGR(rp&v<-y z3~Opcu)?q{;_&E}V_ebGzz+~*>^{bIy|CML*D`luAj~s=PWax!0)0(*wd)7<4LxF?5q{&f+)j!)I=b#;IHY3)Btr)J4g}6DNAvJ3X zD4sKKicTtP7Uc-OACHxa0(zZO@+q2E&LXSwN}x-E=YFio%0anneg{h!3*||4P)Hl# zrEzS%D7`iFRtr_yAeRbm=tqM^j7}pXqQN{N1uDcC?pBp4+DTwdxY}1oD0oeOVEW5c z5FgMkowLG2@}$ewG3Z&^je0Z-qV^#zQ?_nGNa6I)S=4-F1AstmR&l zph&FguGZ!9Eay+gL|ij{Gj_@|yeG>AB5i{T%cfu<9S(-d5sV!k>iH>{g5wS4vF^cL z_u$~NX@>VTy>gWgcwo|Wn#377)F@+JCSh7(x8O}#r|4-F z`3h|oK;(^D8l}RD>4ea}F68JBX&mo=mFi@?GhD99KZxsVA!fi5T4Gw@wD|54H~{(T z9L`;eaHKAUJyl~6r$_bS@z@<~W@Gb8(qd=T>vTvf=M+%>1_U7CV!7KgeBFKn;oYzd z^pdxXx+_$_T2I6u9(L~cTcw>8-?HHCSf$;SWLCV0)fmJlD3rVxEiy4dtv^87f``0k zR9Lm{03`^n4-sv-$u6yY^?e#|lAj53m9>_B5wNB-4Rq+*7sT(Z2c`=4lbzd^8K`W^ zl@Yw446|d(&`MR@M%ox4xs7!h=TONX&@N3MptDe(y^-#*$40=%VbU2U2A~bU1R=($ zhD~t5&P~l&wUyx6o1t`~lk!|_i}|}-5GSJrDBKDlIl0@o=jW{knLqN`bK5ipIr-ZZ zwGC%%TE7|SS$4RtYF&=6^E;YpkRf#OiR8lvs4u6Umshz<1&$irXXkYl(0D_4R9ujQ zU2yCkoIf>~!c=hwxe1A|556(LWHcM)`w$n~BRzt-$9`BB6US%@UX(G3I($aU;I-y3 zSvc?`Iu9)oy(xmn9)MMLJ=h{-eB9$(OWErX>;$c$PIclHp7aU#{20ob?P1FXrv)qx z@_FkMT#)Ga!`&CimSn&!mU#~)bJ=xpSbinVlQz_a3*sDS9T#&r`iN<&k>VNrFXzyF z<#7E88pIU?g$Gw31V{!h0ij3TLbvwSQFyH9QSxGslj4r?B+{Fs&HhWjOVr|j(hb42 z16+@ziqFZN-~Wt80a%FfBTg9u$hzoclaL8<|CcZD%qu#f%}vzXp4P0f7+Cm9M=)78 z_s%Cm&xa(kiW935Z=cc-870DY6&_8zh{yi&VBw{_ zFH$6$94CyB+d(|{+lQ^FLMxi8`xs68s|4F8qN&0gG`Pj1mGNkGx> zQ~6iuH`jyXA)+p6C*Z}F3~h?*s1+~&fi~zoFuQ66)_lh3^bE5MZk(oi{Y3X9*XuU3 zMeF@IG7IrmMe4NdcFTE8lcv2mwZ4gFIiEykCXTyp0N<#`Rk!K7Fw^qOJ2X#FToM>) zsSHsV#t2?@7fFb;G^T#PORdBo*s$|Gw0}kmr$*eT`OeSp@K6@!tE$Zd-ME0#)48~} z?7VuVMYFG&8x_Lxcatq*_&sTHJ{pRpC7AumlEzo01(p7aY^};XE$<7q{YkiSm>V|g hp9oa7jXo6I%fkY;GMj*wdmWxw!{bf2wXU_3;(u1HSp5J1 diff --git a/internal/php5/php5.y b/internal/php5/php5.y index 7867d5c..50edcc3 100644 --- a/internal/php5/php5.y +++ b/internal/php5/php5.y @@ -3367,36 +3367,38 @@ expr_without_variable: } | function is_reference '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' { - $$ = &ast.ExprClosure{ - Position: yylex.(*Parser).builder.NewTokensPosition($1, $9), - FunctionTkn: $1, - AmpersandTkn: $2, - OpenParenthesisTkn: $3, - Params: $4.(*ast.ParserSeparatedList).Items, - SeparatorTkns: $4.(*ast.ParserSeparatedList).SeparatorTkns, - CloseParenthesisTkn: $5, - ClosureUse: $6, - OpenCurlyBracketTkn: $7, - Stmts: $8, - CloseCurlyBracketTkn: $9, - } + closure := $6.(*ast.ExprClosure) + + closure.Position = yylex.(*Parser).builder.NewTokensPosition($1, $9) + closure.FunctionTkn = $1 + closure.AmpersandTkn = $2 + closure.OpenParenthesisTkn = $3 + closure.Params = $4.(*ast.ParserSeparatedList).Items + closure.SeparatorTkns = $4.(*ast.ParserSeparatedList).SeparatorTkns + closure.CloseParenthesisTkn = $5 + closure.OpenCurlyBracketTkn = $7 + closure.Stmts = $8 + closure.CloseCurlyBracketTkn = $9 + + $$ = closure } | T_STATIC function is_reference '(' parameter_list ')' lexical_vars '{' inner_statement_list '}' { - $$ = &ast.ExprClosure{ - Position: yylex.(*Parser).builder.NewTokensPosition($1, $10), - StaticTkn: $1, - FunctionTkn: $2, - AmpersandTkn: $3, - OpenParenthesisTkn: $4, - Params: $5.(*ast.ParserSeparatedList).Items, - SeparatorTkns: $5.(*ast.ParserSeparatedList).SeparatorTkns, - CloseParenthesisTkn: $6, - ClosureUse: $7, - OpenCurlyBracketTkn: $8, - Stmts: $9, - CloseCurlyBracketTkn: $10, - } + closure := $7.(*ast.ExprClosure) + + closure.Position = yylex.(*Parser).builder.NewTokensPosition($1, $10) + closure.StaticTkn = $1 + closure.FunctionTkn = $2 + closure.AmpersandTkn = $3 + closure.OpenParenthesisTkn = $4 + closure.Params = $5.(*ast.ParserSeparatedList).Items + closure.SeparatorTkns = $5.(*ast.ParserSeparatedList).SeparatorTkns + closure.CloseParenthesisTkn = $6 + closure.OpenCurlyBracketTkn = $8 + closure.Stmts = $9 + closure.CloseCurlyBracketTkn = $10 + + $$ = closure } ; @@ -3520,17 +3522,16 @@ function: lexical_vars: /* empty */ { - $$ = nil + $$ = &ast.ExprClosure{} } | T_USE '(' lexical_var_list ')' { - $$ = &ast.ExprClosureUse{ - Position: yylex.(*Parser).builder.NewTokensPosition($1, $4), - UseTkn: $1, - OpenParenthesisTkn: $2, - Uses: $3.(*ast.ParserSeparatedList).Items, - SeparatorTkns: $3.(*ast.ParserSeparatedList).SeparatorTkns, - CloseParenthesisTkn: $4, + $$ = &ast.ExprClosure{ + UseTkn: $1, + UseOpenParenthesisTkn: $2, + Use: $3.(*ast.ParserSeparatedList).Items, + UseSeparatorTkns: $3.(*ast.ParserSeparatedList).SeparatorTkns, + UseCloseParenthesisTkn: $4, } } ; @@ -3538,12 +3539,15 @@ lexical_vars: lexical_var_list: lexical_var_list ',' T_VARIABLE { - variable := &ast.ExprVariable{ + variable := &ast.ExprClosureUse{ Position: yylex.(*Parser).builder.NewTokenPosition($3), - VarName: &ast.Identifier{ + Var: &ast.ExprVariable{ Position: yylex.(*Parser).builder.NewTokenPosition($3), - IdentifierTkn: $3, - Value: $3.Value, + VarName: &ast.Identifier{ + Position: yylex.(*Parser).builder.NewTokenPosition($3), + IdentifierTkn: $3, + Value: $3.Value, + }, }, } @@ -3554,7 +3558,7 @@ lexical_var_list: } | lexical_var_list ',' '&' T_VARIABLE { - reference := &ast.ExprReference{ + variable := &ast.ExprClosureUse{ Position: yylex.(*Parser).builder.NewTokensPosition($3, $4), AmpersandTkn: $3, Var: &ast.ExprVariable{ @@ -3568,43 +3572,46 @@ lexical_var_list: } $1.(*ast.ParserSeparatedList).SeparatorTkns = append($1.(*ast.ParserSeparatedList).SeparatorTkns, $2) - $1.(*ast.ParserSeparatedList).Items = append($1.(*ast.ParserSeparatedList).Items, reference) + $1.(*ast.ParserSeparatedList).Items = append($1.(*ast.ParserSeparatedList).Items, variable) $$ = $1 } | T_VARIABLE { - $$ = &ast.ParserSeparatedList{ - Items: []ast.Vertex{ - &ast.ExprVariable{ + variable := &ast.ExprClosureUse{ + Position: yylex.(*Parser).builder.NewTokenPosition($1), + Var: &ast.ExprVariable{ + Position: yylex.(*Parser).builder.NewTokenPosition($1), + VarName: &ast.Identifier{ Position: yylex.(*Parser).builder.NewTokenPosition($1), - VarName: &ast.Identifier{ - Position: yylex.(*Parser).builder.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, - }, + IdentifierTkn: $1, + Value: $1.Value, }, }, } + + $$ = &ast.ParserSeparatedList{ + Items: []ast.Vertex{ variable }, + } } | '&' T_VARIABLE { - $$ = &ast.ParserSeparatedList{ - Items: []ast.Vertex{ - &ast.ExprReference{ - Position: yylex.(*Parser).builder.NewTokensPosition($1, $2), - AmpersandTkn: $1, - Var: &ast.ExprVariable{ - Position: yylex.(*Parser).builder.NewTokenPosition($2), - VarName: &ast.Identifier{ - Position: yylex.(*Parser).builder.NewTokenPosition($2), - IdentifierTkn: $2, - Value: $2.Value, - }, - }, + variable := &ast.ExprClosureUse{ + Position: yylex.(*Parser).builder.NewTokensPosition($1, $2), + AmpersandTkn: $1, + Var: &ast.ExprVariable{ + Position: yylex.(*Parser).builder.NewTokenPosition($2), + VarName: &ast.Identifier{ + Position: yylex.(*Parser).builder.NewTokenPosition($2), + IdentifierTkn: $2, + Value: $2.Value, }, }, } + + $$ = &ast.ParserSeparatedList{ + Items: []ast.Vertex{ variable }, + } } ; diff --git a/internal/php7/parser_test.go b/internal/php7/parser_test.go index 76706ed..c33bafd 100644 --- a/internal/php7/parser_test.go +++ b/internal/php7/parser_test.go @@ -36268,7 +36268,7 @@ func TestExprClosure_Use(t *testing.T) { EndPos: 36, }, FunctionTkn: &token.Token{ - ID: token.T_FUNCTION, + ID: token.T_FUNCTION, Value: []byte("function"), Position: &position.Position{ StartLine: 1, @@ -36278,7 +36278,7 @@ func TestExprClosure_Use(t *testing.T) { }, FreeFloating: []*token.Token{ { - ID: token.T_OPEN_TAG, + ID: token.T_OPEN_TAG, Value: []byte("jcmV;SBJzD-KMY$d|o#%b;#p^%&>wTW{ z@tkvh=XcI~7=vMd4EUj*1Cq~T}`#t()M3a`t;R%8k<%+ zl6i4)v9TdF4lJiCxZk9>lzYNjPwB4utu4 z8){p2HPu(|ZLGDHp|_i7Pci2R3$(sYR$$2!o|cB~we=ASPgTo~mS$_2wRi8ThPt|7 z(_=pG6P~(fn_D7`Fffg$VeEB^XP*znvp9VsyLbP@)mUFdnP?4iw9Y@pq$nRVq9_$f zHI#^&9$t%`E?R_7&1s~Qtr!R4U+%-=UalrTF22ETS4fDGVsYIbrKV!|3QtxWn`?3C zL!N=g)0`N!)UqrDqf|!w8S>aV-@~ffJ|thK92|X!()ETj{5Ipay_^B-K`zlfalDrB z;8|XSws$xWUA;UVIR~f|>;BDCwCe-bga=NsTlfE!7qL^$a1}@Cg?)UOrJOc5XCf>q zVNAcsWmJguHJqdOT{J#Tn+1Z()pQCkd@9lW*m;6|P?sd;wNg$+&lb`D>XN7ej%rj? z^29(l&BE5t1Q{E|o-8$vGk+7+612^wg(&*FxD=vfJIzGJJc@2F;Ar^sRUdi^I37nX zht<2kTYZs#~`>gOQ3`e=&&3nb2fs8pj0*(AE7c_Y`3pXc-(BajiD%B@(hV*(>=OHH_+dzN<{6X1UoiKk z0OHr8nn$55boW<0ndP$nsA-LPRV3LMUO{E1ttSo6lC8GBW`8ITYr^CacrA{?*Ta0) zLC4BeSs1z{QR%AmJ2+zZ(C`u;j&PqAWZolezAbHc=&JwlAMPa7j*5!_>O=piKAn#$TJf#jbo>0yx8mCB7Ao4o7u^vr=~O0!1K;D<-`%rJ z7`MX;2~!>0!{hha-uPaw`J2Mp;9W5n`b?N#xhwjT1ML3&c{PV#c}A6mZ#yV_nnO6K zLJECdsTUY@M~dl~r0ldpkuzM%CjQZIu-~{uZ+P?OffPmfE=H~Xs;_7Ga*lo^JB z_j$2SnyfC7BqkkmL)2*y$qZbGVn3dqtmdO5LH!KL^_14$CFJz>3Hi#Wt8b7yMS}Vq zKbgo$j`aB?k=mo_4!bl!F09OG}Ug;U7X1fm%;tgV`<(`rKnriW$tXt$Frp500#a^7KX=VR8D0} zXqy@S90^^Z59X*xNlavYxUoM^#eywWO$8AxJ7S5CFNUr5)jU&M%h^T9m?7C!1LW$CAE}nmiZmPFXaabuQ2CKJUp{Bj%+cMI zDwfPjaO=VKDuJ9%S`{iLO=2u-17&8T5Djn$8& zAM%tsBQA|vDL6IW$#OwUYBa!cQqu_3$_h2YLL;Tlz3&H7zutT9IrnVObI!Z{qu@6_ z3a*XuP|B;Zo^`Pv(y<)ROq98PPQh!t*qd-jZa0LFDEO%@7k_#;dI03cU6p5gD6w-Sa19t`u z!In8H9F;yX9_QhZp!>_7S@Hbxr6ntt;^kNsPU-00!XEr{NYa_3R1n_ZO~a5ijEAFo zH`U?O&v*vvW~z8S{2;SJLZZZRFO)blkBG(_K&d!xPH)FcQcbrc<=i?Eb1FCiHavmO?dFnMA5Tq3Eh(l!fbGbFdtS_huf4^;5{B|2)cj zShvnp;|Y27Tp(GOw~L4Nc^rVwBQzD+*V%^!ze{c{ACp@be94uBOSj3f(Ko;1RJJ+k z_6E*jyxG8cl#JrZJr;8PI^$FW$7`H2#_UoNy7e>~6vRt@B)hgr_Bep%)~?+(BabEUN){zL_7j-PPAF@RNkO z6D3!p(W2Q!^5F4b*bDaqYA>#~NZJBcGzwe!4z_J{PW|xoMed}D2J2{Dafw68)DVNU zm$)9~KXATjgJ0bAqlngr7=DQ_eiHHGHDO`RWj>1Eu1If_tRslN9#OwY$R20Mk^8G@ zoZs1Tl(qR2(v58##*}8TeGMn)@Bm@8>WBQR>_+E16oppPg=N=dKqkZsX`8M~7cPb? zTS`AY={HUn(DNkerZ!GQdloG~l2<4)>naa&Jai|K8*%$&8k$mgu<@0IH-4A&ZCk0M zhg%VNtb?CKakH@aatD7+$$H-n4q|(w8*lJ?go>N;PC&4>F}QWpDa$V|za^poVTa-& zLzGl3{!3nzdsPZf+tXs@G1*UPsYdC^KD(XcNpv-Ii=78WQ+jZj}pbWr%eL z)Gea*wyK-+DWi|&pGIZ<2@A&1hF4U69}ywkM=mEEoh?O}wX{D#$rK1w{)h+qsRE}p zsV-IEK;u{KH5W2L3psA*yF(Qre1O=Rn0749v`!#=5G0qjiy}v%tW`)NvpULQ>)L^; zf+X>~!+h7ODS*?lK3Hww^h~>esv=YuvO-n9aI5!$y{vZ2r5$E}Zo|SPsx7LrR2FH` za20^>vs8%o4pBo0I|obo9XkZtXPY^&SF@PilPU^?V7Q4D2_A1 z^u{=~h>Vp#(MYezseNGH?iIU&IOxNC{*4pOu zwcQiIi*acJQ1cwKw_jhbg1^JFnw^Gx<<$@HQRQA zTEl7SW>JR2eJ{E6!$~Te*k|`>A`U03rT^cfkUe@5v8k%m+4K$r&!h=C{1lU6NPu^o ztU|*u8$V*{5rKDvR{%nT7)bi$!$=nhr^$M4yQXQ`J+*-Yly{nl~8F z%qCY=AiHp5vf9zR`ujZ4@}PyBl_`MxHFgkc?o*+ts1+V2O;suS+bp%8dt=_g&ijQK zc6S!FijA!BPD<0R>8gx{AMljg(*Zv_kbFIpcSySh@6f zMT#BVw8+7t5~TF#dFloK@$h`rpJcu)4McG1>m@48;BNnvmQTwbQZvZ+f70DvC@hmD KHx}iKRLZ|&@FlPS diff --git a/internal/php7/php7.y b/internal/php7/php7.y index 00582e4..580e9d4 100644 --- a/internal/php7/php7.y +++ b/internal/php7/php7.y @@ -3178,21 +3178,22 @@ expr_without_variable: inline_function: T_FUNCTION returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type '{' inner_statement_list '}' { - $$ = &ast.ExprClosure{ - Position: yylex.(*Parser).builder.NewTokensPosition($1, $11), - FunctionTkn: $1, - AmpersandTkn: $2, - OpenParenthesisTkn: $4, - Params: $5.(*ast.ParserSeparatedList).Items, - SeparatorTkns: $5.(*ast.ParserSeparatedList).SeparatorTkns, - CloseParenthesisTkn: $6, - ClosureUse: $7, - ColonTkn: $8.(*ast.ReturnType).ColonTkn, - ReturnType: $8.(*ast.ReturnType).Type, - OpenCurlyBracketTkn: $9, - Stmts: $10, - CloseCurlyBracketTkn: $11, - } + closure := $7.(*ast.ExprClosure) + + closure.Position = yylex.(*Parser).builder.NewTokensPosition($1, $11) + closure.FunctionTkn = $1 + closure.AmpersandTkn = $2 + closure.OpenParenthesisTkn = $4 + closure.Params = $5.(*ast.ParserSeparatedList).Items + closure.SeparatorTkns = $5.(*ast.ParserSeparatedList).SeparatorTkns + closure.CloseParenthesisTkn = $6 + closure.ColonTkn = $8.(*ast.ReturnType).ColonTkn + closure.ReturnType = $8.(*ast.ReturnType).Type + closure.OpenCurlyBracketTkn = $9 + closure.Stmts = $10 + closure.CloseCurlyBracketTkn = $11 + + $$ = closure } | T_FN returns_ref '(' parameter_list ')' return_type backup_doc_comment T_DOUBLE_ARROW expr { @@ -3230,17 +3231,16 @@ returns_ref: lexical_vars: /* empty */ { - $$ = nil + $$ = &ast.ExprClosure{} } | T_USE '(' lexical_var_list ')' { - $$ = &ast.ExprClosureUse{ - Position: yylex.(*Parser).builder.NewTokensPosition($1, $4), - UseTkn: $1, - OpenParenthesisTkn: $2, - Uses: $3.(*ast.ParserSeparatedList).Items, - SeparatorTkns: $3.(*ast.ParserSeparatedList).SeparatorTkns, - CloseParenthesisTkn: $4, + $$ = &ast.ExprClosure{ + UseTkn: $1, + UseOpenParenthesisTkn: $2, + Use: $3.(*ast.ParserSeparatedList).Items, + UseSeparatorTkns: $3.(*ast.ParserSeparatedList).SeparatorTkns, + UseCloseParenthesisTkn: $4, } } ; @@ -3264,18 +3264,21 @@ lexical_var_list: lexical_var: T_VARIABLE { - $$ = &ast.ExprVariable{ + $$ = &ast.ExprClosureUse{ Position: yylex.(*Parser).builder.NewTokenPosition($1), - VarName: &ast.Identifier{ + Var: &ast.ExprVariable{ Position: yylex.(*Parser).builder.NewTokenPosition($1), - IdentifierTkn: $1, - Value: $1.Value, + VarName: &ast.Identifier{ + Position: yylex.(*Parser).builder.NewTokenPosition($1), + IdentifierTkn: $1, + Value: $1.Value, + }, }, } } | '&' T_VARIABLE { - $$ = &ast.ExprReference{ + $$ = &ast.ExprClosureUse{ Position: yylex.(*Parser).builder.NewTokensPosition($1, $2), AmpersandTkn: $1, Var: &ast.ExprVariable{ diff --git a/pkg/ast/node.go b/pkg/ast/node.go index 3e3e428..bb90d78 100644 --- a/pkg/ast/node.go +++ b/pkg/ast/node.go @@ -1274,20 +1274,24 @@ func (n *ExprClone) GetPosition() *position.Position { // ExprClosure node type ExprClosure struct { - Position *position.Position - StaticTkn *token.Token - FunctionTkn *token.Token - AmpersandTkn *token.Token - OpenParenthesisTkn *token.Token - Params []Vertex - SeparatorTkns []*token.Token - CloseParenthesisTkn *token.Token - ClosureUse Vertex - ColonTkn *token.Token - ReturnType Vertex - OpenCurlyBracketTkn *token.Token - Stmts []Vertex - CloseCurlyBracketTkn *token.Token + Position *position.Position + StaticTkn *token.Token + FunctionTkn *token.Token + AmpersandTkn *token.Token + OpenParenthesisTkn *token.Token + Params []Vertex + SeparatorTkns []*token.Token + CloseParenthesisTkn *token.Token + UseTkn *token.Token + UseOpenParenthesisTkn *token.Token + Use []Vertex + UseSeparatorTkns []*token.Token + UseCloseParenthesisTkn *token.Token + ColonTkn *token.Token + ReturnType Vertex + OpenCurlyBracketTkn *token.Token + Stmts []Vertex + CloseCurlyBracketTkn *token.Token } func (n *ExprClosure) Accept(v NodeVisitor) { @@ -1300,12 +1304,9 @@ func (n *ExprClosure) GetPosition() *position.Position { // ExprClosureUse node type ExprClosureUse struct { - Position *position.Position - UseTkn *token.Token - OpenParenthesisTkn *token.Token - Uses []Vertex - SeparatorTkns []*token.Token - CloseParenthesisTkn *token.Token + Position *position.Position + AmpersandTkn *token.Token + Var Vertex } func (n *ExprClosureUse) Accept(v NodeVisitor) { diff --git a/pkg/ast/traverser/dfs.go b/pkg/ast/traverser/dfs.go index f980c7f..5c8f792 100644 --- a/pkg/ast/traverser/dfs.go +++ b/pkg/ast/traverser/dfs.go @@ -1152,10 +1152,12 @@ func (t *DFS) Traverse(n ast.Vertex) { } t.visitor.Leave("Params", false) } - if nn.ClosureUse != nil { - t.visitor.Enter("ClosureUse", true) - t.Traverse(nn.ClosureUse) - t.visitor.Leave("ClosureUse", true) + if nn.Use != nil { + t.visitor.Enter("Use", false) + for _, c := range nn.Use { + t.Traverse(c) + } + t.visitor.Leave("Use", false) } if nn.ReturnType != nil { t.visitor.Enter("ReturnType", true) @@ -1176,12 +1178,10 @@ func (t *DFS) Traverse(n ast.Vertex) { if !t.visitor.EnterNode(nn) { return } - if nn.Uses != nil { - t.visitor.Enter("Uses", false) - for _, c := range nn.Uses { - t.Traverse(c) - } - t.visitor.Leave("Uses", false) + if nn.Var != nil { + t.visitor.Enter("Var", true) + t.Traverse(nn.Var) + t.visitor.Leave("Var", true) } case *ast.ExprConstFetch: if nn == nil { diff --git a/pkg/ast/visitor/dumper.go b/pkg/ast/visitor/dumper.go index c086d47..6bc24c3 100644 --- a/pkg/ast/visitor/dumper.go +++ b/pkg/ast/visitor/dumper.go @@ -1143,7 +1143,11 @@ func (v *Dumper) ExprClosure(n *ast.ExprClosure) { v.dumpVertexList("Params", n.Params) v.dumpTokenList("SeparatorTkns", n.SeparatorTkns) v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn) - v.dumpVertex("ClosureUse", n.ClosureUse) + v.dumpToken("UseTkn", n.UseTkn) + v.dumpToken("UseOpenParenthesisTkn", n.UseOpenParenthesisTkn) + v.dumpVertexList("Use", n.Use) + v.dumpTokenList("UseSeparatorTkns", n.UseSeparatorTkns) + v.dumpToken("UseCloseParenthesisTkn", n.UseCloseParenthesisTkn) v.dumpToken("ColonTkn", n.ColonTkn) v.dumpVertex("ReturnType", n.ReturnType) v.dumpToken("OpenCurlyBracketTkn", n.OpenCurlyBracketTkn) @@ -1159,11 +1163,8 @@ func (v *Dumper) ExprClosureUse(n *ast.ExprClosureUse) { v.indent++ v.dumpPosition(n.Position) - v.dumpToken("UseTkn", n.UseTkn) - v.dumpToken("OpenParenthesisTkn", n.OpenParenthesisTkn) - v.dumpVertexList("Uses", n.Uses) - v.dumpTokenList("SeparatorTkns", n.SeparatorTkns) - v.dumpToken("CloseParenthesisTkn", n.CloseParenthesisTkn) + v.dumpToken("AmpersandTkn", n.AmpersandTkn) + v.dumpVertex("Var", n.Var) v.indent-- v.print(v.indent, "},\n") diff --git a/pkg/ast/visitor/formatter.go b/pkg/ast/visitor/formatter.go index 5d2d202..9484b66 100644 --- a/pkg/ast/visitor/formatter.go +++ b/pkg/ast/visitor/formatter.go @@ -1162,9 +1162,16 @@ func (f *formatter) ExprClosure(n *ast.ExprClosure) { } n.CloseParenthesisTkn = f.newToken(')', []byte(")")) - if n.ClosureUse != nil { + n.UseTkn = nil + n.UseOpenParenthesisTkn = nil + n.UseCloseParenthesisTkn = nil + n.UseSeparatorTkns = nil + if len(n.Use) > 0 { f.addFreeFloating(token.T_WHITESPACE, []byte(" ")) - n.ClosureUse.Accept(f) + n.UseTkn = f.newToken(token.T_USE, []byte("use")) + n.OpenParenthesisTkn = f.newToken('(', []byte("(")) + n.SeparatorTkns = f.formatList(n.Use, ',') + n.CloseParenthesisTkn = f.newToken(')', []byte(")")) } n.ColonTkn = nil @@ -1189,10 +1196,11 @@ func (f *formatter) ExprClosure(n *ast.ExprClosure) { } func (f *formatter) ExprClosureUse(n *ast.ExprClosureUse) { - n.UseTkn = f.newToken(token.T_USE, []byte("use")) - n.OpenParenthesisTkn = f.newToken('(', []byte("(")) - n.SeparatorTkns = f.formatList(n.Uses, ',') - n.CloseParenthesisTkn = f.newToken(')', []byte(")")) + if n.AmpersandTkn != nil { + n.AmpersandTkn = f.newToken('&', []byte("&")) + } + + n.Var.Accept(f) } func (f *formatter) ExprConstFetch(n *ast.ExprConstFetch) { diff --git a/pkg/ast/visitor/formatter_test.go b/pkg/ast/visitor/formatter_test.go index ee8637b..b917aea 100644 --- a/pkg/ast/visitor/formatter_test.go +++ b/pkg/ast/visitor/formatter_test.go @@ -3714,9 +3714,9 @@ func TestFormatter_ExprClosure_Use(t *testing.T) { o := bytes.NewBufferString("") n := &ast.ExprClosure{ - ClosureUse: &ast.ExprClosureUse{ - Uses: []ast.Vertex{ - &ast.ExprVariable{ + Use: []ast.Vertex{ + &ast.ExprClosureUse{ + Var: &ast.ExprVariable{ VarName: &ast.Identifier{ Value: []byte("$foo"), }, @@ -3748,16 +3748,9 @@ func TestFormatter_ExprClosureUse(t *testing.T) { o := bytes.NewBufferString("") n := &ast.ExprClosureUse{ - Uses: []ast.Vertex{ - &ast.ExprVariable{ - VarName: &ast.Identifier{ - Value: []byte("$a"), - }, - }, - &ast.ExprVariable{ - VarName: &ast.Identifier{ - Value: []byte("$b"), - }, + Var: &ast.ExprVariable{ + VarName: &ast.Identifier{ + Value: []byte("$a"), }, }, } @@ -3768,7 +3761,33 @@ func TestFormatter_ExprClosureUse(t *testing.T) { p := visitor.NewPrinter(o).WithState(visitor.PrinterStatePHP) n.Accept(p) - expected := `use($a, $b)` + expected := `$a` + actual := o.String() + + if expected != actual { + t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual) + } +} + +func TestFormatter_ExprClosureUse_Reference(t *testing.T) { + o := bytes.NewBufferString("") + + n := &ast.ExprClosureUse{ + AmpersandTkn: &token.Token{}, + Var: &ast.ExprVariable{ + VarName: &ast.Identifier{ + Value: []byte("$a"), + }, + }, + } + + f := visitor.NewFormatter().WithState(visitor.FormatterStatePHP).WithIndent(1) + n.Accept(f) + + p := visitor.NewPrinter(o).WithState(visitor.PrinterStatePHP) + n.Accept(p) + + expected := `&$a` actual := o.String() if expected != actual { diff --git a/pkg/ast/visitor/namespace_resolver_test.go b/pkg/ast/visitor/namespace_resolver_test.go index f42f11e..8a8bb14 100644 --- a/pkg/ast/visitor/namespace_resolver_test.go +++ b/pkg/ast/visitor/namespace_resolver_test.go @@ -562,7 +562,6 @@ func TestResolveClosureName(t *testing.T) { Var: &ast.ExprVariable{VarName: &ast.Identifier{Value: []byte("foo")}}, }, }, - ClosureUse: nil, ReturnType: &ast.Nullable{Expr: nameBC}, Stmts: []ast.Vertex{}, } diff --git a/pkg/ast/visitor/printer.go b/pkg/ast/visitor/printer.go index 255ffe9..8802a43 100644 --- a/pkg/ast/visitor/printer.go +++ b/pkg/ast/visitor/printer.go @@ -684,7 +684,10 @@ func (p *printer) ExprClosure(n *ast.ExprClosure) { p.printToken(n.OpenParenthesisTkn, []byte("(")) p.printSeparatedList(n.Params, n.SeparatorTkns, []byte(",")) p.printToken(n.CloseParenthesisTkn, []byte(")")) - p.printNode(n.ClosureUse) + p.printToken(n.UseTkn, p.ifNodeList(n.Use, []byte("use"))) + p.printToken(n.UseOpenParenthesisTkn, p.ifNodeList(n.Use, []byte("("))) + p.printSeparatedList(n.Use, n.UseSeparatorTkns, []byte(",")) + p.printToken(n.UseCloseParenthesisTkn, p.ifNodeList(n.Use, []byte(")"))) p.printToken(n.ColonTkn, p.ifNode(n.ReturnType, []byte(":"))) p.printNode(n.ReturnType) p.printToken(n.OpenCurlyBracketTkn, []byte("{")) @@ -693,10 +696,8 @@ func (p *printer) ExprClosure(n *ast.ExprClosure) { } func (p *printer) ExprClosureUse(n *ast.ExprClosureUse) { - p.printToken(n.UseTkn, []byte("use")) - p.printToken(n.OpenParenthesisTkn, []byte("(")) - p.printSeparatedList(n.Uses, n.SeparatorTkns, []byte(",")) - p.printToken(n.CloseParenthesisTkn, []byte(")")) + p.printToken(n.AmpersandTkn, nil) + p.printNode(n.Var) } func (p *printer) ExprConstFetch(n *ast.ExprConstFetch) { diff --git a/pkg/ast/visitor/printer_test.go b/pkg/ast/visitor/printer_test.go index d918f0a..571f51e 100644 --- a/pkg/ast/visitor/printer_test.go +++ b/pkg/ast/visitor/printer_test.go @@ -1717,18 +1717,35 @@ func TestPrinterPrintExprClosureUse(t *testing.T) { p := visitor.NewPrinter(o).WithState(visitor.PrinterStatePHP) n := &ast.ExprClosureUse{ - Uses: []ast.Vertex{ - &ast.ExprReference{Var: &ast.ExprVariable{ - VarName: &ast.Identifier{Value: []byte("$foo")}, - }}, - &ast.ExprVariable{ - VarName: &ast.Identifier{Value: []byte("$bar")}, - }, + Var: &ast.ExprVariable{ + VarName: &ast.Identifier{Value: []byte("$foo")}, }, } n.Accept(p) - expected := `use(&$foo,$bar)` + expected := `$foo` + actual := o.String() + + if expected != actual { + t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual) + } +} + +func TestPrinterPrintExprClosureUse_Reference(t *testing.T) { + o := bytes.NewBufferString("") + + p := visitor.NewPrinter(o).WithState(visitor.PrinterStatePHP) + n := &ast.ExprClosureUse{ + AmpersandTkn: &token.Token{ + Value: []byte("&"), + }, + Var: &ast.ExprVariable{ + VarName: &ast.Identifier{Value: []byte("$foo")}, + }, + } + n.Accept(p) + + expected := `&$foo` actual := o.String() if expected != actual { @@ -1754,12 +1771,17 @@ func TestPrinterPrintExprClosure(t *testing.T) { }, }, }, - ClosureUse: &ast.ExprClosureUse{ - Uses: []ast.Vertex{ - &ast.ExprReference{Var: &ast.ExprVariable{ + Use: []ast.Vertex{ + &ast.ExprClosureUse{ + AmpersandTkn: &token.Token{ + Value: []byte("&"), + }, + Var: &ast.ExprVariable{ VarName: &ast.Identifier{Value: []byte("$a")}, - }}, - &ast.ExprVariable{ + }, + }, + &ast.ExprClosureUse{ + Var: &ast.ExprVariable{ VarName: &ast.Identifier{Value: []byte("$b")}, }, },