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

Automation to Place Tombstones and Clean-Up Dead Code #11

Open
scheb opened this issue Aug 17, 2020 · 3 comments
Open

Automation to Place Tombstones and Clean-Up Dead Code #11

scheb opened this issue Aug 17, 2020 · 3 comments

Comments

@scheb
Copy link
Owner

scheb commented Aug 17, 2020

Idea

I'd like to provide some automation to

  1. add tombstones to a codebase
  2. remove dead code from the codebase based on the results from the tombstone library

Since Rector is the standard library for PHP code migrations now, I thought it would be a good thing to use the Rector platform, rather than building my own little code migrations tool.

In detail, it would need to provide 2 rectors:

1. Setting Tombstones

The first rector would add tombstone() function calls to each public method. There could be potentially additional filtering options, which public method to target.

public function foo() {
    // ... Some code here
}

Result after rector was applied:

public function foo() {
    tombstone();
    // ... Some code here
}

2. Deleting Dead Code

The second rector would take a result from the tombstone library (transfer format TBD), providing the information which methods are detected as "dead code". The rector would remove these dead methods from the code.


If this idea would be useful to you, give it a +1

@jawira
Copy link
Contributor

jawira commented Sep 11, 2022

Maybe you can also add a Rector rule to remove tombstones, for example after deleting dead code we want to remove all tombstones (for performance reasons maybe) and uninstall scheb/tombstone.

@scheb
Copy link
Owner Author

scheb commented Sep 13, 2022

@jawira You could easily do that with a regex ;)

@michondr
Copy link

hi! currently implementing this library.

for the first type of rector rule this is what I [and chatgpt] came up with:

<?php

declare(strict_types=1);

namespace Utils\Rector\Rector;

use DateTimeImmutable;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

use function array_unshift;

final class AddTombstones extends AbstractRector
{
    private string $now;

    public function __construct()
    {
        $this->now = (new DateTimeImmutable())->format('Y-m-d');
    }

    public function getRuleDefinition(): RuleDefinition
    {
        return new RuleDefinition(
            'add tombstone method call in every class method',
            [
                new CodeSample(
                    <<<'CODE_SAMPLE'
function someFunction()
{
    // Some code
}
CODE_SAMPLE
                    ,
                    <<<'CODE_SAMPLE'
function someFunction()
{
    tombstone('2024-01-01');
    // Some code
}
CODE_SAMPLE
                ),
            ]
        );
    }

    public function getNodeTypes(): array
    {
        return [Function_::class, ClassMethod::class];
    }

    public function refactor(Node $node)
    {
        if ($this->getName($node) === '__construct') {
            return null;
        }
        if ($node->stmts === null) { //interface
            return null;
        }

        $tombstoneCall = new FuncCall(
            new Name('tombstone'),
            [new Arg(new String_($this->now))]
        );

        array_unshift($node->stmts, new Node\Stmt\Expression($tombstoneCall));

        return $node;
    }
}

I'll do some testing and find out a way to fetch log results for the other rules:

  • remove tombstones which are logged as vampires
  • remove functions where tombstones remain for some configurable time

I suppose private functions can be removed with some static-analysis tool as they cannot be invoked without being referenced, but reflection.... so that's why I'm adding tombstones even to them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants