Issues (45)

src/Console/ParseCommand.php (3 issues)

Labels
1
<?php
2
3
/**
4
 * This file is part of Railt package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Railt\SDL\Console;
13
14
use Phplrt\Source\File;
15
use Railt\SDL\Exception\SyntaxErrorException;
16
use Railt\SDL\Frontend\Ast\Node;
17
use Railt\SDL\Frontend\Parser;
18
use Symfony\Component\Console\Command\Command;
19
use Symfony\Component\Console\Exception\InvalidArgumentException;
20
use Symfony\Component\Console\Exception\RuntimeException;
21
use Symfony\Component\Console\Input\InputArgument;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Output\OutputInterface;
24
use Symfony\Component\Console\Question\Question;
25
26
/**
27
 * Class ParseCommand
28
 */
29
class ParseCommand extends Command
30
{
31
    /**
32
     * {@inheritDoc}
33
     */
34
    public function getName(): string
35
    {
36
        return 'sdl:parse';
37
    }
38
39
    /**
40
     * {@inheritDoc}
41
     */
42
    public function getDescription(): string
43
    {
44
        return 'The command to analyze and display the AST structure of the GraphQL source code';
45
    }
46
47
    /**
48
     * @return void
49
     * @throws InvalidArgumentException
50
     */
51
    public function configure(): void
52
    {
53
        $this->addArgument(
54
            'source',
55
            InputArgument::OPTIONAL,
56
            'GraphQL source file pathname'
57
        );
58
    }
59
60
    /**
61
     * {@inheritDoc}
62
     * @throws \Throwable
63
     */
64
    protected function execute(InputInterface $input, OutputInterface $output): int
65
    {
66
        if ($source = $input->getArgument('source')) {
67
            $source = File::fromPathname($source);
0 ignored issues
show
It seems like $source can also be of type string[]; however, parameter $pathname of Phplrt\Source\File::fromPathname() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

67
            $source = File::fromPathname(/** @scrutinizer ignore-type */ $source);
Loading history...
68
69
            $output->writeln('Parsing <comment>' . $source->getPathname() . '</comment>' . "\n");
70
71
            /** @var Node[] $result */
72
            $result = (new Parser())->parse($source);
73
74
            foreach ($result as $item) {
75
                $output->writeln(\str_repeat('-', 80));
76
                $output->writeln(\vsprintf('    File <info>%s:%d</info>', [
77
                    $item->loc->source->getPathname(),
0 ignored issues
show
The method getPathname() does not exist on Phplrt\Contracts\Source\ReadableInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Phplrt\Source\File\Readable or Phplrt\Source\File\Content or Phplrt\Source\File\Stream. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

77
                    $item->loc->source->/** @scrutinizer ignore-call */ 
78
                                        getPathname(),
Loading history...
78
                    $item->loc->getStartLine(),
0 ignored issues
show
The method getStartLine() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

78
                    $item->loc->/** @scrutinizer ignore-call */ 
79
                                getStartLine(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
79
                ]));
80
                $output->writeln(\str_repeat('-', 80));
81
82
                $output->writeln((string)$item);
83
            }
84
85
            $output->writeln(\str_repeat('-', 80));
86
87
            return 0;
88
        }
89
90
        $this->interactive($input, $output);
91
92
        return 0;
93
    }
94
95
    /**
96
     * @param InputInterface $input
97
     * @param OutputInterface $output
98
     * @return void
99
     * @throws RuntimeException
100
     * @throws \Throwable
101
     */
102
    private function interactive(InputInterface $input, OutputInterface $output): void
103
    {
104
        $parser = new Parser();
105
        $question = new Question($this->line('↳'));
106
        $stream = $this->getHelper('question');
107
108
        while (true) {
109
            $source = $stream->ask($input, $output, $question);
110
111
            if ($source === null) {
112
                continue;
113
            }
114
115
            try {
116
                $result = \implode("\n", [...$parser->parse($source)]);
117
118
                $output->writeln($this->line('⇲', $result, 'yellow'));
119
            } catch (SyntaxErrorException $e) {
120
                $message = \vsprintf('<error> %s on line %d at column %d </error>', [
121
                    $e->getMessage(),
122
                    $e->getPosition()->getLine(),
123
                    $e->getPosition()->getColumn(),
124
                ]);
125
126
                $output->writeln($this->line('⨯', $message, 'red'));
127
            }
128
        }
129
    }
130
131
    /**
132
     * @param string $msg
133
     * @param string $body
134
     * @param string $color
135
     * @return string
136
     */
137
    private function line(string $msg, string $body = '', string $color = 'cyan'): string
138
    {
139
        $lines = \explode("\n", \str_replace("\r", '', $body));
140
141
        $lines = \array_map(static function (string $line, int $i) use ($color, $msg): string {
142
            return \sprintf('<bg=%s> %s </> ', $color, $i ? ' ' : $msg) . $line;
143
        }, $lines, \array_keys($lines));
144
145
146
        return \implode("\n", $lines);
147
    }
148
}
149