Перейти к содержанию

MetaStorm для вашего мозга

MetaStorm позволит вашей IDE глубже понимать код, а заодно пере(за)грузит ваш мозг.

MetaStorm – молот Тора для PHPStorm!⚓︎

MetaStorm — это плагин для PHPStorm, который может сделать вашу IDE умнее. Он позволяет добавлять автодополнение, навигацию по коду и ссылки на свойства, методы и файлы прямо в вашем коде. Всё это достигается с помощью простых конфигурационных файлов в формате XML.


Плагин можно скачать с Marketplace или установить через раздел Plugins в PHPStorm.

🚀 Быстрый старт⚓︎

  1. Создайте конфигурационный файл .meta-storm.xml в вашем проекте:

    <?xml version="1.0" encoding="UTF-8" ?>
    <meta-storm xmlns="meta-storm">
        <definitions>
            <classMethod class="\ArrayHelper" method="getValue" argument="1">
                <properties relatedTo="argument" relatedArgument="0"/>
            </classMethod>
        </definitions>
    </meta-storm>
    
  2. Создайте PHP-файл с примером кода (либо используйте свой):

    <?php
    
    class User { private $id; protected $name; public $age; }
    
    $a = new User;
    
    class ArrayHelper {
        public static function getValue(object $object, string $property) {}
    }
    
    ArrayHelper::getValue($a, 'age');
    
  3. Начните использовать:

    • Нажмите CTRL/CMD на свойстве age, и PHPStorm перенесёт вас к объявлению свойства.
    • Удалите в последней строчке age и начните вводить второй параметр – IDE предложит автодополнение свойств, беря их из объекта $a.
    • Нажмите на свойство $age в классе User, и PHPStorm подсветит все его использования.

Преимущества⚓︎

  • Не требует специального плагина IDE для поддержки вашего фреймворка.
  • Любой может расширить функциональность плагина.
  • Если функция не готова в специальном плагине IDE, MetaStorm готов покрыть её своими возможностями.
  • Конфигурации компонентов могут быть использованы в других проектах, например, Symfony Console.
  • Спасение для одиночных разработчиков – улучшает опыт разработки с минимальными знаниями.
  • Бесплатно и с открытым исходным кодом.

Структура конфигурации⚓︎

Каждый конфигурационный файл следует такой структуре:

<?xml version="1.0" encoding="UTF-8" ?>
<meta-storm xmlns="meta-storm">
    <definitions>
        <!-- таргеты с фичами -->
    </definitions>
    <collections>
        <!-- коллекции -->
    </collections>
</meta-storm>
  • Определения
    • Точка подключения (Где?)
      • Функциональность для добавления (Что?)
        • Метод отображения (Как?)
  • Коллекции
    • Инструкции по сборке коллекций

Общий принцип создания определений таков: берем таргет (точку подключения) и помещаем внутри него фичу (нужную функциональность).

Таргеты⚓︎

classMethod⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
class да полное имя класса \App\Helper\Arrays
method да имя метода getValue
argument да позиция аргумента, который вы хотите сделать интерактивным 0, 1, 2, ...
targetValue нет должен использоваться как целевое значение (строка) true, false
targetInArray нет позиция в выражении массива key, value, none
children нет фичи

<!-- Автодополнение для метода find() в классе модели User -->
<classMethod class="\App\Models\User" method="find" argument="1">
    <properties relatedTo="argument" relatedArgument="0" public="true"/>
</classMethod>
$user = \App\Models\User::find(id: 10, property: 'email');
При вводе второго аргумента (property) IDE будет предлагать свойства класса User.

classConstructor⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
class да полное имя класса \App\Helper\Arrays
argument да позиция аргумента, который вы хотите сделать интерактивным 0, 1, 2, ...
targetValue нет должен использоваться как целевое значение (строка) true, false
targetInArray нет позиция в выражении массива key, value, none
children нет фичи

<!-- Внедрение языковой поддержки в конструктор класса Database -->
<classConstructor class="\App\Database" argument="1">
    <languageInjection language="SQL"/>
</classConstructor>
Второй аргумент конструктора Database будет обрабатываться как SQL-код с подсветкой и автодополнением.

classCallable⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
class да полное имя класса \App\Helper\Arrays
argument да позиция аргумента, который вы хотите сделать интерактивным 0, 1, 2, ...
targetValue нет должен использоваться как целевое значение (строка) true, false
targetInArray нет позиция в выражении массива key, value, none
children нет фичи

<!-- Автодополнение для первого аргумента при вызове объекта EventHandler -->
<classCallable class="\Framework\EventHandler" argument="0">
    <methods relatedTo="containingClass" static="false"/>
