<commit_before><?php

/**
 * This file is part of the mo4-coding-standard (phpcs standard)
 *
 * PHP version 5
 *
 * @category PHP
 * @package  PHP_CodeSniffer-MO4
 * @author   <NAME> <<EMAIL>>
 * @license  http://spdx.org/licenses/MIT MIT License
 * @version  GIT: master
 * @link     https://github.com/Mayflower/mo4-coding-standard
 */

/**
 * Unnecessary Namespace Usage sniff.
 *
 * Full namespace declaration should be skipped in favour of the short declaration.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer-MO4
 * @author    <NAME> <<EMAIL>>
 * @author    <NAME> <<EMAIL>>
 * @author    <NAME> <<EMAIL>>
 * @copyright 2013 <NAME>, some rights reserved.
 * @license   http://spdx.org/licenses/MIT MIT License
 * @link      https://github.com/Mayflower/mo4-coding-standard
 */
class MO4_Sniffs_Formatting_UnnecessaryNamespaceUsageSniff implements PHP_CodeSniffer_Sniff
{
    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(int)
     * @see    Tokens.php
     */
    public function register()
    {
        return array(T_CLASS);
    }

    /**
     * Called when one of the token types that this sniff is listening for
     * is found.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where the
     *                                        token was found.
     * @param int                  $stackPtr  The position in the PHP_CodeSniffer
     *                                        file's token stack where the token
     *                                        was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $baseMsg = 'Shorthand possible. Replace "%s" with "%s"';

        $tokens = $phpcsFile->getTokens();
        $useStatements = $this->getUseStatements($phpcsFile, 0, $stackPtr - 1);
        $nameSpace = $this->getNameSpace($phpcsFile, 0, $stackPtr - 1);

        $nsSep = $phpcsFile->findNext([T_NS_SEPARATOR, T_DOC_COMMENT], $stackPtr + 1);

        while ($nsSep !== false) {
            $classRe = '[\w\x7f-\xff]';
            $classNameEnd = $phpcsFile->findNext(
                [T_NS_SEPARATOR, T_STRING],
                $nsSep,
                null,
                true
            );

            if ($tokens[$nsSep]['code'] === T_NS_SEPARATOR) {
                if ($tokens[$nsSep - 1]['code'] === T_STRING) {
                    $nsSep -= 1;
                }
                $className = $phpcsFile->getTokensAsString($nsSep, $classNameEnd - $nsSep);
                $fullClassName = $this->_getFullyQualifiedClassName($className);

                if (array_key_exists($fullClassName, $useStatements)) {
                    $msg = sprintf(
                        $baseMsg,
                        $className,
                        $useStatements[$fullClassName]
                    );
                    $phpcsFile->addWarning($msg, $nsSep);
                }

                // TODO test
                if (strpos($fullClassName, $nameSpace) === 0) {
                    $msg = sprintf(
                        $baseMsg,
                        $className,
                        substr($fullClassName, strlen($nameSpace))
                    );
                    $phpcsFile->addWarning($msg, $nsSep);
                }
            } else {
                $docLine = $tokens[$nsSep]['content'];
                if (preg_match('/\s+@(param|return|throws|var)/', $docLine) ===  1) {
                    foreach ($useStatements as $fullClassName => $useName) {
                        $className = substr($fullClassName, 1);

                        $pos    = strpos($docLine, $className);
                        $length = strlen($className);

                        if ($pos !== false) {
                            if (1 === preg_match("/$classRe/", $docLine[$pos - 1])) {
                                continue;
                            }

                            $endOfComment = substr($docLine, $pos + $length);

                            if (1 === preg_match('/^(\s|\||\*).*/', $endOfComment)) {
                                // ignore isomorph imports, like "use Exception;"
                                if (($className === $useName) && ($docLine[$pos - 1] != '\\')) {
                                    continue;
                                }

