enhanced the for-loop optimizer (patch from nikic)

This commit is contained in:
Fabien Potencier
2010-12-13 15:20:03 +01:00
parent 991021bf4e
commit e0f20a0c4d
2 changed files with 28 additions and 11 deletions
+15 -10
View File
@@ -76,24 +76,29 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
*
* * "loop" is not used in the "for" tag
* * and there is no include tag without the "only" attribute
* * and there is no inner-for tag (in which case we would need to check parent.loop usage)
* * and there is no inner-for tag (in which case we would need to check loop.parent usage)
*
* This method should be able to optimize for with inner-for tags.
*/
protected function enterOptimizeFor($node, $env)
{
if ($node instanceof Twig_Node_For) {
// disable the loop variable by default
$node->setAttribute('with_loop', false);
if ($this->loops) {
$this->loops[0]->setAttribute('with_loop', true);
}
array_unshift($this->loops, $node);
} elseif ($this->loops && $node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
$this->loops[0]->setAttribute('with_loop', true);
} elseif ($this->loops && $node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
$this->loops[0]->setAttribute('with_loop', true);
} elseif ($this->loops
// when do we need to add the loop variable back?
&& (
// the loop variable is referenced here
($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name'))
||
// include without the only attribute
($this->loops && $node instanceof Twig_Node_Include && !$node->getAttribute('only'))
)
) {
foreach ($this->loops as $loop) {
$loop->setAttribute('with_loop', true);
}
}
}
+13 -1
View File
@@ -29,11 +29,23 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase
{
return array(
array('{% for i in foo %}{% endfor %}', array('i' => false)),
array('{% for i in foo %}{{ loop.index }}{% endfor %}', array('i' => true)),
array('{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', array('i' => true, 'j' => false)),
array('{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)),
array('{% for i in foo %}{% include "foo" %}{% endfor %}', array('i' => true)),
array('{% for i in foo %}{% include "foo" only %}{% endfor %}', array('i' => false)),
// "i" should be false
array('{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
array('{% for i in foo %}{% for j in foo %}{{ loop.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
//array('{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)),
array('{% for i in foo %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
);
}