Passed
Push — master ( 7925f4...acac31 )
by Doug
06:27
created

Extension::initCodeCoverageV9()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 42
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 26
nc 8
nop 2
dl 0
loc 42
ccs 18
cts 18
cp 1
crap 4
rs 9.504
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * Code Coverage Extension for Behat.
6
 *
7
 * @copyright 2013 Anthon Pang
8
 *
9
 * @license BSD-2-Clause
10
 */
11
12
namespace DVDoug\Behat\CodeCoverage;
13
14
use Behat\Testwork\ServiceContainer\Extension as ExtensionInterface;
15
use Behat\Testwork\ServiceContainer\ExtensionManager;
16
use DVDoug\Behat\CodeCoverage\Subscriber\EventSubscriber;
17
use SebastianBergmann\CodeCoverage\CodeCoverage;
18
use SebastianBergmann\CodeCoverage\Driver\Driver;
19
use SebastianBergmann\CodeCoverage\Filter;
20
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverAvailableException;
0 ignored issues
show
Bug introduced by
The type SebastianBergmann\CodeCo...riverAvailableException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
21
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
0 ignored issues
show
Bug introduced by
The type SebastianBergmann\CodeCo...pportAvailableException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use SebastianBergmann\CodeCoverage\RuntimeException;
23
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
24
use Symfony\Component\Config\FileLocator;
25
use Symfony\Component\Console\Input\InputInterface;
26
use Symfony\Component\Console\Output\OutputInterface;
27
use Symfony\Component\DependencyInjection\ContainerBuilder;
28
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
29
use Symfony\Component\DependencyInjection\Reference;
30
31
/**
32
 * Code coverage extension.
33
 *
34
 * @author Anthon Pang <[email protected]>
35 1
 */
