/phpactor

PHP refactoring and introspection tool.

Primary LanguagePHP

Phpactor

phpactor2sm

Build Status

This project aims to provide heavy-lifting refactoring and introspection tools which can be used standalone or as the backend for a text editor to provide intelligent code completion.

Features

  • No indexing: Composer is used to determine where things should be.
  • Move and copy: Move and copy classes, updating PHP references to them.
  • Reflection API: Get reflection data for a given class or file.
  • Type inference: Determine the type of something at a given offset.
  • Transformation: Apply "transformations" to code (e.g. implement interfaces, add missing properties).
  • Class search: Search for a class by its name.
  • VIM Plugin: see plugin README.

Prerequisites

  • Projects MUST use Composer and GIT.
  • PHP 7.

Configuration

Configuration files are loaded and merged from the following locations:

  1. /etc/xdg/phpactor/phpactor.yml
  2. /home/daniel/.config/phpactor/phpactor.yml
  3. <current directory>/.phpactor.yml

For example, to change the default indentation for your current project:

# <path to your project>/.phpactor.yml
indentation: "  " # use 2 spaces instead of 4

Change for all projects:

# $HOME/.config/phpactor/.phpactor.yml
indentation: "  "

The full list of configuration options can be found in this file.

Commands

Move classes

All of the examples below will move the class and update all references in the source code to it.

Move the single class from one path to another:

$ phpactor class:move lib/Path/To/MyClass.php lib/NewLocation.php

Relocate all classes under Acme to Foobar:

$ phpactor class:move lib/Acme lib/Foobar

Relocate all classes in the lib directory to a new subfolder:

$ phpactor class:move lib/* lib/Core

Move a class by name:

$ phpactor class:move "Acme\\BlogPost" "Acme\\Article"

recording

  • Moves individual class files or directories.
  • Move by fully qualified class name of file path.
  • Updates references for all moved classes in currently GIT tree.
  • Use statements are updated or added when required.

Copy classes

As with move, except only update the class names of the copied class(es).

$ phpactor class:copy lib/Path/To/MyClass.php lib/Path/To/CopyOfMyClass.php
$ cat lib/Path/To/CopyOfMyClass.php | grep class
class CopyOfMyClass

Class Search

Search for a class by its (short) name and return a list of fully qualified names => absolute paths.

./bin/phpactor class:search Filesystem
Phpactor\Filesystem\Domain\Filesystem:/.../vendor/phpactor/source-code-filesystem/lib/Domain/Filesystem.php
Symfony\Component\Filesystem\Filesystem:/.../vendor/symfony/filesystem/Filesystem.php

Also returns JSON with --format=json

Information at offset

Return the fully qualified name of the class at the offset in the given file:

$ phpactor offset:info lib/Application/InformationForOffset/InformationForOffset.php 1382
type:Phpactor\ClassFileConverter\ClassName
path:/.../vendor/dtl/class-to-file/lib/ClassName.php

Also returns JSON with --format=json

Reflect class

Return reflection information for a given class name or file:

$ phpactor class:reflect lib/Application/Transformer.php
class:Phpactor\Application\Transformer
class_namespace:Phpactor\Application
class_name:Transformer
methods:
  __construct:
    name:__construct
    abstract:
    visibility:public
    parameters:
      transform:
        name:transform
        has_type:1
        type:CodeTransform
        has_default:
        default:
    static:0
    type:<unknown>
    synopsis:public function __construct(Phpactor\CodeTransform\CodeTransform $transform)
    docblock:
  transform:
# ...

Also returns JSON with --format=json

Transform

The transformation command accepts either a file name or stdin and applies the specified transformations.

$ phpactor class:transform lib/MyClass.php --transform=complete_constructor

Complete Constructor

Name: complete_constructor

This transformation will add any missing assignments in a constructor and add the class properties required.

In:

<?php

class Post
{
    public function __construct(string $hello, Foobar $foobar)
    {
    }
}

Out:

<?php

class Post
{
    /**
     * @var string
     */
    private $hello;

    /**
     * @var Foobar
     */
    private $foobar;

    public function __construct(string $hello, Foobar $foobar)
    {
        $this->hello = $hello;
        $this->foobar = $foobar;
    }
}

Implement contracts

Name: implement_contracts

This transformer will implement any missing interface methods or abstract methods:

In:

<?php

class Post implements \Countable
{
}

Out:

<?php

class Post implements \Countable
{
    /**
     * {@inheritdoc}
     */
    public function count()
    {
    }
}

Packages

About this project

This project attempts to close the gap between text editors such as VIM and IDEs such as PHPStorm.

One of the interesting things about Phpactor is that it does not require any indexing before it is used. It leverages the Composer to determine class locations and to determine class FQNs from file locations. Introspection is done in realtime (using the excellent Tolereant PHP Parser).

Using Composer we can locate a file using a fully qualified class name, when we have located the file we can parse it. This is enough for common auto-completion.

For other use cases, such as searching for a class, we simply perform a file search, but only in those directories mapped by Composer. Even in large projects searching for a class by its (short) name is pretty fast.