openjdk.ruOpenJDK на русском

JEP draft: Rich Notes in Java API Documentation

Расширенные примечания в документации Java API

ОтветственныйHannes Wallnoefer
ТипFeature
ОбластьJDK
СтатусSubmitted
Компонентtools / javadoc(tool)
Обсуждениеjavadoc dash dev at openjdk dot java dot net
РецензентыAlex Buckley, Jonathan Gibbons
Создан2025/07/22 15:20
Обновлён2026/09/15 13:57
Задача8363700

Аннотация

Добавить в Standard Doclet инструмента JavaDoc тег @note, который выделяет в документации API дополнительную информацию, например предупреждения и советы. Эту информацию можно оформлять с развитым форматированием и показывать встроенно, там, где она больше всего помогает читателю. Кроме того, дать разработчикам возможность определять собственные теги для полезных видов дополнительной информации.

Цели

  • Сделать документацию API полезнее и удобнее для чтения.
  • Дать авторам возможность упорядочивать и обозначать разные виды информации, в том числе содержание, требующее особого внимания, и дополнительные материалы.
  • Развить существующую функциональность пользовательских тегов: сделать её гибче и при этом сохранить совместимость с существующими способами использования.

Что не является целью

  • Изменять поведение или интерпретацию существующих пользовательских тегов, определённых через параметр -tag инструмента javadoc.
  • Вводить конструкцию документации, которая отвлекает внимание или визуально доминирует.

Мотивация

Любой Java-разработчик знаком с чтением JavaDoc, чтобы разобраться в API. Большая часть JavaDoc посвящена определению абстракций (классов) и регламентированию операций (методов), но авторы документации API часто хотят дать дополнительную информацию о проектировании и использовании API. Примеры дополнительной информации: фрагменты исходного кода (как в классе Files), предупреждения (как в классе URL), советы по дальнейшему чтению (как в пакете java.util.regex) и обоснования (как в пакете java.time). Все такие фрагменты информации мы называем примечаниями.

В JavaDoc примечания часто лучше всего работают в основном описании класса или метода, где они сразу показывают рекомендуемую практику, дают контекст или проясняют сложный момент. Иначе говоря, примечания по своей природе встроенные. Этим они отличаются от другой дополнительной информации, которая лучше всего работает отдельно от основного описания, например блоков See Also: и API Note:.

К сожалению, авторам комментариев документации приходится вручную помечать текст в основном описании, чтобы выделить его как дополнительную информацию. В результате примечания получают произвольное и малозаметное форматирование. Например, основное описание java.util.Map содержит совет по использованию, который легко пропустить:

Note: great care must be exercised if mutable objects are used as map keys. ...

Авторы и читатели документации получили бы больше возможностей, если бы существовал стандартный способ обозначить примечание в комментариях документации и отобразить его в HTML с единообразным и заметным форматированием. Авторы могли бы систематически выделять дополнительную информацию, а читатели — систематически её распознавать. В результате документация API стала бы содержательнее, полнее и проще в сопровождении.

Описание

Мы вводим тег примечания для представления дополнительной информации в основном описании элемента программы. Например, такой комментарий документации к методу:

/**
 * Determine the maximum foo in a list of bars.
 *
 * {@note There is always a maximum foo, even if the list is empty.}
 *
 * The arguments to this method must be non-null.
 */

создаёт документацию примерно следующего вида:

Определяет максимальный foo в списке bar.

Примечание: максимальный foo существует всегда, даже если список пуст.

Аргументы этого метода не должны быть null.

Синтаксис

Тег примечания можно использовать как блочный тег. В простейшей форме блочное примечание состоит из тега @note, за которым следует пробельный символ, а затем тело примечания:

@note ...

Вывод блочного примечания группируется с другими блочными тегами после основного описания документируемого элемента. Блочный тег заканчивается там, где начинается следующий блочный тег или заканчивается охватывающий комментарий документации.

Тег примечания можно использовать и как встроенный тег. Встроенные примечания заключаются в фигурные скобки. В остальном синтаксис такой же, как у блочных примечаний:

{@note ...}

Вывод встроенного примечания появляется в том месте охватывающего содержания, где стоит тег. Встроенное примечание заканчивается первой закрывающей фигурной скобкой, которая не входит в сбалансированную пару фигурных скобок в теле примечания. Это значит, что встроенное примечание может содержать только сбалансированные пары фигурных скобок (это ограничение общее для всех встроенных тегов).

Атрибуты

Дополнительные сведения о примечании можно задать в виде атрибутов — пар имя=значение, размещённых внутри одной пары круглых скобок ( ) после имени тега и перед телом примечания. Встроенное примечание с одним атрибутом может выглядеть так:

{@note (name=value) ...}

Имя атрибута всегда является простым идентификатором. Значение атрибута можно заключить в одинарные или двойные кавычки. Кавычки обязательны, если значение атрибута содержит пробельные символы или другие символы со специальным значением, а в остальных случаях необязательны. Экранирующие символы не поддерживаются. Несколько атрибутов отделяются друг от друга пробельными символами, например пробелом или переводом строки.

Требования к использованию