36
class Extension implements ExtensionInterface
37
{
38
    /**
39
     * {@inheritdoc}
40 2
     */
41
    public function initialize(ExtensionManager $extensionManager): void
42 2
    {
43
    }
44
45
    /**
46
     * {@inheritdoc}
47 2
     */
48
    public function load(ContainerBuilder $container, array $config): void
49 2
    {
50
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
51 2
52 2
        $servicesFile = 'services.xml';
53
        $loader->load($servicesFile);
54 2
55 2
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
56 2
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
57
    }
58
59
    /**
60
     * {@inheritdoc}
61 4
     */
62
    public function configure(ArrayNodeDefinition $builder): void
63
    {
64 4
        $builder
65 4
            ->children()
66 4
                ->arrayNode('filter')
67 4
                    ->addDefaultsIfNotSet()
68 4
                    ->children()
69 4
                        ->scalarNode('includeUncoveredFiles')
70 4
                            ->defaultTrue()
71 4
                        ->end()
72 4
                        ->scalarNode('processUncoveredFiles')
0 ignored issues
show
Bug introduced by
The method scalarNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

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

72
                        ->/** @scrutinizer ignore-call */ scalarNode('processUncoveredFiles')
Loading history...
73 4
                            ->defaultFalse()
74 4
                        ->end()
75 4
                        ->arrayNode('include')
76 4
                            ->addDefaultsIfNotSet()
77 4
                            ->children()
78 4
                                ->arrayNode('directories')
79 4
                                   ->useAttributeAsKey('name')
80 4
                                   ->normalizeKeys(false)
81 4
                                   ->prototype('array')
82 4
                                       ->children()
83 4
                                           ->scalarNode('prefix')->defaultValue('')->end()
84 4
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
85 4
                                       ->end()
86 4
                                   ->end()
87 4
                                ->end()
88 4
                                ->arrayNode('files')
89 4
                                   ->prototype('scalar')->end()
90 4
                                ->end()
91 4
                            ->end()
92 4
                        ->end()
93 4
                        ->arrayNode('exclude')
94 4
                            ->addDefaultsIfNotSet()
95 4
                            ->children()
96 4
                                ->arrayNode('directories')
97 4
                                   ->useAttributeAsKey('name')
98 4
                                   ->normalizeKeys(false)
99 4
                                   ->prototype('array')
100 4
                                       ->children()
101 4
                                           ->scalarNode('prefix')->defaultValue('')->end()
102 4
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
103 4
                                       ->end()
104 4
                                   ->end()
105 4
                                ->end()
106 4
                                ->arrayNode('files')
107 4
                                   ->prototype('scalar')->end()
108 4
                                ->end()
109 4
                            ->end()
110 4
                        ->end()
111 4
                    ->end()
112 4
                ->end()
113 4
                ->arrayNode('reports')
114 4
                    ->children()
115 4
                        ->arrayNode('clover')
116 4
                            ->children()
117 4
                                ->scalarNode('name')->defaultNull()->end()
118 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
119 4
                            ->end()
120 4
                        ->end()
121 4
                        ->arrayNode('crap4j')
122 4
                            ->children()
123 4
                                ->scalarNode('name')->defaultNull()->end()
124 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
125 4
                            ->end()
126 4
                        ->end()
127 4
                        ->arrayNode('html')
128 4
                            ->children()
129 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
130 4
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
131 4
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
132 4
                            ->end()
133 4
                        ->end()
134 4
                        ->arrayNode('php')
135 4
                            ->children()
136 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
137 4
                            ->end()
138 4
                        ->end()
139 4
                        ->arrayNode('text')
140 4
                            ->children()
141 4
                                ->booleanNode('showColors')->defaultValue(false)->end()
142 4
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
143 4
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
144 4
                                ->booleanNode('showOnlySummary')->defaultValue(false)->end()
145 4
                                ->booleanNode('showUncoveredFiles')->defaultValue(false)->end()
146 4
                            ->end()
147 4
                        ->end()
148 4
                        ->arrayNode('xml')
149 4
                            ->children()
150 4
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
151 4
                            ->end()
152 4
                        ->end()
153 4
                    ->end()
154 4
                ->end()
155 4
            ->end()
156 4
        ->end();
157
    }
158
159
    /**
160
     * {@inheritdoc}
161 4
     */
162
    public function getConfigKey()
163 4
    {
164
        return 'code_coverage';
165
    }
166
167
    /**
168
     * {@inheritdoc}
169 8
     */
170
    public function process(ContainerBuilder $container): void
171
    {
172 8
        /** @var InputInterface $input */
173
        $input = $container->get('cli.input');
174
175 8
        /** @var OutputInterface $output */
176
        $output = $container->get('cli.output');
177 8
178
        $config = $container->getParameter('behat.code_coverage.config.filter');
179 8
180
        $canCollectCodeCoverage = true;
181 8
        try {
182
            $this->initCodeCoverage(new Filter(), $config);
183 6
184 6
            $codeCoverage = $container->getDefinition(CodeCoverage::class);
185 6
            $filter = $container->getDefinition(Filter::class);
186 6
            $codeCoverage->setFactory([new Reference(self::class), 'initCodeCoverage']);
187 2
            $codeCoverage->setArguments([$filter, $config]);
188 2
        } catch (NoCodeCoverageDriverAvailableException | RuntimeException $e) {
189 2
            $output->writeln('<comment>No code coverage driver is available</comment>');
190
            $canCollectCodeCoverage = false;
191
        }
192 8
193 4
        if (!$canCollectCodeCoverage || $input->hasParameterOption('--no-coverage')) {
194
            $container->getDefinition(EventSubscriber::class)->setArgument('$coverage', null);
195 8
        }
196
    }
197 6
198
    public function initCodeCoverage(Filter $filter, array $config): CodeCoverage
199
    {
200 6
        $driverClassReflection = new \ReflectionClass(Driver::class);
201 6
        if ($driverClassReflection->isInterface()) {
202 6
            return $this->initCodeCoverageV678($filter, $config);
203
        }
204 6
205 6
        return $this->initCodeCoverageV9($filter, $config);
206 6
    }
207
208 6
    public function initCodeCoverageV9(Filter $filter, array $config): CodeCoverage
209 6
    {
210 6
        // set up filter
211
        array_walk($config['include']['directories'], static function (array $dir, string $path, Filter $filter): void {
212 6
            $filter->includeDirectory($path, $dir['suffix'], $dir['prefix']);
0 ignored issues
show
Bug introduced by
The method includeDirectory() does not exist on SebastianBergmann\CodeCoverage\Filter. ( Ignorable by Annotation )

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

212
            $filter->/** @scrutinizer ignore-call */ 
213
                     includeDirectory($path, $dir['suffix'], $dir['prefix']);

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...
213 6
        }, $filter);
214 6
215
        array_walk($config['include']['files'], static function (string $file, string $key, Filter $filter): void {
216
            $filter->includeFile($file);
0 ignored issues
show
Bug introduced by
The method includeFile() does not exist on SebastianBergmann\CodeCoverage\Filter. ( Ignorable by Annotation )

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

216
            $filter->/** @scrutinizer ignore-call */ 
217
                     includeFile($file);

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...
217
        }, $filter);
218 6
219 3
        array_walk($config['exclude']['directories'], static function (array $dir, string $path, Filter $filter): void {
220 3
            $filter->excludeDirectory($path, $dir['suffix'], $dir['prefix']);
0 ignored issues
show
Bug introduced by
The method excludeDirectory() does not exist on SebastianBergmann\CodeCoverage\Filter. ( Ignorable by Annotation )

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

220
            $filter->/** @scrutinizer ignore-call */ 
221
                     excludeDirectory($path, $dir['suffix'], $dir['prefix']);

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...
221
        }, $filter);
222
223
        array_walk($config['exclude']['files'], static function (string $file, string $key, Filter $filter): void {
224 6
            $filter->excludeFile($file);
0 ignored issues
show
Bug introduced by
The method excludeFile() does not exist on SebastianBergmann\CodeCoverage\Filter. ( Ignorable by Annotation )

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

224
            $filter->/** @scrutinizer ignore-call */ 
225
                     excludeFile($file);

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...
225
        }, $filter);
226 6
227 2
        // see if we can get a driver
228
        try {
229 4
            $driver = Driver::forLineAndPathCoverage($filter);
0 ignored issues
show
Bug introduced by
The method forLineAndPathCoverage() does not exist on SebastianBergmann\CodeCoverage\Driver\Driver. ( Ignorable by Annotation )

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

229
            /** @scrutinizer ignore-call */ 
230
            $driver = Driver::forLineAndPathCoverage($filter);

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...
230
        } catch (NoCodeCoverageDriverWithPathCoverageSupportAvailableException $e) {
231
            $driver = Driver::forLineCoverage($filter);
0 ignored issues
show
Bug introduced by
The method forLineCoverage() does not exist on SebastianBergmann\CodeCoverage\Driver\Driver. ( Ignorable by Annotation )

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

231
            /** @scrutinizer ignore-call */ 
232
            $driver = Driver::forLineCoverage($filter);

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...
232 6
        }
233 2
234
        // and init coverage
235 4
        $codeCoverage = new CodeCoverage($driver, $filter);
236
237
        if ($config['includeUncoveredFiles']) {
238 6
            $codeCoverage->includeUncoveredFiles();
0 ignored issues
show
Bug introduced by
The method includeUncoveredFiles() does not exist on SebastianBergmann\CodeCoverage\CodeCoverage. ( Ignorable by Annotation )

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

238
            $codeCoverage->/** @scrutinizer ignore-call */ 
239
                           includeUncoveredFiles();

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...
239
        } else {
240
            $codeCoverage->excludeUncoveredFiles();
0 ignored issues
show
Bug introduced by
The method excludeUncoveredFiles() does not exist on SebastianBergmann\CodeCoverage\CodeCoverage. ( Ignorable by Annotation )

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

240
            $codeCoverage->/** @scrutinizer ignore-call */ 
241
                           excludeUncoveredFiles();

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...
241 2
        }
242
243
        if ($config['processUncoveredFiles']) {
244
            $codeCoverage->processUncoveredFiles();
0 ignored issues
show
Bug introduced by
The method processUncoveredFiles() does not exist on SebastianBergmann\CodeCoverage\CodeCoverage. ( Ignorable by Annotation )

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

244
            $codeCoverage->/** @scrutinizer ignore-call */ 
245
                           processUncoveredFiles();

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...
245
        } else {
246
            $codeCoverage->doNotProcessUncoveredFiles();
0 ignored issues
show
Bug introduced by
The method doNotProcessUncoveredFiles() does not exist on SebastianBergmann\CodeCoverage\CodeCoverage. ( Ignorable by Annotation )

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

246
            $codeCoverage->/** @scrutinizer ignore-call */ 
247
                           doNotProcessUncoveredFiles();

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...
247
        }
248
249
        return $codeCoverage;
250
    }
251
252
    public function initCodeCoverageV678(Filter $filter, array $config): CodeCoverage
253
    {
254
        // set up filter
255
        array_walk($config['include']['directories'], static function (array $dir, string $path, Filter $filter): void {
256
            $filter->addDirectoryToWhitelist($path, $dir['suffix'], $dir['prefix']);
257
        }, $filter);
258
259
        array_walk($config['include']['files'], static function (string $file, string $key, Filter $filter): void {
260
            $filter->addFileToWhitelist($file);
261
        }, $filter);
262
263
        array_walk($config['exclude']['directories'], static function (array $dir, string $path, Filter $filter): void {
264
            $filter->removeDirectoryFromWhitelist($path, $dir['suffix'], $dir['prefix']);
265
        }, $filter);
266
267
        array_walk($config['exclude']['files'], static function (string $file, string $key, Filter $filter): void {
268
            $filter->removeFileFromWhitelist($file);
269
        }, $filter);
270
271
        // and init coverage
272
        $codeCoverage = new CodeCoverage(null, $filter);
273
274
        $codeCoverage->setAddUncoveredFilesFromWhitelist($config['includeUncoveredFiles']);
275
        $codeCoverage->setProcessUncoveredFilesFromWhitelist($config['processUncoveredFiles']);
276
277
        return $codeCoverage;
278
    }
279
}
280