Статьи

Применение проверок IDE к пользовательским аннотациям Java

Введение аннотаций в J2SE 5 изменило способ написания и обработки Java. Помимо предопределенных аннотаций Java SE, интегрированные среды, интегрированные среды разработки и наборы инструментов представили свои собственные пользовательские аннотации . Checker Framework предоставил примеры того, как можно использовать пользовательские аннотации для повышения безопасности типов в Java. В этой статье я рассмотрю написание простой пользовательской аннотации и ее использование в NetBeans ( 8.0.2 ) и IntelliJ IDEA ( 14.0.3 ), чтобы помочь разработчикам выявлять проблемы в своем коде, которые требуют дальнейшего внимания.

В статье « Использование большинства метаданных Java», часть 2: Пользовательские аннотации , Джейсон Хантер демонстрирует аннотацию @Unfinished в качестве примера написания пользовательской аннотации Java . В этом посте я продемонстрирую другую реализацию аннотации @Unfinished . В этом вся прелесть пользовательских аннотаций: можно написать аннотацию, которая наилучшим образом соответствует вашим потребностям. Код моей аннотации @Unfinished показан в следующем листинге.

Unfinished.java: Определение пользовательской аннотации @ Unfinished

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package dustin.examples.annotations;
 
import static java.lang.annotation.ElementType.*;
 
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * Example of a custom annotation that marks Java code constructs
 * that are not yet completed.
 *
 * Notes about custom annotations specific to this example:
 *   - @Documented indicates available for public documentation
 *   - CLASS retention policy means that compiler places annotation
 *     information in compiled .class files, but JVM is NOT aware
 *     of the annotation at runtime.
 *   - @Target parameters (statically imported) indicate that this
 *     annotation can be applied to constructors, fields,
 *     local variables, methods, packages, parameters, and
 *     classes/interfaces.
 *   - Methods defined for this @interface without 'default' are
 *     required settings for application of this annotation. In
 *     this case, the "finishBy" element is NOT required (but
 *     recommended!) but the "value" element is required.
 *   - "value" element has special significance in custom Java
 *     annotations: it is the assumed annotation element if
 *     a String is provided to the annotation without explicit
 *     element name called out.
 */
