From d35c1629d50f3b540794de9456deb5113f0c01fc Mon Sep 17 00:00:00 2001
From: anoopjohn <anoopjohn@188049.no-reply.drupal.org>
Date: Fri, 3 Jun 2016 19:55:50 +0200
Subject: [PATCH] Issue #2573195 by pfrenssen, anoopjohn, attiks: Not all
 Drupal.Classes.ClassCreateInstance violations are marked as fixable

---
 .../Classes/ClassCreateInstanceSniff.php      | 29 +++++++++++++++++--
 .../Classes/ClassCreateInstanceUnitTest.inc   |  2 ++
 .../ClassCreateInstanceUnitTest.inc.fixed     |  6 ++--
 .../Classes/ClassCreateInstanceUnitTest.php   |  1 +
 4 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/coder_sniffer/Drupal/Sniffs/Classes/ClassCreateInstanceSniff.php b/coder_sniffer/Drupal/Sniffs/Classes/ClassCreateInstanceSniff.php
index 70f6a17f..28db4277 100644
--- a/coder_sniffer/Drupal/Sniffs/Classes/ClassCreateInstanceSniff.php
+++ b/coder_sniffer/Drupal/Sniffs/Classes/ClassCreateInstanceSniff.php
@@ -55,9 +55,15 @@ class Drupal_Sniffs_Classes_ClassCreateInstanceSniff implements PHP_CodeSniffer_
         if ($nextParenthesis === false || isset($tokens[$nextParenthesis]['parenthesis_owner']) === true) {
             $error       = 'Calling class constructors must always include parentheses';
             $constructor = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true, null, true);
-            // We can only invoke the fixer if we know this is a static constructor
-            // function call.
-            if ($tokens[$constructor]['code'] === T_STRING || $tokens[$constructor]['code'] === T_NS_SEPARATOR) {
+            // We can invoke the fixer if we know this is a static constructor
+            // function call or constructor calls with namespaces, example
+            // "new \DOMDocument;" or constructor with class names in variables
+            // "new $controller;".
+            if ($tokens[$constructor]['code'] === T_STRING
+                || $tokens[$constructor]['code'] === T_NS_SEPARATOR
+                || ($tokens[$constructor]['code'] === T_VARIABLE
+                && $tokens[($constructor + 1)]['code'] === T_SEMICOLON)
+            ) {
                 // Scan to the end of possible string\namespace parts.
                 $nextConstructorPart = $constructor;
                 while (true) {
@@ -83,6 +89,23 @@ class Drupal_Sniffs_Classes_ClassCreateInstanceSniff implements PHP_CodeSniffer_
                 if ($fix === true) {
                     $phpcsFile->fixer->addContent($constructor, '()');
                 }
+
+                // We can invoke the fixer if we know this is a
+                // constructor call with class names in an array
+                // example "new $controller[$i];".
+            } else if ($tokens[$constructor]['code'] === T_VARIABLE
+                && $tokens[($constructor + 1)]['code'] === T_OPEN_SQUARE_BRACKET
+            ) {
+                // Scan to the end of possible multilevel arrays.
+                $nextConstructorPart = $constructor;
+                do {
+                    $nextConstructorPart = $tokens[($nextConstructorPart + 1)]['bracket_closer'];
+                } while ($tokens[($nextConstructorPart + 1)]['code'] === T_OPEN_SQUARE_BRACKET);
+
+                $fix = $phpcsFile->addFixableError($error, $nextConstructorPart, 'ParenthesisMissing');
+                if ($fix === true) {
+                    $phpcsFile->fixer->addContent($nextConstructorPart, '()');
+                }
             } else {
                 $phpcsFile->addError($error, $stackPtr, 'ParenthesisMissing');
             }//end if
diff --git a/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc b/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc
index 8cb98ff2..5c9bdae4 100644
--- a/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc
+++ b/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc
@@ -12,3 +12,5 @@ $obj2 = $obj1->add(new Vendor);
 $obj2 = $obj1->add(new Vendor\DateTools);
 $obj2 = $obj1->add(new Vendor\DateTools\DateInterval);
 $obj2 = $obj1->add(new \Vendor\DateTools\DateInterval);
+
+$bar = new $foo[$x + 1][$y + 1];
diff --git a/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc.fixed b/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc.fixed
index e8b9e806..a15cb054 100644
--- a/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc.fixed
+++ b/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.inc.fixed
@@ -9,8 +9,8 @@ use Vendor\DateTools;
 
 $x = array(new Foo(), array());
 $y = new Foo();
-$z = new $class;
-$bar = new $foo[$x + 1];
+$z = new $class();
+$bar = new $foo[$x + 1]();
 
 $obj1 = new DateTime();
 $obj1 = new \DateTime();
@@ -19,3 +19,5 @@ $obj2 = $obj1->add(new Vendor());
 $obj2 = $obj1->add(new DateTools());
 $obj2 = $obj1->add(new DateInterval());
 $obj2 = $obj1->add(new DateInterval());
+
+$bar = new $foo[$x + 1][$y + 1]();
diff --git a/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.php b/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.php
index 3f734ec1..486de414 100644
--- a/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.php
+++ b/coder_sniffer/Drupal/Test/Classes/ClassCreateInstanceUnitTest.php
@@ -26,6 +26,7 @@ class Drupal_Sniffs_Classes_ClassCreateInstanceUnitTest extends CoderSniffUnitTe
                 12 => 1,
                 13 => 1,
                 14 => 1,
+                16 => 1,
                );
 
     }//end getErrorList()
-- 
GitLab