此 EEP 提出一個針對 Erlang 的結構化文件 API,其中文件將作為語言解析器的一部分處理,並直接包含在已編譯的 .beam 檔案中,以取代 EDoc 風格的註解。Python、Elixir 和 Clojure 是遵循此方法將文件視為資料而非程式碼註解的語言範例。
目前 EDoc 的主要限制在於文件以程式碼註解的形式保存。這需要一個明確的工具來解析這些程式碼註解,這使得 IDE、shell 等等對文件的存取變得複雜。最近在這方面有所改進,透過使 EDoc 編譯為 EEP 48,但仍然需要一個明確的步驟。
此外,就實作而言,「程式碼註解」的方法更加複雜,因為它需要解析原始程式碼以及程式碼註解、解析程式碼註解等等。明確區分文件和程式碼註解也很有益:它們有不同的要求和不同的受眾。
此 EEP 建議為 Erlang 新增兩個模組屬性:-doc
和 -moduledoc
。
如同 EEP 48,此提案僅與 API 參考及其文件相關。它不涵蓋指南、教程和其他文件格式。
此 EEP 建議兩個新的屬性:-doc
和 -moduledoc
。它們可以按如下方式使用
-module(base64).
-moduledoc "
Convenience functions for encoding and decoding from base64.
".
-doc "
Encodes the given binary to base64.
".
-spec encode(binary()) -> binary().
encode(Binary) ->
% ....
-doc "
Decodes the given binary from base64.
".
-spec decode(binary()) -> {ok, binary()} | error.
encode(Binary) ->
% ....
新的 -moduledoc
屬性可以列在任何位置,它將包含給定模組的文件。-doc
屬性必須列在函式、類型屬性或回呼屬性之前的任何位置,並且它將包含以下函式、類型或回呼的文件。例如,下面的例子
-doc "Example".
-spec example() -> ok.
example() -> ok.
等同於
-spec example() -> ok.
-doc "Example".
example() -> ok.
為同一個函式列出多個帶有字串值的 -doc
屬性應相應地發出警告或錯誤,除非文件被設定為隱藏。例如,這是有效的
-doc "Example".
-doc hidden.
example() -> ok.
但這應該警告/錯誤
-doc "Example".
-doc "Updated example".
example() -> ok.
這也一樣
-doc "Example".
example(one) -> 1;
-doc "Updated example".
example(two) -> 2;
模組屬性必須是字串或原子 false
。將模組標記為隱藏表示它不會成為文件的一部分。例如,假設上面的 base64
模組將其某些邏輯委派給私有的 base64_impl
模組
-module(base64_impl).
-moduledoc false.
請注意,模組可能會被隱藏,但個別函式仍然可以被記錄
-module(base64_impl).
-moduledoc false.
-doc "
Some comments as if it was public.
".
decode64(Binary) ->
% ...
根據 EEP 48,這是故意的。例如,base64_impl
對於 base64
功能的使用者來說應該是私有的,但直接在 base64
上工作的開發人員可能仍然希望直接從他們的 IDE 存取 base64_impl
函式的文件。每個文件工具都應相應地處理 hidden
。如果沒有提供 -doc
,根據 EEP 48,它預設為 none
。
-doc
屬性也接受 false
原子。
有些開發人員不喜歡將文件與原始程式碼放在一起。對於這種情況,-doc
和 -moduledoc
也可以提供 {file, Path}
,其中 Path
是包含 doc 屬性的檔案的相對路徑
-moduledoc({file, "../doc/src/manual/my_module.asciidoc"}).
-doc({file, "../doc/src/manual/my_module.my_function.asciidoc"}).
編譯器將讀取該檔案並在編譯時將其嵌入到區塊中。
-doc
屬性也可以用於記錄類型和回呼。
-doc
屬性也可以用於私有函式,以便工具和 IDE 可以在使用者需要時提供文件。但是,私有函式不應出現在 EEP 48 doc 區塊中。
一般而言,私有類型的處理方式與私有函式相同,但是有時類型用於模組內的文件和程式碼共享目的,但使用者不希望將其匯出以供一般使用。一個例子是 ssl 模組中的所有各種選項類型。
因此,任何由公共函式規範或類型引用的私有類型也將包含在文件區塊中。此類類型的 exported
元資料鍵將設定為 false
。
新的模組屬性還必須支援文件元資料,方法是傳遞一個映射作為引數
-module(beam64).
-moduledoc "
Convenience functions for encoding and decoding from base64.
".
-moduledoc #{
author => [<<"The Erlang/OTP team">>],
license => <<"Apache 2 License">>,
cross_references => [binary]
}.
如果多次使用映射呼叫 -moduledoc
,則映射將被合併。這帶來了額外的好處,即共用的元資料可以移至標頭檔
%% prelude.hrl
-moduledoc #{
authors => [<<"The Erlang/OTP team">>],
license => <<"Apache 2 License">>
}.
然後我們可以包含並擴充它
-module(beam64).
-include("prelude.hrl").
-moduledoc "
Convenience functions for encoding and decoding from base64.
".
-moduledoc #{cross_references => [binary]}.
內建屬性列表可在 EEP 48 上找到。
編譯具有 -moduledoc
或 -doc
屬性的模組將在其 .beam 檔案中產生一個 Docs 區塊,使文件可以直接在 shell 中存取。
發布工具也應預設從 .beam 檔案中刪除文件區塊。請注意,這已經由 beam_lib:strip_release/1
和 beam_lib:strip_files/1
完成。
warn_missing_doc
#如果將 warn_missing_doc
標誌傳遞給編譯器,則編譯器會在 EEP 48 doc 區塊中包含的函式、類型或回呼未設定 -doc
屬性時發出警告。
該標誌可以在命令列上作為 +warn_missing_doc
傳遞,也可以作為原始程式碼中的 -compile(warn_missing_doc)
屬性傳遞。
關於文件的一個重要討論是文件應採用的文件格式是什麼。幸運的是,EEP 48 不受格式限制,但是仍然必須列出一個格式。
為了方便使用多種文件格式,Erlang/OTP 允許使用者在 -moduledoc
元資料中放置一個 format
鍵,該鍵應指定所用格式的 mime 類型,如 EEP 48 所指定。預設格式將為 text/markdown
。
-moduledoc(#{ format => "text/edoc" }).
使文件更結構化且可存取的直接後果是,Erlang 可以包含 doctests,這是執行和驗證文件中範例的能力。例如,有人可以這樣寫
-doc """
Encodes the given binary to base64.
1> base64:encode("hello").
<<"aGVsbG8=">>
""".
-spec encode(binary()) -> binary().
encode(Binary) ->
% ....
然後在你的測試套件中
doctests(_Config) ->
ct_doctest:run(base64).
doctest 屬性將存取 base64 Docs 區塊中的文件條目,提取所有範例並執行它們。當然,儘管沒有任何東西阻止在今天的 EDoc 之上實作 doctests,但此 EEP 使 doctests 的實作變得簡單得多。
Doctests 將受益於單獨的 EEP,因為還有一些額外的考慮,例如 doctesting 例外、無法解析的格式等等,但鑑於它們對使用者和文件作者的好處,值得一提。
erl_docgen
呢? #如果此提案被接受,EDoc 會發生什麼事?
此 EEP 提出的工作的一個重要方面是嘗試統一 Erlang/OTP 生態系統中的文件工具。在此之前,有多種工具,EDoc 主要用於開源專案,erl_docgen
用於 Erlang/OTP 專案和其他第三方解決方案。
在短期內,EDoc 將被更新為能夠從包含 text/edoc
文件的 EEP 48 doc 區塊生成 html 報告。指定文件的 EDoc 註解風格將被棄用,但是,為了向後相容性,解析 EDoc 註解的支援將保留很長時間。
從長遠來看,目標是切換文件渲染引擎以使用 ExDoc,它透過將其作為 escript 執行或透過 Rebar3 整合來支援 Erlang 專案。使用 ExDoc 時,使用者可以選擇使用 EDoc 語法或遷移到 Markdown。
同樣,Erlang/OTP 程式碼將被轉換為使用 ExDoc 而不是 erl_docgen
來產生文件。所有目前的 XML 文件檔案都將被轉換為使用 Markdown。
本文檔置於公共領域或在 CC0-1.0-Universal 許可證下,以較寬容者為準。