Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Разработка плагина IntelliJ IDEA. Часть 6

Anna | 5.06.2014 | нет комментариев

В этой части: рефакторинги, форматирование, настройки и другие пригодные функции. Предыдущая часть.

Рефакторинг «Переименование»

Операция переименования в IntelliJ IDEA схожа на «Find Usages», IDEA использует те же правила для поиска элементов для переименования и тот же индекс слов для нахождения файлов, в которых могут быть ссылки на элемент, тот, что будет переименован.

Когда выполняется данный рефакторинг, на целевом элементе вызывается способ PsiNamedElement.setName(), а для всех ссылок на него – способ PsiReference.handleElementRename(). Оба способа исполняют одно основное действие – замену нижележащего AST-узла, новым, содержащим введенный пользователем текст. Создание всецело правильного AST бывает достаточно трудным, но дозволено воспользоваться дальнейшим способом: сделать фальшивый файл пользовательского языка, содержащий нужный узел, и после этого скопировать его.

Пример: реализация способа setName() в плагине Properties.

Иной, связанный с рефакторингом по переименованию интерфейс – NamesValidator. Данный интерфейс разрешает плагину проверять, правильно ли введено пользователем имя идентификатора, т.е. соответствует правилам именования в пользовательском языке и не совпадает с ключевым словом. Если реализация интерфейса не предоставляется плагином, то применяются правила именования Java. Реализация должна быть зарегистрирована в точке растяжения com.intellij.lang.namesValidator.

Пример: NamesValidator для Properties.

Последующая кастомизация процесса переименования допустима на нескольких ярусах. Предоставив реализацию интерфейса RenameHandler, плагин горазд всецело заменить пользовательский интерфейс и логику выполнения рефакторинга по переименованию, что также подразумевает вероятность работы с чем-то хорошим от PsiElement.

Пример: RenameHandler для переименования resource bundle.

Если не требуется переопределять типовой UI, но нужно расширить логику переименования, дозволено предоставить собственную реализацию интерфейса RenamePsiElementProcessor. Что разрешает:

  • Переименовать элемент, чудесный от того, над которым было исполнено действие (скажем, способ базового класса);
  • Переименовать несколько элементов единовременно (если их имена логически связаны, но необходимо самосильно следить за коллизиями);
  • Переопределить логику поиска ссылок в тексте;
  • И тому сходственное.

Пример: RenamePsiElementProcesssor для переименования Property.

Рефакторинг «Безвредное удаление»

Рефакторинг по неопасному удалению тоже построен поверх фреймворка «Find Usages». Для того Дабы применять неопасное удаление обязаны быть реализованы две вещи:

  • интерфейс RefactoringSupportProvider, зарегистрированный в точке растяженияcom.intellij.lang.refactoringSupport и способ isSafeDeleteAvailable(), проверяющий доступность рефакторинга для данного PSI-элемента;
  • способы PsiElement.delete() для элементов, разрешенных в предыдущем пункте. Удаление PSI-элемента реализуется как удаление нижележащих узлов абстрактного синтаксического дерева (пример).

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

Пример: реализация SafeDeleteProcessorDelegate для файлов *.properties.

Механическое форматирование кода

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

Процесс форматирования файла либо фрагмента состоит из следующих основных шагов:

  • реализация FormattingModelBuilder, предоставляющая модель форматирования для обрабатываемого документа;
  • модель форматирования выстраивает конструкцию файла как дерево блоков (объектов Block), с ассоциированными отступами, переносами, выравниванием;
  • движок форматирования вычисляет последовательность пробельных символов (пробелы, табуляции, переносы строк), которая должна быть размещена на границе всякого блока;
  • модель форматирования запрашивает вставку пробельных символов в нужные позиции в файле.

Конструкция блоков обыкновенно повторяет PSI-конструкцию файла. Форматер модифицирует только символы, находящиеся между блоками, следственно дерево блоков должно покрывать все непробельные символы файла, в отвратном случае все, что находится между блоками может быть удалено.

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

Для всякого блока плагин должен определить следующие свойства:

  • пробельный промежуток, определяющий, сколько пробелов (минимальное и наивысшее число) и переводов строк (также минимальное и наивысшее число) обязаны находиться между дочерними блоками, а также сберегать ли теснее существующие пустые строки;
  • отступ – определяет позицию касательно родительского блока. Существует несколько типов отступов: «без отступа», «обыкновенный отступ», «продолжительный отступ». Если модель не определяет определенный вид отступа, по-умолчанию применяется «продолжительный, помимо первого элемента», т.е. 1-й блок в последовательности не имеет отступа, а остальные получают продолжительный;
  • переносы строк – определяет когда длинную строку переносить на следующую. Реализуется вставкой переноса строки перед содержимым блока;
  • выравнивание – определяет, как блоки будут выровнены касательно друг друга. Если для выравнивания 2-х блоков применяется один и тот же объект Alignment и в строке перед вторым блоком только пробелы, то форматер сдвигает его, так Дабы он начинался с того же столбца, что и 1-й.

