Skip to content

Commit 40f5a3e

Browse files
committed
Replace ignore-paths with include/exclude
1 parent ff5635f commit 40f5a3e

File tree

7 files changed

+121
-67
lines changed

7 files changed

+121
-67
lines changed

README.md

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Later, these targets can be retrieved through a convenient interface.
1212

1313
#### Features
1414

15-
- Zero configuration
15+
- Little configuration
1616
- No reflection in the generated file
1717
- No impact on performance
1818
- No dependency (except Composer of course)
@@ -85,6 +85,28 @@ future.
8585
want to add it to your `.gitignore` file.
8686

8787

88+
#### Sample configuration
89+
90+
The plugin only inspects paths and files specified in the configuration, that's usually your "src"
91+
directory. Add this section to your `composer.json` file to enable the generation of the attributes
92+
file on autoload dump.
93+
94+
Check the [Configuration options](#configuration) for more details.
95+
96+
```json
97+
{
98+
"extra": {
99+
"composer-attribute-collector": {
100+
"include": [
101+
"src"
102+
]
103+
}
104+
}
105+
}
106+
```
107+
108+
109+
88110

89111
## Frequently Asked Questions
90112

@@ -122,34 +144,40 @@ You can require the attributes file as shown in the usage example, but it's pref
122144

123145
## Configuration
124146

125-
### Ignoring paths ([root-only][])
147+
### Excluding paths or files ([root-only][])
126148

127-
composer-attribute-collector inspects files that participate in the autoload process. This can cause
128-
issues with files that have side effects. For instance, `symfony/cache` is known to cause issues, so
129-
we're excluding paths matching `{vendor}/symfony/cache/Traits` from inspection. Additional paths can
130-
be specified using the `extra` section of `composer.json`. The specified paths are relative to the
131-
`composer.json` file, and the `{vendor}` placeholder is replaced with the path to the vendor folder.
149+
Use the `include` property to define the paths or files to inspect for attributes. Without this
150+
property, the attributes file will be empty.
151+
152+
The specified paths are relative to the `composer.json` file, and the `{vendor}` placeholder is
153+
replaced with the path to the vendor folder.
132154

133155
```json
134156
{
135157
"extra": {
136158
"composer-attribute-collector": {
137-
"ignore-paths": [
138-
"path/to/ignore"
159+
"include": [
160+
"path-or-file/to/include"
139161
]
140162
}
141163
}
142164
}
143165
```
144166

145-
For instance, if you are only concerned about the attributes of your own project, you could ignore the vendor directory:
167+
### Excluding paths or files ([root-only][])
168+
169+
Use the `exclude` property to excluded paths or files from inspection. This is handy when files
170+
cause issues or have side effects.
171+
172+
The specified paths are relative to the `composer.json` file, and the `{vendor}` placeholder is
173+
replaced with the path to the vendor folder.
146174

147175
```json
148176
{
149177
"extra": {
150178
"composer-attribute-collector": {
151-
"ignore-paths": [
152-
"vendor"
179+
"exclude": [
180+
"path-or-file/to/ignore"
153181
]
154182
}
155183
}
@@ -168,6 +196,20 @@ Use the `symfony` command to create a new project. If you don't have it yet, you
168196
symfony new --webapp my_project
169197
```
170198

199+
Add the `composer-attribute-collector` node to `extra` in the `composer.json` file:
200+
201+
```json
202+
{
203+
"extra": {
204+
"composer-attribute-collector": {
205+
"include": [
206+
"src"
207+
]
208+
}
209+
}
210+
}
211+
```
212+
171213
Now get into that project and install the plugin. You'll be asked if you trust the plugin and wish
172214
to activate it. If you wish to continue, choose `y`.
173215

src/Config.php

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use InvalidArgumentException;
88
use RuntimeException;
99

10-
use function array_merge;
1110
use function dirname;
1211
use function is_string;
1312
use function realpath;
@@ -24,14 +23,8 @@
2423
final class Config
2524
{
2625
public const EXTRA = 'composer-attribute-collector';
27-
public const EXTRA_IGNORE_PATHS = 'ignore-paths';
28-
29-
public const BUILTIN_IGNORE_PATHS = [
30-
31-
// https://github.com/olvlvl/composer-attribute-collector/issues/4
32-
"{vendor}/symfony/cache/Traits"
33-
34-
];
26+
public const EXTRA_INCLUDE = 'include';
27+
public const EXTRA_EXCLUDE = 'exclude';
3528

3629
/**
3730
* If a path starts with this placeholder, it is replaced with the absolute path to the vendor directory.
@@ -55,30 +48,31 @@ public static function from(PartialComposer $composer): self
5548

5649
$rootDir .= DIRECTORY_SEPARATOR;
5750

58-
/** @var array{ ignore-paths?: non-empty-string[] } $extra */
51+
/** @var array{ include?: non-empty-string[], exclude?: non-empty-string[] } $extra */
5952
$extra = $composer->getPackage()->getExtra()[self::EXTRA] ?? [];
6053

61-
$ignorePaths = self::expandPaths(
62-
array_merge($extra[self::EXTRA_IGNORE_PATHS] ?? [], self::BUILTIN_IGNORE_PATHS),
63-
$vendorDir,
64-
$rootDir
65-
);
54+
$include = self::expandPaths($extra[self::EXTRA_INCLUDE] ?? [], $vendorDir, $rootDir);
55+
$exclude = self::expandPaths($extra[self::EXTRA_EXCLUDE] ?? [], $vendorDir, $rootDir);
6656

6757
return new self(
6858
attributesFile: "$vendorDir/attributes.php",
69-
ignorePaths: $ignorePaths,
59+
include: $include,
60+
exclude: $exclude,
7061
);
7162
}
7263

7364
/**
7465
* @param non-empty-string $attributesFile
7566
* Absolute path to the `attributes.php` file.
76-
* @param string[] $ignorePaths
77-
* Paths that should be ignored for attributes collection.
67+
* @param string[] $include
68+
* Paths that should be included to attributes collection.
69+
* @param string[] $exclude
70+
* Paths that should be excluded from attributes collection.
7871
*/
7972
public function __construct(
8073
public string $attributesFile,
81-
public array $ignorePaths,
74+
public array $include,
75+
public array $exclude,
8276
) {
8377
}
8478

src/Filter/PathFilter.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
<?php
22

3-
/*
4-
* (c) Olivier Laviale <olivier.laviale@gmail.com>
5-
*
6-
* For the full copyright and license information, please view the LICENSE
7-
* file that was distributed with this source code.
8-
*/
9-
103
namespace olvlvl\ComposerAttributeCollector\Filter;
114

125
use Composer\IO\IOInterface;
@@ -20,23 +13,34 @@
2013
final class PathFilter implements Filter
2114
{
2215
/**
23-
* @param string[] $matches
16+
* @param string[] $include
17+
* @param string[] $exclude
2418
*/
2519
public function __construct(
26-
private array $matches
20+
private array $include,
21+
private array $exclude,
2722
) {
2823
}
2924

3025
public function filter(string $filepath, string $class, IOInterface $io): bool
3126
{
32-
foreach ($this->matches as $match) {
27+
foreach ($this->exclude as $match) {
3328
if (str_starts_with($filepath, $match)) {
3429
$io->debug("Discarding '$class' because its path matches '$match'");
3530

3631
return false;
3732
}
3833
}
3934

40-
return true;
35+
foreach ($this->include as $match) {
36+
if (str_starts_with($filepath, $match)) {
37+
38+
return true;
39+
}
40+
}
41+
42+
$io->debug("Discarding '$class' because it does not match any included path");
43+
44+
return false;
4145
}
4246
}

src/Plugin.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
<?php
22

3-
/*
4-
* (c) Olivier Laviale <olivier.laviale@gmail.com>
5-
*
6-
* For the full copyright and license information, please view the LICENSE
7-
* file that was distributed with this source code.
8-
*/
9-
103
namespace olvlvl\ComposerAttributeCollector;
114

125
use Composer\Composer;
@@ -20,9 +13,7 @@
2013
use olvlvl\ComposerAttributeCollector\Filter\PathFilter;
2114
use ReflectionException;
2215

23-
use function array_merge;
2416
use function file_put_contents;
25-
use function is_string;
2617
use function microtime;
2718
use function spl_autoload_register;
2819
use function sprintf;
@@ -163,7 +154,10 @@ private static function setupAutoload(array $classMap): void
163154
private static function buildFileFilter(Config $config): Filter
164155
{
165156
return new Filter\Chain([
166-
new PathFilter($config->ignorePaths),
157+
new PathFilter(
158+
include: $config->include,
159+
exclude: $config->exclude
160+
),
167161
new ContentFilter(),
168162
new InterfaceFilter()
169163
]);

tests/ConfigTest.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ public function testFrom(): void
1818
{
1919
$extra = [
2020
Config::EXTRA => [
21-
Config::EXTRA_IGNORE_PATHS => [
21+
Config::EXTRA_INCLUDE => [
22+
'tests',
2223
'{vendor}/vendor1/package1',
23-
'tests/Acme/PSR4/IncompatibleSignature.php'
24-
]
24+
],
25+
Config::EXTRA_EXCLUDE => [
26+
'tests/Acme/PSR4/IncompatibleSignature.php',
27+
'{vendor}/vendor1/package1/file.php',
28+
],
2529
]
2630
];
2731

@@ -44,11 +48,14 @@ public function testFrom(): void
4448

4549
$expected = new Config(
4650
attributesFile: "$cwd/vendor/attributes.php",
47-
ignorePaths: [
51+
include: [
52+
"$cwd/tests",
4853
"$cwd/vendor/vendor1/package1",
54+
],
55+
exclude: [
4956
"$cwd/tests/Acme/PSR4/IncompatibleSignature.php",
50-
"$cwd/vendor/symfony/cache/Traits",
51-
]
57+
"$cwd/vendor/vendor1/package1/file.php",
58+
],
5259
);
5360

5461
$actual = Config::from($composer);

tests/Filter/PathFilterTest.php

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,16 @@ protected function setUp(): void
2121
{
2222
parent::setUp();
2323

24-
$this->filter = new PathFilter([
25-
"/absolute/path/to/symfony/cache/Traits"
26-
]);
24+
$this->filter = new PathFilter(
25+
include: [
26+
"/app/src",
27+
"/app/vendor",
28+
],
29+
exclude: [
30+
"/app/src/Excluded.php",
31+
"/app/vendor/symfony/cache/Traits",
32+
],
33+
);
2734
}
2835

2936
/**
@@ -43,7 +50,7 @@ public function testFilter(string $filepath, string $class, bool $expected): voi
4350
$io
4451
->expects($this->once())
4552
->method('debug')
46-
->with($this->stringStartsWith("Discarding '$class' because its path matches"));
53+
->with($this->stringStartsWith("Discarding '$class'"));
4754
}
4855

4956
$actual = $this->filter->filter($filepath, $class, $io);
@@ -58,10 +65,13 @@ public function provideFilter(): array
5865
{
5966
return [
6067

61-
[ "/absolute/path/to/symfony/cache/Traits/RedisCluster5Proxy.php", "RedisCluster5Proxy", false ],
62-
[ "some/prefix/absolute/path/to/symfony/cache/Traits/RedisCluster5Proxy.php", "RedisCluster5Proxy", true ],
63-
[ "symfony/cache/Traits/RedisCluster5Proxy.php", "RedisCluster5Proxy", true ],
64-
[ "/absolute/path/to/symfony/routing/Route.php", "Route", true ],
68+
[ "/app/src/some/file.php", "SampleClass", true ],
69+
[ "/app/src/Excluded.php", "SampleClass", false ],
70+
[ "/app/vendor/symfony/routing/Route.php", "Route", true ],
71+
[ "/app/vendor/symfony/cache/Traits/RedisCluster5Proxy.php", "RedisCluster5Proxy", false ],
72+
[ "vendor/symfony/cache/Traits/RedisCluster5Proxy.php", "RedisCluster5Proxy", false ],
73+
[ "symfony/cache/Traits/RedisCluster5Proxy.php", "RedisCluster5Proxy", false ],
74+
[ "/vendor/symfony/routing/Route.php", "Route", false ],
6575

6676
];
6777
}

tests/PluginTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ protected function setUp(): void
8282

8383
$config = new Config(
8484
$filepath,
85-
[
85+
include: [
86+
"$cwd/tests"
87+
],
88+
exclude: [
8689
"$cwd/tests/Acme/PSR4/IncompatibleSignature.php"
8790
]
8891
);

0 commit comments

Comments
 (0)