Как и блочные примечания, встроенные примечания отображаются как блочные элементы HTML, поэтому их следует использовать только там, где допускается flow content, а не внутри абзаца, где допускается только phrasing content.

Теги примечаний можно использовать как в традиционных комментариях документации, так и в комментариях в формате Markdown.

Отображение

И у встроенных, и у блочных примечаний тело примечания отображается как текстовый блок с заголовком, по умолчанию Note:. Встроенные примечания отображаются с вертикальной чертой слева, чтобы они выделялись на фоне окружающего текста:

Inline note

Блочные примечания со стилем по умолчанию отображаются с небольшим заголовком и текстом с отступом, в той же компоновке, что и другие блочные теги:

Block note

Элемент HTML верхнего уровня, создаваемый для блочного примечания, использует CSS-класс block-note, а элемент верхнего уровня для встроенного примечания — CSS-класс inline-note. Дополнительные CSS-классы можно добавить с помощью атрибутов или пользовательских тегов примечаний, как описано ниже.

У всех примечаний есть HTML-атрибут id, благодаря которому на них можно ссылаться напрямую через фрагмент URL. По умолчанию ID примечания создаётся автоматически, но автор примечания может задать его явно, как описано ниже.

И встроенные, и блочные теги примечаний могут содержать встроенные теги, например {@link}, {@code} и {@snippet}, а также элементы HTML, подходящие для использования в комментариях документации. Например, вот фрагмент кода внутри встроенного примечания:

/**
 * {@note The following code shows how to use {@link Optional#isPresent}:
 * {@snippet :
 * if (v.isPresent()) {
 *     System.out.println("v: " + v.get());
 * }
 * }
 * }
 */

Примечание отображается так:

Rich content note

Атрибуты, распознаваемые тегом @note

Тег @note в Standard Doclet распознаёт следующие атрибуты:

Атрибут header

Атрибут header задаёт заголовок, который используется вместо Note:.

Например, {@note (header='Caution:') Untrusted input must be verified!} даёт следующий вывод:

Caution: недоверенные входные данные необходимо проверять!

Атрибут kind

Атрибут kind характеризует содержание примечания. Значение атрибута записывается как дополнительный CSS-класс в элементе HTML, создаваемом для примечания, с префиксом note-tag-. Например, {@note (kind=requirement) ...} создаёт элемент HTML с атрибутом class="inline-note note-tag-requirement".

Таблица стилей Standard Doclet по умолчанию объявляет стили для следующих видов примечаний:

Другие виды можно определить через атрибуты или с помощью пользовательских тегов примечаний (описаны ниже) и оформить с помощью пользовательских таблиц стилей.

Атрибут id

Атрибут id делает примечание адресуемым как цель фрагмента: к элементу HTML, создаваемому для примечания, добавляется атрибут id с заданным значением. Например, {@note (id="usage-note") ...} создаёт элемент HTML с атрибутом id="usage-note", на который можно сослаться по URL с идентификатором фрагмента #usage-note.

Другие атрибуты

Атрибуты, кроме описанных выше, Standard Doclet игнорирует.

Пользовательские теги примечаний

Параметр -tag инструмента javadoc уже предоставляет механизм для определения пользовательских тегов, которые можно использовать для любых целей, в том числе для дополнительной информации. Однако возможности этих тегов ограничены: их можно использовать только как блочные теги, и они не поддерживают оформление и настройку.

Мы расширяем параметр -tag, чтобы с его помощью можно было определять пользовательские теги, являющиеся псевдонимами тега примечания. Такой пользовательский тег можно использовать и как встроенный, и как блочный, а его вывод можно оформлять стилями. Любое использование пользовательского тега эквивалентно тегу примечания, в котором атрибут kind содержит имя пользовательского тега, а атрибут header — заголовок тега, заданный в командной строке.

Например, следующий аргумент командной строки определяет пользовательский тег @warning, который можно использовать во всех видах элементов и который является псевдонимом для @note (kind='warning' header='Warning:'):

-tag 'warning:A:Warning:'

Следующее использование:

{@warning Remember to flush the cache before syncing.}

эквивалентно:

{@note (kind='warning' header='Warning:') Remember to flush the cache before syncing.}

Оба тега дают одинаковый вывод с CSS-классом note-tag-warning в элементе HTML, создаваемом для примечания:

Warning: не забудьте сбросить кэш перед синхронизацией.

Пользовательские теги могут содержать атрибуты, в том числе kind и header. Например, с пользовательским тегом @warning, определённым выше:

{@warning (kind='supercritical') Do not call this method until shutdown.}

эквивалентно:

{@note (kind='supercritical' header='Warning:') Do not call this method until shutdown.}

а HTML, созданный для примечания, имеет CSS-класс note-tag-supercritical.

Поскольку теги @note можно использовать и как встроенные, и как блочные, в аргументе параметра -tag можно использовать два новых символа в качестве флагов location, чтобы управлять использованием определяемого тега:

B to only allow use as block tag
I to only allow use as inline tag