Специальный случай применения форматера — когда пользователь плагина нажимает Enter во время редактирования начального кода. Дабы определить значение отступа, движок форматирования вызывает способ getChildAttributes() либо на блоке непринужденно до курсора, либо на родительском, в зависимости от возвращенного значения способа isIncomplete() на блоке до курсора. Если блок закончен, то на нем и вызывается getChildAttributes(); в отвратном случае вызов происходит на родительском блоке.

Настройки жанра кода

Для определения величины отступа по-умолчанию и, скажем, Дабы дозволить пользователю настроить размер табуляции и отступов, дозволено реализовать интерфейс FileTypeIndentOptionsProvider, тот, что нужно зарегистрироватьв точке растяжения fileTypeIndentOptionsProvider. Способ интерфейса createIndentOptions() определяет значение по-умолчанию для отступов.

Для больше эластичного управления настройками допустимо зарегистрировать в точке растяженияcom.intellij.applicationConfigurable реализацию интерфейса Configurable, тот, что представляет собой Java Swing форму, отображаемую в диалоге Settings.

Инспекции

Инспекции начального кода для пользовательских языков применяют тот же API, что и остальные инспекции и базируются на классе LocalInspectionTool.

Функциональность LocalInspectionTool Отчасти дублирует Annotator, основные различия заключаются в поддержке пакетной обработки кода (запускается действием «Analyze | Inspect Code…»), вероятности отключить инспекции и настройке их опций. Если ничего из перечисленного не требуется, к примеру, обзор необходимо запускать только в энергичном редакторе, то применение Annotator больше выигрышно, т.к. он владеет лучшей эффективностью (вследствие поддержке инкрементального обзора) и большей гибкостью в плане подсветки ошибок.

Пример: простая инспекция для файлов .properties.

Пользовательские Intentions (quickfix) также применяют типовой API, они обязаны предоставлять реализацию интерфейса IntentionAction, зарегистрированную в точке растяжения <intentionAction> в plugin.xml.

Пример: легкой Intention для Groovy.

Отображение конструкции кода

Отображение конструкции кода может быть настроено на нескольких ярусах. Если языковой плагин предоставляет реализацию интерфейса StructureView, он может всецело заменить типовой компонент. Правда для большинства языков это не требуется и типовой Structure View может быть переиспользован.
В первую очередь нужно зарегистрировать реализацию интерфейса PsiStructureViewFactory в точке растяжения com.intellij.lang.psiStructureViewFactory.

Пример: PsiStructureViewFactory для файлов .properties.

Для повторного применения встроенной реализации, плагин должен возвратить TreeBasedStructureViewBuilderиз способа PsiStructureViewFactory.getStructureViewBuilder(). В качестве модели плагин может определить подкласс TextEditorBasedStructureViewModel, и переопределив его способы, настроить отображение конструкции для пользовательского языка.

Пример: StructureViewModel для файлов .properties.

Базовый способ getRoot() возвращает экземпляр интерфейса StructureViewTreeElement. IDEA не предоставляет стандартной реализации этого интерфейса, следственно плагин должен реализовать его всецело.

Обыкновенно Structure View строится на основе PSI-дерева. В реализации способа StructureViewTreeElement.getChildren() обязаны быть представлены дочерние элементы нынешнего узла, которые будут отображены в структуре кода. Иной значимый способ – это getPresentation(), тот, что применяется для настройки текста, признаков, иконки и т.д., показываемых в Structure View.

Реализация способа StructureViewTreeElement.getChildren() должна совпадать с TextEditorBasedStructureViewModel.getSuitableClasses(). Конечный способ возвращает массив PsiElement, которые могут бытьпоказаны как элементы конструкции кода и использованы в качестве целевых элементов при наведении курсора, если энергична опция «Autoscroll from source».

Пример: StructureViewElement для Property.

Функция «Surround With»

Для поддержки действия «Code | Surround With…», плагин должен зарегистрировать как минимум одну реализацию интерфейса SurroundDescriptor в точке растяжения com.intellij.lang.surroundDescriptor. Всякий дескриптор определяет тип фрагмента кода, тот, что может быть им обернут — скажем, один отвечает за выражения, 2-й — за обработку операторов. Всякий дескриптор содержит массив объектов Surrounder, определяющих специфичные образцы, используемые для оборачивания выделенного текста (скажем, «Surround With if», «Surround With for»).

