blob: 9a899d26b7fac7269f78da9c7c5939b1b2c84023 [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. Выберите "File" > "New Project" (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" and "API утилит" уже установлены автоматически мастером генерации кода. Оставшиеся две зависимости "Javac API Wrapper" and "Исходные файлы Java" потребуются для генерации новых фрагментов кода Java с помощью созданной интеграции генератора кода.
[start=2]
1. Откройте созданный класс.
[start=3]
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=4]
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[Другие связанные руководства]