Loïc Faugeron Technical Blog

SpecGen v0.2 20/05/2015

TL;DR: SpecGen v0.2 inserts use statements.

SpecGen v0.2 has been released, it introduces a small change: use statement insertion.

It inserts use statements

Let's go back to the sources of the example used in the previous article and clean it a little bit:

rm -rf src

Given the following specification:

<?php
// File: spec/Vendor/Project/RequestHandlerSpec.php

namespace spec\Vendor\Project;

use PhpSpec\ObjectBehavior;
use Vendor\Project\Message\Request;

class RequestHandlerSpec extends ObjectBehavior
{
    function it_takes_a_request_and_returns_a_response(Request $request)
    {
        $parameters = array();
        $isEnabled = true;
        $this->handle($request, $parameters, $isEnabled)->shouldHaveType('Vendor\Project\Message\Response');
    }
}

When we run the test suite:

phpspec run

Then we should get the following file, with a use statement:

<?php

namespace Vendor\Project;

use Vendor\Project\Message\Request;

class RequestHandler
{
    public function handle(Request $request, array $argument1, $argument2)
    {
    }
}

It doesn't insert use statements twice

Given the following new step in our specification:

<?php
// File: spec/Vendor/Project/RequestHandlerSpec.php

namespace spec\Vendor\Project;

use PhpSpec\ObjectBehavior;
use Vendor\Project\Message\Request;

class RequestHandlerSpec extends ObjectBehavior
{
    function it_takes_a_request_and_returns_a_response(Request $request)
    {
        $parameters = array();
        $isEnabled = true;
        $this->handle($request, $parameters, $isEnabled)->shouldHaveType('Vendor\Project\Message\Response');
    }

    function it_supports_request(Request $request)
    {
        $this->supports($request)->shouldBe(true);
    }
}

When we run the test suite:

phpspec run

Then we should get the following file, without new use statements:

<?php

namespace Vendor\Project;

use Vendor\Project\Message\Request;

class RequestHandler
{
    public function handle(Request $request, array $argument1, $argument2)
    {
    }

    public function supports(Request $request)
    {
    }
}

It doesn't insert use statement for same namespace

Let's clear everything:

rm -rf src

Given the following specification:

<?php
// File: spec/Vendor/Project/RequestHandlerSpec.php

namespace spec\Vendor\Project;

use PhpSpec\ObjectBehavior;
use Vendor\Project\Request;

class RequestHandlerSpec extends ObjectBehavior
{
    function it_takes_a_request_and_returns_a_response(Request $request)
    {
        $parameters = array();
        $isEnabled = true;
        $this->handle($request, $parameters, $isEnabled)->shouldHaveType('Vendor\Project\Response');
    }
}

Note: Request and RequestHandler are both in the same namespace.

When we run the test suite:

phpspec run

Then we should get the following, without any use statements:

<?php

namespace Vendor\Project;

class RequestHandler
{
    public function handle(Request $request, array $argument1, $argument2)
    {
    }
}

Behind the hood

This small feature was the occasion to refactor SpecGen a bit! This resulted in the introduction of CodeEditor, a facade for a home made CommandBus and for Redaktilo's Editor.

With these, the code to generate a method and insert a use statement looks like this:

$file = $this->codeEditor->open($fileName);
$this->codeEditor->handle(new InsertUseStatements($file, $fullyQualifiedNames));
$this->codeEditor->handle(new InsertMethod($file, $method));
$this->codeEditor->save($file);

Conclusion

While some improvements can still be done (use statements in alphabetical order, typehint interfaces only), the version 0.3 will mainly be about the introduction of a new generator: insertion of properties when the method is a constructor.

Stay tuned!

Reference: see the phpspec reference article