package printer_test
import (
	"bytes"
	"testing"
	"github.com/z7zmey/php-parser/meta"
	"github.com/z7zmey/php-parser/node"
	"github.com/z7zmey/php-parser/node/expr"
	"github.com/z7zmey/php-parser/node/expr/assign"
	"github.com/z7zmey/php-parser/node/expr/binary"
	"github.com/z7zmey/php-parser/node/expr/cast"
	"github.com/z7zmey/php-parser/node/name"
	"github.com/z7zmey/php-parser/node/scalar"
	"github.com/z7zmey/php-parser/node/stmt"
	"github.com/z7zmey/php-parser/printer"
)
func TestPrinterPrintFile(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&node.Root{
		Stmts: []node.Node{
			&stmt.Namespace{
				NamespaceName: &name.Name{
					Parts: []node.Node{
						&name.NamePart{Value: "Foo"},
					},
				},
			},
			&stmt.Class{
				Modifiers: []node.Node{&node.Identifier{Value: "abstract"}},
				ClassName: &name.Name{
					Parts: []node.Node{
						&name.NamePart{Value: "Bar"},
					},
				},
				Extends: &stmt.ClassExtends{
					ClassName: &name.Name{
						Parts: []node.Node{
							&name.NamePart{Value: "Baz"},
						},
					},
				},
				Stmts: []node.Node{
					&stmt.ClassMethod{
						Modifiers:  []node.Node{&node.Identifier{Value: "public"}},
						MethodName: &node.Identifier{Value: "greet"},
						Stmt: &stmt.StmtList{
							Stmts: []node.Node{
								&stmt.Echo{
									Exprs: []node.Node{
										&scalar.String{Value: "'Hello world'"},
									},
								},
							},
						},
					},
				},
			},
		},
	})
	expected := `HTML"},
			&stmt.Expression{
				Expr: &expr.Variable{
					VarName: &node.Identifier{
						Value: "a",
					},
				},
			},
		},
	})
	expected := `
