Я занялся разработкой плагина для Yii3 под PHPStorm некоторое время назад.
Помимо плагина время от времени заглядываю в сам Yii3, на работе использую Yii2, различные библиотеки и вовсе на чистом PHP сделаны.

Переключаться между инструментами проблем не вызывает, но некоторые вещи имеют несколько бонусных DX (Developer Experience) очков, а некоторые в минусе.

Логично ведь, что если ты пишешь функцию, которая должна принимать значение из набора, то нужно показать этот набор. А может еще и свалидировать ошибку. А еще и провалиться внутрь по CTRL+Click. А еще и обратный референс найти. Ну и рефакторинг общий сделать, раз уж разошлись.

Давайте разберем пример:

$this->render('index', $params);

Вы сотню раз видели такой код и скорее всего точно можно угадать, что эта функция принимает имя вью файла и параметры в качестве аргументов.

Может ли 'index' быть любым? Скорее всего нет. Может ли 'index' быть заменен на 'view'? Скорее всего да, если есть такой файл. Как понять есть ли такой файл? Сходить и посмотреть в директорию. В директории есть следующие файлы: 'index.php', 'view.php', 'create.php', 'update.php'

Ну и отлично? Нужно их и показать в автокомплите. Стоп, метод render() принимает имя файла без его расширения .php. Ну тогда и отрежем? Отрежем.

Раз уж знаем файл, то предоставим на него reference, чтобы PHPStorm предоставил переход к файлу и автоматический рефакторинг.

Таким образом мы можем сделать подсказки и для какого-нибудь FileHelper::read('/path/to/file.txt') :

  • Знаем что будет файл

  • Знаем откуда будем отталкиваться если это relative path Значит можем сделать lookup в директорию и достать подсказки?

Помимо подсказок «в файл» скорее всего вы часто сталкиваетесь еще и с подсказками «в свойство»:

$activeRecord->getAttribute('<property>')
$activeRecord->getLabel('<property>')
Helper::getColumn($object, '<property>')
Helper::index($objects, '<property>')
$queryBuilder->where(['<property>' => '<value>])

И куча других примеров. Если функция принимает аргументом значение одного из свойств из нужного объекта, то скорее всего, при нарушении этого ограничения, вы получите исключение?

Такие фишки обычно закладывают в ABCD Plugin. Но этот плагин может не обновляться, отказаться от поддержки легаси, не существовать под вашу версию IDE, не поддерживать новые фичи и точно не будет поддерживать thrid-party libraries. В такие плагины закладывают немного иной функционал, но зачастую докидывают и всякие автокомплиты с референсингом.

Теперь не нужно искать плагин под вашу любимую библиотеку или собственный метод:

В README описан пример и на мой взгляд он довольно понятен. Если нет, дайте мне знать.
Разберем несколько вариантов конфига, но для начала вводная:
Нулевое. Пишите сколько угодно файлов, храните их где хотите, главное чтобы файл имел окончание .meta-storm.xml
Первое. Всё должно лежать внутри:

<?xml version="1.0" encoding="UTF-8" ?>
<meta-storm xmlns="meta-storm">
    <definitions>
		----- тут все определения -----
    </definitions>
</meta-storm>

Второе. На данный момент есть 2 варианта референсинга: файлы и свойства.
Третье. Есть текстовые процессоры: regexp и append для файлов.

Подсказка метода render() в Yii2 фреймворке:

<files  
  className="\yii\base\Controller"  
  methodName="render"  
  argumentIndex="0"  
  fileExt="php"  
  relatedTo="file"  
>  
  <directoryProcessors>  
    <regexp from="Controller\.php" to=""/>  
    <regexp from="([a-z])([A-Z])" to="$1-$2"/>  
    <regexp from="/controllers/" to="/views/"/>  
    <regexp from="/modules/([^\\/]+)/views/" to="/themes/default/modules/$1/views/"/>  
  </directoryProcessors>  
</files>

Подсказка метода render() в файле представления:

<files  
  className="\yii\base\View"  
  methodName="render"  
  argumentIndex="0"  
  fileExt="php"  
  relatedTo="directory"  
/>
  • Одинаково для renderFile , renderAjax

Подсказка мейлера:

<files  
  className="\yii\swiftmailer\Mailer"  
  methodName="compose"  
  argumentIndex="0"  
  fileExt="php"  
  relatedTo="project"  
>  
  <directoryProcessors>  
    <append value="common/mail/" />  
  </directoryProcessors>  
</files>

Подсказка Active Form:

<properties  
  className="\yii\widgets\ActiveForm"  
  methodName="field"  
  argumentIndex="1"  
  relatedTo="argument"  
  relatedArgumentIndex="0"  
/>

Подсказка ArrayHelper:

<properties  
  className="\yii\helpers\ArrayHelper"  
  methodName="getColumn"  
  argumentIndex="1"  
  relatedTo="argument"  
  relatedArgumentIndex="0"  
/>

Описывать значения className и methodName думаю смысла нет.
argumentIndex – это позиция аргумента, которому вы будете добавлять интерактив.
relatedTo – та самая вещь, которая побудила меня написать этот плагин, значения могут быть следующие: file, directory, project, argument, variable, все они описаны в документации. Основная мысль заложенная здесь – это base, от которой нужно отталкиваться:

  • Искать файлы в текущей директории

  • Искать файлы по статическому пути

  • Искать файлы по имени текущего файла, предварительно преобразовав его

  • Искать данные в переменной $var->

  • Искать в аргументе: property($obj, 'prop1')

Первая версия содержит описанный выше функционал, но уже есть некоторые планы на будущее. Буду рад фидбеку и желаемым фичам.

Как появится время, буду раскидывать Pull Request в используемые проекты. Вы уже сейчас можете установить себе плагин и попробовать покрыть любые из используемых кейсов.

Обсуждение доработок, фичей и багов можно вести в Issue на гитхабе.


Полезные ссылки

Обсуждение можно продолжить у меня в телеграмм канале

Комментарии (0)