Skip to content

Commit

Permalink
initial short array and closure this transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
igorw committed Jul 21, 2013
1 parent 904a13c commit 0a9dd8d
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 2 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"require": {
"nikic/php-parser": "0.9.*@dev"
},
"autoload": {
"files": ["src/php55.php"]
}
}
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
>
<testsuites>
<testsuite>
<directory>./tests/</directory>
<directory suffix="_test.php">./tests/</directory>
</testsuite>
</testsuites>

Expand Down
89 changes: 89 additions & 0 deletions src/php55.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace galapagos\php55;

function transform_code($code, callable $transform) {
$parser = new \PHPParser_Parser(new \PHPParser_Lexer);
$prettyPrinter = new \PHPParser_PrettyPrinter_Default;

$ast = $parser->parse($code);
$ast = $transform($ast);
return '<?php ' . $prettyPrinter->prettyPrint($ast);
}

function transform_with_visitors($code, array $visitors) {
return transform_code($code, function ($ast) use ($code, $visitors) {
$traverser = new \PHPParser_NodeTraverser;
foreach ($visitors as $visitor) {
$traverser->addVisitor($visitor);
}
return $traverser->traverse($ast);
});
}

function transform_short_array($code) {
return transform_with_visitors($code, []);
}

function transform_closure_this($code) {
return transform_with_visitors($code, [
new NodeVisitor_ClosureThis,
]);
}

class NodeVisitor_ClosureThis extends \PHPParser_NodeVisitorAbstract
{
private $method = null;
private $closure = null;

public function enterNode(\PHPParser_Node $node) {
if ($node instanceof \PHPParser_Node_Stmt_ClassMethod) {
$this->method = $node;
}

if ($this->method && $node instanceof \PHPParser_Node_Expr_Closure) {
$this->closure = $node;
}

if ($this->closure
&& $node instanceof \PHPParser_Node_Expr_Variable
&& 'this' === $node->name) {

$this->method->setAttribute('has_that', true);
$this->closure->setAttribute('has_that', true);
return new \PHPParser_Node_Expr_Variable('that');
}
}

public function leaveNode(\PHPParser_Node $node) {
if ($node instanceof \PHPParser_Node_Expr_Closure) {
$has_that = $this->closure->getAttribute('has_that');
$this->closure = null;

if ($has_that) {
$node = clone $node;
$node->uses = array_merge($node->uses, [
new \PHPParser_Node_Expr_Variable('that'),
]);
return $node;
}
}

if ($node instanceof \PHPParser_Node_Stmt_ClassMethod) {
$has_that = $this->method->getAttribute('has_that');
$this->method = null;
$this->closure = null;

if ($has_that) {
$node = clone $node;
$node->stmts = array_merge([
new \PHPParser_Node_Expr_Assign(
new \PHPParser_Node_Expr_Variable('that'),
new \PHPParser_Node_Expr_Variable('this')
),
], $node->stmts);
return $node;
}
}
}
}
43 changes: 43 additions & 0 deletions tests/php55/closure_this_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace galapagos\php55;

class closure_this_test extends \PHPUnit_Framework_TestCase
{
function test_closure_this() {
$this->assertSame(<<<'EOF'
<?php class foo
{
public function bar()
{
$that = $this;
return function () use($that) {
return $that->baz();
};
}
public function baz()
{
return 'foo:bar:baz';
}
}
EOF
,
transform_closure_this(<<<'EOF'
<?php class foo
{
public function bar()
{
return function () {
return $this->baz();
};
}
public function baz()
{
return 'foo:bar:baz';
}
}
EOF
)
);
}
}
27 changes: 27 additions & 0 deletions tests/php55/short_array_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace galapagos\php55;

class short_array_test extends \PHPUnit_Framework_TestCase {
function test_short_array_empty() {
$this->assertSame('<?php return array();', transform_short_array('<?php return [];'));
}

function test_short_array_list() {
$this->assertSame('<?php return array(1, 2, 3);', transform_short_array('<?php return [1, 2, 3];'));
}

function test_short_array_map() {
$this->assertSame(
"<?php return array('foo' => 'bar', 'baz' => 'qux');",
transform_short_array("<?php return ['foo' => 'bar', 'baz' => 'qux'];")
);
}

function test_short_array_nested() {
$this->assertSame(
"<?php return array('foo' => array('+', 1, 2, array('+', 0, 3)));",
transform_short_array("<?php return ['foo' => ['+', 1, 2, ['+', 0, 3]]];")
);
}
}

0 comments on commit 0a9dd8d

Please sign in to comment.