Documenting code

Crystal can generate documentation from comments using a subset of Markdown.

To generate documentation for a project, invoke crystal docs. By default this will create a docs directory, with a docs/index.html entry point. For more details see Using the compiler – Creating documentation.

  • Documentation should be positioned right above definitions of classes, modules, and methods. Leave no blanks between them.
  1. # A unicorn is a **legendary animal** (see the `Legendary` module) that has been
  2. # described since antiquity as a beast with a large, spiraling horn projecting
  3. # from its forehead.
  4. class Unicorn
  5. end
  6. # Bad: This is not attached to any class.
  7. class Legendary
  8. end
  • The documentation of a method is included into the method summary and the method details. The former includes only the first line, the latter includes the entire documentation. In short, it is preferred to:

    1. State a method’s purpose or functionality in the first line.
    2. Supplement it with details and usages after that.

For instance:

  1. # Returns the number of horns this unicorn has.
  2. #
  3. # ```
  4. # Unicorn.new.horns # => 1
  5. # ```
  6. def horns
  7. @horns
  8. end
  • Use the third person: Returns the number of horns this unicorn has instead of Return the number of horns this unicorn has.

  • Parameter names should be italicized (surrounded with single asterisks * or underscores _):

  1. # Creates a unicorn with the specified number of *horns*.
  2. def initialize(@horns = 1)
  3. raise "Not a unicorn" if @horns != 1
  4. end
  • Code blocks that have Crystal code can be surrounded with triple backticks or indented with four spaces.
  1. # ```
  2. # unicorn = Unicorn.new
  3. # unicorn.speak
  4. # ```

or

  1. # unicorn = Unicorn.new
  2. # unicorn.speak
  • Text blocks, for example to show program output, must be surrounded with triple backticks followed by the “text” keyword.
  1. # ```text
  2. # "I'm a unicorn"
  3. # ```
  • To automatically link to other types, enclose them with single backticks.
  1. # the `Legendary` module
  • To automatically link to methods of the currently documented type, use a hash like #horns or #index(char), and enclose it with single backticks.

  • To automatically link to methods in other types, do OtherType#method(arg1, arg2) or just OtherType#method, and enclose it with single backticks.

For example:

  1. # Check the number of horns with `#horns`.
  2. # See what a unicorn would say with `Unicorn#speak`.
  • To show the value of an expression inside code blocks, use # =>.
  1. 1 + 2 # => 3
  2. Unicorn.new.speak # => "I'm a unicorn"
  • Use :ditto: to use the same comment as in the previous declaration.
  1. # :ditto:
  2. def number_of_horns
  3. horns
  4. end
  • Use :nodoc: to hide public declarations from the generated documentation. Private and protected methods are always hidden.
  1. class Unicorn
  2. # :nodoc:
  3. class Helper
  4. end
  5. end

Inheriting Documentation

When an instance method has no doc comment, but a method with the same signature exists in a parent type, the documentation is inherited from the parent method.

For example:

  1. abstract class Animal
  2. # Returns the name of `self`.
  3. abstract def name : String
  4. end
  5. class Unicorn < Animal
  6. def name : String
  7. "unicorn"
  8. end
  9. end

The documentation for Unicorn#name would be:

  1. Description copied from class `Animal`
  2. Returns the name of `self`.

The child method can use :inherit: to explicitly copy the parent’s documentation, without the Description copied from ... text. :inherit: can also be used to inject the parent’s documentation into additional documentation on the child.

For example:

  1. abstract class Parent
  2. # Some documentation common to every *id*.
  3. abstract def id : Int32
  4. end
  5. class Child < Parent
  6. # Some documentation specific to *id*'s usage within `Child`.
  7. #
  8. # :inherit:
  9. def id : Int32
  10. -1
  11. end
  12. end

The documentation for Child#id would be:

  1. Some documentation specific to *id*'s usage within `Child`.
  2. Some documentation common to every *id*.

NOTE: Inheriting documentation only works on instance, non-constructor methods.

Flagging Classes, Modules, and Methods

Given a valid keyword, Crystal will automatically generate visual flags that help highlight problems, notes and/or possible issues.

The supported flag keywords are:

  • BUG
  • DEPRECATED
  • FIXME
  • NOTE
  • OPTIMIZE
  • TODO

Flag keywords must be the first word in their respective line and must be in all caps. An optional trailing colon is preferred for readability.

  1. # Makes the unicorn speak to STDOUT
  2. #
  3. # NOTE: Although unicorns don't normally talk, this one is special
  4. # TODO: Check if unicorn is asleep and raise exception if not able to speak
  5. # TODO: Create another `speak` method that takes and prints a string
  6. def speak
  7. puts "I'm a unicorn"
  8. end
  9. # Makes the unicorn talk to STDOUT
  10. #
  11. # DEPRECATED: Use `speak`
  12. def talk
  13. puts "I'm a unicorn"
  14. end

Use Crystal’s code formatter

Crystal’s built-in code formatter can be used not just to format your code,
but also to format code samples included in documentation blocks.

This is done automatically when crystal tool format is invoked, which
will automatically format all .cr files in current directory.

To format a single file:

  1. $ crystal tool format file.cr

To format all .cr files within a directory:

  1. $ crystal tool format src/

Use this tool to unify code styles and to submit documentation improvements to
Crystal itself.

The formatter is also fast, so very little time is lost if you format the
entire project instead of a single file.

A Complete Example

  1. # A unicorn is a **legendary animal** (see the `Legendary` module) that has been
  2. # described since antiquity as a beast with a large, spiraling horn projecting
  3. # from its forehead.
  4. #
  5. # To create a unicorn:
  6. #
  7. # ```
  8. # unicorn = Unicorn.new
  9. # unicorn.speak
  10. # ```
  11. #
  12. # The above produces:
  13. #
  14. # ```text
  15. # "I'm a unicorn"
  16. # ```
  17. #
  18. # Check the number of horns with `#horns`.
  19. class Unicorn
  20. include Legendary
  21. # Creates a unicorn with the specified number of *horns*.
  22. def initialize(@horns = 1)
  23. raise "Not a unicorn" if @horns != 1
  24. end
  25. # Returns the number of horns this unicorn has
  26. #
  27. # ```
  28. # Unicorn.new.horns # => 1
  29. # ```
  30. def horns
  31. @horns
  32. end
  33. # :ditto:
  34. def number_of_horns
  35. horns
  36. end
  37. # Makes the unicorn speak to STDOUT
  38. def speak
  39. puts "I'm a unicorn"
  40. end
  41. # :nodoc:
  42. class Helper
  43. end
  44. end