22
33namespace SlevomatCodingStandard \Sniffs \Types ;
44
5+ use SlevomatCodingStandard \Helpers \SniffSettingsHelper ;
6+
57class EmptyLinesAroundTypeBracesSniff implements \PHP_CodeSniffer_Sniff
68{
79
810 const CODE_NO_EMPTY_LINE_AFTER_OPENING_BRACE = 'NoEmptyLineAfterOpeningBrace ' ;
911
1012 const CODE_MULTIPLE_EMPTY_LINES_AFTER_OPENING_BRACE = 'MultipleEmptyLinesAfterOpeningBrace ' ;
1113
14+ const CODE_INCORRECT_EMPTY_LINES_AFTER_OPENING_BRACE = 'IncorrectEmptyLinesAfterOpeningBrace ' ;
15+
1216 const CODE_NO_EMPTY_LINE_BEFORE_CLOSING_BRACE = 'NoEmptyLineBeforeClosingBrace ' ;
1317
1418 const CODE_MULTIPLE_EMPTY_LINES_BEFORE_CLOSING_BRACE = 'MultipleEmptyLinesBeforeClosingBrace ' ;
1519
20+ const CODE_INCORRECT_EMPTY_LINES_BEFORE_CLOSING_BRACE = 'IncorrectEmptyLinesBeforeClosingBrace ' ;
21+
22+ /** @var int */
23+ public $ linesCountAfterOpeningBrace = 1 ;
24+
25+ /** @var int */
26+ public $ linesCountBeforeClosingBrace = 1 ;
27+
1628 /**
1729 * @return int[]
1830 */
@@ -31,74 +43,119 @@ public function register(): array
3143 * @param int $stackPointer
3244 */
3345 public function process (\PHP_CodeSniffer_File $ phpcsFile , $ stackPointer )
46+ {
47+ $ this ->processOpeningBrace ($ phpcsFile , $ stackPointer );
48+ $ this ->processClosingBrace ($ phpcsFile , $ stackPointer );
49+ }
50+
51+ private function processOpeningBrace (\PHP_CodeSniffer_File $ phpcsFile , int $ stackPointer )
3452 {
3553 $ tokens = $ phpcsFile ->getTokens ();
3654 $ typeToken = $ tokens [$ stackPointer ];
3755 $ openerPointer = $ typeToken ['scope_opener ' ];
3856 $ openerToken = $ tokens [$ openerPointer ];
3957 $ nextPointerAfterOpeningBrace = $ phpcsFile ->findNext (T_WHITESPACE , $ openerPointer + 1 , null , true );
4058 $ nextTokenAfterOpeningBrace = $ tokens [$ nextPointerAfterOpeningBrace ];
41-
59+ $ linesCountAfterOpeningBrace = SniffSettingsHelper:: normalizeInteger ( $ this -> linesCountAfterOpeningBrace );
4260 $ lines = $ nextTokenAfterOpeningBrace ['line ' ] - $ openerToken ['line ' ] - 1 ;
43- if ($ lines === 0 ) {
61+
62+ if ($ lines === $ linesCountAfterOpeningBrace ) {
63+ return ;
64+ }
65+
66+ if ($ linesCountAfterOpeningBrace === 1 ) {
67+ if ($ lines === 0 ) {
68+ $ fix = $ phpcsFile ->addFixableError (sprintf (
69+ 'There must be one empty line after %s opening brace. ' ,
70+ $ typeToken ['content ' ]
71+ ), $ openerPointer , self ::CODE_NO_EMPTY_LINE_AFTER_OPENING_BRACE );
72+ } else {
73+ $ fix = $ phpcsFile ->addFixableError (sprintf (
74+ 'There must be one empty line after %s opening brace. ' ,
75+ $ typeToken ['content ' ]
76+ ), $ openerPointer , self ::CODE_MULTIPLE_EMPTY_LINES_AFTER_OPENING_BRACE );
77+ }
78+ } else {
4479 $ fix = $ phpcsFile ->addFixableError (sprintf (
45- 'There must be one empty line after %s opening brace. ' ,
80+ 'There must be exactly %d empty lines after %s opening brace. ' ,
81+ $ linesCountAfterOpeningBrace ,
4682 $ typeToken ['content ' ]
47- ), $ openerPointer , self ::CODE_NO_EMPTY_LINE_AFTER_OPENING_BRACE );
83+ ), $ openerPointer , self ::CODE_INCORRECT_EMPTY_LINES_AFTER_OPENING_BRACE );
84+ }
85+
86+ if (!$ fix ) {
87+ return ;
88+ }
4889
49- if ($ fix ) {
50- $ phpcsFile ->fixer ->beginChangeset ();
90+ if ($ lines < $ linesCountAfterOpeningBrace ) {
91+ $ phpcsFile ->fixer ->beginChangeset ();
92+ for ($ i = $ lines ; $ i < $ linesCountAfterOpeningBrace ; $ i ++) {
5193 $ phpcsFile ->fixer ->addNewline ($ openerPointer );
52- $ phpcsFile ->fixer ->endChangeset ();
5394 }
54- } elseif ($ lines > 1 ) {
55- $ fix = $ phpcsFile ->addFixableError (sprintf (
56- 'There must be one empty line after %s opening brace. ' ,
57- $ typeToken ['content ' ]
58- ), $ openerPointer , self ::CODE_MULTIPLE_EMPTY_LINES_AFTER_OPENING_BRACE );
59-
60- if ($ fix ) {
61- $ phpcsFile ->fixer ->beginChangeset ();
62- for ($ i = $ openerPointer + 3 ; $ i < $ nextPointerAfterOpeningBrace ; $ i ++) {
63- if ($ tokens [$ i ]['content ' ] !== $ phpcsFile ->eolChar ) {
64- break ;
65- }
66- $ phpcsFile ->fixer ->replaceToken ($ i , '' );
95+ $ phpcsFile ->fixer ->endChangeset ();
96+ } else {
97+ $ phpcsFile ->fixer ->beginChangeset ();
98+ for ($ i = $ openerPointer + $ linesCountAfterOpeningBrace + 2 ; $ i < $ nextPointerAfterOpeningBrace ; $ i ++) {
99+ if ($ tokens [$ i ]['content ' ] !== $ phpcsFile ->eolChar ) {
100+ break ;
67101 }
68- $ phpcsFile ->fixer ->endChangeset ( );
102+ $ phpcsFile ->fixer ->replaceToken ( $ i , '' );
69103 }
104+ $ phpcsFile ->fixer ->endChangeset ();
70105 }
106+ }
71107
108+ private function processClosingBrace (\PHP_CodeSniffer_File $ phpcsFile , int $ stackPointer )
109+ {
110+ $ tokens = $ phpcsFile ->getTokens ();
111+ $ typeToken = $ tokens [$ stackPointer ];
72112 $ closerPointer = $ typeToken ['scope_closer ' ];
73113 $ closerToken = $ tokens [$ closerPointer ];
74114 $ previousPointerBeforeClosingBrace = $ phpcsFile ->findPrevious (T_WHITESPACE , $ closerPointer - 1 , null , true );
75115 $ previousTokenBeforeClosingBrace = $ tokens [$ previousPointerBeforeClosingBrace ];
76-
116+ $ linesCountBeforeClosingBrace = SniffSettingsHelper:: normalizeInteger ( $ this -> linesCountBeforeClosingBrace );
77117 $ lines = $ closerToken ['line ' ] - $ previousTokenBeforeClosingBrace ['line ' ] - 1 ;
78- if ($ lines === 0 ) {
79- $ fix = $ phpcsFile ->addFixableError (sprintf (
80- 'There must be one empty line before %s closing brace. ' ,
81- $ typeToken ['content ' ]
82- ), $ closerPointer , self ::CODE_NO_EMPTY_LINE_BEFORE_CLOSING_BRACE );
83118
84- if ($ fix ) {
85- $ phpcsFile ->fixer ->beginChangeset ();
86- $ phpcsFile ->fixer ->addNewlineBefore ($ closerPointer );
87- $ phpcsFile ->fixer ->endChangeset ();
119+ if ($ lines === $ linesCountBeforeClosingBrace ) {
120+ return ;
121+ }
122+
123+ if ($ linesCountBeforeClosingBrace === 1 ) {
124+ if ($ lines === 0 ) {
125+ $ fix = $ phpcsFile ->addFixableError (sprintf (
126+ 'There must be one empty line before %s closing brace. ' ,
127+ $ typeToken ['content ' ]
128+ ), $ closerPointer , self ::CODE_NO_EMPTY_LINE_BEFORE_CLOSING_BRACE );
129+ } else {
130+ $ fix = $ phpcsFile ->addFixableError (sprintf (
131+ 'There must be one empty line before %s closing brace. ' ,
132+ $ typeToken ['content ' ]
133+ ), $ closerPointer , self ::CODE_MULTIPLE_EMPTY_LINES_BEFORE_CLOSING_BRACE );
88134 }
89- } elseif ( $ lines > 1 ) {
135+ } else {
90136 $ fix = $ phpcsFile ->addFixableError (sprintf (
91- 'There must be one empty line before %s closing brace. ' ,
137+ 'There must be exactly %d empty lines before %s closing brace. ' ,
138+ $ linesCountBeforeClosingBrace ,
92139 $ typeToken ['content ' ]
93- ), $ closerPointer , self ::CODE_MULTIPLE_EMPTY_LINES_BEFORE_CLOSING_BRACE );
140+ ), $ closerPointer , self ::CODE_INCORRECT_EMPTY_LINES_BEFORE_CLOSING_BRACE );
141+ }
94142
95- if ($ fix ) {
96- $ phpcsFile ->fixer ->beginChangeset ();
97- for ($ i = $ previousPointerBeforeClosingBrace + 3 ; $ i < $ closerPointer ; $ i ++) {
98- $ phpcsFile ->fixer ->replaceToken ($ i , '' );
99- }
100- $ phpcsFile ->fixer ->endChangeset ();
143+ if (!$ fix ) {
144+ return ;
145+ }
146+
147+ if ($ lines < $ linesCountBeforeClosingBrace ) {
148+ $ phpcsFile ->fixer ->beginChangeset ();
149+ for ($ i = $ lines ; $ i < $ linesCountBeforeClosingBrace ; $ i ++) {
150+ $ phpcsFile ->fixer ->addNewlineBefore ($ closerPointer );
151+ }
152+ $ phpcsFile ->fixer ->endChangeset ();
153+ } else {
154+ $ phpcsFile ->fixer ->beginChangeset ();
155+ for ($ i = $ previousPointerBeforeClosingBrace + $ linesCountBeforeClosingBrace + 2 ; $ i < $ closerPointer ; $ i ++) {
156+ $ phpcsFile ->fixer ->replaceToken ($ i , '' );
101157 }
158+ $ phpcsFile ->fixer ->endChangeset ();
102159 }
103160 }
104161
0 commit comments