diff vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Classes/UnusedUseStatementSniff.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 129ea1e6d783
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Classes/UnusedUseStatementSniff.php	Wed Nov 29 16:09:58 2017 +0000
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Drupal_Sniffs_Classes_UnusedUseStatementSniff.
+ *
+ * @category PHP
+ * @package  PHP_CodeSniffer
+ * @link     http://pear.php.net/package/PHP_CodeSniffer
+ */
+
+/**
+ * Checks for "use" statements that are not needed in a file.
+ *
+ * @category PHP
+ * @package  PHP_CodeSniffer
+ * @link     http://pear.php.net/package/PHP_CodeSniffer
+ */
+class Drupal_Sniffs_Classes_UnusedUseStatementSniff implements PHP_CodeSniffer_Sniff
+{
+
+
+    /**
+     * Returns an array of tokens this test wants to listen for.
+     *
+     * @return array
+     */
+    public function register()
+    {
+        return array(T_USE);
+
+    }//end register()
+
+
+    /**
+     * Processes this test, when one of its tokens is encountered.
+     *
+     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
+     * @param int                  $stackPtr  The position of the current token in
+     *                                        the stack passed in $tokens.
+     *
+     * @return void
+     */
+    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
+    {
+        $tokens = $phpcsFile->getTokens();
+
+        // Only check use statements in the global scope.
+        if (empty($tokens[$stackPtr]['conditions']) === false) {
+            return;
+        }
+
+        // Seek to the end of the statement and get the string before the semi colon.
+        $semiColon = $phpcsFile->findEndOfStatement($stackPtr);
+        if ($tokens[$semiColon]['code'] !== T_SEMICOLON) {
+            return;
+        }
+
+        $classPtr = $phpcsFile->findPrevious(
+            PHP_CodeSniffer_Tokens::$emptyTokens,
+            ($semiColon - 1),
+            null,
+            true
+        );
+
+        if ($tokens[$classPtr]['code'] !== T_STRING) {
+            return;
+        }
+
+        // Search where the class name is used. PHP treats class names case
+        // insensitive, that's why we cannot search for the exact class name string
+        // and need to iterate over all T_STRING tokens in the file.
+        $classUsed      = $phpcsFile->findNext(T_STRING, ($classPtr + 1));
+        $lowerClassName = strtolower($tokens[$classPtr]['content']);
+
+        // Check if the referenced class is in the same namespace as the current
+        // file. If it is then the use statement is not necessary.
+        $namespacePtr = $phpcsFile->findPrevious([T_NAMESPACE], $stackPtr);
+        // Check if the use statement does aliasing with the "as" keyword. Aliasing
+        // is allowed even in the same namespace.
+        $aliasUsed = $phpcsFile->findPrevious(T_AS, ($classPtr - 1), $stackPtr);
+
+        if ($namespacePtr !== false && $aliasUsed === false) {
+            $nsEnd     = $phpcsFile->findNext(
+                [
+                 T_NS_SEPARATOR,
+                 T_STRING,
+                 T_WHITESPACE,
+                ],
+                ($namespacePtr + 1),
+                null,
+                true
+            );
+            $namespace = trim($phpcsFile->getTokensAsString(($namespacePtr + 1), ($nsEnd - $namespacePtr - 1)));
+
+            $useNamespacePtr = $phpcsFile->findNext([T_STRING], ($stackPtr + 1));
+            $useNamespaceEnd = $phpcsFile->findNext(
+                [
+                 T_NS_SEPARATOR,
+                 T_STRING,
+                ],
+                ($useNamespacePtr + 1),
+                null,
+                true
+            );
+            $use_namespace   = rtrim($phpcsFile->getTokensAsString($useNamespacePtr, ($useNamespaceEnd - $useNamespacePtr - 1)), '\\');
+
+            if (strcasecmp($namespace, $use_namespace) === 0) {
+                $classUsed = false;
+            }
+        }//end if
+
+        while ($classUsed !== false) {
+            if (strtolower($tokens[$classUsed]['content']) === $lowerClassName) {
+                // If the name is used in a PHP 7 function return type declaration
+                // stop.
+                if ($tokens[$classUsed]['code'] === T_RETURN_TYPE) {
+                    return;
+                }
+
+                $beforeUsage = $phpcsFile->findPrevious(
+                    PHP_CodeSniffer_Tokens::$emptyTokens,
+                    ($classUsed - 1),
+                    null,
+                    true
+                );
+                // If a backslash is used before the class name then this is some other
+                // use statement.
+                if ($tokens[$beforeUsage]['code'] !== T_USE && $tokens[$beforeUsage]['code'] !== T_NS_SEPARATOR) {
+                    return;
+                }
+
+                // Trait use statement within a class.
+                if ($tokens[$beforeUsage]['code'] === T_USE && empty($tokens[$beforeUsage]['conditions']) === false) {
+                    return;
+                }
+            }//end if
+
+            $classUsed = $phpcsFile->findNext([T_STRING, T_RETURN_TYPE], ($classUsed + 1));
+        }//end while
+
+        $warning = 'Unused use statement';
+        $fix     = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse');
+        if ($fix === true) {
+            // Remove the whole use statement line.
+            $phpcsFile->fixer->beginChangeset();
+            for ($i = $stackPtr; $i <= $semiColon; $i++) {
+                $phpcsFile->fixer->replaceToken($i, '');
+            }
+
+            // Also remove whitespace after the semicolon (new lines).
+            while (isset($tokens[$i]) === true && $tokens[$i]['code'] === T_WHITESPACE) {
+                $phpcsFile->fixer->replaceToken($i, '');
+                if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) {
+                    break;
+                }
+
+                $i++;
+            }
+
+            // Replace @var data types in doc comments with the fully qualified class
+            // name.
+            $useNamespacePtr = $phpcsFile->findNext([T_STRING], ($stackPtr + 1));
+            $useNamespaceEnd = $phpcsFile->findNext(
+                [
+                 T_NS_SEPARATOR,
+                 T_STRING,
+                ],
+                ($useNamespacePtr + 1),
+                null,
+                true
+            );
+            $fullNamespace   = $phpcsFile->getTokensAsString($useNamespacePtr, ($useNamespaceEnd - $useNamespacePtr));
+
+            $tag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($stackPtr + 1));
+
+            while ($tag !== false) {
+                if (($tokens[$tag]['content'] === '@var' || $tokens[$tag]['content'] === '@return')
+                    && isset($tokens[($tag + 1)]) === true
+                    && $tokens[($tag + 1)]['code'] === T_DOC_COMMENT_WHITESPACE
+                    && isset($tokens[($tag + 2)]) === true
+                    && $tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING
+                    && strpos($tokens[($tag + 2)]['content'], $tokens[$classPtr]['content']) === 0
+                ) {
+                    $replacement = '\\'.$fullNamespace.substr($tokens[($tag + 2)]['content'], strlen($tokens[$classPtr]['content']));
+                    $phpcsFile->fixer->replaceToken(($tag + 2), $replacement);
+                }
+
+                $tag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($tag + 1));
+            }
+
+            $phpcsFile->fixer->endChangeset();
+        }//end if
+
+    }//end process()
+
+
+}//end class