diff --git a/blink/internal/fixer/rules/method_argument_space.go b/blink/internal/fixer/rules/method_argument_space.go index 64647f92c0..c0bdc238ac 100644 --- a/blink/internal/fixer/rules/method_argument_space.go +++ b/blink/internal/fixer/rules/method_argument_space.go @@ -702,7 +702,9 @@ func isCallOrDeclParen(s *tokens.Stream, open int) bool { case token.Ident, token.Variable: return true case token.Punct: - return t.Value == ")" || t.Value == "]" + // ")" and "]" end a prior call/subscript; "}" ends a dynamic name like + // "->{$method}(" or "${$var}(" + return t.Value == ")" || t.Value == "]" || t.Value == "}" case token.Keyword: lv := strings.ToLower(t.Value) // "class" matches an anonymous class constructor: `new class (...)`; diff --git a/blink/internal/fixer/rules/yoda_style.go b/blink/internal/fixer/rules/yoda_style.go index 1ada097e07..ad7f48db76 100644 --- a/blink/internal/fixer/rules/yoda_style.go +++ b/blink/internal/fixer/rules/yoda_style.go @@ -105,10 +105,31 @@ func yodaMirror(v string) string { return v } +// isInterpolatedString reports whether t is a double-quoted string that contains +// a variable interpolation, making it a runtime value rather than a constant. +func isInterpolatedString(t token.Token) bool { + if t.Kind != token.String || len(t.Value) == 0 || t.Value[0] != '"' { + return false + } + for i := 1; i < len(t.Value); i++ { + if t.Value[i] == '\\' { + i++ + continue + } + if t.Value[i] == '$' || (t.Value[i] == '{' && i+1 < len(t.Value) && t.Value[i+1] == '$') { + return true + } + } + return false +} + func isYodaLiteral(t token.Token) bool { switch t.Kind { - case token.Number, token.String: + case token.Number: return true + case token.String: + // a double-quoted string with interpolation ("...{$x}...") is not a constant + return !isInterpolatedString(t) case token.Ident: return true case token.Keyword: @@ -137,8 +158,9 @@ func (f YodaStyle) Fix(s *tokens.Stream) bool { if !ok || !isLeftBoundary(s, prevMeaningfulIndex(s, ls)) { continue } - // right must be a variable expression (not itself a constant), bounded - rs := nextSignificantIndex(s, i) + // right must be a variable expression (not itself a constant), bounded; + // skip a comment between the operator and the operand ("=== /* c */ $x") + rs := nextMeaningfulIndex(s, i) if rs < 0 { continue } @@ -169,7 +191,7 @@ func (f YodaStyle) Fix(s *tokens.Stream) bool { continue } // left must be a variable expression (not itself a constant), bounded - le := prevSignificantIndex(s, i) + le := prevMeaningfulIndex(s, i) if le < 0 { continue } @@ -180,6 +202,13 @@ func (f YodaStyle) Fix(s *tokens.Stream) bool { if ls == le && isYodaLiteral(s.At(ls)) { continue // both sides constant } + // a unary prefix ("!!$a", "@$a") is part of the operand; blink's primary + // start does not span it, so leave the comparison rather than swap only + // the variable and strand the prefix + if p := prevMeaningfulIndex(s, ls); p >= 0 && s.At(p).Kind == token.Punct && + (s.At(p).Value == "!" || s.At(p).Value == "@") { + continue + } if !isLeftBoundary(s, prevMeaningfulIndex(s, ls)) { continue } @@ -189,6 +218,22 @@ func (f YodaStyle) Fix(s *tokens.Stream) bool { if len(swaps) == 0 { return false } + // drop any swap whose operand span overlaps an earlier (inner) one; applying + // overlapping ranges would interleave tokens and corrupt the output + kept := swaps[:0:0] + for _, sw := range swaps { + overlaps := false + for _, k := range kept { + if sw.ls <= k.re && k.ls <= sw.re { + overlaps = true + break + } + } + if !overlaps { + kept = append(kept, sw) + } + } + swaps = kept for _, sw := range slices.Backward(swaps) { left := append([]token.Token(nil), s.Tokens()[sw.ls:sw.le+1]...) mid := append([]token.Token(nil), s.Tokens()[sw.le+1:sw.rs]...) @@ -208,7 +253,7 @@ func (f YodaStyle) Fix(s *tokens.Stream) bool { // before the comparison at op: a plain literal, signed number, empty array, // bare constant, or "Name::class". func leftLiteralOperand(s *tokens.Stream, op int) (int, int, bool) { - le := prevSignificantIndex(s, op) + le := prevMeaningfulIndex(s, op) if le < 0 { return 0, 0, false } @@ -278,6 +323,9 @@ func rightComparisonOperandEnd(s *tokens.Stream, rs int) int { if t.Kind == token.Whitespace || t.Kind == token.Comment || t.Kind == token.DocComment { continue } + if t.Kind == token.CloseTag { + return end // "?>" ends the operand; never pull the close tag in + } if t.Kind == token.Punct { switch t.Value { case "(", "[", "{": @@ -386,7 +434,9 @@ func isLeftBoundary(s *tokens.Stream, p int) bool { t := s.At(p) if t.Kind == token.Punct { switch t.Value { - case "(", "[", "{", ",", ";", "&&", "||", "?", "??", ":", "=", "!", "=>", ".": + // "." (concat) binds tighter than comparison, so an operand next to it is + // part of a larger concat expression, not a standalone comparison operand + case "(", "[", "{", ",", ";", "&&", "||", "?", "??", ":", "=", "!", "=>": return true } return false @@ -405,9 +455,12 @@ func isRightBoundary(s *tokens.Stream, j int) bool { return true } t := s.At(j) + if t.Kind == token.CloseTag { + return true + } if t.Kind == token.Punct { switch t.Value { - case ")", "]", "}", ";", ",", ":", "&&", "||", "?", "??", ".", "=>": + case ")", "]", "}", ";", ",", ":", "&&", "||", "?", "??", "=>": return true } return false @@ -425,7 +478,7 @@ func isRightBoundary(s *tokens.Stream, j int) bool { // just after the comparison at op: a plain literal, signed number, empty array, // bare constant, or "Name::class". It mirrors leftLiteralOperand. func yodaRightLiteralOperand(s *tokens.Stream, op int) (int, int, bool) { - rs := nextSignificantIndex(s, op) + rs := nextMeaningfulIndex(s, op) if rs < 0 { return 0, 0, false } diff --git a/blink/internal/fixer/rules/yoda_style_phpcsfixer_test.go b/blink/internal/fixer/rules/yoda_style_phpcsfixer_test.go new file mode 100644 index 0000000000..d2065b99c9 --- /dev/null +++ b/blink/internal/fixer/rules/yoda_style_phpcsfixer_test.go @@ -0,0 +1,487 @@ +package rules + +import "testing" + +// Cases ported from php-cs-fixer YodaStyleFixerTest. Documents parity; +// not all pass yet - blink is being changed to match. +func TestYodaStylePhpCsFixerCases(t *testing.T) { + cases := []struct { + name string + cfg map[string]any + input string + expected string + }{ + {"yoda#0", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, "array[$var]) === $a;", "array[$var]) === $a;"}, + {"yoda#65", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "array[$var]) === $a;", "array[$var]) === $a;"}, + {"yoda#66", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "array[$var]);", "array[$var]);"}, + {"yoda#67", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "array[$var]);", "array[$var]);"}, + {"yoda#68", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "getStuff() === $myVariable;", "getStuff() === $myVariable;"}, + {"yoda#73", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "getStuff() === $myVariable;", "getStuff() === $myVariable;"}, + {"yoda#74", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "getStuff();", "getStuff();"}, + {"yoda#75", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "getStuff();", "getStuff();"}, + {"yoda#76", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " 2;", " 2;"}, + {"yoda#81", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " 2;", " 2;"}, + {"yoda#82", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject1->{$index}+$b === \"\";", "myObject1->{$index}+$b === \"\";"}, + {"yoda#83", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myObject1->{$index}+$b === \"\";", "myObject1->{$index}+$b === \"\";"}, + {"yoda#84", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "$a === $foo->$b->$c;", "$a === $foo->$b->$c;"}, + {"yoda#91", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "$a === $foo->$b->$c;", "$a === $foo->$b->$c;"}, + {"yoda#92", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "1&&$c<=10;", "1&&$c<=10;"}, + {"yoda#129", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "1&&$c<=10;", "1&&$c<=10;"}, + {"yoda#130", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "", ""}, + {"yoda#133", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "", ""}, + {"yoda#134", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "", ""}, + {"yoda#135", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "", ""}, + {"yoda#136", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, "", ""}, + {"yoda#137", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": true}, "", ""}, + {"yoda#138", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myArray[$index] === \"\";", "myArray[$index];"}, + {"yoda#143", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myArray[$index];", "myArray[$index] === \"\";"}, + {"yoda#144", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myArray[$index]->/*1*//*2*//*3*/a === \"\";", "myArray[$index]->/*1*//*2*//*3*/a;"}, + {"yoda#145", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myArray[$index]->/*1*//*2*//*3*/a;", "myArray[$index]->/*1*//*2*//*3*/a === \"\";"}, + {"yoda#146", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myArray[$index]->a === \"\";", "myArray[$index]->a;"}, + {"yoda#147", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myArray[$index]->a;", "myArray[$index]->a === \"\";"}, + {"yoda#148", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject2-> {$index} === \"\";", "myObject2-> {$index};"}, + {"yoda#149", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myObject2-> {$index};", "myObject2-> {$index} === \"\";"}, + {"yoda#150", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject3->{$index}->a === \"\";", "myObject3->{$index}->a;"}, + {"yoda#151", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myObject3->{$index}->a;", "myObject3->{$index}->a === \"\";"}, + {"yoda#152", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject4->{$index}->{$index}->a === \"\";", "myObject4->{$index}->{$index}->a;"}, + {"yoda#153", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myObject4->{$index}->{$index}->a;", "myObject4->{$index}->{$index}->a === \"\";"}, + {"yoda#154", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject4->$index->a === \"\";", "myObject4->$index->a;"}, + {"yoda#155", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myObject4->$index->a;", "myObject4->$index->a === \"\";"}, + {"yoda#156", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "", ""}, + {"yoda#161", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "", ""}, + {"yoda#162", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "{$a === null ? \"a\" : \"b\"} === null;", "{null === $a ? \"a\" : \"b\"};"}, + {"yoda#165", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "{null === $a ? \"a\" : \"b\"};", "{$a === null ? \"a\" : \"b\"} === null;"}, + {"yoda#166", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "b === 0) : $b->a === 0;\n} else {\n if ($c === ($b === null)) {\n return $d === false;\n }\n}", "b) : 0 === $b->a;\n} else {\n if ($c === (null === $b)) {\n return false === $d;\n }\n}"}, + {"yoda#167", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "b) : 0 === $b->a;\n} else {\n if ($c === (null === $b)) {\n return false === $d;\n }\n}", "b === 0) : $b->a === 0;\n} else {\n if ($c === ($b === null)) {\n return $d === false;\n }\n}"}, + {"yoda#168", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "getStuff() === 2;", "getStuff();"}, + {"yoda#175", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "getStuff();", "getStuff() === 2;"}, + {"yoda#176", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject5->{$index}->/*1*//*2*/b === \"\";", "myObject5->{$index}->/*1*//*2*/b;"}, + {"yoda#177", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "myObject5->{$index}->/*1*//*2*/b;", "myObject5->{$index}->/*1*//*2*/b === \"\";"}, + {"yoda#178", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $value) {\n uniqid() !== false ? 1 : 2;\n }\n uniqid() !== false ? 1 : 2;\n }", " $value) {\n false !== uniqid() ? 1 : 2;\n }\n false !== uniqid() ? 1 : 2;\n }"}, + {"yoda#183", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $value) {\n false !== uniqid() ? 1 : 2;\n }\n false !== uniqid() ? 1 : 2;\n }", " $value) {\n uniqid() !== false ? 1 : 2;\n }\n uniqid() !== false ? 1 : 2;\n }"}, + {"yoda#184", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "array[$var]);", "array[$var]) === $a;"}, + {"yoda#187", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": true}, "array[$var]) === $a;", "array[$var]);"}, + {"yoda#188", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, "getStuff();", "getStuff() === $myVariable;"}, + {"yoda#189", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": true}, "getStuff() === $myVariable;", "getStuff();"}, + {"yoda#190", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, " 2;", " 2 === $k;"}, + {"yoda#209", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": true}, " 2 === $k;", " 2;"}, + {"yoda#210", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, "= 2;", "= 2 === $k;"}, + {"yoda#213", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": true}, "= 2 === $k;", "= 2;"}, + {"yoda#214", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, "> 2;", "> 2 === $k;"}, + {"yoda#219", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": true}, "> 2 === $k;", "> 2;"}, + {"yoda#220", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": true}, ">= $b === 4 ? 2 : 3;", ">= 4 === $b ? 2 : 3;"}, + {"yoda#287", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, ">= 4 === $b ? 2 : 3;", ">= $b === 4 ? 2 : 3;"}, + {"yoda#288", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, ">= 2;", ">= 2;"}, + {"yoda#327", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, ">= 2;", ">= 2;"}, + {"yoda#328", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $d;", " $d;"}, + {"yoda#339", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $d;", " $d;"}, + {"yoda#340", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $c === array(1) ? $b : $d;", " $c === array(1) ? $b : $d;"}, + {"yoda#367", map[string]any{"equal": false, "identical": false, "less_and_greater": false, "always_move_variable": false}, " $c === array(1) ? $b : $d;", " $c === array(1) ? $b : $d;"}, + {"yoda#368", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c) = $c === array(1) ? $b : $d;", " $a, \"b\" => $b, \"c\" => $c) = $c === array(1) ? $b : $d;"}, + {"yoda#369", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c) = $c === array(1) ? $b : $d;", " $a, \"b\" => $b, \"c\" => $c) = $c === array(1) ? $b : $d;"}, + {"yoda#370", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $x1, \"y\" => $y1), list(\"x\" => $x2, \"y\" => $y2)) = $points;", " $x1, \"y\" => $y1), list(\"x\" => $x2, \"y\" => $y2)) = $points;"}, + {"yoda#371", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $x1, \"y\" => $y1), list(\"x\" => $x2, \"y\" => $y2)) = $points;", " $x1, \"y\" => $y1), list(\"x\" => $x2, \"y\" => $y2)) = $points;"}, + {"yoda#372", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " list($x1, $y1), \"second\" => list($x2, $y2)) = $points;", " list($x1, $y1), \"second\" => list($x2, $y2)) = $points;"}, + {"yoda#373", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " list($x1, $y1), \"second\" => list($x2, $y2)) = $points;", " list($x1, $y1), \"second\" => list($x2, $y2)) = $points;"}, + {"yoda#374", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c] = $a[0];", " $a, \"b\" => $b, \"c\" => $c] = $a[0];"}, + {"yoda#377", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c] = $a[0];", " $a, \"b\" => $b, \"c\" => $c] = $a[0];"}, + {"yoda#378", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c) = $c === 1 ? $b : $d;", " $a, \"b\" => $b, \"c\" => $c) = 1 === $c ? $b : $d;"}, + {"yoda#387", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c) = 1 === $c ? $b : $d;", " $a, \"b\" => $b, \"c\" => $c) = $c === 1 ? $b : $d;"}, + {"yoda#388", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c) = $c === A::B ? $b : $d;", " $a, \"b\" => $b, \"c\" => $c) = A::B === $c ? $b : $d;"}, + {"yoda#389", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $a, \"b\" => $b, \"c\" => $c) = A::B === $c ? $b : $d;", " $a, \"b\" => $b, \"c\" => $c) = $c === A::B ? $b : $d;"}, + {"yoda#390", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $b) = [\"a\" => $c === 7 ? 5 : 1, \"b\" => 7];", " $b) = [\"a\" => 7 === $c ? 5 : 1, \"b\" => 7];"}, + {"yoda#391", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $b) = [\"a\" => 7 === $c ? 5 : 1, \"b\" => 7];", " $b) = [\"a\" => $c === 7 ? 5 : 1, \"b\" => 7];"}, + {"yoda#392", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, " $b] = [\"a\" => $c === 7 ? 5 : 1, \"b\" => 7];", " $b] = [\"a\" => 7 === $c ? 5 : 1, \"b\" => 7];"}, + {"yoda#393", map[string]any{"equal": false, "identical": false, "less_and_greater": nil, "always_move_variable": false}, " $b] = [\"a\" => 7 === $c ? 5 : 1, \"b\" => 7];", " $b] = [\"a\" => $c === 7 ? 5 : 1, \"b\" => 7];"}, + {"yoda#394", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "= 3;", "= 3;"}, + {"yoda#400", map[string]any{"equal": true, "identical": true, "less_and_greater": true, "always_move_variable": false}, " $b;"}, + {"yoda#401", map[string]any{"equal": true, "identical": true, "less_and_greater": false, "always_move_variable": false}, " $b;", " $b) || $d;"}, + {"yoda#403", map[string]any{"equal": true, "identical": true, "less_and_greater": false, "always_move_variable": false}, " $b) || $d;", " 3;\n ", " 3;\n "}, + {"yoda#405", map[string]any{"equal": true, "identical": false, "less_and_greater": nil, "always_move_variable": false}, "event == 'created') {\n foreach ($revision->getModified() as $col => $data) {\n $model->$col = $data['new'];\n }\n} else {\n foreach ($revision->getModified() as $col => $data) {\n $model->$col = $data['old'];\n }\n}", "event == 'created') {\n foreach ($revision->getModified() as $col => $data) {\n $model->$col = $data['new'];\n }\n} else {\n foreach ($revision->getModified() as $col => $data) {\n $model->$col = $data['old'];\n }\n}"}, + {"yoda#407", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "$a[1] === $bar[$baz]{1}->$a[1][2][3]->$d[$z]{1};", "$a[1] === $bar[$baz]{1}->$a[1][2][3]->$d[$z]{1};"}, + {"yoda#411", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "a{2}+1 == 2;", "a{2}+1 == 2;"}, + {"yoda#412", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "getStuff();", "getStuff() === $myVariable;"}, + {"yoda#416", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "b[5]?->c === 42;", "b[5]?->c;"}, + {"yoda#417", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "myObject1?->{$index}+$b === \"\";", "myObject1?->{$index}+$b === \"\";"}, + {"yoda#418", map[string]any{"equal": true, "identical": true, "less_and_greater": nil, "always_move_variable": false}, "