mpartel
mpartel

Reputation: 4492

PhpStorm autocompletion in traits

I have a trait that must always be mixed in to a subclass of \PHPUnit_Framework_TestCase. PhpStorm doesn't know this. Is there anything I can do to get PhpStorm to autocomplete and "typecheck" things like assertNull inside the trait?

<?php
trait MyTestUtils
{
    public function foo()
    {
        $this->assertNu // autocomplete?
    }
}

The best I could come up with so far is putting the following in each method:

/** @var \PHPUnit_Framework_TestCase|MyTestUtils $this */

But this is repetitive and doesn't understand protected memebers. Is there a better option?

Upvotes: 17

Views: 6507

Answers (3)

Oliver Maksimovic
Oliver Maksimovic

Reputation: 3262

UPDATE: Since PhpStorm 2016.1.2 (build 145.1616) autocompletion in traits works out-of-the-box. It is smart enough to figure out what classes use the trait, and then provide the autocompletion. Link to the issue: https://youtrack.jetbrains.com/issue/WI-16368

Previously replied with:

You can use:

@method \PHPUnit_Framework_TestCase assertTrue($condition, $message = '')

...in docblock of the trait itself, but the downside is that you'd need to put @method for each method that you'd like to have autocomplete for, which is not too bad if you're using a sane number of method calls in your trait. Or, "document" only those methods that you're using most often.

Upvotes: 8

Stephen
Stephen

Reputation: 18917

Besides using the php docblock to document $this, the only other way I'm aware of, which also, arguably makes your trait more "safe" anyway, is to define abstract methods on the trait itself, e.g.:

 trait F {

    /**
     * @return string[]
     */
    abstract public function Foo();

    /**
     * @return self
     */
    abstract public function Bar();
}

abstract class Bar {
    use F;

    /**
     * @return bool|string[]
     */
    public function Baz () {
        if ($this->Bar()) {
            return $this->Foo();
        }

        return false;
    }
}

Upvotes: 11

Konr Ness
Konr Ness

Reputation: 2153

I would argue that this is not a valid use-case for a PHP trait. Your trait, as written is not guaranteed to only be used on classes that extend \PHPUnit_Framework_TestCase. This introduces very tightly coupled code. The best practice of Traits is for them to be very loosely coupled and only be aware of their own contents.

I would instead recommend that you either:

  1. create a subclass of \PHPUnit_Framework_TestCase that your test cases that need this functionality can extend
  2. create custom assertion classes. These can many times be used for doing groups of custom assertions.

Both techniques are detailed here: http://phpunit.de/manual/4.1/en/extending-phpunit.html

These are the two recommended best practices for where to place helper methods such as these.

Upvotes: 5

Related Questions