                                $msg = sprintf(
                                    $baseMsg,
                                    $className,
                                    $useStatements[$fullClassName]
                                );
                                $phpcsFile->addWarning($msg, $nsSep);
                            }
                        }
                    }

                    $pattern = sprintf("/%s(\w+)/", preg_quote($nameSpace));
                    $matches = array();
                    if (preg_match($pattern, $docLine, $matches) === 1) {
                        $msg = sprintf(
                            $baseMsg,
                            $matches[0],
                            $matches[1]
                        );
                        $phpcsFile->addWarning($msg, $nsSep);
                    }
                }

            }

            $nsSep = $phpcsFile->findNext([T_NS_SEPARATOR, T_DOC_COMMENT], $classNameEnd + 1);
        }
    }

    /**
     * get all use statements in range
     *
     * @param PHP_CodeSniffer_File $phpcsFile PHP CS File
     * @param int                  $start     start pointer
     * @param int                  $end       end pointer
     *
     * @return array
     */
    protected  function getUseStatements(PHP_CodeSniffer_File $phpcsFile, $start, $end)
    {
        $useStatements = array();
        $i             = $start;
        $tokens        = $phpcsFile->getTokens();
        $useTokenPtr   = $phpcsFile->findNext(T_USE, $i, $end);

        while ($useTokenPtr !== false) {
            $classNameStart = $phpcsFile->findNext(
                PHP_CodeSniffer_Tokens::$emptyTokens,
                $useTokenPtr + 1,
                $end,<commit_msg>fixed unnecessary namespace usage warning sniff<commit_after><?php

/**
 * This file is part of the mo4-coding-standard (phpcs standard)
 *
 * PHP version 5
 *
 * @category PHP
 * @package  PHP_CodeSniffer-MO4
 * @author   <NAME> <<EMAIL>>
 * @license  http://spdx.org/licenses/MIT MIT License
 * @version  GIT: master
 * @link     https://github.com/Mayflower/mo4-coding-standard
 */

/**
 * Unnecessary Namespace Usage sniff.
 *
 * Full namespace declaration should be skipped in favour of the short declaration.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer-MO4
 * @author    <NAME> <<EMAIL>>
 * @author    <NAME> <<EMAIL>>
 * @author    <NAME> <<EMAIL>>
 * @copyright 2013 Xaver Loppenstedt, some rights reserved.
 * @license   http://spdx.org/licenses/MIT MIT License
 * @link      https://github.com/Mayflower/mo4-coding-standard
 */
class MO4_Sniffs_Formatting_UnnecessaryNamespaceUsageSniff implements PHP_CodeSniffer_Sniff
{
    /**
     * Registers the tokens that this sniff wants to listen for.
     *
     * @return array(int)
     * @see    Tokens.php
     */
    public function register()
    {
        return array(T_CLASS);
    }

    /**
     * Called when one of the token types that this sniff is listening for
     * is found.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where the
     *                                        token was found.
     * @param int                  $stackPtr  The position in the PHP_CodeSniffer
     *                                        file's token stack where the token
     *                                        was found.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $docCommentTags = array('@param', '@return', '@throws', '@var');
        $classRe        = '[\w\x7f-\xff]';

        $baseMsg = 'Shorthand possible. Replace "%s" with "%s"';

        $tokens = $phpcsFile->getTokens();
        $useStatements = $this->getUseStatements($phpcsFile, 0, $stackPtr - 1);
        $nameSpace = $this->getNameSpace($phpcsFile, 0, $stackPtr - 1);

        $nsSep = $phpcsFile->findNext(
            [T_NS_SEPARATOR, T_DOC_COMMENT_OPEN_TAG],
            $stackPtr + 1
        );

        while ($nsSep !== false) {
            $classNameEnd = $phpcsFile->findNext(
                [T_NS_SEPARATOR, T_STRING],
                $nsSep,
                null,
                true
            );

            if ($tokens[$nsSep]['code'] === T_NS_SEPARATOR) {
                if ($tokens[$nsSep - 1]['code'] === T_STRING) {
                    $nsSep -= 1;
                }
                $className = $phpcsFile->getTokensAsString($nsSep, $classNameEnd - $nsSep);
                $fullClassName = $this->_getFullyQualifiedClassName($className);

                if (array_key_exists($fullClassName, $useStatements)) {
                    $msg = sprintf(
                        $baseMsg,
                        $className,
                        $useStatements[$fullClassName]
                    );
                    $phpcsFile->addWarning($msg, $nsSep);
                }

                // TODO test
                if (strpos($fullClassName, $nameSpace) === 0) {
                    $msg = sprintf(
                        $baseMsg,
                        $className,
                        substr($fullClassName, strlen($nameSpace))
                    );
                    $phpcsFile->addWarning($msg, $nsSep);
                }
            } else {
                foreach ($tokens[$nsSep]['comment_tags'] as $tag) {
                    if (!in_array($tokens[$tag]['content'], $docCommentTags)) {
                        continue;
                    }

                    $lineEnd = $phpcsFile->findNext(
                        [T_DOC_COMMENT_CLOSE_TAG, T_DOC_COMMENT_STAR],
                        $tag + 1
                    );
                    $docLine = $phpcsFile->getTokensAsString($tag, $lineEnd - $tag);
                    foreach ($useStatements as $fullClassName => $useName) {
                        $className = substr($fullClassName, 1);

                        $pos    = strpos($docLine, $className);
                        $length = strlen($className);

                        if ($pos !== false) {
                            if (1 === preg_match("/$classRe/", $docLine[$pos - 1])) {
                                continue;
                            }

                            $endOfComment = substr($docLine, $pos + $length);

                            if (1 === preg_match('/^(\s|\||\*).*/', $endOfComment)) {
                                // ignore isomorph imports, like "use Exception;"
                                if (($className === $useName) && ($docLine[$pos - 1] !== '\\')) {
                                    continue;
                                }

                                $msg = sprintf(
                                    $baseMsg,
                                    $className,
                                    $useStatements[$fullClassName]
                                );
                                $phpcsFile->addWarning($msg, $tag);
                            }
                        }
                    }

                    $pattern = sprintf("/%s(\w+)/", preg_quote($nameSpace));
                    $matches = array();
                    if (preg_match($pattern, $docLine, $matches) === 1) {
                        $msg = sprintf(
                            $baseMsg,
                            $matches[0],
                            $matches[1]
                        );
                        $phpcsFile->addWarning($msg, $tag);
                    }
                }
            }

            $nsSep = $phpcsFile->findNext([T_NS_SEPARATOR, T_DOC_COMMENT_OPEN_TAG], $classNameEnd + 1);
        }
    }

    /**
     * get all use statements in range
     *
     * @param PHP_CodeSniffer_File $phpcsFile PHP CS File
     * @param int                  $start     start pointer
     * @param int                  $end       end pointer
     *
     * @return array
     */
    protected  function getUseStatements(PHP_CodeSniffer_File $phpcsFile, $start, $end)
    {
        $useStatements = array();
        $i             = $start;
        $tokens        = $phpcsFile->getTokens();
        $useTokenPtr   = $phpcsFile->findNext(T_USE, $i, $end);

        while ($useTokenPtr !== false) {
            $classNameStart = $phpcsFile->findNext(
                PHP_CodeSniffer_Tokens::$emptyTokens,
                $useTokenPtr + 1,
                $end,
{'fraction_non_alphanumeric': 0.11759643220405289, 'fraction_numerical': 0.00485095062984117, 'mean_word_length': 1.2571075401730532, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 62, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1785465', 'n_tokens_mistral': 3497, 'n_tokens_neox': 3292, 'n_words': 711}