diff --git a/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php b/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php index ea4970dbf8..84facf0540 100644 --- a/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php +++ b/src/Standards/Squiz/Sniffs/Objects/ObjectInstantiationSniff.php @@ -48,21 +48,37 @@ public function process(File $phpcsFile, $stackPtr) $prev = $phpcsFile->findPrevious($allowedTokens, ($stackPtr - 1), null, true); $allowedTokens = [ - T_EQUAL => true, - T_DOUBLE_ARROW => true, - T_FN_ARROW => true, - T_MATCH_ARROW => true, - T_THROW => true, - T_RETURN => true, - T_INLINE_THEN => true, - T_INLINE_ELSE => true, + T_EQUAL => T_EQUAL, + T_COALESCE_EQUAL => T_COALESCE_EQUAL, + T_DOUBLE_ARROW => T_DOUBLE_ARROW, + T_FN_ARROW => T_FN_ARROW, + T_MATCH_ARROW => T_MATCH_ARROW, + T_THROW => T_THROW, + T_RETURN => T_RETURN, ]; - if (isset($allowedTokens[$tokens[$prev]['code']]) === false) { - $error = 'New objects must be assigned to a variable'; - $phpcsFile->addError($error, $stackPtr, 'NotAssigned'); + if (isset($allowedTokens[$tokens[$prev]['code']]) === true) { + return; } + $ternaryLikeTokens = [ + T_COALESCE => true, + T_INLINE_THEN => true, + T_INLINE_ELSE => true, + ]; + + // For ternary like tokens, walk a little further back to see if it is preceded by + // one of the allowed tokens (within the same statement). + if (isset($ternaryLikeTokens[$tokens[$prev]['code']]) === true) { + $hasAllowedBefore = $phpcsFile->findPrevious($allowedTokens, ($prev - 1), null, false, null, true); + if ($hasAllowedBefore !== false) { + return; + } + } + + $error = 'New objects must be assigned to a variable'; + $phpcsFile->addError($error, $stackPtr, 'NotAssigned'); + }//end process() diff --git a/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc b/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc index f58af275cd..41c881289d 100644 --- a/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc +++ b/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.inc @@ -23,6 +23,24 @@ function returnMatch() { } } +// Issue 3333. +$time2 ??= new \DateTime(); +$time3 = $time1 ?? new \DateTime(); +$time3 = $time1 ?? $time2 ?? new \DateTime(); + +function_call($time1 ?? new \DateTime()); +$return = function_call($time1 ?? new \DateTime()); // False negative depending on interpretation of the sniff. + +function returnViaTernary() { + return ($y == false ) ? ($x === true ? new Foo : new Bar) : new FooBar; +} + +function nonAssignmentTernary() { + if (($x ? new Foo() : new Bar) instanceof FooBar) { + // Do something. + } +} + // Intentional parse error. This must be the last test in the file. function new ?> diff --git a/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php b/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php index fa32521c85..f9979fa29f 100644 --- a/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php +++ b/src/Standards/Squiz/Tests/Objects/ObjectInstantiationUnitTest.php @@ -26,8 +26,10 @@ class ObjectInstantiationUnitTest extends AbstractSniffUnitTest public function getErrorList() { return [ - 5 => 1, - 8 => 1, + 5 => 1, + 8 => 1, + 31 => 1, + 39 => 2, ]; }//end getErrorList()