</classCallable>
При вызове объекта EventHandler как функции, первый аргумент будет предлагать методы (все, кроме статических) текущего класса.

classProperty⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
class да полное имя класса \App\Helper\Arrays
property да имя свойства tableName, property, ...
targetValue нет должен использоваться как целевое значение (строка) true, false
targetInArray нет позиция в выражении массива key, value, none
children нет фичи

<!-- Связь свойства "table" класса Entity с коллекцией таблиц БД -->
<classProperty class="\Framework\Entity" property="table">
    <tables database="main"/>
</classProperty>
Значение свойства table в классе Entity будет автодополняться списком таблиц из базы main.

function⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя функции file_get_contents
argument да позиция аргумента, который вы хотите сделать интерактивным 0, 1, 2, ...
targetValue нет должен использоваться как целевое значение (строка) true, false
targetInArray нет позиция в выражении массива key, value, none
children нет фичи

<!-- Автодополнение для первого аргумента функции view() -->
<function name="view" argument="0">
    <files relatedTo="directory" extension=".twig"/>
</function>
При вызове view('...') IDE предложит файлы с расширением .twig из текущей директории.

returnValue⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
class да полное имя класса \App\Helper\Arrays
method да имя метода getValue
children нет фичи

<!-- Возвращаемое значение метода tableName связывается с коллекцией таблиц -->
<returnValue class="\ActiveRecord" method="tableName">
    <tables database=".+"/>
</returnValue>
Значение, возвращаемое ActiveRecord::tableName(), будет проверяться на соответствие существующим таблицам БД.

Ещё пример:

<returnValue class="\Migration" method="tableName">
    <tables database=".+"/>
</returnValue>
class CreateUsersTable extends Migration {
    public function tableName() {
        return 'usr_list'; // Ошибка: таблица 'usr_list' не существует
    }
}

files⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
xpath да строка xpath для обхода сущностей $project/resources/templates/
extension нет имя метода getValue
children нет фичи

<!-- Обработка всех PHP-файлов в директории templates -->
<files xpath="$project/resources/templates" extension=".php">
    <variableInjection name="this" class="\Framework\View\View"/>
</files>
Во всех PHP-файлах в директории templates переменная $this будет типизирована как \Framework\View\View.

Ещё пример:

<classMethod class="\Illuminate\Support\Facades\Route" method="get" argument="1">
    <files relatedTo="directory" xpath="$project/resources/views" extension=".blade.php"/>
</classMethod>
// В blade-шаблоне:
<a href="{{ route('users.edit') }}"> <!-- IDE предложит 'users.edit' из списка всех роутов -->

Фичи⚓︎

Фичи не используются сами по себе и должны находиться внутри таргетов.

properties⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
relatedTo нет (если задан xpath) относительная точка для поиска записей См. relatedTo
xpath нет (если задан relatedTo) строка xpath для обхода сущностей См. xpath
relatedArgument нет индекс связанного аргумента, полезный для многих значений relatedTo 0, 1, 2, ...
public нет показывать или скрывать такие свойства true, false
protected нет показывать или скрывать такие свойства true, false
private нет показывать или скрывать такие свойства true, false
static нет показывать или скрывать такие свойства true, false
dynamic нет показывать или скрывать такие свойства true, false
children нет процессоры функций
<!-- Автодополнение публичных свойств класса из первого аргумента -->
<properties relatedTo="argument" relatedArgument="0" public="true"/>

methods⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
relatedTo нет (если задан xpath) относительная точка для поиска записей См. relatedTo
xpath нет (если задан relatedTo) строка xpath для обхода сущностей См. xpath
relatedArgument нет индекс связанного аргумента, полезный для многих значений relatedTo 0, 1, 2, ...
public нет показывать или скрывать такие методы true, false
protected нет показывать или скрывать такие методы true, false
private нет показывать или скрывать такие методы true, false
abstract нет показывать или скрывать такие методы true, false
static нет показывать или скрывать такие методы true, false
dynamic нет показывать или скрывать такие методы true, false
children нет процессоры функций
<!-- Показывает нестатические методы текущего класса -->
<methods relatedTo="containingClass" static="false"/>

Ещё пример:

<classMethod class="\yii\widgets\ActiveForm" method="field" argument="2">
    <methods
        relatedTo="argument"
        relatedArgument="0"
        static="false"
        public="true"
    />
</classMethod>
<?= $form->field($model, 'attribute', [
    'inputOptions' => ['class' => 'form-control']
])-> // IDE предложит методы модели $model

files⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
relatedTo нет (если задан xpath) относительная точка для поиска записей См. relatedTo
xpath нет (если задан relatedTo) строка xpath для обхода сущностей См. xpath
extension нет расширение файла, которое вы хотите отфильтровать и скрыть от автозаполнения (пусто), php, blade.php, ...
children нет процессоры функций
<!-- Автодополнение изображений в директории ресурсов -->
<files relatedTo="directory" extension=".png">
    <regexp from="\.png$" to=""/>