@Documented
@Retention(RetentionPolicy.CLASS)
@Target({CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface Unfinished
{
   /** Description of the unfinished construct. */
   String value();
 
   /**
    * Date, build, or event by which the annotated construct
    * is anticipated to be finished.
    */
   String finishBy() default "Unknown";
}

В следующем листинге кода показано применение @Unfinished в простом классе, над которым еще предстоит много работы.

WorkInProgress.java: применение пользовательской аннотации @Unfinished

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package dustin.examples.annotations.demo;
 
import dustin.examples.annotations.Unfinished;
 
/**
 * Demonstrates custom Java annotation @Unfinished.
 */
public class WorkInProgress
{
   @Unfinished("This will do something good by Revision 2.")
   public void doSomethingGood()
   {
   }
 
   @Unfinished(value = "Do something good here.", finishBy = "Revision 2")
   public void doSomethingElseGood()
   {
   }
}

Неполный класс по умолчанию использует элемент аннотации «value» для одного метода, а затем добавляет использование элемента «doneBy» для второго метода. Есть несколько наблюдений, которые можно сделать из определения двух последних списков кодов или использования @Unfinished :

  1. Включение «по умолчанию» для элемента аннотации означает, что те, кто использует аннотацию, не обязаны предоставлять значение для этого элемента.
  2. Элемент «value» предполагается, если в аннотации указано только одно значение и оно указано без явного имени элемента.
  3. Имя «значение» не нужно указывать, если указан только один элемент аннотации, но необходимо указывать, если указано более одного элемента аннотации.
  4. Здесь был использован уровень хранения CLASS, потому что я чувствовал, что инструменты, работающие с скомпилированной версией классов Java, смогут использовать эту информацию, и я не ожидаю использования этой информации во время выполнения.
  5. Желателен тщательный выбор элементов аннотации, которые должны иметь значения «по умолчанию», поскольку отсутствие «по умолчанию» требует указания элемента, что в некоторых случаях может быть желательным поведением.

Использование пользовательских аннотаций может обеспечить стандартизированный механизм для создания «исполняемых» и более контролируемых описаний для других разработчиков и для инструментов. Этот подход часто выгоден по сравнению с тем, чтобы оставлять сообщения с комментариями, поскольку комментарии, как правило, менее стандартизированы и подвержены опечаткам и различиям в чувствительности к регистру, написанию и другим несоответствиям. Аннотации лучше обеспечивают соблюдение соглашений и позволяют использовать инструменты для более эффективного использования того, что они сообщают, чем анализ произвольного текста. Возможно, самый очевидный способ получить некоторые из этих преимуществ пользовательских аннотаций над произвольными комментариями — это обработчик аннотаций. Несколько IDE и сред, таких как Checker Framework, обрабатывают аннотации. Есть также многочисленные онлайн-ссылки, касающиеся написания пользовательских процессоров аннотаций, которые можно использовать с компилятором Jav для предоставления предупреждений. В оставшейся части этого поста я остановлюсь на том, как можно применить две наиболее популярных среды Java IDE ( NetBeans и IntelliJ IDEA ), чтобы сообщать об этих аннотациях в качестве подсказок / проверок. В этой статье я не рассматриваю интеграцию процессора аннотаций в процессы компиляции IDE или интеграцию пользовательского процессора с компилятором Java командной строки.

Проверка аннотации @Unfinished в NetBeans

Ранее я писал в блоге о создании настраиваемой подсказки NetBeans 7.1, и этот процесс почти такой же, как и в NetBeans 8. Первым шагом является использование параметра « Рефакторинг -> Проверка и преобразование…», как показано на следующем снимке экрана.

netbeans802-refactorInspectAndTransform

Когда выбран Refactor -> Inspect and Transform… , появляется всплывающее окно, подобное показанному ниже.

netbeans802-inspectTransformScreen1

Я собираюсь применить эту новую проверку ко всем моим открытым проектам, как показано в поле «Проверка» последнего снимка экрана. При нажатии на кнопку « Обзор » открывается окно « Управление инспекциями », как показано на следующем снимке экрана.

netbeans802-manageInspections

Нажатие на кнопку « Создать… » позволяет разработчику создать пользовательский контроль в разделе « Custom-> Inspection» .

netbeans802-CustomInspection

Вы можете нажать кнопку «Редактировать сценарий», чтобы создать пользовательскую проверку, которая включает в себя возможность переименовать проверку. Я переименовал инспекцию в «Незаконченный кодекс». На следующем снимке экрана показан код, который я добавил для проверки «Незаконченный код».

netbeans802-unfinishedInspectionScript

В коде сценария для этой проверки «Незаконченный код» (который также показан ниже) описание указано как «Незаконченный код». Исходный шаблон указывается как @dustin.examples.annotations.Unfinished($parameters$) (полное имя пакета @interface определяющего пользовательскую аннотацию с $parameters$ указывающим один или несколько параметров). Символы => указывают на целевой шаблон. В этом случае целевой шаблон пуст, что указывает на то, что предлагаемое преобразование должно удалить аннотацию @Unfinished . Дополнительные сведения о синтаксисе редактора проверок NetBeans см. В публикации пользователя Geertjan Wielenga « Пользовательские декларативные советы в IDE NetBeans 7.1» .

1
2
3
4
<!description="Unfinished Code">
@dustin.examples.annotations.Unfinished($parameters$)
=>
;;

После проверки NetBeans пришло время попробовать ее. Следующие два снимка экрана демонстрируют выбор этой инспекции для запуска и результаты ее запуска.

netbeans802-readyToRunUnfinishedCodeInspection

netbeans802-runningUnfinishedInspection

Результат выполнения проверки является примером того, как мы можем использовать NetBeans в сочетании с настраиваемой аннотацией для быстрой идентификации аннотированного кода и соответствующей обработки.

Проверка @ незавершенной аннотации в IntelliJ IDEA

Один из способов начать создание пользовательской аннотации в IntelliJ IDEA — это открыть Анализ -> Проверить код… и нажать кнопку «…» во всплывающем окне « Задать область проверки », как показано на следующих двух снимках экрана.

idea14-Step01-analyzeInspectCode

idea14-step02-selectEllipseButtonSpecifyInspectionScope

На следующем снимке экрана показано диалоговое окно « Проверки ».

idea14-step03-inspectionsDialog

Снимок экрана, только что показанный, показывает, что « Проверка поиска конструкции » НЕ проверена. Установка этого флажка (флажок справа от названия «Проверка поиска по структуре») приводит к тому, что выбирается уровень «Серьезность» и позволяет добавить определенный контроль (знак «плюс» становится серым на зеленый).

idea14-step04-inspectionsDialog-StructuralInspectionSelected

Нажав на зеленый знак плюс ( + ), можно выбрать один из двух вариантов: «Добавить шаблон поиска…» или «Добавить шаблон замены…». Различие здесь похоже на различие NetBeans между Источником -> Проверять и Рефакторинг -> Проверять и преобразовывать… и я сосредоточусь здесь на « Заменить шаблон » здесь.

idea14-версии STEP05-searchOrReplaceOptions

При выборе «Добавить шаблон замены…» отображается диалоговое окно « Замена структуры ».

idea14-step06-structuralReplaceDialog

Самый простой способ создать пользовательский контроль — это адаптировать существующий шаблон. Это можно сделать, нажав кнопку « Скопировать существующий шаблон… ». Для двух проверок, которые я создаю для этого сообщения в блоге, я скопировал существующие шаблоны « аннотированный класс » и « аннотированные методы » соответственно, чтобы создать свои собственные пользовательские шаблоны «Незаконченный класс» и «Незаконченный метод».

idea14-step07-existingTemplates-annotatedClass

idea14-step08-existingTemplates-annotatedMethod

На приведенных выше снимках экрана показаны «существующие шаблоны», которые я скопировал, а на приведенных ниже снимках экрана показаны созданные мной пользовательские шаблоны для «Незавершенного класса» и «Незаконченного метода».

idea14-step09-customTemplate-UnfinishedClass

idea14-Step10-customTemplate-UnfinishedMethod

Для каждого из пользовательских шаблонов («Незаконченный класс» и «Незаконченный метод») мне нужно нажать кнопку « Редактировать переменные… » и указать регулярные выражения для каждой переменной (идентификаторы, помеченные знаком $ на передней и задней части), которые будут поиск. Для большинства переменных (таких как имя класса, имя метода и т. Д.) Я использую регулярное представление «все символы» ( . * ), Но для $Annotation$ в каждом из этих шаблонов я использую dustin.examples.annotations.Unfinished Следующий снимок экрана является типичным примером этого, который показывает настройку переменной аннотации для шаблона «Неопределенный метод».

idea14-step11-customTemplate-UnfinishedMethodAnnotationVariable

Я могу использовать Анализ -> Выполнить проверку по имени … чтобы выполнить любую из моих новых проверок. Следующие три снимка экрана демонстрируют запуск новой проверки «Незаконченный метод».

idea14-step12-customTemplate-runInspectionByName

idea14-Step13-customTemplate-runStructuralSearchInspection

idea14-Step14-unfinishedMethodInspectionResults

Результат выполнения проверки является примером того, как мы можем использовать IntelliJ IDEA в сочетании с пользовательской аннотацией, чтобы быстро идентифицировать аннотированный код и обрабатывать его соответствующим образом.

Вывод

В этом посте продемонстрировано использование возможностей NetBeans и IntelliJ IDEA для создания пользовательских инспекций для создания инспекций, которые могут предупредить разработчиков о наличии пользовательских аннотаций в их коде. В публикации демонстрировалась простая аннотация @Unfinished и как применять пользовательские проверки в NetBeans и IntelliJ IDEA, чтобы помочь идентифицировать код, использующий эти аннотации.