Passed
Push — master ( 23458e...f5dfbe )
by Doug
03:55
created

Extension::initCodeCoverageV678()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 1.0001

Importance

Changes 0
Metric Value
cc 1
eloc 16
nc 1
nop 2
dl 0
loc 26
ccs 17
cts 18
cp 0.9444
crap 1.0001
rs 9.7333
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;
21
use SebastianBergmann\CodeCoverage\NoCodeCoverageDriverWithPathCoverageSupportAvailableException;
22
use SebastianBergmann\CodeCoverage\RuntimeException;
0 ignored issues
show
Bug introduced by
The type SebastianBergmann\CodeCoverage\RuntimeException 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...
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
 */
36
class Extension implements ExtensionInterface
37
{
38
    /**
39
     * {@inheritdoc}
40
     */
41 22
    public function initialize(ExtensionManager $extensionManager): void
42
    {
43 22
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 22
    public function load(ContainerBuilder $container, array $config): void
49
    {
50 22
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/Resources/config'));
51
52 22
        $servicesFile = 'services.xml';
53 22
        $loader->load($servicesFile);
54
55 22
        $container->setParameter('behat.code_coverage.config.filter', $config['filter']);
56 22
        $container->setParameter('behat.code_coverage.config.reports', $config['reports'] ?? []);
57 22
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 44
    public function configure(ArrayNodeDefinition $builder): void
63
    {
64
        $builder
65 44
            ->children()
66 44
                ->arrayNode('filter')
67 44
                    ->addDefaultsIfNotSet()
68 44
                    ->children()
69 44
                        ->scalarNode('includeUncoveredFiles')
70 44
                            ->defaultTrue()
71 44
                        ->end()
72 44
                        ->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 44
                            ->defaultFalse()
74 44
                        ->end()
75 44
                        ->arrayNode('include')
76 44
                            ->addDefaultsIfNotSet()
77 44
                            ->children()
78 44
                                ->arrayNode('directories')
79 44
                                   ->useAttributeAsKey('name')
80 44
                                   ->normalizeKeys(false)
81 44
                                   ->prototype('array')
82 44
                                       ->children()
83 44
                                           ->scalarNode('prefix')->defaultValue('')->end()
84 44
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
85 44
                                       ->end()
86 44
                                   ->end()
87 44
                                ->end()
88 44
                                ->arrayNode('files')
89 44
                                   ->prototype('scalar')->end()
90 44
                                ->end()
91 44
                            ->end()
92 44
                        ->end()
93 44
                        ->arrayNode('exclude')
94 44
                            ->addDefaultsIfNotSet()
95 44
                            ->children()
96 44
                                ->arrayNode('directories')
97 44
                                   ->useAttributeAsKey('name')
98 44
                                   ->normalizeKeys(false)
99 44
                                   ->prototype('array')
100 44
                                       ->children()
101 44
                                           ->scalarNode('prefix')->defaultValue('')->end()
102 44
                                           ->scalarNode('suffix')->defaultValue('.php')->end()
103 44
                                       ->end()
104 44
                                   ->end()
105 44
                                ->end()
106 44
                                ->arrayNode('files')
107 44
                                   ->prototype('scalar')->end()
108 44
                                ->end()
109 44
                            ->end()
110 44
                        ->end()
111 44
                    ->end()
112 44
                ->end()
113 44
                ->arrayNode('reports')
114 44
                    ->children()
115 44
                        ->arrayNode('clover')
116 44
                            ->children()
117 44
                                ->scalarNode('name')->defaultNull()->end()
118 44
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
119 44
                            ->end()
120 44
                        ->end()
121 44
                        ->arrayNode('crap4j')
122 44
                            ->children()
123 44
                                ->scalarNode('name')->defaultNull()->end()
124 44
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
125 44
                            ->end()
126 44
                        ->end()
127 44
                        ->arrayNode('html')
128 44
                            ->children()
129 44
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
130 44
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
131 44
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
132 44
                            ->end()
133 44
                        ->end()
134 44
                        ->arrayNode('php')
135 44
                            ->children()
136 44
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
137 44
                            ->end()
138 44
                        ->end()
139 44
                        ->arrayNode('text')
140 44
                            ->children()
141 44
                                ->booleanNode('showColors')->defaultValue(false)->end()
142 44
                                ->scalarNode('lowUpperBound')->defaultValue(50)->end()
143 44
                                ->scalarNode('highLowerBound')->defaultValue(90)->end()
144 44
                                ->booleanNode('showOnlySummary')->defaultValue(false)->end()
145 44
                                ->booleanNode('showUncoveredFiles')->defaultValue(false)->end()
146 44
                            ->end()
147 44
                        ->end()
148 44
                        ->arrayNode('xml')
149 44
                            ->children()
150 44
                                ->scalarNode('target')->isRequired()->cannotBeEmpty()->end()
151 44
                            ->end()
152 44
                        ->end()
153 44
                    ->end()
154 44
                ->end()
155 44
            ->end()
156 44
        ->end();
157 44
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162 44
    public function getConfigKey()
163
    {
164 44
        return 'code_coverage';
165
    }
166
167
    /**
168
     * {@inheritdoc}
169
     */
170 88
    public function process(ContainerBuilder $container): void
171
    {
172
        /** @var InputInterface $input */
173 88
        $input = $container->get('cli.input');
174
175
        /** @var OutputInterface $output */
176 88
        $output = $container->get('cli.output');
177
178 88
        $config = $container->getParameter('behat.code_coverage.config.filter');
179
180 88
        $canCollectCodeCoverage = true;
181
        try {
182 88
            $this->initCodeCoverage(new Filter(), $config);
183
184 66
            $codeCoverage = $container->getDefinition(CodeCoverage::class);
185 66
            $filter = $container->getDefinition(Filter::class);
186 66
            $codeCoverage->setFactory([new Reference(self::class), 'initCodeCoverage']);
187 66
            $codeCoverage->setArguments([$filter, $config]);
188 22
        } catch (NoCodeCoverageDriverAvailableException | RuntimeException $e) {
189 22
            $output->writeln('<comment>No code coverage driver is available</comment>');
190 22
            $canCollectCodeCoverage = false;
191
        }
192
193 88
        if (!$canCollectCodeCoverage || $input->hasParameterOption('--no-coverage')) {
194 44
            $container->getDefinition(EventSubscriber::class)->setArgument('$coverage', null);
195
        }
196 88
    }
197
198 66
    public function initCodeCoverage(Filter $filter, array $config): CodeCoverage
199
    {
200 66
        $driverClassReflection = new \ReflectionClass(Driver::class);
201 66
        if ($driverClassReflection->isInterface()) {
202 36
            return $this->initCodeCoverageV678($filter, $config);
203
        }
204
205 30
        return $this->initCodeCoverageV9($filter, $config);
206
    }
207
208 30
    public function initCodeCoverageV9(Filter $filter, array $config): CodeCoverage
209
    {
210
        // set up filter
211 30
        array_walk($config['include']['directories'], static function (array $dir, string $path, Filter $filter): void {
212 30
            $filter->includeDirectory($path, $dir['suffix'], $dir['prefix']);
213 30
        }, $filter);
214
215 30
        array_walk($config['include']['files'], static function (string $file, string $key, Filter $filter): void {
216 30
            $filter->includeFile($file);
217 30
        }, $filter);
218
219 30
        array_walk($config['exclude']['directories'], static function (array $dir, string $path, Filter $filter): void {
220 30
            $filter->excludeDirectory($path, $dir['suffix'], $dir['prefix']);
221 30
        }, $filter);
222
223 30
        array_walk($config['exclude']['files'], static function (string $file, string $key, Filter $filter): void {
224 30
            $filter->excludeFile($file);
225 30
        }, $filter);
226
227
        // see if we can get a driver
228
        try {
229 30
            $driver = Driver::forLineAndPathCoverage($filter);
230 15
        } catch (NoCodeCoverageDriverWithPathCoverageSupportAvailableException $e) {
231 15
            $driver = Driver::forLineCoverage($filter);
232
        }
233
234
        // and init coverage
235 30
        $codeCoverage = new CodeCoverage($driver, $filter);
236
237 30
        if ($config['includeUncoveredFiles']) {
238 10
            $codeCoverage->includeUncoveredFiles();
239
        } else {
240 20
            $codeCoverage->excludeUncoveredFiles();
241
        }
242
243 30
        if ($config['processUncoveredFiles']) {
244 10
            $codeCoverage->processUncoveredFiles();
245
        } else {
246 20
            $codeCoverage->doNotProcessUncoveredFiles();
247
        }
248
249 30
        return $codeCoverage;
250
    }
251
252 36
    public function initCodeCoverageV678(Filter $filter, array $config): CodeCoverage
253
    {
254
        // set up filter
255 18
        array_walk($config['include']['directories'], static function (array $dir, string $path, Filter $filter): void {
256 36
            $filter->addDirectoryToWhitelist($path, $dir['suffix'], $dir['prefix']);
0 ignored issues
show
Bug introduced by
The method addDirectoryToWhitelist() 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

256
            $filter->/** @scrutinizer ignore-call */ 
257
                     addDirectoryToWhitelist($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...
257 36
        }, $filter);
258
259 18
        array_walk($config['include']['files'], static function (string $file, string $key, Filter $filter): void {
260 36
            $filter->addFileToWhitelist($file);
0 ignored issues
show
Bug introduced by
The method addFileToWhitelist() 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

260
            $filter->/** @scrutinizer ignore-call */ 
261
                     addFileToWhitelist($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...
261 36
        }, $filter);
262
263 18
        array_walk($config['exclude']['directories'], static function (array $dir, string $path, Filter $filter): void {
264 36
            $filter->removeDirectoryFromWhitelist($path, $dir['suffix'], $dir['prefix']);
0 ignored issues
show
Bug introduced by
The method removeDirectoryFromWhitelist() 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

264
            $filter->/** @scrutinizer ignore-call */ 
265
                     removeDirectoryFromWhitelist($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...
265 36
        }, $filter);
266
267 18
        array_walk($config['exclude']['files'], static function (string $file, string $key, Filter $filter): void {
268 36
            $filter->removeFileFromWhitelist($file);
0 ignored issues
show
Bug introduced by
The method removeFileFromWhitelist() 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

268
            $filter->/** @scrutinizer ignore-call */ 
269
                     removeFileFromWhitelist($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...
269 36
        }, $filter);
270
271
        // and init coverage
272 36
        $codeCoverage = new CodeCoverage(null, $filter);
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type SebastianBergmann\CodeCoverage\Driver\Driver expected by parameter $driver of SebastianBergmann\CodeCo...Coverage::__construct(). ( Ignorable by Annotation )

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

272
        $codeCoverage = new CodeCoverage(/** @scrutinizer ignore-type */ null, $filter);
Loading history...
273
274 36
        $codeCoverage->setAddUncoveredFilesFromWhitelist($config['includeUncoveredFiles']);
0 ignored issues
show
Bug introduced by
The method setAddUncoveredFilesFromWhitelist() 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

274
        $codeCoverage->/** @scrutinizer ignore-call */ 
275
                       setAddUncoveredFilesFromWhitelist($config['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...
275 36
        $codeCoverage->setProcessUncoveredFilesFromWhitelist($config['processUncoveredFiles']);
0 ignored issues
show
Bug introduced by
The method setProcessUncoveredFilesFromWhitelist() 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

275
        $codeCoverage->/** @scrutinizer ignore-call */ 
276
                       setProcessUncoveredFilesFromWhitelist($config['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...
276
277 36
        return $codeCoverage;
278
    }
279
}
280