| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| = Учебный курс по интеграции генератора кода |
| :jbake-type: platform_tutorial |
| :jbake-tags: tutorials |
| :jbake-status: published |
| :syntax: true |
| :source-highlighter: pygments |
| :toc: left |
| :toc-title: |
| :icons: font |
| :experimental: |
| :description: Учебный курс по интеграции генератора кода - Apache NetBeans |
| :keywords: Apache NetBeans Platform, Platform Tutorials, Учебный курс по интеграции генератора кода |
| |
| В этом руководстве показан способ написания модуля, интегрирующего новые элементы в функцию генерации кода NetBeans, которая вызывается сочетанием клавиш ALT+INSERT в редакторе. |
| |
| |
| |
| |
| |
| |
| |
| Дополнительно, в целях поиска и устранения ошибок, можно link:http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=11179[загрузить готовый пример] и изучить исходный код. |
| |
| |
| == Введение в интеграцию генератора кода |
| |
| Функция "генератор кода", которая впервые появилась в среде IDE NetBeans 6.5, состоит из списка позиций, выводимых при нажатии ALT+INSERT. Каждая позиция вызывает генерацию кода в редакторе. |
| |
| |
| image::images/code-generator_code-generator-5.png[] |
| |
| |
| == Создание проекта модуля |
| |
| В этом разделе используется мастер для создания структуры исходного кода, требуемого любым модулем NetBeans. Эта структура исходного кода состоит из ряда папок в особых местах и набора файлов, которые требуются в любом случае. Например, для каждого модуля NetBeans требуется папка ``nbproject`` , в которой хранятся метаданные проекта, а также файл ``layer.xml`` , в котором объявляется регистрация таких элементов как кнопки панелей управления и окна. |
| |
| |
| [start=1] |
| 1. Выберите в меню "Файл" команду "Новый проект" (CTRL+SHIFT+N). В разделе "Категории" выберите параметр "Модули NetBeans". В области "Проекты" выберите "Модуль" и нажмите кнопку "Далее". |
| |
| [start=2] |
| 1. На панели "Имя и расположение" в поле "Имя проекта" введите ``DemoCodeGenerator`` . В поле "Расположение проекта" укажите любой каталог на компьютере, например ``c:\mymodules`` . Оставьте переключатель "Отдельный модуль" выбранным. Панель должна выглядеть следующим образом: |
| |
| |
| image::images/code-generator_code-generator-1.png[] |
| |
| Нажмите кнопку "Далее". |
| |
| |
| [start=3] |
| 1. На панели "Основные настройки модуля" введите ``org.netbeans.modules.demo`` в поле "Основа кодового имени". Установите флажок "Создать слой XML" и оставьте местоположение локализуемого файла ресурсов и слоя XML по умолчанию; при этом они будут храниться в пакете с именем ``org/netbeans/modules/demo`` . Панель должна выглядеть следующим образом: |
| |
| |
| image::images/code-generator_code-generator-2.png[] |
| |
| |
| [start=4] |
| 1. Нажмите кнопку "Готово". |
| |
| В среде IDE создается проект ``DemoCodeGenerator`` . Проект содержит все исходные файлы и метаданные проекта, например, сценарий сборки проекта Ant. Проект откроется в среде IDE. Логическую структуру проекта можно просмотреть в окне "Проекты" (CTRL+1), а его файловую структуру – в окне "Файлы" (CTRL+2). |
| |
| |
| == Использование диалогового окна "Поставщик генератора кода" |
| |
| В этом разделе с помощью мастера будет создан класс заглушки и сущности слоя, необходимые для начала интеграции с функцией генератора кода. |
| |
| |
| [start=1] |
| 1. Щелкните узел проекта правой кнопкой мыши и выберите команду "Создать > Прочее". В диалоговом окне "Новый файл" выберите "Разработка модулей > Генератор кода", как показано ниже: |
| |
| |
| image::images/code-generator_code-generator-3.png[] |
| |
| |
| [start=2] |
| 1. Установите следующие значения на панели "Новый генератор кода": |
| * *Имя класса.* Имя класса для заглушки, генерируемой мастером. Введите в это поле значение "DemoCodeGenerator". |
| * *Пакет.* Пакет, в котором будет создан класс заглушки. Выберите в раскрывающемся списке пункт "org.netbeans.modules.demo". |
| * *Тип MIME.* Тип MIME, к которому применяется интеграция генератора кода. Введите в это поле значение "x-java". |
| * *Создать CodeGeneratorContextProvider.* Добавление дополнительных объектов к поиску генератора кода. Не устанавливайте этот флажок. |
| |
| На экране должны быть представлены следующие параметры: |
| |
| |
| image::images/code-generator_code-generator-4.png[] |
| |
| |
| [start=3] |
| 1. Нажмите кнопку "Готово". |
| |
| Окно "Проекты" должно выглядеть следующим образом: |
| |
| |
| image::images/code-generator_code-generator-6.png[] |
| |
| В файле ``layer.xml`` должен содержаться следующий текст: |
| |
| |
| [source,xml] |
| ---- |
| |
| <filesystem> |
| <folder name="Editors"> |
| <folder name="text"> |
| <folder name="x-java"> |
| <folder name="CodeGenerators"> |
| <file name="org-netbeans-modules-demo-DemoCodeGenerator$Factory.instance"/> |
| </folder> |
| </folder> |
| </folder> |
| </folder> |
| </filesystem> |
| ---- |
| |
| Сгенерированный класс должен выглядеть следующим образом: |
| |
| |
| [source,java] |
| ---- |
| |
| public class DemoCodeGenerator implements CodeGenerator { |
| |
| JTextComponent textComp; |
| |
| /** |
| * |
| * @param context containing JTextComponent and possibly other items |
| * registered by {@link CodeGeneratorContextProvider} |
| */ |
| private DemoCodeGenerator(Lookup context) { |
| // Не рекомендуется сохранять Lookup снаружи ctor |
| textComp = context.lookup(JTextComponent.class); |
| } |
| |
| public static class Factory implements CodeGenerator.Factory { |
| |
| public List create(Lookup context) { |
| return Collections.singletonList(new DemoCodeGenerator(context)); |
| } |
| } |
| |
| /** |
| * Имя, вставляемое в диалоговое окно "Вставить код" |
| */ |
| public String getDisplayName() { |
| return "Sample Generator"; |
| } |
| |
| /** |
| * Эта функция вызывается при выборе этого генератора в диалоговом окне "Вставить код" |
| */ |
| public void invoke() { |
| } |
| |
| } |
| ---- |
| |
| |
| == Написание кода интеграции генератора кода |
| |
| Далее необходимо реализовать интерфейс API. Используются следующие классы интерфейса API: |
| |
| |=== |
| |Класс |Описание |
| |
| |JavaSource |Определяется позднее |
| |
| |CancellableTask |Определяется позднее |
| |
| |WorkingCopy |Определяется позднее |
| |
| |CompilationUnitTree |Определяется позднее |
| |
| |TreeMaker |Определяется позднее |
| |
| |ClassTree |Определяется позднее |
| |
| |ModifiersTree |Определяется позднее |
| |
| |VariableTree |Определяется позднее |
| |
| |TypeElement |Определяется позднее |
| |
| |ExpressionTree |Определяется позднее |
| |
| |MethodTree |Определяется позднее |
| |=== |
| |
| Ниже указываются зависимости требуемых модулей, которые затем реализуются в собственном модуле. |
| |
| |
| [start=1] |
| 1. Щелкните правой кнопкой мыши проект, выберите "Свойства", а затем укажите следующие 4 зависимости на панели "Библиотеки": |
| |
| |
| image::images/code-generator_code-generator-7.png[] |
| |
| NOTE: Обратите внимание, что "Библиотека редактора 2" и "API утилит" уже установлены автоматически мастером генерации кода. Оставшиеся две зависимости – "Javac API Wrapper" и "Исходные файлы Java" – потребуются для генерации новых фрагментов кода Java с помощью созданной интеграции генератора кода. |
| |
| |
| [start=2] |
| 1. Откройте сгенерированный класс и измените метод ``invoke()`` следующим образом: |
| |
| [source,java] |
| ---- |
| |
| public void invoke() { |
| try { |
| Document doc = textComp.getDocument(); |
| JavaSource javaSource = JavaSource.forDocument(doc); |
| CancellableTask task = new CancellableTask<WorkingCopy>() { |
| public void run(WorkingCopy workingCopy) throws IOException { |
| workingCopy.toPhase(Phase.RESOLVED); |
| CompilationUnitTree cut = workingCopy.getCompilationUnit(); |
| TreeMaker make = workingCopy.getTreeMaker(); |
| for (Tree typeDecl : cut.getTypeDecls()) { |
| if (Tree.Kind.CLASS == typeDecl.getKind()) { |
| ClassTree clazz = (ClassTree) typeDecl; |
| ModifiersTree methodModifiers = |
| make.Modifiers(Collections.<Modifier>singleton(Modifier.PUBLIC), |
| Collections.<AnnotationTree>emptyList()); |
| VariableTree parameter = |
| make.Variable(make.Modifiers(Collections.<Modifier>singleton(Modifier.FINAL), |
| Collections.<AnnotationTree>emptyList()), |
| "arg0", |
| make.Identifier("Object"), |
| null); |
| TypeElement element = workingCopy.getElements().getTypeElement("java.io.IOException"); |
| ExpressionTree throwsClause = make.QualIdent(element); |
| MethodTree newMethod = |
| make.Method(methodModifiers, |
| "writeExternal", |
| make.PrimitiveType(TypeKind.VOID), |
| Collections.<TypeParameterTree>emptyList(), |
| Collections.singletonList(parameter), |
| Collections.<ExpressionTree>singletonList(throwsClause), |
| "{ throw new UnsupportedOperationException(\"Не поддерживается.\") }", |
| null); |
| ClassTree modifiedClazz = make.addClassMember(clazz, newMethod); |
| workingCopy.rewrite(clazz, modifiedClazz); |
| } |
| } |
| } |
| public void cancel() { |
| } |
| }; |
| ModificationResult result = javaSource.runModificationTask(task); |
| result.commit(); |
| } catch (Exception ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| ---- |
| |
| |
| [start=3] |
| 1. Убедитесь в том, что определены следующие выражения импорта: |
| |
| [source,java] |
| ---- |
| |
| import com.sun.source.tree.AnnotationTree; |
| import com.sun.source.tree.ClassTree; |
| import com.sun.source.tree.CompilationUnitTree; |
| import com.sun.source.tree.ExpressionTree; |
| import com.sun.source.tree.MethodTree; |
| import com.sun.source.tree.ModifiersTree; |
| import com.sun.source.tree.Tree; |
| import com.sun.source.tree.TypeParameterTree; |
| import com.sun.source.tree.VariableTree; |
| import java.io.IOException; |
| import java.util.Collections; |
| import java.util.List; |
| import javax.lang.model.element.Modifier; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.type.TypeKind; |
| import javax.swing.text.Document; |
| import javax.swing.text.JTextComponent; |
| import org.netbeans.api.java.source.CancellableTask; |
| import org.netbeans.api.java.source.JavaSource; |
| import org.netbeans.api.java.source.JavaSource.Phase; |
| import org.netbeans.api.java.source.ModificationResult; |
| import org.netbeans.api.java.source.TreeMaker; |
| import org.netbeans.api.java.source.WorkingCopy; |
| import org.netbeans.spi.editor.codegen.CodeGenerator; |
| import org.netbeans.spi.editor.codegen.CodeGeneratorContextProvider; |
| import org.openide.util.Exceptions; |
| import org.openide.util.Lookup; |
| ---- |
| |
| |
| == Установка и ознакомление с функциональными возможностями |
| |
| Теперь установим модуль и воспользуемся функцией интеграции генератора кода. Для построения и установки модуля в среде IDE используется сценарий построения Ant. При создании проекта автоматически создается сценарий построения. |
| |
| |
| [start=1] |
| 1. В окне "Проекты" щелкните проект правой кнопкой мыши и выберите "Выполнить". |
| |
| Запускается новый экземпляр среды IDE, и выполняется установка модуля интеграции генератора кода. |
| |
| |
| [start=2] |
| 1. Нажмите сочетание клавиш ALT+INSERT; в списке появится новый элемент: |
| |
| |
| image::images/code-generator_code-generator-5.png[] |
| |
| |
| [start=3] |
| 1. Щелкните этот элемент, и будет выполнена вставка кода. |
| |
| |
| == Создание совместно используемого исполняемого файла модуля |
| |
| Готовый модуль можно предоставить для использования другими разработчиками. Для этого необходимо создать и распространить двоичный файл "NBM" (модуль NetBeans). |
| |
| |
| [start=1] |
| 1. В окне "Проекты" щелкните проект правой кнопкой мыши и выберите "Создать NBM". |
| |
| Создается файл NBM, который можно просмотреть в окне "Файлы" (CTRL+2). |
| |
| |
| [start=2] |
| 1. Чтобы предоставить этот файл для использования другим разработчикам, можно, например, воспользоваться link:http://plugins.netbeans.org/PluginPortal/[порталом подключаемых модулей NetBeans]. Для установки модуля получатель должен воспользоваться диспетчером подключаемых модулей ("Сервис > Подключаемые модули"). |
| |
| |
| link:http://netbeans.apache.org/community/mailing-lists.html[Мы ждем ваших отзывов] |
| |
| |
| |
| == Что дальше? |
| |
| Дополнительные сведения о создании и разработке модулей NetBeans приведены в следующих ресурсах: |
| |
| * link:https://netbeans.apache.org/platform/index.html[Домашняя страница платформы NetBeans] |
| * link:https://bits.netbeans.org/dev/javadoc/[Список интерфейсов API среды NetBeans (текущая версия разработки)] |
| * link:https://netbeans.apache.org/kb/docs/platform_ru.html[Другие связанные руководства] |