Share
Embed
Transcript
33 slides
-
Автор ты кто Юрий Артамонов @jreznot ▪ Разрабатывал фреймворки и
библиотеки для Java на протяжении 9 лет ▪ Придумываю новые возможности IDE для ваших любимых JVM фреймворков в IntelliJ IDEA ▪ Беспристрастный член ПК конференций Joker/JPoint 2 -
План действий 1. Что такое Language Injections 2. Как использовать
в проекте 3. Пишем плагин 4. Как предоставить свои Injected References 5. А ещё: auto completion, find usages и rename refactoring 3 -
String Obsession! Строки используются в дизайне API повсеместно: 1. Ключи
в словарях 2. Файловые и сетевые пути 3. Идентификаторы ресурсов, URL 4. Логины пользователей 5. Заголовки HTTP 6. … Но к чему это приводит ?!! 5 -
Причины String Obsession ▪ Сложно расширить компилятор / интерпретатор любимого
языка ▪ Мета-данные и аннотации требуют строк ▪ Внешние системы принимают строковые запросы (пример: SQL) ▪ В конфигурационных файлах нельзя писать код ▪ Так проще и все привыкли! 6 -
Решение 1. Language Injections Точки расширения для плагинов: ▪ LanguageInjector
▪ ReferenceInjector 8 -
Где полезно в реальной жизни ▪ Regexp ▪ SQL ▪
JSON ▪ XML & HTML ▪ XPath ▪ JavaScript ▪ ... 9 -
Способы применения 1. Вручную 2. Комментарий // language=SQL 3. Аннотация
@Language(“SQL”) compile 'org.jetbrains:annotations:18.0.0' 4. Плагин для IDE! 10 -
Новый JEP ? [ide-support-dev] @Language annotation for JDK 13 text
blocks. > For example, imagine this annotation on top of a text block: > @Language("text/html") Проблемы: 1. Аннотации привязаны к языку 2. Формат MIME Type / Language ID 3. Нужны ли ещё параметры: prefix / suffix ? 4. Должны ли редакторы выводить язык литерала из использований? 5. А что там с @Nullable / @NotNull в JDK ? 11 -
Как поделиться настройками Способы: 1. Move to Project Scope +
Commit .idea to VCS 2. Export to XML 3. Плагин для IDE ! 13 -
Как создать плагин 14 1. Проверить/включить Plugin DevKit 2. Создать
Gradle проект с библиотекой IntelliJ Platform Plugin 3. Объявить и реализовать нужные точки расширения -
Ключевые внутренности IDE ▪ Компоненты и сервисы ▪ Виртуальная файловая
система (VFS) ▪ Поддержка языков (PSI) ▪ Редактор кода ▪ Инспекции ▪ Индексы ▪ Фоновые процессы ▪ UI библиотека ▪ Точки расширения IntelliJ Platform IDEA CE (Java, Groovy, Kotlin) PHP Support Ruby Support IDEA Ultimate PHP Storm RubyMine 15 -
Расширенная конфигурация IntelliLang Точка расширения: org.intellij.intelliLang.injectionConfig <depends>org.intellij.intelliLang</depends> <extensions defaultExtensionNs="org.intellij.intelliLang"> <injectionConfig
config="javaInjections.xml"/> </extensions> Полезные атрибуты: ▪ prefix / suffix ▪ value-pattern ▪ ignore-pattern 16 -
Инжектим в XML Plugin DevKit: <injection language="Groovy" injector-id="xml"> <display-name>IntelliJ IDEA
pattern</display-name> <place><![CDATA[ xmlTag().withLocalName("place") .withParent(xmlTag().withLocalName("injection") .withParent(xmlTag().withLocalName("component"))) ]]> </place> </injection> 17 -
JSON Schema Файлы: JSON / YAML Атрибут: x-intellij-language-injection: /schema.json "messageRegex":
{ "type": "string", "description": "Regex pattern to check test error message", "x-intellij-language-injection": "RegExp" } 18 -
Решение 2. Ссылки в PSI дереве ▪ Позволяют установить связь
между PsiElement и его использованиями: usage ➜ declaration ▪ Можно добавить cсылки без необходимости расширять язык! См. PsiReferenceContributor PsiLanguageInjectionHost 19 -
Internal Mode Специальный режим работы IDE, в котором доступны опции
для разработчиков. ▪ Internal Actions ▪ View PSI / Dump UAST ▪ Dumb Mode Switch ▪ … Автоматически доступен в режиме отладки плагина. Включить в VM Options своей IDE: -Didea.is.internal=true 20 -
PSI Viewer Tools - View PSI Structure of Current File
Позволяет изучить структуру PSI дерева в файле: ▪ PSI Tree ▪ References ▪ Language injections 21 -
Повторное использование ссылок Все PsiLanguageInjectionHost элементы потенциально могут содержать ссылки
и код на другом языке: ▪ Строковые литералы ▪ Комментарии ▪ XML теги и атрибуты ▪ JSON, .properties, ... Точка расширения: ReferenceInjector 22 -
Ссылки на веб-ресурсы class IssueCodeInjector : ReferenceInjector() { override fun
getReferences(element: PsiElement, context: ProcessingContext, range: TextRange): Array<PsiReference> По шагам: 1. Получаем значение элемента по range 2. Определяем целевой URL 3. Переиспользуем WebReference из platform-impl 23 -
Валидация значений Способы валидации: 1. Инспекции, см. LocalInspectionTool 2. Переопределение
способа поиска деклараций А какие значения правильные? a. Спецификация на значение b. Белый список c. Здравый смысл 24 (?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)* |"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x 09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+ [a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[ 0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-] *[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x0 1-\x09\x0b\x0c\x0e-\x7f])+)\]) -
Предоставляем Quick Fix Ссылка должна реализовать LocalQuickFixProvider: override fun getQuickFixes():
Array<LocalQuickFix>? { return arrayOf(AddCustomHttpHeaderFix(myElement)) } и обработчик: class AddCustomHttpHeaderFix(myElement: PsiElement) : LocalQuickFixOnPsiElement(myElement) { override fun invoke(project: Project, file: PsiFile, startElement: PsiElement, endElement: PsiElement) { 25 -
Find Usages по ссылкам Упрощённый алгоритм поиска элементов: 1. Выяснить
область поиска ссылок и деклараций: getUseScope() и getResolveScope() 2. Найти все файлы, в которых встречается текст по words index 3. Для каждого найденного места определить есть ли там ссылки, resolve() и isEquivalentTo() См. ReferencesSearch.search(SearchParameters) 26 -
Rename Refactoring 1. Вызов диалога в RenamePsiElementProcessor.createRenameDialog 2. Поиск использований
3. Изменение литералов в PsiReferenceBase.handleElementRename(newElementName) 27 -
Автодополнение по коду проекта Варианты для ссылок: 1. Захардкодить! 2.
Сконфигурировать 3. Спросить у пользователя 4. Поискать при помощи магии ! 28 -
Как что-то нужное найти Модуль java-indexing-api предоставляет методы поиска по
стандартным индексам: ▪ ReferencesSearch ▪ MethodReferenceSearch ▪ AnnotatedElementsSearch ▪ … Query<PsiReference> MethodReferencesSearch.search(psiMethod, scope, strict) Query<PsiReference> AnnotatedElementsSearch.searchPsiMethods(annotationClass, scope) 29 -
Стандартные индексы IDE Индексация: ▪ WordIndex - слова ▪ IdIndex
- идентификаторы ▪ FileNameIndex - имена файлов ▪ FileTypeIndex - файлы по типам ▪ JavaAnnotationIndex - аннотации ▪ JavaShortClassNameIndex - имена классов ▪ ... 30 -
Сложные применения 1. Литерал может содержать множество ссылок, пример -
URL Path * 2. Реактивное автодополнение при помощи CompletionContributor, пример - Message Queue *: * новые возможности IntelliJ IDEA Ultimate 2020.1 31 -
Куда копать дальше ▪ Исходный код IntelliJ IDEA CE: github.com/JetBrains/intellij-community
▪ Документация Plugin DevKit: jetbrains.org/intellij/sdk/docs/basics.html ▪ Slack: jetbrains-platform NEW! https://plugins.jetbrains.com/slack ▪ Forum: IntelliJ IDEA Open API and Plugin Development 32