1515use Composer \IO \IOInterface ;
1616use Composer \Plugin \PluginInterface ;
1717use Composer \Script \Event ;
18+ use olvlvl \ComposerAttributeCollector \Filter \ContentFilter ;
19+ use olvlvl \ComposerAttributeCollector \Filter \InterfaceFilter ;
20+ use olvlvl \ComposerAttributeCollector \Filter \PathFilter ;
1821use ReflectionAttribute ;
1922use ReflectionClass ;
2023use ReflectionException ;
2124use ReflectionMethod ;
22- use Throwable ;
2325
26+ use function array_filter ;
2427use function array_map ;
25- use function file_get_contents ;
28+ use function array_merge ;
2629use function file_put_contents ;
2730use function implode ;
28- use function interface_exists ;
2931use function is_string ;
3032use function spl_autoload_register ;
31- use function str_contains ;
3233use function var_export ;
3334
35+ use const ARRAY_FILTER_USE_BOTH ;
36+
3437/**
3538 * @internal
3639 */
3740final class Plugin implements PluginInterface, EventSubscriberInterface
3841{
42+ public const EXTRA = 'composer-attribute-collector ' ;
43+ public const EXTRA_IGNORE_PATHS = 'ignore-paths ' ;
44+
45+ private const PROBLEMATIC_PATHS = [
46+ // https://github.com/olvlvl/composer-attribute-collector/issues/4
47+ 'symfony/cache/Traits '
48+ ];
49+
3950 /**
4051 * @uses onPostAutoloadDump
4152 *
@@ -97,6 +108,13 @@ public static function dump(
97108
98109 self ::setupAutoload ($ classMap );
99110
111+ $ filter = self ::buildClassMapFilter ($ composer );
112+ $ classMap = array_filter (
113+ $ classMap ,
114+ fn ($ class , $ filepath ) => $ filter ->filter ($ class , $ filepath , $ io ),
115+ ARRAY_FILTER_USE_BOTH
116+ );
117+
100118 $ collection = self ::collectAttributes ($ classMap , $ io );
101119 $ code = self ::render ($ collection );
102120
@@ -116,6 +134,23 @@ private static function setupAutoload(array $classMap): void
116134 });
117135 }
118136
137+ private static function buildClassMapFilter (Composer $ composer ): Filter
138+ {
139+ $ extra = $ composer ->getPackage ()->getExtra ()[self ::EXTRA ] ?? [];
140+ /** @var string[] $ignore_paths */
141+ $ ignore_paths = array_merge (
142+ // @phpstan-ignore-next-line
143+ $ extra [self ::EXTRA_IGNORE_PATHS ] ?? [],
144+ self ::PROBLEMATIC_PATHS
145+ );
146+
147+ return new Filter \Chain ([
148+ new PathFilter ($ ignore_paths ),
149+ new ContentFilter (),
150+ new InterfaceFilter ()
151+ ]);
152+ }
153+
119154 /**
120155 * @param array<class-string, non-empty-string> $classMap
121156 *
@@ -126,24 +161,6 @@ private static function collectAttributes(array $classMap, IOInterface $io): Col
126161 $ collector = new Collector ();
127162
128163 foreach ($ classMap as $ class => $ filepath ) {
129- $ content = file_get_contents ($ filepath );
130-
131- assert (is_string ($ content ));
132-
133- if (!str_contains ($ content , '#[ ' )) {
134- continue ;
135- }
136-
137- try {
138- if (interface_exists ($ class )) {
139- continue ;
140- }
141- } catch (Throwable $ e ) {
142- $ io ->warning ("Discarding ' $ class' because an error occurred during loading: {$ e ->getMessage ()}" );
143-
144- continue ;
145- }
146-
147164 $ classReflection = new ReflectionClass ($ class );
148165
149166 if (self ::isAttribute ($ classReflection )) {
0 commit comments