HTML
>=$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
// binary
func TestPrinterPrintBinaryBitwiseAnd(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.BitwiseAnd{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AmpersandToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a &$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryBitwiseOr(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.BitwiseOr{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.VerticalBarToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a |$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryBitwiseXor(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.BitwiseXor{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaretToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a ^$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryBooleanAnd(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.BooleanAnd{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.BooleanAndToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a &&$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryBooleanOr(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.BooleanOr{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.BooleanOrToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a ||$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryCoalesce(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Coalesce{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CoalesceToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a ??$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryConcat(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Concat{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DotToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a .$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryDiv(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Div{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SlashToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a /$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryEqual(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Equal{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IsEqualToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a ==$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryGreaterOrEqual(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.GreaterOrEqual{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IsGreaterOrEqualToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a >=$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryGreater(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Greater{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.GreaterToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a >$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryIdentical(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Identical{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IsIdenticalToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a ===$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryLogicalAnd(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.LogicalAnd{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.LogicalAndToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a and$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryLogicalOr(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.LogicalOr{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.LogicalOrToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a or$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryLogicalXor(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.LogicalXor{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.LogicalXorToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a xor$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryMinus(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Minus{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.MinusToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a -$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryMod(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Mod{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PercentToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a %$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryMul(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Mul{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AsteriskToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a *$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryNotEqual(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.NotEqual{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IsNotEqualToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a !=$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryNotIdentical(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.NotIdentical{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IsNotIdenticalToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a !==$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryPlus(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Plus{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PlusToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a +$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryPow(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Pow{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PowToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a **$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryShiftLeft(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.ShiftLeft{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SlToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a <<$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinaryShiftRight(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.ShiftRight{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SrToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a >>$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinarySmallerOrEqual(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.SmallerOrEqual{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IsSmallerOrEqualToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a <=$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinarySmaller(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Smaller{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.LessToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a <$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBinarySpaceship(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&binary.Spaceship{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SpaceshipToken,
			},
		},
		Left:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Right: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a <=>$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
// cast
func TestPrinterPrintArray(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.Array{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ArrayCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (array)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintBool(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.Bool{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.BoolCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (bool)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintDouble(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.Double{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoubleCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (float)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintInt(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.Int{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IntCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (int)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintObject(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.Object{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ObjectCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (object)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintString(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.String{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.StringCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (string)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintUnset(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&cast.Unset{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.UnsetCastToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` (unset)$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
// expr
func TestPrinterPrintExprArrayDimFetch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ArrayDimFetch{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenSquareBracket,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseSquareBracket,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
		Dim:      &scalar.Lnumber{Value: "1"},
	})
	expected := `$var [1 ]`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprArrayItemWithKey(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ArrayItem{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoubleArrowToken,
			},
		},
		Key: &scalar.String{Value: "'Hello'"},
		Val: &expr.Variable{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.VariableToken,
				},
			},
			VarName: &node.Identifier{Value: "world"},
		},
	})
	expected := `'Hello' => $world`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprArrayItem(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ArrayItem{
		Val: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "world"}}},
	})
	expected := `&$world`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprArray(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Array{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ArrayToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Items: []node.Node{
			&expr.ArrayItem{
				Key: &scalar.String{Value: "'Hello'"},
				Val: &expr.Variable{VarName: &node.Identifier{Value: "world"}},
			},
			&expr.ArrayItem{
				Key: &scalar.Lnumber{Value: "2"},
				Val: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}}},
			},
			&expr.ArrayItem{
				Val: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
			},
		},
	})
	expected := ` array ('Hello'=>$world,2=>&$var,$var )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprBitwiseNot(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.BitwiseNot{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.TildeToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` ~$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprBooleanNot(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.BooleanNot{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ExclamationMarkToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` !$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprClassConstFetch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ClassConstFetch{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PaamayimNekudotayimToken,
			},
		},
		Class: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
		ConstantName: &node.Identifier{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.IdentifierToken,
				},
			},
			Value: "CONST",
		},
	})
	expected := `$var :: CONST`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprClone(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Clone{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloneToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` clone$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprClosureUse(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ClosureUse{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.UseToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Uses: []node.Node{
			&expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "foo"}}},
			&expr.Variable{VarName: &node.Identifier{Value: "bar"}},
		},
	})
	expected := ` use (&$foo,$bar )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprClosure(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Closure{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.StaticToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.FunctionToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AmpersandToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
		},
		Static:     true,
		ReturnsRef: true,
		Params: []node.Node{
			&node.Parameter{
				ByRef:    true,
				Variadic: false,
				Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
			},
		},
		ClosureUse: &expr.ClosureUse{
			Uses: []node.Node{
				&expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
				&expr.Variable{VarName: &node.Identifier{Value: "b"}},
			},
		},
		ReturnType: &name.FullyQualified{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ColonToken,
				},
			},
			Parts: []node.Node{&name.NamePart{Value: "Foo"}},
		},
		Stmts: []node.Node{
			&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
		},
	})
	expected := ` static function & (&$var )use(&$a,$b) :\Foo {$a; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprConstFetch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ConstFetch{
		Constant: &name.Name{Parts: []node.Node{&name.NamePart{Value: "null"}}},
	})
	expected := "null"
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintDie(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Die{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ExitToken,
			},
		},
		Expr: &expr.Variable{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			VarName: &node.Identifier{Value: "var"},
		},
	})
	expected := ` die ($var )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintEmpty(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Empty{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EmptyToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` empty ($var )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrettyPrinterrorSuppress(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ErrorSuppress{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AtToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` @$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintEval(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Eval{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EvalToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` eval ($var )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExit(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Exit{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ExitToken,
			},
		},
		Expr: &expr.Variable{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			VarName: &node.Identifier{Value: "var"},
		},
	})
	expected := ` exit ($var )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintFunctionCall(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.FunctionCall{
		Function: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
		ArgumentList: &node.ArgumentList{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Arguments: []node.Node{
				&node.Argument{
					IsReference: true,
					Expr:        &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				},
				&node.Argument{
					Variadic: true,
					Expr:     &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				},
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "c"}},
				},
			},
		},
	})
	expected := `$var (&$a,...$b,$c )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintInclude(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Include{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IncludeToken,
			},
		},
		Expr: &scalar.String{Value: "'path'"},
	})
	expected := ` include'path'`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintIncludeOnce(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.IncludeOnce{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IncludeOnceToken,
			},
		}, Expr: &scalar.String{Value: "'path'"},
	})
	expected := ` include_once'path'`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintInstanceOf(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.InstanceOf{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.InstanceofToken,
			},
		},
		Expr:  &expr.Variable{VarName: &node.Identifier{Value: "var"}},
		Class: &name.Name{Parts: []node.Node{&name.NamePart{Value: "Foo"}}},
	})
	expected := `$var instanceofFoo`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintIsset(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Isset{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IssetToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Variables: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "a"}},
			&expr.Variable{VarName: &node.Identifier{Value: "b"}},
		},
	})
	expected := ` isset ($a,$b )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintList(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.List{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ListToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Items: []node.Node{
			&expr.ArrayItem{
				Val: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
			},
			&expr.ArrayItem{
				Val: &expr.List{
					Items: []node.Node{
						&expr.ArrayItem{
							Val: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
						},
						&expr.ArrayItem{
							Val: &expr.Variable{VarName: &node.Identifier{Value: "c"}},
						},
					},
				},
			},
		},
	})
	expected := ` list ($a,list($b,$c) )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintMethodCall(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.MethodCall{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ObjectOperatorToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "foo"}},
		Method:   &node.Identifier{Value: "bar"},
		ArgumentList: &node.ArgumentList{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Arguments: []node.Node{
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				},
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				},
			},
		},
	})
	expected := `$foo ->bar ($a,$b )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintNew(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.New{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.NewToken,
			},
		},
		Class: &name.Name{
			Parts: []node.Node{
				&name.NamePart{
					Meta: []meta.Meta{
						&meta.WhiteSpace{
							Value:     " ",
							TokenName: meta.StringToken,
						},
					},
					Value: "Foo",
				},
			},
		},
		ArgumentList: &node.ArgumentList{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Arguments: []node.Node{
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				},
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				},
			},
		},
	})
	expected := ` new Foo ($a,$b )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintPostDec(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.PostDec{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DecToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := `$var --`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintPostInc(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.PostInc{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IncToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := `$var ++`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintPreDec(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.PreDec{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DecToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` --$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintPreInc(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.PreInc{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IncToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` ++$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintPrint(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Print{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PrintToken,
			},
		},
		Expr: &expr.Variable{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			VarName: &node.Identifier{Value: "var"},
		},
	})
	expected := ` print ($var )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintPropertyFetch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.PropertyFetch{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ObjectOperatorToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "foo"}},
		Property: &node.Identifier{Value: "bar"},
	})
	expected := `$foo ->bar`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprReference(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Reference{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AmpersandToken,
			},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "foo"}},
	})
	expected := ` &$foo`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintRequire(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Require{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.RequireToken,
			},
		},
		Expr: &scalar.String{Value: "'path'"},
	})
	expected := ` require'path'`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintRequireOnce(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.RequireOnce{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.RequireOnceToken,
			},
		},
		Expr: &scalar.String{Value: "'path'"},
	})
	expected := ` require_once'path'`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintShellExec(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ShellExec{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.BackquoteToken,
			},
		},
		Parts: []node.Node{
			&scalar.EncapsedStringPart{Value: "hello "},
			&expr.Variable{VarName: &node.Identifier{Value: "world"}},
			&scalar.EncapsedStringPart{Value: "!"},
		},
	})
	expected := " `hello $world!`"
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExprShortArray(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ShortArray{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenSquareBracket,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseSquareBracket,
			},
		},
		Items: []node.Node{
			&expr.ArrayItem{
				Key: &scalar.String{Value: "'Hello'"},
				Val: &expr.Variable{VarName: &node.Identifier{Value: "world"}},
			},
			&expr.ArrayItem{
				Key: &scalar.Lnumber{Value: "2"},
				Val: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}}},
			},
			&expr.ArrayItem{
				Val: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
			},
		},
	})
	expected := ` ['Hello'=>$world,2=>&$var,$var ]`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintShortList(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.ShortList{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenSquareBracket,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseSquareBracket,
			},
		},
		Items: []node.Node{
			&expr.ArrayItem{
				Val: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
			},
			&expr.ArrayItem{
				Val: &expr.List{
					Items: []node.Node{
						&expr.ArrayItem{
							Val: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
						},
						&expr.ArrayItem{
							Val: &expr.Variable{VarName: &node.Identifier{Value: "c"}},
						},
					},
				},
			},
		},
	})
	expected := ` [$a,list($b,$c) ]`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStaticCall(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.StaticCall{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PaamayimNekudotayimToken,
			},
		},
		Class: &node.Identifier{Value: "Foo"},
		Call:  &node.Identifier{Value: "bar"},
		ArgumentList: &node.ArgumentList{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Arguments: []node.Node{
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				},
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				},
			},
		},
	})
	expected := `Foo ::bar ($a,$b )`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStaticPropertyFetch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.StaticPropertyFetch{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PaamayimNekudotayimToken,
			},
		},
		Class:    &node.Identifier{Value: "Foo"},
		Property: &expr.Variable{VarName: &node.Identifier{Value: "bar"}},
	})
	expected := `Foo ::$bar`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintTernary(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Ternary{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.QuestionMarkToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
		},
		Condition: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		IfFalse:   &expr.Variable{VarName: &node.Identifier{Value: "b"}},
	})
	expected := `$a ? :$b`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintTernaryFull(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Ternary{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.QuestionMarkToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
		},
		Condition: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		IfTrue:    &expr.Variable{VarName: &node.Identifier{Value: "b"}},
		IfFalse:   &expr.Variable{VarName: &node.Identifier{Value: "c"}},
	})
	expected := `$a ?$b :$c`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintUnaryMinus(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.UnaryMinus{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.MinusToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` -$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintUnaryPlus(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.UnaryPlus{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.PlusToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` +$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintVariable(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Variable{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.VariableToken,
			},
		},
		VarName: &expr.Variable{
			VarName: &node.Identifier{Value: "var"},
		},
	})
	expected := ` $$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintYieldFrom(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.YieldFrom{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.YieldFromToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` yield from$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintYield(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Yield{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.YieldToken,
			},
		},
		Value: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` yield$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintYieldFull(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&expr.Yield{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.YieldToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoubleArrowToken,
			},
		},
		Key:   &expr.Variable{VarName: &node.Identifier{Value: "k"}},
		Value: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
	})
	expected := ` yield$k =>$var`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
// stmt
func TestPrinterPrintAltElseIf(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltElseIf{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseifToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
			},
		},
	})
	expected := ` elseif ($a ) :$b;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltElseIfEmpty(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltElseIf{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseifToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.StmtList{},
	})
	expected := ` elseif ($a ) :`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltElse(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltElse{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
		},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
			},
		},
	})
	expected := ` else :$b;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltElseEmpty(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltElse{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
		},
		Stmt: &stmt.StmtList{},
	})
	expected := ` else :`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltFor(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltFor{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForInitSemicolonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForCondSemicolonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EndforToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Init: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "a"}},
		},
		Cond: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "b"}},
		},
		Loop: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "c"}},
		},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
			},
		},
	})
	expected := ` for ($a ;$b ;$c ) :$d; endfor ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltForeach(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltForeach{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForeachToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AsToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoubleArrowToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EndforeachToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Expr:     &expr.Variable{VarName: &node.Identifier{Value: "var"}},
		Key:      &expr.Variable{VarName: &node.Identifier{Value: "key"}},
		Variable: &expr.Reference{Variable: &expr.Variable{VarName: &node.Identifier{Value: "val"}}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
			},
		},
	})
	expected := ` foreach ($var as$key =>&$val ) :$d; endforeach ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltIf(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltIf{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IfToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EndifToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}}},
			},
		},
		ElseIf: []node.Node{
			&stmt.AltElseIf{
				Cond: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				Stmt: &stmt.StmtList{
					Stmts: []node.Node{
						&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
					},
				},
			},
			&stmt.AltElseIf{
				Cond: &expr.Variable{VarName: &node.Identifier{Value: "c"}},
				Stmt: &stmt.StmtList{},
			},
		},
		Else: &stmt.AltElse{
			Stmt: &stmt.StmtList{
				Stmts: []node.Node{
					&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
				},
			},
		},
	})
	expected := ` if ($a ) :$d;elseif($b):$b;elseif($c):else:$b; endif ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtAltSwitch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltSwitch{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SwitchToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SwitchSemicolonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EndswitchToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
		CaseList: &stmt.CaseList{
			Cases: []node.Node{
				&stmt.Case{
					Cond: &scalar.String{Value: "'a'"},
					Stmts: []node.Node{
						&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
					},
				},
				&stmt.Case{
					Cond: &scalar.String{Value: "'b'"},
					Stmts: []node.Node{
						&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
					},
				},
			},
		},
	})
	expected := ` switch ($var ) : ;case'a':$a;case'b':$b; endswitch ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintAltWhile(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.AltWhile{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.WhileToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ColonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EndwhileToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}}},
			},
		},
	})
	expected := ` while ($a ) :$b; endwhile ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtBreak(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Break{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.BreakToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Expr: &scalar.Lnumber{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Value: "1",
		},
	})
	expected := " break (1 ) ;"
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtCase(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Case{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaseToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaseSeparatorToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmts: []node.Node{
			&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
		},
	})
	expected := ` case$a :$a;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtCaseEmpty(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Case{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaseToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaseSeparatorToken,
			},
		},
		Cond:  &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmts: []node.Node{},
	})
	expected := " case$a :"
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtCatch(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Catch{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CatchToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
		},
		Types: []node.Node{
			&name.Name{Parts: []node.Node{&name.NamePart{Value: "Exception"}}},
			&name.FullyQualified{Parts: []node.Node{&name.NamePart{Value: "RuntimeException"}}},
		},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "e"}},
		Stmts: []node.Node{
			&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
		},
	})
	expected := ` catch (Exception|\RuntimeException$e ) {$a; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtClassMethod(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.ClassMethod{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.FunctionToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AmpersandToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Modifiers:  []node.Node{&node.Identifier{Value: "public"}},
		ReturnsRef: true,
		MethodName: &node.Identifier{Value: "foo"},
		Params: []node.Node{
			&node.Parameter{
				ByRef:        true,
				VariableType: &node.Nullable{Expr: &name.Name{Parts: []node.Node{&name.NamePart{Value: "int"}}}},
				Variable:     &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				DefaultValue: &expr.ConstFetch{Constant: &name.Name{Parts: []node.Node{&name.NamePart{Value: "null"}}}},
			},
			&node.Parameter{
				Variadic: true,
				Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
			},
		},
		ReturnType: &name.Name{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ColonToken,
				},
			},
			Parts: []node.Node{&name.NamePart{Value: "void"}},
		},
		Stmt: &stmt.StmtList{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenCurlyBracesToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseCurlyBracesToken,
				},
			},
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
			},
		},
	})
	expected := `public function &foo (?int&$a=null,...$b ) :void {$a; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtAbstractClassMethod(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.ClassMethod{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.FunctionToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AmpersandToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Modifiers:  []node.Node{&node.Identifier{Value: "public"}},
		ReturnsRef: true,
		MethodName: &node.Identifier{Value: "foo"},
		Params: []node.Node{
			&node.Parameter{
				ByRef:        true,
				VariableType: &node.Nullable{Expr: &name.Name{Parts: []node.Node{&name.NamePart{Value: "int"}}}},
				Variable:     &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				DefaultValue: &expr.ConstFetch{Constant: &name.Name{Parts: []node.Node{&name.NamePart{Value: "null"}}}},
			},
			&node.Parameter{
				Variadic: true,
				Variable: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
			},
		},
		ReturnType: &name.Name{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ColonToken,
				},
			},
			Parts: []node.Node{&name.NamePart{Value: "void"}},
		},
		Stmt: &stmt.Nop{},
	})
	expected := `public function &foo (?int&$a=null,...$b ) :void;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtClass(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Class{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ClassToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
		},
		Modifiers: []node.Node{&node.Identifier{Value: "abstract"}},
		ClassName: &node.Identifier{Value: "Foo"},
		Extends: &stmt.ClassExtends{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ExtendsToken,
				},
			},
			ClassName: &name.Name{Parts: []node.Node{&name.NamePart{Value: "Bar"}}},
		},
		Implements: &stmt.ClassImplements{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ImplementsToken,
				},
			},
			InterfaceNames: []node.Node{
				&name.Name{Parts: []node.Node{&name.NamePart{Value: "Baz"}}},
				&name.Name{Parts: []node.Node{&name.NamePart{Value: "Quuz"}}},
			},
		},
		Stmts: []node.Node{
			&stmt.ClassConstList{
				Modifiers: []node.Node{&node.Identifier{Value: "public"}},
				Consts: []node.Node{
					&stmt.Constant{
						ConstantName: &node.Identifier{Value: "FOO"},
						Expr:         &scalar.String{Value: "'bar'"},
					},
				},
			},
		},
	})
	expected := `abstract classFoo extendsBar implementsBaz,Quuz {publicconstFOO='bar'; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtAnonymousClass(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Class{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ClassToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
		},
		Modifiers: []node.Node{&node.Identifier{Value: "abstract"}},
		ArgumentList: &node.ArgumentList{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Arguments: []node.Node{
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
				},
				&node.Argument{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				},
			},
		},
		Extends: &stmt.ClassExtends{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ExtendsToken,
				},
			},
			ClassName: &name.Name{Parts: []node.Node{&name.NamePart{Value: "Bar"}}},
		},
		Implements: &stmt.ClassImplements{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ImplementsToken,
				},
			},
			InterfaceNames: []node.Node{
				&name.Name{Parts: []node.Node{&name.NamePart{Value: "Baz"}}},
				&name.Name{Parts: []node.Node{&name.NamePart{Value: "Quuz"}}},
			},
		},
		Stmts: []node.Node{
			&stmt.ClassConstList{
				Modifiers: []node.Node{&node.Identifier{Value: "public"}},
				Consts: []node.Node{
					&stmt.Constant{
						ConstantName: &node.Identifier{Value: "FOO"},
						Expr:         &scalar.String{Value: "'bar'"},
					},
				},
			},
		},
	})
	expected := `abstract class ($a,$b ) extendsBar implementsBaz,Quuz {publicconstFOO='bar'; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtClassConstList(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.ClassConstList{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ConstToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Modifiers: []node.Node{&node.Identifier{Value: "public"}},
		Consts: []node.Node{
			&stmt.Constant{
				ConstantName: &node.Identifier{Value: "FOO"},
				Expr:         &scalar.String{Value: "'a'"},
			},
			&stmt.Constant{
				ConstantName: &node.Identifier{Value: "BAR"},
				Expr:         &scalar.String{Value: "'b'"},
			},
		},
	})
	expected := `public constFOO='a',BAR='b' ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtConstant(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Constant{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EqualToken,
			},
		},
		ConstantName: &node.Identifier{Value: "FOO"},
		Expr:         &scalar.String{Value: "'BAR'"},
	})
	expected := "FOO ='BAR'"
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtContinue(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Continue{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ContinueToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Expr: &scalar.Lnumber{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.OpenParenthesisToken,
				},
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.CloseParenthesisToken,
				},
			},
			Value: "1",
		},
	})
	expected := ` continue (1 ) ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDeclareStmts(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Declare{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DeclareToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Consts: []node.Node{
			&stmt.Constant{
				ConstantName: &node.Identifier{Value: "FOO"},
				Expr:         &scalar.String{Value: "'bar'"},
			},
		},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Nop{},
			},
		},
	})
	expected := ` declare (FOO='bar' ){;}`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDeclareExpr(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Declare{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DeclareToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Consts: []node.Node{
			&stmt.Constant{
				ConstantName: &node.Identifier{Value: "FOO"},
				Expr:         &scalar.String{Value: "'bar'"},
			},
		},
		Stmt: &stmt.Expression{Expr: &scalar.String{Value: "'bar'"}},
	})
	expected := ` declare (FOO='bar' )'bar';`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDeclareNop(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Declare{
		Consts: []node.Node{
			&stmt.Constant{
				ConstantName: &node.Identifier{Value: "FOO"},
				Expr:         &scalar.String{Value: "'bar'"},
			},
		},
		Stmt: &stmt.Nop{},
	})
	expected := `declare(FOO='bar');`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDefalut(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Default{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DefaultToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaseSeparatorToken,
			},
		},
		Stmts: []node.Node{
			&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
		},
	})
	expected := ` default :$a;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDefalutEmpty(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Default{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DefaultToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CaseSeparatorToken,
			},
		},
		Stmts: []node.Node{},
	})
	expected := ` default :`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDo_Expression(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Do{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.WhileToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Cond: &scalar.Lnumber{Value: "1"},
		Stmt: &stmt.Expression{
			Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		},
	})
	expected := ` do$a; while (1 ) ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtDo_StmtList(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Do{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.WhileToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Cond: &scalar.Lnumber{Value: "1"},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}}},
			},
		},
	})
	expected := ` do{$a;} while (1 ) ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtEcho(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Echo{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.EchoToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Exprs: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "a"}},
			&expr.Variable{VarName: &node.Identifier{Value: "b"}},
		},
	})
	expected := ` echo$a,$b ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtElseIfStmts(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.ElseIf{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseifToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Nop{},
			},
		},
	})
	expected := ` elseif ($a ){;}`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtElseIfExpr(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.ElseIf{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseifToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.Expression{Expr: &scalar.String{Value: "'bar'"}},
	})
	expected := ` elseif ($a )'bar';`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtElseIfNop(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.ElseIf{
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.Nop{},
	})
	expected := `elseif($a);`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtElseStmts(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Else{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseToken,
			},
		},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Nop{},
			},
		},
	})
	expected := ` else{;}`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtElseExpr(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Else{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ElseToken,
			},
		},
		Stmt: &stmt.Expression{Expr: &scalar.String{Value: "'bar'"}},
	})
	expected := ` else'bar';`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtElseNop(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Else{
		Stmt: &stmt.Nop{},
	})
	expected := `else;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintExpression(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Expression{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Expr: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
	})
	expected := `$a ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtFinally(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Finally{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.FinallyToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
		},
		Stmts: []node.Node{
			&stmt.Nop{},
		},
	})
	expected := ` finally {; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtFor(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.For{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForInitSemicolonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForCondSemicolonToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Init: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "a"}},
			&expr.Variable{VarName: &node.Identifier{Value: "b"}},
		},
		Cond: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "c"}},
			&expr.Variable{VarName: &node.Identifier{Value: "d"}},
		},
		Loop: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "e"}},
			&expr.Variable{VarName: &node.Identifier{Value: "f"}},
		},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Nop{},
			},
		},
	})
	expected := ` for ($a,$b ;$c,$d ;$e,$f ){;}`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtForeach(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Foreach{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.ForeachToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AsToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.DoubleArrowToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Expr:     &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Key:      &expr.Variable{VarName: &node.Identifier{Value: "k"}},
		Variable: &expr.Variable{VarName: &node.Identifier{Value: "v"}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Nop{},
			},
		},
	})
	expected := ` foreach ($a as$k =>$v ){;}`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtFunction(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Function{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.FunctionToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.AmpersandToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
		},
		ReturnsRef:   true,
		FunctionName: &node.Identifier{Value: "foo"},
		Params: []node.Node{
			&node.Parameter{
				ByRef:    true,
				Variadic: false,
				Variable: &expr.Variable{VarName: &node.Identifier{Value: "var"}},
			},
		},
		ReturnType: &name.FullyQualified{
			Meta: []meta.Meta{
				&meta.WhiteSpace{
					Value:     " ",
					TokenName: meta.ColonToken,
				},
			},
			Parts: []node.Node{&name.NamePart{Value: "Foo"}},
		},
		Stmts: []node.Node{
			&stmt.Nop{},
		},
	})
	expected := ` function &foo (&$var ) :\Foo {; }`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtGlobal(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Global{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.GlobalToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Vars: []node.Node{
			&expr.Variable{VarName: &node.Identifier{Value: "a"}},
			&expr.Variable{VarName: &node.Identifier{Value: "b"}},
		},
	})
	expected := ` global$a,$b ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtGoto(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.Goto{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.GotoToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		Label: &node.Identifier{Value: "FOO"},
	})
	expected := ` gotoFOO ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintStmtGroupUse(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.GroupUse{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.UseToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.NsSeparatorToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseCurlyBracesToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
		UseType: &node.Identifier{Value: "function"},
		Prefix:  &name.Name{Parts: []node.Node{&name.NamePart{Value: "Foo"}}},
		UseList: []node.Node{
			&stmt.Use{
				Use:   &name.Name{Parts: []node.Node{&name.NamePart{Value: "Bar"}}},
				Alias: &node.Identifier{Value: "Baz"},
			},
			&stmt.Use{
				Use: &name.Name{Parts: []node.Node{&name.NamePart{Value: "Quuz"}}},
			},
		},
	})
	expected := ` usefunctionFoo \ {BarasBaz,Quuz } ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintHaltCompiler(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.HaltCompiler{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.HaltCompilerToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.SemiColonToken,
			},
		},
	})
	expected := ` __halt_compiler ( ) ;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintIfExpression(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.If{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IfToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.Expression{
			Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
		},
		ElseIf: []node.Node{
			&stmt.ElseIf{
				Cond: &expr.Variable{VarName: &node.Identifier{Value: "c"}},
				Stmt: &stmt.StmtList{
					Stmts: []node.Node{
						&stmt.Expression{
							Expr: &expr.Variable{VarName: &node.Identifier{Value: "d"}},
						},
					},
				},
			},
			&stmt.ElseIf{
				Cond: &expr.Variable{VarName: &node.Identifier{Value: "e"}},
				Stmt: &stmt.Nop{},
			},
		},
		Else: &stmt.Else{
			Stmt: &stmt.Expression{
				Expr: &expr.Variable{VarName: &node.Identifier{Value: "f"}},
			},
		},
	})
	expected := ` if ($a )$b;elseif($c){$d;}elseif($e);else$f;`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintIfStmtList(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.If{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.IfToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.OpenParenthesisToken,
			},
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.CloseParenthesisToken,
			},
		},
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.StmtList{
			Stmts: []node.Node{
				&stmt.Expression{
					Expr: &expr.Variable{VarName: &node.Identifier{Value: "b"}},
				},
			},
		},
	})
	expected := ` if ($a ){$b;}`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintIfNop(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.If{
		Cond: &expr.Variable{VarName: &node.Identifier{Value: "a"}},
		Stmt: &stmt.Nop{},
	})
	expected := `if($a);`
	actual := o.String()
	if expected != actual {
		t.Errorf("\nexpected: %s\ngot: %s\n", expected, actual)
	}
}
func TestPrinterPrintInlineHtml(t *testing.T) {
	o := bytes.NewBufferString("")
	p := printer.NewPrinter(o)
	p.Print(&stmt.InlineHtml{
		Meta: []meta.Meta{
			&meta.WhiteSpace{
				Value:     " ",
				TokenName: meta.InlineHTMLToken,
			},
		},
		Value: "test",
	})
	expected := ` ?>test