77use Rector \Contract \Rector \RectorInterface ;
88use Rector \ProcessAnalyzer \RectifiedAnalyzer ;
99use Rector \Skipper \SkipVoter \ClassSkipVoter ;
10+ use Rector \Skipper \ValueObject \SkipMatch ;
1011/**
1112 * @api
1213 * @see \Rector\Tests\Skipper\Skipper\SkipperTest
@@ -25,11 +26,16 @@ final class Skipper
2526 * @readonly
2627 */
2728 private ClassSkipVoter $ classSkipVoter ;
28- public function __construct (RectifiedAnalyzer $ rectifiedAnalyzer , \Rector \Skipper \Skipper \PathSkipper $ pathSkipper , ClassSkipVoter $ classSkipVoter )
29+ /**
30+ * @readonly
31+ */
32+ private \Rector \Skipper \Skipper \UsedSkipCollector $ usedSkipCollector ;
33+ public function __construct (RectifiedAnalyzer $ rectifiedAnalyzer , \Rector \Skipper \Skipper \PathSkipper $ pathSkipper , ClassSkipVoter $ classSkipVoter , \Rector \Skipper \Skipper \UsedSkipCollector $ usedSkipCollector )
2934 {
3035 $ this ->rectifiedAnalyzer = $ rectifiedAnalyzer ;
3136 $ this ->pathSkipper = $ pathSkipper ;
3237 $ this ->classSkipVoter = $ classSkipVoter ;
38+ $ this ->usedSkipCollector = $ usedSkipCollector ;
3339 }
3440 /**
3541 * @param string|object $element
@@ -47,20 +53,34 @@ public function shouldSkipFilePath(string $filePath): bool
4753 */
4854 public function shouldSkipElementAndFilePath ($ element , string $ filePath ): bool
4955 {
50- if (!$ this ->classSkipVoter ->match ($ element )) {
56+ $ skipMatch = $ this ->matchSkip ($ element , $ filePath );
57+ if (!$ skipMatch instanceof SkipMatch) {
5158 return \false;
5259 }
53- return $ this ->classSkipVoter ->shouldSkip ($ element , $ filePath );
60+ $ this ->markSkipUsed ($ skipMatch );
61+ return \true;
5462 }
5563 /**
56- * @param class-string<RectorInterface> $rectorClass
64+ * Match a class/path skip without marking it used. Callers that can only tell whether the skip
65+ * actually prevented a change later on must mark it used themselves via markSkipUsed().
5766 * @param string|object $element
5867 */
59- public function shouldSkipCurrentNode ($ element , string $ filePath, string $ rectorClass , Node $ node ): bool
68+ public function matchSkip ($ element , string $ filePath ): ? SkipMatch
6069 {
61- if ($ this ->shouldSkipElementAndFilePath ($ element, $ filePath )) {
62- return \true ;
70+ if (! $ this ->classSkipVoter -> match ($ element )) {
71+ return null ;
6372 }
73+ return $ this ->classSkipVoter ->matchSkip ($ element , $ filePath );
74+ }
75+ public function markSkipUsed (SkipMatch $ skipMatch ): void
76+ {
77+ $ this ->usedSkipCollector ->markUsed ($ skipMatch ->getSkippedClass (), $ skipMatch ->getMatchedPath ());
78+ }
79+ /**
80+ * @param class-string<RectorInterface> $rectorClass
81+ */
82+ public function shouldSkipCurrentNode (string $ rectorClass , Node $ node ): bool
83+ {
6484 return $ this ->rectifiedAnalyzer ->hasRectified ($ rectorClass , $ node );
6585 }
6686}
0 commit comments