Skip to content

Commit f18bc5a

Browse files
authored
Merge pull request #1186 from TravisCarden/feature/composer_psr
Add `composer_validate_autoload` task
2 parents 49baf65 + 0e537d8 commit f18bc5a

8 files changed

Lines changed: 221 additions & 2 deletions

File tree

doc/tasks.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ grumphp:
1717
composer_normalize: ~
1818
composer_require_checker: ~
1919
composer_script: ~
20+
composer_validate_autoload: ~
2021
deptrac: ~
2122
doctrine_orm: ~
2223
ecs: ~
@@ -83,6 +84,7 @@ Every task has its own default configuration. It is possible to overwrite the pa
8384
- [Composer Normalize](tasks/composer_normalize.md)
8485
- [Composer Require Checker](tasks/composer_require_checker.md)
8586
- [Composer Script](tasks/composer_script.md)
87+
- [Composer Validate Autoload](tasks/composer_validate_autoload.md)
8688
- [Doctrine ORM](tasks/doctrine_orm.md)
8789
- [Ecs EasyCodingStandard](tasks/ecs.md)
8890
- [ESLint](tasks/eslint.md)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Composer Validate Autoload
2+
3+
This task checks for PSR-4 or PSR-0 mapping errors. It will run [`composer dump-autoload`](https://getcomposer.org/doc/03-cli.md#dump-autoload-dumpautoload) (with the `--dry-run` option to avoid actually changing files). The configuration looks like:
4+
5+
***Config***
6+
7+
```yaml
8+
# grumphp.yml
9+
grumphp:
10+
tasks:
11+
composer_validate_autoload:
12+
file: ./composer.json
13+
strict_ambiguous: false
14+
```
15+
16+
**file**
17+
18+
*Default: ./composer.json*
19+
20+
Specifies at which location the `composer.json` file can be found.
21+
22+
**strict_ambiguous**
23+
24+
*Default: false*
25+
26+
Checks whether the same class is ever defined in multiple files. It is set to `false` by default, as enabling it can result in false positives--especially in the common case where polyfill packages are present in the vendor directory.

grumphp.yml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ grumphp:
1616
no_check_lock: true
1717
composer_normalize:
1818
use_standalone: true
19+
composer_validate_autoload: ~
1920
yamllint:
2021
parse_custom_tags: true
2122
ignore_patterns:

resources/config/tasks.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ services:
6969
tags:
7070
- {name: grumphp.task, task: composer_require_checker}
7171

72+
GrumPHP\Task\ComposerValidateAutoload:
73+
arguments:
74+
- '@process_builder'
75+
- '@formatter.raw_process'
76+
tags:
77+
- {name: grumphp.task, task: composer_validate_autoload}
78+
7279
GrumPHP\Task\Deptrac:
7380
arguments:
7481
- '@process_builder'
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace GrumPHP\Task;
6+
7+
use GrumPHP\Formatter\ProcessFormatterInterface;
8+
use GrumPHP\Runner\TaskResult;
9+
use GrumPHP\Runner\TaskResultInterface;
10+
use GrumPHP\Task\Config\ConfigOptionsResolver;
11+
use GrumPHP\Task\Context\ContextInterface;
12+
use GrumPHP\Task\Context\GitPreCommitContext;
13+
use GrumPHP\Task\Context\RunContext;
14+
use Symfony\Component\OptionsResolver\OptionsResolver;
15+
16+
/**
17+
* @extends AbstractExternalTask<ProcessFormatterInterface>
18+
*/
19+
class ComposerValidateAutoload extends AbstractExternalTask
20+
{
21+
public function canRunInContext(ContextInterface $context): bool
22+
{
23+
return $context instanceof GitPreCommitContext || $context instanceof RunContext;
24+
}
25+
26+
public static function getConfigurableOptions(): ConfigOptionsResolver
27+
{
28+
$resolver = new OptionsResolver();
29+
$resolver->setDefaults([
30+
'file' => './composer.json',
31+
'strict_ambiguous' => false,
32+
]);
33+
34+
$resolver->addAllowedTypes('file', ['string']);
35+
$resolver->addAllowedTypes('strict_ambiguous', ['bool']);
36+
37+
return ConfigOptionsResolver::fromOptionsResolver($resolver);
38+
}
39+
40+
public function run(ContextInterface $context): TaskResultInterface
41+
{
42+
$config = $this->getConfig()->getOptions();
43+
$composerDir = pathinfo($config['file'], PATHINFO_DIRNAME);
44+
$composerFile = pathinfo($config['file'], PATHINFO_BASENAME);
45+
$files = $context->getFiles()
46+
->path($composerDir)
47+
->name($composerFile);
48+
if (0 === \count($files)) {
49+
return TaskResult::createSkipped($this, $context);
50+
}
51+
52+
$config = $this->getConfig()->getOptions();
53+
54+
$arguments = $this->processBuilder->createArgumentsForCommand('composer');
55+
$arguments->add('dump-autoload');
56+
$arguments->add('--optimize');
57+
$arguments->add('--dry-run');
58+
$arguments->add('--strict-psr');
59+
$arguments->addOptionalArgument('--strict-ambiguous', $config['strict_ambiguous']);
60+
61+
$process = $this->processBuilder->buildProcess($arguments);
62+
$process->run();
63+
64+
if (!$process->isSuccessful()) {
65+
return TaskResult::createFailed($this, $context, $process->getErrorOutput());
66+
}
67+
68+
return TaskResult::createPassed($this, $context);
69+
}
70+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace GrumPHPTest\Unit\Task;
6+
7+
use GrumPHP\Task\ComposerValidateAutoload;
8+
use GrumPHP\Task\Context\GitPreCommitContext;
9+
use GrumPHP\Task\Context\RunContext;
10+
use GrumPHP\Task\TaskInterface;
11+
use GrumPHP\Test\Task\AbstractExternalTaskTestCase;
12+
13+
class ComposerValidateAutoloadTest extends AbstractExternalTaskTestCase
14+
{
15+
protected function provideTask(): TaskInterface
16+
{
17+
return new ComposerValidateAutoload(
18+
$this->processBuilder->reveal(),
19+
$this->formatter->reveal()
20+
);
21+
}
22+
23+
public function provideConfigurableOptions(): iterable
24+
{
25+
yield 'defaults' => [
26+
[],
27+
[
28+
'file' => './composer.json',
29+
'strict_ambiguous' => false,
30+
]
31+
];
32+
}
33+
34+
public function provideRunContexts(): iterable
35+
{
36+
yield 'run-context' => [
37+
true,
38+
$this->mockContext(RunContext::class)
39+
];
40+
41+
yield 'pre-commit-context' => [
42+
true,
43+
$this->mockContext(GitPreCommitContext::class)
44+
];
45+
46+
yield 'other' => [
47+
false,
48+
$this->mockContext()
49+
];
50+
}
51+
52+
public function provideFailsOnStuff(): iterable
53+
{
54+
yield 'exitCode1' => [
55+
[],
56+
$this->mockContext(RunContext::class, ['composer.json']),
57+
function () {
58+
$this->mockProcessBuilder(
59+
'composer',
60+
$this->mockProcess(1, '', 'nope'),
61+
);
62+
},
63+
'nope',
64+
];
65+
}
66+
67+
public function providePassesOnStuff(): iterable
68+
{
69+
yield 'exitCode0' => [
70+
[],
71+
$this->mockContext(RunContext::class, ['composer.json']),
72+
function () {
73+
$this->mockProcessBuilder('composer', $this->mockProcess());
74+
}
75+
];
76+
}
77+
78+
public function provideSkipsOnStuff(): iterable
79+
{
80+
yield 'no-files' => [
81+
[],
82+
$this->mockContext(RunContext::class),
83+
function () {}
84+
];
85+
}
86+
87+
public function provideExternalTaskRuns(): iterable
88+
{
89+
yield 'defaults' => [
90+
[],
91+
$this->mockContext(RunContext::class, ['composer.json']),
92+
'composer',
93+
[
94+
'dump-autoload',
95+
'--optimize',
96+
'--dry-run',
97+
'--strict-psr',
98+
]
99+
];
100+
yield 'strict-ambiguous' => [
101+
['strict_ambiguous' => true],
102+
$this->mockContext(RunContext::class, ['composer.json']),
103+
'composer',
104+
[
105+
'dump-autoload',
106+
'--optimize',
107+
'--dry-run',
108+
'--strict-psr',
109+
'--strict-ambiguous',
110+
]
111+
];
112+
}
113+
}

test/Unit/Task/ESLintTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace GrumPHP\Test\Unit\Task;
5+
namespace GrumPHPTest\Unit\Task;
66

77
use GrumPHP\Runner\FixableTaskResult;
88
use GrumPHP\Task\Context\GitPreCommitContext;

test/Unit/Task/StylelintTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
declare(strict_types=1);
44

5-
namespace GrumPHP\Test\Unit\Task;
5+
namespace GrumPHPTest\Unit\Task;
66

77
use GrumPHP\Runner\FixableTaskResult;
88
use GrumPHP\Task\Context\GitPreCommitContext;

0 commit comments

Comments
 (0)