</files>

directories⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
relatedTo нет (если задан xpath) относительная точка для поиска записей См. relatedTo
xpath нет (если задан relatedTo) строка xpath для обхода сущностей См. xpath
children нет процессоры функций
<!-- Предлагает поддиректории в папке migrations -->
<directories xpath="$project/database/migrations"/>

tables⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
database да точное имя подключения ИЛИ регулярное выражение main, .+, ...
children нет процессоры функций
<!-- Список таблиц из всех баз данных -->
<tables database=".+"/>

returnType⚓︎

Параметры

returnType:

Параметр Обязательный Описание Возможные значения
children нет список псевдонимов

alias:

Параметр Обязательный Описание Возможные значения
name да значение аргумента, соответствующее возвращаемому классу int, user
class да полное имя класса \IntResult, \UserFactory
<!-- Связывает возвращаемые типы с кастомными классами -->
<returnType>
    <alias name="int" class="\Result\IntResult"/>
    <alias name="string" class="\Result\StringResult"/>
</returnType>

При указании нескольких типов сразу будет использоваться объединение типов.

variableInjection⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя переменной this, urlGenerator
class да полное имя класса \Framework\View\View, \Framework\Router\UrlGenerator
<!-- Внедрение переменной $generator типа UrlGenerator в шаблоны -->
<variableInjection name="generator" class="\Framework\Router\UrlGenerator"/>

Ещё пример:

<files xpath="$project/views" extension=".twig">
    <variableInjection name="app" class="\Core\Application"/>
    <variableInjection name="user" class="\Models\User"/>
</files>
{{ app.request.path }} <!-- Навигация к классу Application -->
{{ user.email }} <!-- Автодополнение свойств User -->

languageInjection⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
language да известный язык PHPStorm RegExp, CSS, SQL и пр.

<!-- Внедрение поддержки синтаксиса SQL -->
<languageInjection language="SQL"/>
Ещё пример:

<classMethod class="\App\DB\QueryBuilder" method="whereRaw" argument="0">
    <languageInjection language="SQL"/>
    <tables database="main"/>
</classMethod>
// Полноценная подсветка SQL + автодополнение таблиц БД
$query->whereRaw("SELECT * FROM users WHERE id = ?", [1]);

collection⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя коллекции tags, cycle/orm:entities
argument да позиция аргумента, который вы хотите сделать интерактивным 0, 1, 2, ...
children нет процессоры функций
<!-- Использование предопределённой коллекции HTML-тегов -->
<collection name="GLOBAL:html-tags" argument="0"/>

arrayValues⚓︎

Возвращает значения массива для автозавершения ввода.

<arrayValues xpath="\SomeClass.$someProperty"/>

arrayKeys⚓︎

Возвращает ключи массива для автозавершения ввода.

<arrayKeys xpath="\SomeClass.$someProperty"/>

stopCompletion⚓︎

Позволяет отключить встроенное автозавершение ввода PHPStorm.

<!-- другие фичи -->
<stopCompletion/>

icon⚓︎

Позволяет отображать иконку.

<files xpath="$project/" extension="php">
    <icon xpath="$project/examples/injection/icons/users.svg"/>
</files>

Глобальные коллекции⚓︎

Название Описание Пример
GLOBAL:env Предоставляет собранные переменные окружения из вызовов функции putenv и файлов .env APP_ENV, APP_DEBUG
GLOBAL:html-tags Предоставляет список известных HTML-тегов div, span, abbr
GLOBAL:http-headers Предоставляет список HTTP-заголовков Accept, Content-Type
GLOBAL:http-methods Предоставляет список HTTP-методов GET, POST, PUT
GLOBAL:mime-types Предоставляет список известных MIME-типов application/json, image/jpeg
GLOBAL:php-classes Предоставляет полные имена классов PHP \App\MyService
GLOBAL:php-functions Предоставляет список всех PHP функций, включая встроенные и пользовательские time, user_function
GLOBAL:php-interfaces Предоставляет список всех PHP интерфейсов в вашем проекте \App\MyServiceInterface
GLOBAL:php-traits Предоставляет список всех PHP трейтов в вашем проекте \App\Traits\Deletable

<function name="sendRequest" argument="0">
    <collection name="GLOBAL:http-methods"/>
</function>
sendRequest('GET', $url); // Подскажет GET, POST, PUT и т. д.

Коллекции⚓︎

Коллекции можно объединять. Определяйте их внутри тегов <collections></collections>:

