@@ -102,8 +102,7 @@ private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closingTag
102102 $ error = 'Opening PHP tag must be on a line by itself ' ;
103103 $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'ContentAfterOpen ' );
104104 if ($ fix === true ) {
105- $ first = $ phpcsFile ->findFirstOnLine (T_WHITESPACE , $ stackPtr , true );
106- $ padding = (strlen ($ tokens [$ first ]['content ' ]) - strlen (ltrim ($ tokens [$ first ]['content ' ])));
105+ $ padding = $ this ->calculateLineIndent ($ phpcsFile , $ stackPtr );
107106
108107 $ phpcsFile ->fixer ->beginChangeset ();
109108 $ phpcsFile ->fixer ->replaceToken ($ stackPtr , rtrim ($ tokens [$ stackPtr ]['content ' ]));
@@ -147,17 +146,7 @@ private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closingTag
147146 }
148147 }//end if
149148
150- $ indent = 0 ;
151- $ first = $ phpcsFile ->findFirstOnLine (T_WHITESPACE , $ stackPtr );
152- if ($ first === false ) {
153- $ first = $ phpcsFile ->findFirstOnLine (T_INLINE_HTML , $ stackPtr );
154- if ($ first !== false ) {
155- $ indent = (strlen ($ tokens [$ first ]['content ' ]) - strlen (ltrim ($ tokens [$ first ]['content ' ])));
156- }
157- } else {
158- $ indent = ($ tokens [($ first + 1 )]['column ' ] - 1 );
159- }
160-
149+ $ indent = $ this ->calculateLineIndent ($ phpcsFile , $ stackPtr );
161150 $ contentColumn = ($ tokens [$ firstContent ]['column ' ] - 1 );
162151 if ($ contentColumn !== $ indent ) {
163152 $ error = 'First line of embedded PHP code must be indented %s spaces; %s found ' ;
@@ -180,52 +169,40 @@ private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closingTag
180169
181170 $ lastContentBeforeBlock = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ stackPtr - 1 ), null , true );
182171 if ($ tokens [$ lastContentBeforeBlock ]['line ' ] === $ tokens [$ stackPtr ]['line ' ]
183- && trim ($ tokens [$ lastContentBeforeBlock ]['content ' ]) !== ''
172+ && (($ tokens [$ lastContentBeforeBlock ]['code ' ] === T_INLINE_HTML
173+ && trim ($ tokens [$ lastContentBeforeBlock ]['content ' ]) !== '' )
174+ || ($ tokens [($ lastContentBeforeBlock - 1 )]['code ' ] !== T_INLINE_HTML
175+ && $ tokens [($ lastContentBeforeBlock - 1 )]['line ' ] === $ tokens [$ stackPtr ]['line ' ]))
184176 ) {
185177 $ error = 'Opening PHP tag must be on a line by itself ' ;
186178 $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'ContentBeforeOpen ' );
187179 if ($ fix === true ) {
188- $ padding = 0 ;
189- $ first = $ phpcsFile ->findFirstOnLine (T_WHITESPACE , $ stackPtr );
190- if ($ first === false ) {
191- $ first = $ phpcsFile ->findFirstOnLine (T_INLINE_HTML , $ stackPtr );
192- if ($ first !== false ) {
193- $ padding = (strlen ($ tokens [$ first ]['content ' ]) - strlen (ltrim ($ tokens [$ first ]['content ' ])));
194- }
195- } else {
196- $ padding = ($ tokens [($ first + 1 )]['column ' ] - 1 );
197- }
180+ $ padding = $ this ->calculateLineIndent ($ phpcsFile , $ lastContentBeforeBlock );
198181
182+ $ phpcsFile ->fixer ->beginChangeset ();
199183 $ phpcsFile ->fixer ->addContentBefore ($ stackPtr , $ phpcsFile ->eolChar .str_repeat (' ' , $ padding ));
200- }
184+
185+ // Make sure we don't leave trailing whitespace behind.
186+ if ($ tokens [($ stackPtr - 1 )]['code ' ] === T_INLINE_HTML
187+ && trim ($ tokens [($ stackPtr - 1 )]['content ' ]) === ''
188+ ) {
189+ $ phpcsFile ->fixer ->replaceToken (($ stackPtr - 1 ), '' );
190+ }
191+
192+ $ phpcsFile ->fixer ->endChangeset ();
193+ }//end if
201194 } else {
202195 // Find the first token on the first non-empty line we find.
203196 for ($ first = ($ lastContentBeforeBlock - 1 ); $ first > 0 ; $ first --) {
204197 if ($ tokens [$ first ]['line ' ] === $ tokens [$ stackPtr ]['line ' ]) {
205198 continue ;
206199 } else if (trim ($ tokens [$ first ]['content ' ]) !== '' ) {
207200 $ first = $ phpcsFile ->findFirstOnLine ([], $ first , true );
208- if ($ tokens [$ first ]['code ' ] === T_COMMENT
209- && $ tokens [$ first ]['content ' ] !== ltrim ($ tokens [$ first ]['content ' ])
210- ) {
211- // This is a subsequent line in a star-slash comment containing leading indent.
212- // We'll need the first line of the comment to correctly determine the indent.
213- continue ;
214- }
215-
216201 break ;
217202 }
218203 }
219204
220- $ expected = 0 ;
221- if ($ tokens [$ first ]['code ' ] === T_INLINE_HTML
222- && trim ($ tokens [$ first ]['content ' ]) !== ''
223- ) {
224- $ expected = (strlen ($ tokens [$ first ]['content ' ]) - strlen (ltrim ($ tokens [$ first ]['content ' ])));
225- } else if ($ tokens [$ first ]['code ' ] === T_WHITESPACE ) {
226- $ expected = ($ tokens [($ first + 1 )]['column ' ] - 1 );
227- }
228-
205+ $ expected = $ this ->calculateLineIndent ($ phpcsFile , $ first );
229206 $ expected += 4 ;
230207 $ found = ($ tokens [$ stackPtr ]['column ' ] - 1 );
231208 if ($ found > $ expected ) {
@@ -261,17 +238,7 @@ private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closingTag
261238 ) {
262239 $ closerIndent = $ indent ;
263240 } else {
264- $ first = $ phpcsFile ->findFirstOnLine (T_WHITESPACE , $ closingTag , true );
265-
266- while ($ tokens [$ first ]['code ' ] === T_COMMENT
267- && $ tokens [$ first ]['content ' ] !== ltrim ($ tokens [$ first ]['content ' ])
268- ) {
269- // This is a subsequent line in a star-slash comment containing leading indent.
270- // We'll need the first line of the comment to correctly determine the indent.
271- $ first = $ phpcsFile ->findFirstOnLine (T_WHITESPACE , ($ first - 1 ), true );
272- }
273-
274- $ closerIndent = ($ tokens [$ first ]['column ' ] - 1 );
241+ $ closerIndent = $ this ->calculateLineIndent ($ phpcsFile , $ closingTag );
275242 }
276243
277244 $ phpcsFile ->fixer ->beginChangeset ();
@@ -290,10 +257,10 @@ private function validateMultilineEmbeddedPhp($phpcsFile, $stackPtr, $closingTag
290257 $ error = 'Closing PHP tag must be on a line by itself ' ;
291258 $ fix = $ phpcsFile ->addFixableError ($ error , $ closingTag , 'ContentAfterEnd ' );
292259 if ($ fix === true ) {
293- $ first = $ phpcsFile -> findFirstOnLine ( T_WHITESPACE , $ closingTag, true );
260+ $ indent = $ this -> calculateLineIndent ( $ phpcsFile , $ closingTag );
294261 $ phpcsFile ->fixer ->beginChangeset ();
295262 $ phpcsFile ->fixer ->addNewline ($ closingTag );
296- $ phpcsFile ->fixer ->addContent ($ closingTag , str_repeat (' ' , ( $ tokens [ $ first ][ ' column ' ] - 1 ) ));
263+ $ phpcsFile ->fixer ->addContent ($ closingTag , str_repeat (' ' , $ indent ));
297264
298265 if ($ tokens [$ firstContentAfterBlock ]['code ' ] === T_INLINE_HTML ) {
299266 $ trimmedHtmlContent = ltrim ($ tokens [$ firstContentAfterBlock ]['content ' ]);
@@ -513,4 +480,44 @@ private function reportEmptyTagSet(File $phpcsFile, $stackPtr, $closeTag)
513480 }//end reportEmptyTagSet()
514481
515482
483+ /**
484+ * Calculate the indent of the line containing the stackPtr.
485+ *
486+ * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
487+ * @param int $stackPtr The position of the current token in the
488+ * stack passed in $tokens.
489+ *
490+ * @return int
491+ */
492+ private function calculateLineIndent (File $ phpcsFile , $ stackPtr )
493+ {
494+ $ tokens = $ phpcsFile ->getTokens ();
495+
496+ for ($ firstOnLine = $ stackPtr ; $ tokens [$ firstOnLine ]['column ' ] !== 1 ; $ firstOnLine --);
497+
498+ // Check if this is a subsequent line in a star-slash comment containing leading indent.
499+ // In that case, we'll need the first line of the comment to correctly determine the indent.
500+ while ($ tokens [$ firstOnLine ]['code ' ] === T_COMMENT
501+ && $ tokens [$ firstOnLine ]['content ' ] !== ltrim ($ tokens [$ firstOnLine ]['content ' ])
502+ ) {
503+ for (--$ firstOnLine ; $ tokens [$ firstOnLine ]['column ' ] !== 1 ; $ firstOnLine --);
504+ }
505+
506+ $ indent = 0 ;
507+ if ($ tokens [$ firstOnLine ]['code ' ] === T_WHITESPACE ) {
508+ $ indent = ($ tokens [($ firstOnLine + 1 )]['column ' ] - 1 );
509+ } else if ($ tokens [$ firstOnLine ]['code ' ] === T_INLINE_HTML
510+ || $ tokens [$ firstOnLine ]['code ' ] === T_END_HEREDOC
511+ || $ tokens [$ firstOnLine ]['code ' ] === T_END_NOWDOC
512+ ) {
513+ $ indent = (strlen ($ tokens [$ firstOnLine ]['content ' ]) - strlen (ltrim ($ tokens [$ firstOnLine ]['content ' ])));
514+ } else if ($ tokens [$ firstOnLine ]['code ' ] === T_DOC_COMMENT_WHITESPACE ) {
515+ $ indent = (strlen ($ tokens [$ firstOnLine ]['content ' ]) - strlen (ltrim ($ tokens [$ firstOnLine ]['content ' ])) - 1 );
516+ }
517+
518+ return $ indent ;
519+
520+ }//end calculateLineIndent()
521+
522+
516523}//end class
0 commit comments