Разработка плагинов
на базе IntelliJ Platform
Николай Чашников
Nikolay.Chashnikov@jetbrains.com
Continuous Integration
● сборка плагина
● запуск тестов
● установка и обновление плагина в IDE
Структура дистрибутива плагина
samplePlugin.zip
samplePlugin
lib
samplePlugin.jar
plugin classes
META-INF
plugin.xml
pluginLib.jar
...
Сборка плагина вне IDE
● IntelliJ IDEA Project runner (TeamCity)
● Ant (Build | Generate Ant Build)
● ...
Настройка проекта для сборки на TeamCity

создание артефакта для плагина
(File | Project Structure | Artifacts)
Build Configuration на TeamCity
● настройка VCS
● настройка внешних зависимостей (IDEA
SDK)
○ получение через VCS
○ копирование на build agent
○ получение из стороннего репозитория
(отдельный build step)
Автоматические тестирование
● честные unit tests
● функциональные тесты в формате unit
tests
○
○
○
○

тестируют поведение
загружают IntelliJ Platform (без UI)
время работы достаточно велико
не меняются при изменении реализации
Запуск тестов на TeamCity
● через Ant, Maven,...
● через IntelliJ IDEA Project runner:
○ создать shared run configuration в IDEA
○ положить соответствующий файл в VCS
○ добавить название run configuration в настройках
IDEA Project runner
Возможности TeamCity
● автоматический запуск тестов
● просмотр результатов, история
● назначение ответственного за падение
тестов
● проверка изменений до коммита в VCS
(Remote Run)
Установка плагина в IDE
● из репозитория plugins.jetbrains.com
● с диска (Settings | Plugins | Install plugin
from disk)
● из собственного репозитория
Собственый репозиторий плагинов
File | Settings | Plugins | Browse Repositories | Manage Repositories,
добавить ссылку на plugins.xml.
plugins.xml:
<plugins>
<plugin id="samplePlugin" url="PluginZipFileUrl.zip" version="1.0"/>
</plugins>
Архитектура
IntelliJ Platform
Компоненты, сервисы, точки расширения
Система компонентов
● экземпляры объектов хранятся в
иерархии контейнеров PicoContainer
● иерархия состоит из трёх уровней
○ Application
○ Project
○ Module

● регистрируются в plugin.xml
Получение экземпляра компонента
● метод getInstance(), getInstance(project),
getInstance(module)
● dependency injection через параметры
конструктора (другие компоненты данного
уровня или более высоких уровней)
Компоненты
● наследуются от ApplicationComponent,
ProjectComponent, ModuleComponent
● регистрируются в <application-components>, <projectcomponents>,... в plugin.xml
● загружаются при старте IDE (загрузке проекта,
загрузке модуля)

init

use

dispose
Сервисы
● не накладывают ограничений на
наследование
● регистрируются в <applicationService>,
<projectService>, <moduleService>
● загружаются при первом обращении
(ServiceManager.getService())
● если реализован интерфейс Disposable,
метод dispose вызовется при закрытии IDE
(проекта, модуля)
Точки расширения
●
●
●
●

регистрируются в <extensionPoints>
полное имя - <plugin id>.<extension name>
предполагают несколько реализаций
для доступа к расширениям создаётся
константа ExtensionPointName
Точки расширения
● бывают двух видов:
○ beanClass - дают возможность задавать
атрибуты расширения прямо в xml
○ interface - в расширении указывается только
ссылка на класс, реализующий интерфейс

● могут быть уровня проекта или модуля
(атрибут area), по умолчанию уровня
application
Расширения
● регистрируются в <extensions>
○ для расширений вида beanClass заполняются
атрибуты
○ для расширений вида interface указывается
полное имя класса в атрибуте implementation

● загружаются при первом обращении
(ExtensionPointName.getExtensions())
Плагины и
их зависимости
Plugin classpath
● jar файлы плагина (*.jar в директории ‘lib’)
● jar файлы плагинов, от которых он
зависит
● jar файлы IDEA (*.jar в директории
<IDEA_HOME>/lib )
Зависимости плагина
Определяются через <depends> в plugin.xml
Опциональные зависимости
Задаются тэгом
<depends optional=”true”
config-file=”fileName.xml”>
в plugin.xml
Компоненты из файла fileName.xml
загружаются только в случае, если
указанный плагин доступен
Работа с фреймворками
Конфигурирование фреймворка
●
●
●
●

конфигурирование не требуется
специальная библиотека (SDK)
на уровне модуля
на уровне проекта
Фреймворк без конфигурации
● не требуется явных действий “добавить фреймворк”
● экшены (completion, inspections,...) определяют
наличие фреймворка по аннотациям, наличию
класса в зависимостях модуля (JavaPsiFacade.findClass(...,module.
getModuleWithDependenciesAndLibrariesScope()),...
Фреймворк-библиотека
● задаётся при помощи LibraryType
● можно хранить дополнительные
настройки прямо в библиотеке
● настройки редактируются в библиотеке в
диалоге Project Structure
Фреймворк в настройками в
модуле
● задаётся при помощи Facet (extension
FacetType)
● настройки редактируются в диалоге
Project Structure
Фреймворк с настройками в проекте
● настройки хранятся в project service
● редактируются в диалоге Settings
(extension projectConfigurable)
Подключение фреймворка
● extension frameworkSupport (класс
FrameworkSupportProvider)
● опция появляется в диалоге “New
Project/Module Wizard” и в диалоге “Add
Framework Support” (popup menu в Project
View)
Ссылки
Исходный код плагина с примерами:
https://github.com/chashnikov/intellij-sample-plugin

Plugin development for intelli j platform