<meta-storm xmlns="meta-storm">
    <definitions>
        <target>
            <collection name="имя коллекции" />
        </target>
    </definitions>
    <collections>
        <!-- коллекции-->
    </collections>
</meta-storm>

attributeClass⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя коллекции tags, cycle/orm:entities
class да полное имя класса атрибута \Attributes\AsCommand
<!-- Сбор всех классов с атрибутом AsCommand -->
<attributeClass name="commands" class="\Attributes\AsCommand"/>

attributeArgument⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя коллекции tags, cycle/orm:entities
class да полное имя класса атрибута \Attributes\AsCommand
argument да позиция аргумента, который вы хотите собрать 0, 1, 2, ...
<!-- Сбор первого аргумента атрибута Route -->
<attributeArgument name="routes" class="\Framework\Attributes\Route" argument="0"/>

Ещё пример:

<collections>
    <attributeArgument
        name="api-endpoints"
        class="\App\Attributes\Endpoint"
        argument="0"
    />
</collections>

<definitions>
    <function name="fetchData" argument="0">
        <collection name="api-endpoints"/>
    </function>
</definitions>
#[Endpoint('/api/users')]
class UserController {}

fetchData('/api/'); // IDE предложит все зарегистрированные эндпойнты

jsonFile⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя коллекции tags, cycle/orm:entities
xpath да строка xpath для обхода сущностей $project/resources/translations/en.json
<!-- Сбор ключей из JSON-файла переводов -->
<jsonFile name="translations" xpath="$project/resources/lang/en.json"/>

Ещё пример:

<jsonFile name="config-keys" xpath="$project/config/app.json">
    <regexp from="([A-Z])" to="_$1"/>
    <case from=".*" case="lower"/>
</jsonFile>
config('APP_ENV'); // IDE предложит 'app_env' после обработки

strings⚓︎

Параметры
Параметр Обязательный Описание Возможные значения
name да имя коллекции tags, cycle/orm:entities
children нет строки сами по себе
<!-- Статический набор строк -->
<strings name="greetings">
    <value>Hello</value>
    <value>Привет</value>
</strings>

Переменные окружения⚓︎

Переменные окружения позволяют осуществлять позднюю статическую привязку для определений между поставщиком и пользователем.

Параметр Обязательный Описание Возможные значения
name да имя переменной VIEW-THEME, YII2/FRAMEWORK:VIEW-THEME
value да значения переменной dark, database-name, ...
children нет процессоры функций
<!-- Переопределение темы представлений -->
<envs>
    <env name="VIEW-THEME" value="light"/>
</envs>

Процессоры⚓︎

regexp⚓︎

<!-- Преобразование CamelCase в snake_case -->
<regexp from="([a-z])([A-Z])" to="$1_$2"/>

case⚓︎

<!-- Приведение к нижнему регистру -->
<case from=".*" case="lower"/>

append⚓︎

<!-- Добавление префикса `/api/v1` к путям -->
<append value="/api/v1"/>
Ещё пример:

<collection name="custom-tags">
    <strings name="html-tags">
        <value>modal</value>
        <value>accordion</value>
    </strings>
    <append value="-component"/>
</collection>
Component::render('modal'); // При вводе предложит 'modal-component'

Дополнительно⚓︎

relatedTo⚓︎

  • Сложный параметр, изменяющий интерпретацию файлов
  • Возможные значения:
    • file – связано с текущим (открытым) файлом
    • containingClass – связано с текущим (открытым) классом
    • directory – связано с директорией текущего файла
    • project – связано с путём проекта
    • argument – связано с позиционным аргументом: это $obj в $service->method($obj, $prop)
    • variable – связано с переменной, содержащей метод: это $service в $service->method()

xpath⚓︎

XPath для <files>⚓︎

  • Строка, используемая для обхода файловой системы, как обычный путь на основе Unix
  • XPath должен начинаться с относительной точки:
    • $project – базовый путь проекта
    • $file – связано с текущим файлом
    • $directory – связано с текущей директорией

Советы⚓︎

  • Конфигурационные файлы могут быть размещены в любом месте проекта.
  • Используйте коллекции для определения наборов значений, таких как теги HTML или методы HTTP.
  • Поддерживайте свои конфигурации в пакетах и распространяйте их вместе с библиотеками.

Примеры конфигураций⚓︎

Заключение⚓︎

Мы получаем мощный инструмент, который делает разработку на PHP быстрее и удобнее. Но готовы ли вы сломать мозг в попытках создать свой конфиг?

Задать вопросы или подкинуть идеи разработчику можно в телеге.

Если вам понравился плагин, поставьте звезду репозиторию на GitHub. В документации можно ознакомиться со всеми примерами и полным описанием доступных параметров.

Комментарии