Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve indentation from previous PHP block #907

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,19 @@ class Generic_Sniffs_WhiteSpace_ScopeIndentSniff implements PHP_CodeSniffer_Snif
*/
protected $nonIndentingScopes = array();

/**
* Does previous PHP block indentation matters for next PHP block?
*
* If FALSE (default), the PHP block indentation does not affect next
* PHP blocks and every T_OPEN tag (new PHP block) resets indentation
* to the tag's one. If TRUE, when a PHP block has remaining openend
* scopes, to be closed in following PHP blocks, then indentation is
* preserved and next PHP block block must match it.
*
* @var bool
*/
public $observePreviousPhpBlockIndentation = false;

/**
* Show debug output for this sniff.
*
Expand Down Expand Up @@ -164,6 +177,7 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
$openScopes = array();
$adjustments = array();
$setIndents = array();
$previousPhpBlockIndentation = null;

$tokens = $phpcsFile->getTokens();
$first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr);
Expand Down Expand Up @@ -856,6 +870,18 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
$currentIndent += $adjustments[$i];
}

// Verify if we must continue matching indentation from previous PHP block.
if ($this->observePreviousPhpBlockIndentation === true) {
// Only if there is any indentation saved from previous PHP block.
if ($previousPhpBlockIndentation !== null) {
$currentIndent = $previousPhpBlockIndentation;
$previousPhpBlockIndentation = null;
if ($this->_debug === true) {
echo "\t=> reusing indentation of $currentIndent from previous PHP block".PHP_EOL;
}
}
}

// Make sure it is divisible by our expected indent.
$currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
$setIndents[$i] = $currentIndent;
Expand All @@ -876,6 +902,18 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
echo "Close PHP tag found on line $line".PHP_EOL;
}

// Verify if we must save indentation from current PHP block.
if ($this->observePreviousPhpBlockIndentation === true) {
$previousPhpBlockIndentation = null;
// Only if there are opened scopes.
if (empty($openScopes) === false) {
$previousPhpBlockIndentation = $currentIndent;
if ($this->_debug === true) {
echo "\t=> saving indentation of $previousPhpBlockIndentation for use in next PHP block".PHP_EOL;
}
}
}

if ($tokens[$lastOpenTag]['line'] !== $tokens[$i]['line']) {
$currentIndent = ($tokens[$i]['column'] - 1);
$lastCloseTag = $i;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
@codingStandardsChangeSetting Generic.WhiteSpace.ScopeIndent exact false
@codingStandardsChangeSetting Generic.WhiteSpace.ScopeIndent observePreviousPhpBlockIndentation true
<?php
$a = 10;
if ($condition) {
$ok = true;
$bad = true;
$okNonExact = true;
// Now we capture current indentation to be used in next php block
// (because there are open scopes).
?>
<span>here we want some html</span>
<?php
$ok = true;
$bad = true;
$okNonExact = true;
}
// Have closed the scope, next PHP blocks are free to have any indentation.
?>
<span>here we want some html</span>
<?php require('ok.php'); ?>
<?php require('ok.php'); ?>
<?php require('ok.php'); ?>
<?php require('ok.php'); ?>
<?php
if ($condition) {
$ok = true;
?>
<span>here we want some html</span>
<?php
$bad = true;
$bad = true;
$ok = true;
if ($condition) {
$ok = true;
}
}
// The close tag must be aligned, hence next one fails.
?>

<?php
// And, also, it does not affect normal operations at all,
// adding some picked from ScopeIndentUnitTest.1.inc to confirm
// everything continues working ok.
<?php
class Test {
function __construct()
{
$this->hello();
}

function hello()
{
echo 'hello';
}//end hello()

function hello2()
{
if (TRUE) {
echo 'hello'; // no error here as its more than 4 spaces.
} else {
echo 'bye';
}

while (TRUE) {
echo 'hello';
}

do {
echo 'hello';
} while (TRUE);
}

function hello3()
{
switch ($hello) {
case 'hello':
break;
}
}

}

?>
<pre>
</head>
<body>
<?php
if ($form->validate()) {
$safe = $form->getSubmitValues();
}
?>
</pre>
<?php

class Test2
{
function __construct()
{
// $this->open(); // error here
}

public function open()
{
// Some inline stuff that shouldn't error
if (TRUE) echo 'hello';
foreach ($tokens as $token) echo $token;
}

/**
* This is a comment 1.
* This is a comment 2.
* This is a comment 3.
* This is a comment 4.
*/
public function close()
{
// All ok.
if (TRUE) {
if (TRUE) {
} else if (FALSE) {
foreach ($tokens as $token) {
switch ($token) {
case '1':
case '2':
if (true) {
if (false) {
if (false) {
if (false) {
echo 'hello';
}
}
}
}
break;
case '5':
break;
}
do {
while (true) {
foreach ($tokens as $token) {
for ($i = 0; $i < $token; $i++) {
echo 'hello';
}
}
}
} while (true);
}
}
}
}

/*
This is another c style comment 1.
This is another c style comment 2.
This is another c style comment 3.
This is another c style comment 4.
This is another c style comment 5.
*/

/* This is a T_COMMENT
*
*
*
*/

/** This is a T_DOC_COMMENT
*/

/*
This T_COMMENT has a newline in it.

*/

public function read()
{
echo 'hello';

// no errors below.
$array = array(
'this',
'that' => array(
'hello',
'hello again' => array(
'hello',
),
),
);
}
}

abstract class Test3
{
public function parse()
{

foreach ($t as $ndx => $token) {
if (is_array($token)) {
echo 'here';
} else {
$ts[] = array("token" => $token, "value" => '');

$last = count($ts) - 1;

switch ($token) {
case '(':

if ($last >= 3 &&
$ts[0]['token'] != T_CLASS &&
$ts[$last - 2]['token'] == T_OBJECT_OPERATOR &&
$ts[$last - 3]['token'] == T_VARIABLE ) {


if (true) {
echo 'hello';
}
}
array_push($braces, $token);
break;
}
}
}
}
}

public function test()
{
$o = <<<EOF
this is some text
this is some text
this is some text
this is some text
this is some text
this is some text
EOF;

return $o;
}

if ($a === true || $a === true || $a === true || $a === true ||
$a === true || $a === true || $a === true || $a === true) {

echo 'hello';
}
// Some example from #907 leading to failures on
// all the PHP indentations with the setting enabled.
<?php
if ($foo) {
foreach ($bar as $baz) {
if ($baz) {
?>
<div>
<div>
<div>
<?php
if ($baz > 1) {
echo '1';
}
?>
</div>
<?php
if ($baz > 1) {
echo '2';
}
?>
</div>
<?php
if ($baz > 1) {
echo '3';
}
?>
</div>
<?php
}
}
}
Loading