blob: f1fdf6b08eb333ab385be25155cefa4c5dae2162 [file] [log] [blame]
//
// 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[Другие связанные руководства]