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

Parsing a Class doesn't includes method body. #59

Closed
DarkGhostHunter opened this issue May 2, 2020 · 2 comments
Closed

Parsing a Class doesn't includes method body. #59

DarkGhostHunter opened this issue May 2, 2020 · 2 comments

Comments

@DarkGhostHunter
Copy link

DarkGhostHunter commented May 2, 2020

Version: 3.3.4

Bug Description

Using an existing class won't register method bodies at all.

Steps To Reproduce

Create one class with a method body, and then parse it manually.

<?php

namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        //
    }
}
use App\Providers\EventServiceProvider;

$class = \Nette\PhpGenerator\ClassType::from(EventServiceProvider::class);

echo $class->getMethod('boot')->getBody(); // ''

Expected Behavior

use App\Providers\EventServiceProvider;

$class = \Nette\PhpGenerator\ClassType::from(EventServiceProvider::class);

echo $class->getMethod('boot')->getBody(); //  'parent::boot();\n\n//'

Possible Solution

Add this method to retrieve the body inside the \PhpGenerator\Factory::fromMethodReflection:

protected function getMethodBody(\ReflectionMethod $from) : string
{
    $lines = file($from->getFileName());
    $string = '';

    for ($start = $from->getStartLine()+1, $end = $from->getEndLine()-1; $start < $end; $start++) {
        $string .= $lines[$start];
    }

    return $string;
}

From there, the only thing would be to "unpad" each line.

@divineniiquaye
Copy link

divineniiquaye commented May 6, 2020

Should have a proper way of returning the exact same body.

Your code is OK. But I think, it can be better, Try this:

This code is using "Strings" class from Nette Utils

protected function getMethodBody(\ReflectionMethod $from) : string
{
    if (false === $from->getFileName()) {
        return '';
    }

    $codeLines = file($from->getFileName());
    $lineOfCode = array_slice($codeLines, $from->getStartLine() + 1, $from->getEndLine() - $from->getStartLine() - 2);

    $unindentedLines = array_map(function ($lineOfCode) {
        // Search for 2 tabs indent, then begin from a new line
        if (Strings::startsWith($lineOfCode, "\t")) {
            return Strings::substring($lineOfCode, strlen("\t\t"));
        }

        // preserve all other lines of code in body.
        return $lineOfCode;
    }, $lineOfCode);

    return "\n".implode('', $unindentedLines);
}

@dg
Copy link
Member

dg commented May 6, 2020

This is duplicated to #4. Because content can't be extracted 100% correctly (for example in minified code or due to bad coding style), I don't want to try. So please add this functionality in your code.

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

No branches or pull requests

3 participants