Files
swift-mirror/docs/proposals/DocumentationComments.rst
Chris Lattner 0f6c14cee3 fix typo
Swift SVN r14522
2014-02-28 17:01:02 +00:00

434 lines
14 KiB
ReStructuredText

:orphan:
===============================
Documentation Comments in Swift
===============================
Big Picture
===========
- Swift documentation comments will start with a special character sequence.
They can be line-based ``///`` or block-based ``/** ... */``.
- Swift comments will use only ReST markup (reStructuredText) inside
documentation comments. No Doxygen or HeaderDoc commands (\foo or @foo) will
be allowed. We will try to produce fixits if the parser encounters Doxygen
syntax, but this will be done only for the most widely used commands.
[Rationale: for a completely new language compatibility with Doxygen is not
deemed extremely important. Compatibility with existing infrastructure
around existing, standartized markup language (ReST) is much more compelling.
ReST markup is versatile -- DevPubs have been using it for Swift
documentation for some time already. ReST has a specification, so different
implementations should be able to interoperate. ReST is extensible, so we
will be able to invent markup in future if we want to express something
special that is not described in the standard.
Developers will have to learn a lot of new syntax for the language anyway,
and documentation comments will be the most complicated part. Templates and
the Swift book will guide them. Warnings and fixits for the most popular
Doxygen tags will also help. ]
- March milestone: top-level commands are recognized, brief description is
available in code completion results on the SourceKit side.
- GM milestone: the most important ReST inline markup is recognized.
Micro Details
=============
- No explicit markup for brief description. Brief description is always the
first paragraph without special markup.
- Documentation for function parameters and generic parameters uses the same
syntax.
- We will start implementing ReST parsing, starting with recognizing top-level
structure, and will prioritize/implement specific features based on feedback
from DevPubs and DaveA.
Example
=======
Here is how documentation comments can look like in ReST markup::
/// Lorem ipsum dolor sit amet, consectetur adipiscing elit.
///
/// :param: bar Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi. Quisque venenatis in
/// erat non suscipit. Praesent varius tellus tortor.
///
/// :returns: ut bibendum ligula sit amet arcu euismod sagittis.
func foo(bar: Int) -> Double {
}
ReST specification is available here:
http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html
Old Proposal
============
The old proposal follows.
In this document [P1] [P2] [P3] [P4] designate priorities.
March milestone
===============
[P1] Brief documentation and discussion
---------------------------------------
- Markup for a single-paragraph brief documentation.
- Markup for the "discussion" part.
We filter the comment text to find all "normal" paragraphs (not parameter
documentation, not return value documentation etc.) Paragraphs are separated
by a blank line. The first such paragraph is the brief description (to show in
code completion, for example), the rest is the "discussion".
Example::
/// Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse \
/// ornare, ipsum vitae mattis adipiscing, lorem risus mattis elit, nec | Brief documentation
/// imperdiet justo est at nisi. /
///
/// Quisque venenatis in erat non suscipit. Praesent varius tellus tortor, ut \
/// rutrum arcu vestibulum id. |
/// | Discussion.
/// Ut bibendum ligula sit amet arcu euismod sagittis. Morbi pulvinar nisl ac |
/// dapibus pharetra. /
func foo() {
}
Note that we don't use ``\brief`` or ``\discussion`` in this simple case
because the command is redundant.
[P1] Documentation for function parameters
------------------------------------------
Proposed syntax::
/// \param bar Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi.
func foo(bar: Ornare) {
}
[P1] Documentation for generic parameters
-----------------------------------------
Proposed syntax::
/// \genericparam T Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi.
class Array<T> {
}
Note: HeaderDoc uses ``templatefield`` for C++ templates. Using the term
``field`` with regards to template or generic parameters is not correct neither
for C++ not for Swift.
[P1] Documentation for the return value
---------------------------------------
Proposed syntax::
/// \result The square root of a given number.
func sqrt(x: Double) -> Double {
}
/// \returns the square root of a given number.
func sqrt(x: Double) -> Double {
}
/// \return the square root of a given number.
func sqrt(x: Double) -> Double {
}
Discussion questions:
- Do we want just a single tag (``\result``), or do we want aliases? Aliases
are helpful to blend together commands and text in cases like this::
/// \returns 0 on success, non-zero error code on failure.
func f() -> Int {
}
- If we want aliases, do we want both ``\returns`` and ``\return``, or just the
former? I think only ``\returns`` can be used to write correct prose here.
- Do we want to allow using multiple ``\returns`` commands? Developers do this
in Doxygen (it was probably not designed to be this way, but right now it
works anyway)::
/// \returns 0 on success.
/// \returns error code on failure.
func f() -> Int {
}
[P2] Documentation for parameters of closures that are function parameters
--------------------------------------------------------------------------
For example, documentation for ``x`` in the following function declaration can
be specified like this::
/// \param callback Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi.
///
/// \param x Quisque venenatis in erat non suscipit.
func foo(callback: (x: Int)->())
For now we propose to use ``\param`` as well. In GM we will look into using
indentation here, and showing indented in Quick Help::
/// \param callback Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi.
///
/// \param x Quisque venenatis in erat non suscipit.
func foo(callback: (x: Int)->())
Special character to use in commands
------------------------------------
We should decide if we want to use the ``\`` character or ``@`` on commands,
or if we want something else. We definitely don't want to allow to use
multiple styles and provoke another style discussion or per-project
preferences.
- We are going to reserve ``\`` anyway as an escape character. Using ``\`` for
commands as well will allow us to reserve ``@`` for now and use it for a
different purpose in future.
- Using ``@`` would be "compatible" with HeaderDoc users, but otherwise it is
just a waste of a special character.
Note that Clang's documentation parser supports both ``\`` and ``@``, so
"consistency with Clang" is not an argument either way.
A completely different direction. What about using ``:command:``? This would
be compatible with ReStructuredText. For example::
/// :param: bar Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi.
func foo(bar: Ornare) {
}
/// :returns: the square root of a given number.
func sqrt(x: Double) -> Double {
}
GM milestone
============
[P3] brief part that is longer than one paragraph
-------------------------------------------------
Sometimes the author wants to have brief description to run longer than one
paragraph.
Proposed syntax::
/// \brief Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
/// | Brief description.
/// Suspendisse ornare, ipsum vitae mattis adipiscing, lorem risus mattis |
/// elit, nec imperdiet justo est at nisi. /
///
/// \discussion Quisque venenatis in erat non suscipit. Praesent varius \
/// tellus tortor, ut rutrum arcu vestibulum id. |
/// | Discussion.
/// Ut bibendum ligula sit amet arcu euismod sagittis. Morbi pulvinar nisl ac |
/// dapibus pharetra. /
func foo() {
}
Discussion question: ``\brief`` or ``\abstract``? "``\brief``" is shorter and
has a precedent in Doxygen, "``\abstract``" has precedent in HeaderDoc.
[P4] specifying whether a parameter is logically "out" or "in,out"
------------------------------------------------------------------
Swift supports multiple return values, so this feature is not needed for native
Swift code. But it could be used for example, for pointers that are trafficed
through C interfaces.
Proposed syntax::
/// \param [out] extraResult Set to zero if...
func foo(extraResult: UnsafePointer<Int>) -> Int {
}
[P4] documentation for parameters of closures that are function parameters
--------------------------------------------------------------------------
Consider using indentation, as described previously.
Features related to the markup
==============================
- [P1] inline, monospaced font
- [P3] inline, bold
- [P3] inline, italic
- [P1] block, monospaced font
HeaderDoc has a precedent for using opening and closing commands for inline
markup::
/// Passing a negative number to
/// <tt>
/// @textblock
/// func sqrt(x: Double) -> Double
/// @/textblock
/// </tt>
/// is not allowed.
This syntax wastes *five lines* to mark up a few words with monospaced font.
I did a quick search on Clownfish, and ``textblock`` has 71 hits, while
``discussion`` has 6000+. Basically, if the syntax is that bad, nobody is
going to use it.
Doxygen has a more concise alternative that has another shortcoming, though --
it is limited to a single word::
/// Passing a negative number to \c sqrt() is not allowed.
For inline markup I explicitly don't want to follow HeaderDoc's or
Doxygen's precedent, because they are not good ones.
Proposed syntax for italics, bold and monospaced text, precedented by
ReStructuredText::
/// *Text in italics.* Normal text. **Text in bold.**
///
/// Passing a negative number to ``func sqrt(x: Double) -> Double`` is not
/// allowed.
Proposed syntax for any other inline markup, precedented by ReStructuredText::
/// :role:`text, multiple words allowed`
///
/// Square root of x :sup:`2` is x.
Proposed syntax for monospaced block markup, precedented by ReStructuredText::
/// Ipsum vitae mattis adipiscing, lorem risus mattis
/// elit, nec imperdiet justo est at nisi:
///
/// ::
///
/// func sqrt(x: Float) -> Float {
/// return Float(sqrt(Double(x)))
/// }
To mark up a paragraph as monospaced block, add a paragraph that contains just
"``::``", and indent the following paragraphs.
Shorthand syntax::
/// Ipsum vitae mattis adipiscing, lorem risus mattis elit, nec imperdiet
/// justo est at nisi::
///
/// func sqrt(x: Float) -> Float {
/// return Float(sqrt(Double(x)))
/// }
Finish the paragraph with "``::``" and indent the following paragraphs.
Why ReStructuredText?
- The syntax is concise and easy to read in raw form. This is important
because programmers are going to read raw comments *a lot*.
- ReStructuredText has a specification (public domain), and other people have
already though about all the parsing ambiguities and other difficulties that
arise when implementing parsing essentially free-form text.
- There are existing tools to process ReStructuredText. While this is not
helpful for the implementation inside the compiler (we have special needs to
produce good diagnostics and point back to the source code), this will
definitely help in future.
Features related to links in markup
===================================
Note that we don't need to implement the *parsing* and *resolving* of
references, just specify what we want to expect there, and treat the reference
as 'inline monospaced' markup.
[P3] Reference a parameter of the current function
--------------------------------------------------
Proposed syntax::
/// If :p:`flag` is true, then...
func f(flag: Bool) {
}
Do we need this feature? Can we just use inline monospaced markup? ::
/// If ``flag`` is true, then...
func f(flag: Bool) {
}
[P3] Reference any declaration
------------------------------
Proposed syntax::
/// See also :ref:`cos(Double)`.
func sin(x: Double) -> Double {
}
Custom link text can be specified in angle brackets::
/// See also :ref:`cos(Double) <cosine function>`.
func sin(x: Double) -> Double {
}
Use of HTML in markup
=====================
The proposed syntax is powerful enough to express anything, including lists and
tables. We should just ban using HTML.
HeaderDoc features that we *don't* want
=======================================
Doxygen and HeaderDoc have shortcomings that we should not carry over to Swift.
Among those I would like to explicitly mention:
- Violation of DRY principle (don't repeat yourself). From HeaderDoc
documentation::
/*!
@function FunctionName
This is a comment about FunctionName.
*/
char *FunctionName(int k);
The tool should be smart enough to recognize where the comment is attached to.
- Pointless limitations of commands. For example, Doxygen inline markup is
limited to single words::
/// \em emphasis \c monospaced etc.
Doxygen's brief descriptions are limited to a single paragraph.
Doxygen's parameter documentation is limited to a single paragraph. (Did not
check HeaderDoc.)
- Strange semantics of ``\brief`` and ``\discussion`` in Doxygen. Consider
this example::
/// Aaa. } Discussion, part 1.
///
/// \brief Bbb. } Brief description.
///
/// Ccc. \
/// | Discussion continues here.
/// \discussion Ddd. /