Два новых флага взаимоисключающие и используются вместе с существующими флагами расположения, чтобы ограничить использование пользовательского тега только блочным или только встроенным режимом. По умолчанию пользовательский тег можно использовать и в блочном, и во встроенном режиме. Например, следующий аргумент командной строки создаёт тег @safetytip, который можно использовать только как блочный тег в описаниях методов:

-tag 'safetytip:MB:Safety Message:'

Рекомендации по написанию примечаний

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

Использование встроенных примечаний

В следующих примерах показано, где встроенные примечания могут быть уместны:

  • Примечания, которые дают контекст, предысторию или другую дополнительную информацию, которая может заинтересовать читателя. Примером может служить следующее примечание в документации метода ExecutorService.submit(Callable):

    Примечание: класс Executors содержит набор методов, которые могут преобразовать некоторые другие распространённые объекты, похожие на замыкания, например PrivilegedAction, в форму Callable, чтобы их можно было передать на выполнение.

  • Примечания, которые содержат предупреждения или другие важные сообщения, заслуживающие выделения, чтобы читатель их не пропустил. Пример — следующее примечание в описании интерфейса List:

    Примечание: хотя спискам разрешено содержать самих себя в качестве элементов, рекомендуется крайняя осторожность: методы equals и hashCode для такого списка уже не определены корректно.

    Возможно, здесь заголовок и стиль «Caution» или «Warning» были бы уместнее, чем общий «Note».

Примеры того, где встроенные примечания неуместны, встречаются по всей документации Java SE API. Пользовательские блочные теги используются и будут использоваться дальше для специальной дополнительной информации в спецификациях API Java SE и JDK. Например, @apiNote создаёт раздел «API Note:», а @implSpec создаёт раздел «Implementation Requirements:». Эта информация самостоятельна и не зависит от контекста основного описания, поэтому размещать её внутри текста нет смысла. Встроенные примечания следует использовать для материала, который естественно относится к основному описанию и раньше оформлялся пользовательской HTML-разметкой или вообще без разметки.

Явные ID и ID по умолчанию

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

Для блочных примечаний это обычно не так важно: в большинстве случаев в документационном комментарии есть только одно блочное примечание данного вида, а ID по умолчанию зависит только от содержащего элемента и вида примечания, поэтому он естественным образом остаётся стабильным при изменениях.

Для встроенных примечаний ID по умолчанию содержит ещё и порядковый номер, который указывает позицию примечания среди примечаний того же вида в содержащем документационном комментарии. Поэтому добавление, перемещение или удаление примечаний может повлиять на ID по умолчанию других примечаний в том же документационном комментарии. По этой причине во встроенных комментариях, на которые могут ссылаться, хорошей практикой будет использовать явные ID.

Ещё одна распространённая причина использовать явные ID как во встроенных, так и в блочных примечаниях — придать фрагменту URL смысловое значение, например «#usage-warning».

Вложенные примечания

Хотя встроенные теги примечаний можно вкладывать в другие встроенные или блочные теги примечаний, мы не считаем, что такой способ использования будет распространённым, и не собираемся предоставлять для этого случая специальные стили CSS. Для большинства практических задач примечания лучше организовывать плоско и последовательно.

Альтернативы

Мы рассматривали расширение Taglet API, чтобы разработчикам было проще реализовывать собственные пользовательские теги примечаний. Однако мы считаем, что примечания достаточно важны, чтобы предоставить готовое решение и не требовать от каждого писать собственные таглеты.

Мы рассматривали добавление в инструмент javadoc отдельной опции для пользовательских примечаний вместо расширения опции -tag. Однако новая опция во многом дублировала бы -tag, и пользоваться инструментом стало бы сложнее.

Мы рассматривали механизм шаблонов для настройки вывода примечаний, но он значительно усложнял решение. Описанные выше стили CSS дают достаточно гибкости для типичных сценариев.

Мы рассматривали синтаксис атрибутов из фрагментов кода (snippets), где атрибуты отделяются от тела фрагмента двоеточием и символом новой строки. Однако обязательный разделитель, такой как последовательность «двоеточие — новая строка» во фрагментах кода, нарушил бы совместимость с существующими пользовательскими тегами, которую этот JEP стремится сохранить.

В более ранних версиях этого JEP для атрибутов примечаний использовались квадратные скобки вместо круглых. Однако квадратные скобки конфликтуют с синтаксисом ссылок в документационных комментариях в формате Markdown, поэтому мы решили использовать для атрибутов круглые скобки.

Тестирование

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

Риски и допущения

Два разных способа представления примечаний — встроенный тег примечания и пользовательские теги, определённые с помощью -tag, — предусмотрены потому, что эти механизмы будут привлекательны для разных групп пользователей. Для небольших и менее формальных проектов тег примечания даёт быстрый и гибкий способ создавать примечания без изменений в сборке приложения. Для крупных проектов определение пользовательских тегов через -tag — способ предоставить утверждённый набор функций, подобных примечаниям, с удобным синтаксисом тегов.

Риск тега примечания в том, что его могут использовать чрезмерно и в местах, где лучше подошёл бы сплошной текст. Мы предполагаем, что авторы документации API будут использовать этот тег обдуманно.