Когда выполняется действие «Surround With…», IDEA опрашивает по очереди все дескрипторы, пока один не возвратит непустой массив из способа getElementsToSurround(). Тогда вызывается способ Surrounder.isApplicable() для всякого элемента массива, Дабы проверить могут ли использоваться их образцы в данном контексте. Если пользователь выделяет определенный Surrounder в сплывающем меню, то выполняется его способ surroundElements().

Навигация до классов и литералов

Пользовательские плагины могут предоставлять их личные элементы, которые будут включены в список, показываемый IDEA, когда пользователь выбирает действие «Go to | Class…» либо «Go to | Symbol…».
Для того Дабы сделать это, плагин обязан предоставить реализацию интерфейса ChooseByNameContributor и зарегистрировать в точке растяжения com.intellij.gotoSymbolContributor либоcom.intellij.gotoClassContributor.
Всякая реализация должна уметь возвращать полный список имен из используемого плана, тот, что будет отфильтрован IDEA в соответствии с введенным текстом в диалоге поиска. Для всякого имени в списке, должен быть предоставлен список из объектов NavigationItem, которые определяют местоположение имени, выбранного из списка.

Документация

Для применения разных типов встроенной в среду интегрированной разработки документации (всплывающая по Ctrl-hover, стремительная по Ctrl-Q), плагин должен предоставить реализацию интерфейсаDocumentationProvider и зарегистрировать ее в точке растяжения lang.documentationProvider. Начиная с IDEA версии 10.5, существует типовой базовый класс AbstractDocumentationProvider.
Способ getQuickNavigateInfo() применяется для показа документации при наведении курсора мыши с зажатой клавишей Ctrl.

Пример: DocumentationProvider для языка Properties.

Разные добавочные функции

Для поддержки функции подсветки парных скобок, все что требуется — это реализовать интерфейсPairedBraceMatcher и возвратить массив пар скобок (BracePair). Всякая пара скобок определяет символы открывающих и закрывающих скобок и соответствующие им типы токенов (в тезисе, допустимо применять многосимвольные токены, такие как begin/end, но их подсветка не будет всецело правильна).

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

Сворачивание блоков кода контролируется плагином через интерфейс FoldingBuilder. Способ buildFoldRegions() возвращает список текстовых диапазонов, которые могут быть свернуты (массив объектов FoldingDescriptor), замещающий текст на месте свернутого блока определяется способом getPlaceholderText(), а состояние по-умолчанию – способом isCollapsedByDefault(). Блоки дозволено объединять в группы: так сворачивание одно элемента из группы сворачивает остальные и напротив. Для создания групп имеется фабричный способ FoldingGroup.newGroup(). Сделанный класс должен быть зарегистрирован в точке растяженияlang.foldingBuilder.

Комментатор – это функция IDEA, дозволяющая закомментировать нынешнюю строку либо выделенный диапазон текста. Функция контролируется интерфейсом Commenter, тот, что определяет префикс для однострочных комментариев, префикс и суффикс для блочных комментариев, если они имеются в пользовательском языке. Интерфейс должен быть зарегистрирован в точке растяжения lang.commenter.

Пример: комментатор для языка Properties.

Список заметок «To Do» — функция механически становится доступна, когда плагин предоставляет реализацию способа ParserDefinition.getCommentTokens(). Позже чего заметки дозволено оставлять в комментариях вида «// Todo текст заметки», и просматривать на панели «To Do View» (Alt 6).

Функция «View | Context Info» поддерживается пользовательскими языками начиная с IDEA 10.5. Для ее работы требуется реализация Structure view, основанная на TreeBasedStructureViewBuilder и реализация интерфейса DeclarationRangeHandler, зарегистрированная в точке растяжения declarationRangeHandler.

Строковые маркеры помогают помечать всякий код иконками на полях редактора. Иконки могут предоставлять навигацию к связанному Psi-элементу. Для реализации этой функции IntelliJ IDEA предоставляет классRelatedItemLineMarkerProvider.
Провайдер маркеров должен быть зарегистрирован в точке растяжения codeInsight.lineMarkerProvider.

Файловые образцы определяют, какое содержимое будет сгенерировано при создании нового файла определенного типа. Они разрешают создавать файлы, которые теснее содержат определенный первоначальный начальный код (образцы поддерживают метасимволы: дата/время, пользователь, пакет/класс и т.д.). Их дозволено просматривать, редактировать и создавать на странице «Settings | File Templates». Добавочно, IntelliJ IDEA предоставляет комфортный API для управления образцами из кода плагинов. Для этого нужно определить экземпляр интерфейса FileTemplateGroupDescriptorFactory и зарегистрировать его в точке растяжения com.intellij.fileTemplateGroup.

Все статьи цикла: 123456.
Продолжение следует.
Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB