Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: Undefined offset: -1 #2766

Closed
ksn135 opened this issue Dec 14, 2019 · 9 comments

Comments

@ksn135
Copy link

ksn135 commented Dec 14, 2019

Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: Undefined offset: -1 in phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php on line 2 in phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Runner.php:2
Stack trace:
#0 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php(2): PHP_CodeSniffer\Runner->handleErrors(8, 'Undefined offse...', 'phar:///usr/loc...', 2, Array)
#1 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Files/File.php(2): PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions\ReturnTypeDeclarationSniff->process(Object(PHP_CodeSniffer\Files\LocalFile), 99)
#2 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Files/LocalFile.php(2): PHP_CodeSniffer\Files\File->process()
#3 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Fixer.php(2): PHP_CodeSniffer\Files\LocalFile->process()
#4 phar:///usr/local/Ce in phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Runner.php on line 2

@jrfnl
Copy link
Contributor

jrfnl commented Dec 14, 2019

@ksn135 Thanks for reporting. Could you post a small code sample with which this error can be reproduced ?

@ksn135
Copy link
Author

ksn135 commented Dec 14, 2019

Source file:

<?php
namespace Ksn135\CompanyBundle\Command;

use Ksn135\CompanyBundle\Email\DeliveredMessage;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Ksn135\CompanyBundle\Events\EmailDeliveredEvent;
use Ksn135\CompanyBundle\EventListener\EmailDeliveryListener;

class DeliverEmailCommand extends ContainerAwareCommand
{

protected function configure()
    {
        $this->setName('mailparser:email:deliver')
            ->setDescription('Deliver email message to database')
            ->setHelp(
                <<<EOF
Читает входящий поток данных из стандартного ввода и пытается 
разобрать входящие данные как сообщение почты, после чего отправляет их на запись в БД
    EOF
        );
    }

    protected function execute(InputInterface $params, OutputInterface $output)
    {
        locale_set_default('ru');

        /**
         * Viva, Nifty hacks: New in Symfony 3.1: Input and Output Stream for Processes!
         * https://symfony.com/blog/new-in-symfony-3-1-input-and-output-stream-for-processes
         * use Symfony\Component\Process\Process;
         * $process = new Process('cat');
         * $process->setInput('file.txt');
         * $process->run();
         *
         * @var string $data
         */

        $delivered = new DeliveredMessage(STDIN, $this->getContainer()->get('doctrine.orm.default_entity_manager'));

        $this->getContainer()->get('event_dispatcher')->dispatch(
            EmailDeliveryListener::DELIVERED_EMAIL_COMMAND, new EmailDeliveredEvent(
            $delivered,
            $this->getContainer()->get('ksn135_company.email'),
            $this->getContainer()->get('fos_comment.manager.thread'),
            $this->getContainer()->get('fos_comment.manager.comment'),
            $this->getContainer()->get('security.token_storage'),
        $this->getContainer()->get('stof_doctrine_extensions.listener.blameable')
            )
            );
        
    }
}

Command that produce error:

→ phpcbf --standard=PSR12 DeliverEmailCommand.php

Fatal error: Uncaught PHP_CodeSniffer\Exceptions\RuntimeException: Undefined offset: -1 in phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php on line 2 in phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Runner.php:2
Stack trace:
#0 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Standards/PSR12/Sniffs/Functions/ReturnTypeDeclarationSniff.php(2): PHP_CodeSniffer\Runner->handleErrors(8, 'Undefined offse...', 'phar:///usr/loc...', 2, Array)
#1 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Files/File.php(2): PHP_CodeSniffer\Standards\PSR12\Sniffs\Functions\ReturnTypeDeclarationSniff->process(Object(PHP_CodeSniffer\Files\LocalFile), 97)
#2 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Files/LocalFile.php(2): PHP_CodeSniffer\Files\File->process()
#3 phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Fixer.php(2): PHP_CodeSniffer\Files\LocalFile->process()
#4 phar:///usr/local/Ce in phar:///usr/local/Cellar/php-code-sniffer/3.5.3/bin/phpcbf/src/Runner.php on line 2

@ksn135
Copy link
Author

ksn135 commented Dec 14, 2019

Maybe EOF language construction?
Error free code, after manual cleanup:

<?php

namespace Ksn135\CompanyBundle\Command;

use Ksn135\CompanyBundle\Email\DeliveredMessage;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Ksn135\CompanyBundle\Events\EmailDeliveredEvent;
use Ksn135\CompanyBundle\EventListener\EmailDeliveryListener;

class DeliverEmailCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this->setName('mailparser:email:deliver')
            ->setDescription('Deliver email message to database')
            ->setHelp("Читает входящий поток данных из стандартного ввода и пытается разобрать входящие данные как " .
                "сообщение почты, " . "после чего отправляет их на запись в БД");
    }

    protected function execute(InputInterface $params, OutputInterface $output)
    {
        locale_set_default('ru');
        $delivered = new DeliveredMessage(STDIN, $this->getContainer()->get('doctrine.orm.default_entity_manager'));
        $this->getContainer()->get('event_dispatcher')->dispatch(
            EmailDeliveryListener::DELIVERED_EMAIL_COMMAND,
            new EmailDeliveredEvent(
                $delivered,
                $this->getContainer()->get('ksn135_company.email'),
                $this->getContainer()->get('fos_comment.manager.thread'),
                $this->getContainer()->get('fos_comment.manager.comment'),
                $this->getContainer()->get('security.token_storage'),
                $this->getContainer()->get('stof_doctrine_extensions.listener.blameable')
            )
        );
    }
}

@ksn135
Copy link
Author

ksn135 commented Dec 14, 2019

Another example, source code:

<?php
namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;

class OfficeCommand extends ContainerAwareCommand
{

    protected function configure()
    {
        $this->setName('office:convert:pdf')
            ->setDescription('Convert office document to PDF output format')
            ->addArgument('inputfile', InputArgument::REQUIRED, 'Input file source')
            ->addArgument('outputdir', InputArgument::REQUIRED, 'Output folder destination')
            ->setHelp(
            <<<EOF
Convert Office files from <inputfile> to <outputdir>, `libreoffice` is required, stderr is ignored
(only exit code tested for success) 
EOF
);
        ;
        // ->addOption('rotate','r',InputOption::VALUE_REQUIRED,'Choose rotate degree: 90 (default)', '90')
        /*
         * >setHelp(<<<EOF
         * The <info>office:convert:pdf</info> command converts office documents from input and stores pdf to output.
         * <info>php app/console swiftmailer:spool:send --message-limit=10 --time-limit=10 --recover-timeout=900
         * --mailer=default</info>
         * EOF
         * )
         */
    }

    protected function execute(InputInterface $params, OutputInterface $output)
    {
        $inputFile = $params->getArgument('inputfile');
        $outputDir = $params->getArgument('outputdir');

        $loCmd = new Process('libreoffice --convert-to pdf "' . $inputFile . '" --outdir ' . $outputDir, $outputDir,
            [ 
                'HOME' => $outputDir,
                'JRE_HOME' => $this->getContainer()->getParameter('java.jre.location')
            ]);
        $loCmd->run();
        if ($loCmd->isSuccessful()) {
            $output->writeln("<comment>'$outputDir'</comment> converted");
        } else {
            $errorOutput = $loCmd->getErrorOutput();
            $output->writeln("Error converting: $errorOutput");
        }
    }
}

Command:

→ phpcbf --standard=PSR12 OfficeCommand.php

@jrfnl
Copy link
Contributor

jrfnl commented Dec 15, 2019

@ksn135 I've done some testing and am finding it hard to reproduce the issue.

With the first example code block (DeliverEmailCommand.php) I can reproduce the issue, but only on PHP < 7.3.

As that code contains some very specific PHP 7.3 syntax (flexible heredoc/nowdoc), you will never be able to get reliable results with PHPCS unless you run it on PHP 7.3 or higher.

The tokenizing of PHP 7.3 flexible heredoc/nowdoc is not possible to correct/backfill in older PHP versions, so if your project has a minimum PHP version of 7.3, you should run PHPCS on PHP 7.3 or higher.

Even then, the code on PHP 7.3 contains parse errors (incorrect use of flexible heredoc/nowdoc) and while PHPCS can work around some parse errors, parse errors in general cause less reliable results.

As for the second code sample (OfficeCommand.php), I can't seem to reproduce the issue either way, not in PHP 7.2 nor in PHP 7.3/7.4.

Please check on which PHP version you are running PHPCS.

@ksn135
Copy link
Author

ksn135 commented Dec 16, 2019

Please check on which PHP version you are running PHPCS.

→ php -v
PHP 7.0.32 (cli) (built: Nov 29 2018 01:21:25) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.0.32, Copyright (c) 1999-2017, by Zend Technologies

@jrfnl
Copy link
Contributor

jrfnl commented Dec 16, 2019

@ksn135 Well that explains it then. Either don't use flexible heredoc/nowdoc or scan files which use flexible heredoc/nowdoc only on PHP 7.3 or higher.

@pytnik89
Copy link

To reproduce this behaviour you can do folowing:
php ./vendor/bin/phpcbf --standard=PSR12 File.php
The File.php:

<?php

namespace FileSpace;

class File
{

    public static function xxx(): string
    {
        $zzz = self::yyy();
        ob_start();
        foreach ($zzz as $key => $value) {
            ?>
            <td></td>
            <? //The root evil here I suppose
        }
        $return = ob_get_contents();
        ob_end_clean();
        return $return;
    }

    public static function yyy()
    {
        return [];
    }
}

I suppose that in case of such code behaviour should be tollerant to the version of php.

@gsherwood
Copy link
Member

Closing as there isn't a code change that can resolve this. A different PHP version must be used due to the way tokenizing works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants