MetaStorm – IDE в IDE. Первое большое обновление

49393397de0a189bc8a3d4771027930f.jpeg

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

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

Фидбек

После первого релиза пришло довольно много фидбека, как с запросами на различные фичи, так и с багрепортами. В том числе, что в статье ничего не понятно: ни для чего этот плагин нужен, ни как его правильно конфигурировать.
Я делал некоторые изменения в README проекта, но лучше не становилось. Пришлось разбираться с корней и мучать людей. Однако, всем понравилось.

По размеру кодовой базы плагин увеличился в 3 раза, с ~2 300 строк кода до ~6 700.
Однако своевременное изменение архитектуры позволило не превратить 6 700 в 16 700 и не сделало плагин неподдерживаемым и сложным для внедрения новых фич.
Каждая из фич практически полностью изолирована и выполняет только свою часть. Да, есть связующие части, но в большей степени компоненты изолированы.

Большое спасибо за идеи по развитию, применению, структуре конфигов, фичам и тестированию @roxblnfk @Cutcode

Сравнение с прошлой версией

Способ конфигурирования изменился и успел сформировать принцип построения, который вряд ли будет меняться.

Давайте рассмотрим на примере, как было раньше:


Во что это превратилось теперь:

  
      

Можно сразу заметить, что раньше отправной точкой был сразу комбинированный набор:

Так как появилась потребность иметь разные точки монтирования фичей, практически само собой сформировался следующий гайдлайн:

  • Target (Таргет) — определение места в коде, куда нужно добавить желаемый функционал

  • Feature (Фича) — описание что мы хотим предоставить для пользователя в таргете

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

Определение гайдлайна позволило сделать гибче как сам способ конфигурирования, так и архитектуру внутри исходного кода.
Теперь внедрение нового таргета занимает относительно мало времени и не аффектит существующие таргеты и фичи. Благодаря композиции появилась возможность комбинировать фичи и таргеты как угодно, с ограничениями лишь логическими. Например, нельзя обратиться к 1 аргументу у возвращаемого значения, т.к. поддерживается только одиночные строки и т.п…

Фичи для методов и файлов тоже получили изменения:

  • Методы

  
      

  • Файлы

  
      

Фичи методов и свойств обзавелись фильтрами.
Теперь при конфигурировании фичей вы можете указать опциональные параметры для фильтрации свойств или методов по их модификаторам:


	 private="false" 
	 static="false" 
	 />  

Все фильтров имеют по умолчанию значения true, что означает «включение» данного типа в итоговый набор. Установите значение false, если хотите исключить выбранный модификатор.
Если вы хотите иметь несколько противоположных друг другу набору итоговых данные, то можете сделать композицию из нужных фильтров:


	
	
 

Такая конфигурация будет включать в себя следующие методы:

Фича «Файлы»

Фича теперь работает с любыми «расширениями» файлов, например .blade.php.
В первой версии нельзя было отрезать .blade.php, так как .blade — это суффикс в названии файла. Следующий код не работал:


Этот момент был исправлен и теперь всё будет работать:


XPath

После многочисленных обсуждений пришло понимание, что нужен некий pointer, который поможет искать необходимые сущности в коде, в том числе «прыжки» от класса к классу.
Например, в следующем примере:

class Foo { public Bar $bar; }
class Buzz { public string $template = Foo::class; }

Можно прыгать от точки к точке различными способами:

Однако, связей не может быть в вакууме, поэтому XPath должен начинаться с одного из нескольких установленных значений:

  • $containingClass — класс, в котором сейчас установлен курсор

  • $argument — выбранный аргумент. Например, это $obj в $service->method($obj, $prop)

  • $variable — переменная или свойство класса, на котором был таргет. Например, это $service в $service->method() Связи в XPath разделяются точкой, переменные предопределяются префиксом $, а методы должны заканчиваться на ().

Разберем еще один пример:

class Foo { public Bar $bar; }
class Buzz { 
	public function getTemplate(): Foo {} 
	public function action() {
		'' // <--- позиция мыши
	} 
}

XPath от позиции мыши до Foo::$bar можно описать следующим образом:
$containingClass.getTemplate().$bar

Можно XPath и для файлов, только отправные точки будут другими:

  • $project — базовая директория проекта

  • $directory — директория, в которой находится текущий файл

  • $file — текущий файл

Текущий файл можно использовать для дальнейших манипуляций с регуляркой. Например, найти директорию с шаблонами по имени контроллера.

Фича «Значения из массива»

С помощью XPath можно добраться до нужного элемента и вытащить из массива строки для подсказок:

  
	  

  
class ArrayValues  
{  
    public array $strings = ['value1', 'value2', 'value5', 77, 10 => ['inner']];
}  
  
  
$resolver = new ArrayValues();  
$resolver->get('');

В  попадутся лишь 'value1, value2, value5, т.к. лишь эти элементы являются строками.
Расширять поиск на другие типы может и имеет смысл, но кейсов использования на данный момент нет, поэтому и нет поддержки, но всё может поменяться в любой момент.

Фича «Таблицы»

Появилась возможность добавить в автокомплит названия таблиц из базы данных!
Выглядит это следующим образом:

  
	

При наборе текста в Finder::getTables() будут подсказываться все названия таблиц из базы данных с именем demo.

А чтобы не зря добавлять подсказку таблиц, я добавил новый таргет — возвращаемое значение.
Теперь можно делать автокомплит таблиц для метода определения таблицы в Active Record моделях или аналогичных местах:

  
    

Коллекции

Коллекции появились как механизм упрощения управления наборами данных, нужных для подсказок.
Коллекции работают следующим образом:

  • Коллекция имеет собственное имя

  • Коллекция может формироваться из различных коллекторов

  • Коллекция используется как фича внутри таргета

Пример коллекции статических строк:

  
      
          
    
  
  
      
        Hello  
        Static  
        World  
    

Помимо статичных строк есть еще несколько коллекторов:

  • Коллектор сбора использования атрибута :

  • Коллектор сбора аргументов из использования атрибута :

Переменные

Появилось требования дать юзерам возможность управлять подсказками от вендора.
Например, вендор может описать подсказки для поиска файлов-шаблонов в директории со стандартной темой default.
Но если есть дефолтная, то есть и кастомная тема? Для этого случая и хотелось бы дать пользователю возможность использовать все конфиги от вендора, но с небольшим «но».

Работает это следующим образом:

  • Вы, как вендор, составляете подсказки

  • В изменяемую часть вставляете переменную

  • Переменную инициализируете со значением по умолчанию

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

Пример вендор конфига:
vendor/xepozz/library/.meta-storm.xml:

  
      
          
            
				  
            
		
	
  
  
      

Пример пользовательского конфига:
.meta-storm.xml:

  
      

Таким образом вы переопределяете изменяемую часть из вендора и пользуетесь всеми фичами.

Однако есть некоторые ограничения:

  • Имя переменной должно начинаться и заканчиваться на букву

  • Имя переменной может содержать следующие символы: a-z, 0-9, :, _, -

  • Переменная из vendor/* директории может быть переопределена любым другим вендором или пользователем.

  • Пользовательские конфиги, расположенные вне vendor директории имеют приоритет над теми, которые находятся внутри vendor/*

  • Использование переменных с одинаковым именем в разных вендорах может вызвать неконтролируемый хаос, поэтому делайте имена переменных уникальными

Как и имена коллекций, хорошо бы называть переменные с префиксом по имени вендора+пакета.
Например:

  
      

На текущий момент использование переменных окружений разрешено лишь в  и  процессорах. Если вам требуется эта функциональность в другом месте, дайте мне знать.

Планы на будущее:

  • Добавить кнопку поиска ссылающихся референсов на открытый файл

  • Добавить фичи по улучшению типизации для ваших автокомплитов

  • Добавить поддержку резолва дженериков через конфиги

  • Добавить возможность объявлять переменную-призрак для файлов-шаблонов

  • Написать тесты

    • Раньше я делал ручное тестирование на тестируемом стенде

    • Сейчас плагин стал в 3 раза больше и тестировать вручную уже не представляется посильным

  • Внедрять ещё таргеты и фичи специально для вас

  • Раскидывать конфиги по различным библиотекам

А ещё у MetaStorm появился телеграмм канал, где вы можете задать свои вопросы по плагину и конфигурированию, следить за обновлениями, зарепортить баг или попросить новую фичу.
Закидывайте ссылки на репозитории, куда вы внедрили Meta Storm в чат.
На странице публичного репозитория вы можете посмотреть более детальное описание всех возможностей конфигурирования плагина.

Например уже сейчас вы можете делать Moonshine админку на Temporal с Cycle ORM под капотом и использовать максимальное количество фич от MetaStorm! Это ли не amazing?

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

© Habrahabr.ru