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

JEP 105: DocTree API

DocTree API

ОтветственныйJonathan Gibbons
ТипFeature
ОбластьJDK
СтатусClosed / Delivered
Выпуск8
Компонентtools / javac
Обсуждениеcompiler dash dev at openjdk dot java dot net
ТрудоёмкостьS
ДлительностьS
БлокируетJEP 172: DocLint
ОдобренBrian Goetz
Создан2011/07/25 20:00
Обновлён2015/02/13 19:41
Задача8046095

Аннотация

Расширить Compiler Tree API, чтобы обеспечить структурированный доступ к содержимому комментариев javadoc.

Цели

Обеспечить доступ к синтаксическим элементам комментария javadoc.

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

Целью не является проверка HTML-тегов в комментарии javadoc на семантическую корректность, то есть проверка HTML по DTD или аналогичному описанию; однако с помощью этого API должно быть возможно создавать такие инструменты.

Мотивация

Этот API позволит создать новое поколение инструментов для работы с документирующими комментариями. Такие инструменты можно будет написать либо с использованием Compiler API и Tree API, либо в виде обработчиков аннотаций. Один инструмент, которого давно, очень давно не хватает, — обновлённый аналог старого доклета DocCheck, который проверял бы простые правила и рекомендации для содержимого документирующих комментариев и который так и не был обновлён с учётом изменений языка в Java 5 и более поздних версиях.

javadoc тоже можно было бы переписать так, чтобы он использовал новые структурированные объекты документирующих комментариев и мог указывать в сообщениях об ошибках дополнительную информацию, например позиции в исходном коде. Разбор HTML также помог бы javadoc генерировать корректный XHTML. Хотя после работы, проделанной над javadoc в JDK 7, генерировать XHTML для разделов, которые создаёт сам javadoc, легко, сейчас у javadoc нет средств, чтобы проверить или подтвердить корректность использования XHTML в документирующих комментариях обрабатываемых им исходных файлов.

Описание

Проблема (проблемы)…

В JDK 5 был один сканер, который умел читать документирующие комментарии так, как это требовалось javadoc. В JDK 6 код был переработан и разделён на два сканера: один умел читать документирующие комментарии и подходил для javadoc, а другой не умел и подходил для javac. Так было до тех пор, пока мы не добавили в javac различные публичные API, через которые клиенты и обработчики аннотаций могли при желании получить доступ к документирующим комментариям.

Это значит, что существует 3 типа клиентов документирующих комментариев:

  1. комментарии не нужны — javac, когда не нужно запускать обработчики аннотаций
  2. комментарии точно нужны — javadoc
  3. комментарии, возможно, нужны — клиенты публичного API javac, включая обработчики аннотаций, запускаемые javac

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

Другая проблема таблицы документирующих комментариев в том, что она устроена очень примитивно. Это просто отображение узла дерева на строку, где строка — документирующий комментарий в том виде, в каком он нужен javadoc, то есть с удалённым началом каждой строки (пробельными символами и обычным «*»). Из-за этого действительно очень трудно сопоставить позиции внутри документирующего комментария с позициями в исходном файле, и именно поэтому javadoc не выдаёт традиционных сообщений об ошибках «в стиле emacs» вида «parameter name not found» или «exception not declared to be thrown».

Та же примитивная таблица документирующих комментариев доступна клиентам Tree API. Для любого узла дерева можно получить строку документирующего комментария. И всё; дальше вы предоставлены сами себе. Идея (идеи)…

Первым делом нужно усовершенствовать таблицу документирующих комментариев, которая хранится в каждой единице компиляции. Заменить

Map<JCTree, String> docComments;

на

Map<JCTree, JCDocComment> docComments;

JCDocComment — новый внутренний объект javac, который предоставляет ленивый доступ к строке документирующего комментария. Как минимум он содержит начальную позицию документирующего комментария в исходном файле: позицию символа «/».

interface JCDocComment {
    int getPosition();
    String getComment();
}

Благодаря этому у нас может быть до трёх разных сканеров документирующих комментариев для трёх разных типов клиентов. Для javac без обработчиков аннотаций мы, как и сейчас, продолжаем использовать стандартный Scanner и оставляем таблицу docComments пустой. Для javadoc мы, как и сейчас, продолжаем читать документирующие комментарии, только теперь сохраняем их в объектах JCDocComment. Для javac, когда неизвестно, нужны документирующие комментарии или нет, мы просто сохраняем начальную позицию документирующего комментария. Так нам не приходится хранить текст всех документирующих комментариев, когда они не нужны. Цена этого в том, что когда комментарии всё же нужны, приходится возвращаться к исходному файлу и восстанавливать из него текст комментария. Возможны разные стратегии. Если нужен хотя бы один документирующий комментарий в исходном файле, можно просканировать их все. Заметим, что сканировать исходный текст между комментариями не нужно: начальная позиция комментария нам известна, поэтому текст между комментариями можно просто пропустить. Или можно читать комментарии по мере необходимости и полагаться на кэш содержимого, чтобы не читать содержимое исходного файла заново для каждого отдельного комментария.

Следующая идея — более удобное, разобранное представление документирующих комментариев.

Документирующий комментарий состоит из

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

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

  • обычный текст, включая символы из некорректных фрагментов, такие как '<', '>', '&', '{' и т. д.
  • открывающий HTML-элемент, который содержит имя и список пар «имя–значение», например '<a href="Object.html">'
  • закрывающий HTML-элемент, который содержит имя, например '</a>'
  • HTML-мнемоника символа, например '&amp;'
  • таглет, например {@link Object}

Очевидно, всё это можно смоделировать простой иерархией узлов дерева, поэтому я предлагаю новый пакет com.sun.source.doccomments, который будет содержать интерфейсы для этих узлов. Лучше всего сделать эту иерархию отдельной от существующей com.sun.source.tree.Tree, поэтому я предлагаю новый общий суперинтерфейс com.sun.source.doccomments.DTree. Затем можно расширить вспомогательные методы в com.sun.source.util, чтобы обеспечить доступ к разобранному документирующему комментарию для любого узла дерева и получение информации о позиции в исходном коде для любого узла DTree.

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

Разбор этих комментариев не будет дешёвым: всё, что связано с лексическим и синтаксическим анализом, дёшево не бывает. Поэтому это ещё одна причина предоставлять и использовать ленивый доступ к документирующим комментариям через описанную выше таблицу JCDocComment. Только теперь в ней есть и более интересный метод — для получения DTree комментария, и это ещё одна причина не хранить простую строку, которая предоставляется сейчас.

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

Для проверки нового API будут написаны регрессионные тесты langtools. Один из тестов будет читать и обрабатывать все комментарии API JDK.

Особых требований к платформе или оборудованию нет.

Зависимости

Эта работа не зависит от других JEP.

Ожидается, что от этого JEP будут зависеть другие JEP.

Влияние

  • Другие компоненты JDK: javadoc
  • Совместимость: минимальное
  • Интернационализация: минимальное
  • Локализация: минимальное