@@ -51,7 +51,7 @@ final class DocBlockHeaderFixer extends AbstractFixer implements ConfigurableFix
5151 public function getDefinition (): FixerDefinitionInterface
5252 {
5353 return new FixerDefinition (
54- 'Add configurable DocBlock annotations before class declarations. ' ,
54+ 'Add configurable DocBlock annotations before class, interface, trait, and enum declarations. ' ,
5555 [],
5656 );
5757 }
@@ -63,7 +63,10 @@ public function getName(): string
6363
6464 public function isCandidate (Tokens $ tokens ): bool
6565 {
66- return $ tokens ->isTokenKindFound (T_CLASS );
66+ return $ tokens ->isTokenKindFound (T_CLASS )
67+ || $ tokens ->isTokenKindFound (T_INTERFACE )
68+ || $ tokens ->isTokenKindFound (T_TRAIT )
69+ || $ tokens ->isTokenKindFound (T_ENUM );
6770 }
6871
6972 public function getConfigurationDefinition (): FixerConfigurationResolverInterface
@@ -81,7 +84,7 @@ public function getConfigurationDefinition(): FixerConfigurationResolverInterfac
8184 ->setAllowedValues (Separate::getList ())
8285 ->setDefault (Separate::None->value )
8386 ->getOption (),
84- (new FixerOptionBuilder ('add_class_name ' , 'Add class name before annotations ' ))
87+ (new FixerOptionBuilder ('add_structure_name ' , 'Add structure name before annotations ' ))
8588 ->setAllowedTypes (['bool ' ])
8689 ->setDefault (false )
8790 ->getOption (),
@@ -103,45 +106,45 @@ protected function applyFix(SplFileInfo $file, Tokens $tokens): void
103106 for ($ index = 0 , $ limit = $ tokens ->count (); $ index < $ limit ; ++$ index ) {
104107 $ token = $ tokens [$ index ];
105108
106- if (!$ token ->isGivenKind (T_CLASS )) {
109+ if (!$ token ->isGivenKind ([ T_CLASS , T_INTERFACE , T_TRAIT , T_ENUM ] )) {
107110 continue ;
108111 }
109112
110- $ className = $ this ->getClassName ($ tokens , $ index );
111- $ this ->processClassDocBlock ($ tokens , $ index , $ annotations , $ className );
113+ $ structureName = $ this ->getStructureName ($ tokens , $ index );
114+ $ this ->processStructureDocBlock ($ tokens , $ index , $ annotations , $ structureName );
112115 }
113116 }
114117
115118 /**
116119 * @param array<string, string|array<string>> $annotations
117120 */
118- private function processClassDocBlock (Tokens $ tokens , int $ classIndex , array $ annotations , string $ className ): void
121+ private function processStructureDocBlock (Tokens $ tokens , int $ structureIndex , array $ annotations , string $ structureName ): void
119122 {
120- $ existingDocBlockIndex = $ this ->findExistingDocBlock ($ tokens , $ classIndex );
123+ $ existingDocBlockIndex = $ this ->findExistingDocBlock ($ tokens , $ structureIndex );
121124 $ preserveExisting = $ this ->resolvedConfiguration ['preserve_existing ' ] ?? true ;
122125
123126 if (null !== $ existingDocBlockIndex ) {
124127 if ($ preserveExisting ) {
125- $ this ->mergeWithExistingDocBlock ($ tokens , $ existingDocBlockIndex , $ annotations , $ className );
128+ $ this ->mergeWithExistingDocBlock ($ tokens , $ existingDocBlockIndex , $ annotations , $ structureName );
126129 } else {
127- $ this ->replaceDocBlock ($ tokens , $ existingDocBlockIndex , $ annotations , $ className );
130+ $ this ->replaceDocBlock ($ tokens , $ existingDocBlockIndex , $ annotations , $ structureName );
128131 }
129132 } else {
130- $ this ->insertNewDocBlock ($ tokens , $ classIndex , $ annotations , $ className );
133+ $ this ->insertNewDocBlock ($ tokens , $ structureIndex , $ annotations , $ structureName );
131134 }
132135 }
133136
134- private function getClassName (Tokens $ tokens , int $ classIndex ): string
137+ private function getStructureName (Tokens $ tokens , int $ structureIndex ): string
135138 {
136- // Look for the class name token after the 'class' keyword
137- for ($ i = $ classIndex + 1 , $ limit = $ tokens ->count (); $ i < $ limit ; ++$ i ) {
139+ // Look for the structure name token after the keyword (class/interface/trait/enum)
140+ for ($ i = $ structureIndex + 1 , $ limit = $ tokens ->count (); $ i < $ limit ; ++$ i ) {
138141 $ token = $ tokens [$ i ];
139142
140143 if ($ token ->isWhitespace ()) {
141144 continue ;
142145 }
143146
144- // The first non-whitespace token after 'class' should be the class name
147+ // The first non-whitespace token after the keyword should be the structure name
145148 if ($ token ->isGivenKind (T_STRING )) {
146149 return $ token ->getContent ();
147150 }
@@ -153,9 +156,9 @@ private function getClassName(Tokens $tokens, int $classIndex): string
153156 return '' ;
154157 }
155158
156- private function findExistingDocBlock (Tokens $ tokens , int $ classIndex ): ?int
159+ private function findExistingDocBlock (Tokens $ tokens , int $ structureIndex ): ?int
157160 {
158- for ($ i = $ classIndex - 1 ; $ i >= 0 ; --$ i ) {
161+ for ($ i = $ structureIndex - 1 ; $ i >= 0 ; --$ i ) {
159162 $ token = $ tokens [$ i ];
160163
161164 if ($ token ->isWhitespace ()) {
@@ -178,32 +181,32 @@ private function findExistingDocBlock(Tokens $tokens, int $classIndex): ?int
178181 /**
179182 * @param array<string, string|array<string>> $annotations
180183 */
181- private function mergeWithExistingDocBlock (Tokens $ tokens , int $ docBlockIndex , array $ annotations , string $ className ): void
184+ private function mergeWithExistingDocBlock (Tokens $ tokens , int $ docBlockIndex , array $ annotations , string $ structureName ): void
182185 {
183186 $ existingContent = $ tokens [$ docBlockIndex ]->getContent ();
184187 $ existingAnnotations = $ this ->parseExistingAnnotations ($ existingContent );
185188 $ mergedAnnotations = $ this ->mergeAnnotations ($ existingAnnotations , $ annotations );
186189
187- $ newDocBlock = $ this ->buildDocBlock ($ mergedAnnotations , $ className );
190+ $ newDocBlock = $ this ->buildDocBlock ($ mergedAnnotations , $ structureName );
188191 $ tokens [$ docBlockIndex ] = new Token ([T_DOC_COMMENT , $ newDocBlock ]);
189192 }
190193
191194 /**
192195 * @param array<string, string|array<string>> $annotations
193196 */
194- private function replaceDocBlock (Tokens $ tokens , int $ docBlockIndex , array $ annotations , string $ className ): void
197+ private function replaceDocBlock (Tokens $ tokens , int $ docBlockIndex , array $ annotations , string $ structureName ): void
195198 {
196- $ newDocBlock = $ this ->buildDocBlock ($ annotations , $ className );
199+ $ newDocBlock = $ this ->buildDocBlock ($ annotations , $ structureName );
197200 $ tokens [$ docBlockIndex ] = new Token ([T_DOC_COMMENT , $ newDocBlock ]);
198201 }
199202
200203 /**
201204 * @param array<string, string|array<string>> $annotations
202205 */
203- private function insertNewDocBlock (Tokens $ tokens , int $ classIndex , array $ annotations , string $ className ): void
206+ private function insertNewDocBlock (Tokens $ tokens , int $ structureIndex , array $ annotations , string $ structureName ): void
204207 {
205208 $ separate = $ this ->resolvedConfiguration ['separate ' ] ?? 'none ' ;
206- $ insertIndex = $ this ->findInsertPosition ($ tokens , $ classIndex );
209+ $ insertIndex = $ this ->findInsertPosition ($ tokens , $ structureIndex );
207210
208211 $ tokensToInsert = [];
209212
@@ -213,14 +216,14 @@ private function insertNewDocBlock(Tokens $tokens, int $classIndex, array $annot
213216 }
214217
215218 // Add the DocBlock
216- $ docBlock = $ this ->buildDocBlock ($ annotations , $ className );
219+ $ docBlock = $ this ->buildDocBlock ($ annotations , $ structureName );
217220 $ tokensToInsert [] = new Token ([T_DOC_COMMENT , $ docBlock ]);
218221
219222 // For compatibility with no_blank_lines_after_phpdoc, only add bottom separation when 'separate' is not 'none'
220223 // This prevents conflicts with PHP-CS-Fixer rules that manage DocBlock spacing
221224 if (in_array ($ separate , ['bottom ' , 'both ' ], true )) {
222- // Check if there's already whitespace after the class declaration
223- $ nextToken = $ tokens [$ classIndex ] ?? null ;
225+ // Check if there's already whitespace after the structure declaration
226+ $ nextToken = $ tokens [$ structureIndex ] ?? null ;
224227 if (null !== $ nextToken && !$ nextToken ->isWhitespace ()) {
225228 $ tokensToInsert [] = new Token ([T_WHITESPACE , "\n" ]);
226229 }
@@ -229,12 +232,12 @@ private function insertNewDocBlock(Tokens $tokens, int $classIndex, array $annot
229232 $ tokens ->insertAt ($ insertIndex , $ tokensToInsert );
230233 }
231234
232- private function findInsertPosition (Tokens $ tokens , int $ classIndex ): int
235+ private function findInsertPosition (Tokens $ tokens , int $ structureIndex ): int
233236 {
234- $ insertIndex = $ classIndex ;
237+ $ insertIndex = $ structureIndex ;
235238
236239 // Look backwards for attributes, final, abstract keywords
237- for ($ i = $ classIndex - 1 ; $ i >= 0 ; --$ i ) {
240+ for ($ i = $ structureIndex - 1 ; $ i >= 0 ; --$ i ) {
238241 $ token = $ tokens [$ i ];
239242
240243 if ($ token ->isWhitespace ()) {
@@ -287,21 +290,21 @@ private function mergeAnnotations(array $existing, array $new): array
287290 /**
288291 * @param array<string, string|array<string>> $annotations
289292 */
290- private function buildDocBlock (array $ annotations , string $ className ): string
293+ private function buildDocBlock (array $ annotations , string $ structureName ): string
291294 {
292- $ addClassName = $ this ->resolvedConfiguration ['add_class_name ' ] ?? false ;
295+ $ addStructureName = $ this ->resolvedConfiguration ['add_structure_name ' ] ?? false ;
293296
294- if (empty ($ annotations ) && !$ addClassName ) {
297+ if (empty ($ annotations ) && !$ addStructureName ) {
295298 return "/** \n */ " ;
296299 }
297300
298301 $ docBlock = "/** \n" ;
299302
300- // Add class name with dot if configured
301- if ($ addClassName && !empty ($ className )) {
302- $ docBlock .= " * {$ className }. \n" ;
303+ // Add structure name with dot if configured
304+ if ($ addStructureName && !empty ($ structureName )) {
305+ $ docBlock .= " * {$ structureName }. \n" ;
303306
304- // Add empty line after class name if there are annotations - compatible with phpdoc_separation
307+ // Add empty line after structure name if there are annotations - compatible with phpdoc_separation
305308 if (!empty ($ annotations )) {
306309 $ docBlock .= " * \n" ;
307310 }
0 commit comments