Chapter 8
Documenting Your Code with Scaladoc

Code documentation can take many forms, ranging from manually authored web pages, README.md files, and generated API docs to no documentation at all. The nature of the code and the intended audience have a role to play in choosing what is right for your project. Suppose you have decided to document your code using Scaladoc. What's next? In this chapter you will learn about how to use Scaladoc syntax and the associated tooling to create documentation from Scaladoc comments embedded in your source code.

To get started you need to know what can be documented and what the formatting and linking options are. You also need to be aware of the tooling options you can apply to generate the API docs. Once you have your documentation generated, you need to know what to do next to expose it to a wider audience.

You will also learn about the structure of Scaladoc, both at the source level and in the rendered form. What options exist for generating the documentation from the command line, or from Maven or SBT? What are the limits of wiki syntax? Examples in this chapter will illustrate these general rules.

WHY DOCUMENT YOUR CODE?

Lack of documentation is becoming a problem for acceptance.

Wietse Venema, creator of Postfix

Creating high quality useful documentation is a time consuming business. You might reasonably ask the question: Why bother? You have to decide where on the documentation continuum you want to land. Should you provide no documentation at all because the unit tests are adequate documentation? Or go with comprehensive documentation that has embedded REPL examples? Factors that feed into your decision include the type of project you are developing, the anticipated project lifecycle, any coding guidelines in force, the expected audience, and the cost of creating the documentation and taking it forward through project iterations. This section will help you make these decisions.

Revealing the Benefits

Scaladoc plays a critical role making your code accessible to others, particularly when the luxury of face-to-face contact is not an option. With a few concise words and pointed examples, you can orient the user and get them on a productive track. Scaladoc is an especially good choice for documenting library code. As an example of effective Scaladoc, take a look at the documentation for the Scala Standard Library Regex class (http://www.scala-lang.org/api/current/#scala.util.matching.Regex). With a handful of code examples linked with explanatory text, the class becomes immediately accessible.

Scaladoc is far from the only option for documentation. Some libraries flourish while eschewing Scaladoc almost entirely. Scaladoc sports the key advantage of being embedded in your code and supporting a simple wiki syntax. Nearly all documentation authoring can be accomplished without switching out of your IDE.

Bookending the Continuum

As a Scala developer you already have a good idea of what makes for useful documentation. This helps when you start authoring your own documentation.

Some projects, such as ScalaTest, are ahead of the documenation curve (http://doc.scalatest.org/2.2.6/index.html#org.scalatest.FlatSpec). But how is this layout achieved? You will find out later in this chapter. Let's first examine Scala documentation in general.

Choosing What to Document

Let's explore what type of documentation is useful. If you have coding guidelines that stipulate project documentation requirements then you'll want to use the remainder of this chapter to learn how to unleash the power of Scaladoc. If you have no guidelines, then consider creating a set of documentation objectives.

If, on the other hand, you are developing a library for others to use, you will need to determine if Scaladoc can form part of the adoption path for your end users. If you decide to take this route, later sections in this chapter cover the inclusion of examples in Scaladoc.

One final question to explore is whether you have the opportunity to add Scaladoc after development activities are complete. If the answer is no, then document the code incrementally as you develop it. An advantage of interlacing documentation and development is that there is less context switching. Even when your planned activities include a later documentation phase, you should evaluate bringing this forward and document as you code. The results are better and the net effort will be lower. Let's dive into Scaladoc and discover the many advantages of implementing it.

SCALADOC STRUCTURE

Scaladoc refers to three different things: the command line tool scaladoc, source code comments with wiki syntax and tags, and the generated documentation viewed in a browser. The meaning will normally be clear from the context. In this section you will see a breakdown of the structural elements of the generated documentation, and you will learn how to use the Scaladoc UI.

Overall Layout

The generated Scaladoc is a collection of HTML pages that can be viewed with a browser. The files can reside locally or they can be published on the web. Options for web publication are covered later in this chapter.

These are the files and directory you see after generating the documentation using the scaladoc command:

$ ls -1 scaladocs/
com/
deprecated-list.html
index/
index.html
index.js
lib/
package.html

Navigate to http://www.scala-lang.org/api/ and take a look at the overall layout of the page. You will see in Figure 8.1 how it is divided into two sections: the index pane and the content pane.

Snapshot of the overall layout of the page of Root Package.

Figure 8.1

The index pane is where you search the documentation. The content pane displays documentation grouped by class, trait, object or package. The UI is unsurprising to use, but investing a few minutes studying each element will pay off. Time to dive in.

Index Pane

Your entry point into the documentation is the index pane shown in Figure 8.2. This pane is partitioned into the search field, the full index, the kind filter, and finally the entities grouped under the package they belong to.

Snapshot of an index pane. This pane is partitioned into the search fi eld, the full index, the kind filter, and finally the entities grouped under the package they belong to.

Figure 8.2

Searching for Entities

When you type text into the search box, the list of entities is restricted. The filtering behavior differs based on the presence or not of capital letters in the search text (see Figure 8.3). When the query term is all lower case, the filter is case insensitive and contains a match on the fully qualified name of each entity.

This example shows packages, classes, and traits.

Snapshot of a text typed into the search box. Packages, classes, and traits are also shown.

Figure 8.3

Including one or more capital letters in the query term applies a camel case match (see Figure 8.4).

Snapshot of one or more capital letters in the query term typed in the search box.

Figure 8.4

The query box has a hidden feature in Scaladoc generated from Scala 2.11.7. Append a dollar to your query term and this works in the same way as if it were part of a regular expression. For example, Map$ will match AbstractMap not ImmutableMapFactory.

Indexing It All

Underneath the query box you will find a horizontal list of clickable letters bookended by a hash and the word deprecated (see Figure 8.5). Clicking any of these elements will show a listing of entities, methods, functions, and public and protected vals and vars.

Snapshot of a query box. A horizontal list of clickable letters bookended by a hash and the word deprecated is seen underneath the box.

Figure 8.5

When you click R you will see what is shown in Figure 8.6.

Snapshot of a query box with five entries acting as links to the entities that contain the entry.

Figure 8.6

Under each entry are links to the entities that contain the entry. You should be aware that when the default Scaladoc generation options are used, nested types will not be found from the query box. An example of this can be found in the Z section where Zero is shown contained in Duration, but querying for Z does not show Zero.

Occupying the next slot down you will encounter the kind filter. This toggles between hiding packages and not hiding them. This is useful when you are seeking an overview of the packages. Once you have arrived at the package of interest, click show to reveal the contained entities.

When you have restricted the display to packages, entering query text will automatically turn off the package restriction.

Figure 8.7 shows the index pane restricted by query text with some packages collapsed. This figure also serves to illustrate the entities type indicator: O for object, C for class, and T for trait. Two columns suffice for this as a class, and a trait cannot share the same name in the same package. The O, C, and P letters are clickable and navigate the content pane directly to the entity type. Clicking the entity name navigates to the class or trait unless there is only an object for the name.

Snapshot of an index pane restricted by query text with some packages collapsed.

Figure 8.7

Content Pane

The content pane is on the right (see Figure 8.8). After you have clicked on a package, class, trait, or object, information about the selected entity is displayed here. The pane is divided into three sections: top level information, filtering and ordering options, and entity member details. Each section is described in the following text. Before you step though the process of adding Scaladoc to the example project, a quick tour of the notable features of the content pane is in order. ParMap from the standard library has this documentation.

Snapshot of a content pane on the right.

Figure 8.8

Top-Level Information

Depending on what you select, you will be presented with information regarding a class, a trait, an object, or a package. The types of information that are shown depend on both the type of entity and the entity itself. Objects, for example, will not include a Known Subclasses section because objects do not have subclasses.

Starting from the top and working down you will see a large letter: O, C, T, or P denoting Object, Class, Trait, or Package respectively. Next to this is the entity name. The large letter is clickable. If you start at a class Foo, which has a companion object, clicking the C navigates to the object Foo, and the letter switches to O. One way to think about this is that clicking takes you to the next entity related by name if such an entity exists. There are a limited set of such relationships that can exist:

  • Class and Object
  • Trait and Object

Over to the right (see Figure 8.8) you find the label Related Docs: introducing links to the related entity if it exists and a link to the package the entity is in. Hover the mouse over the top right to reveal a hidden Scaladoc feature. A link icon appears. Right click and copy to obtain a link to use to navigate directly to the entity page you are currently on. Permalinks are also available for each entity member. See Figure 8.9 for an example.

Illustration depicting the label Related Docs page.

Figure 8.9

Following the entity name is the entity signature. This corresponds to the code you find in a source file without the template body. Class parameters, variance annotations, optional superclass, and mixins will be seen here. Hovering over a name will show the fully qualified version of the name.

Residing under the entity signature is the class, trait, object, or package level documentation. The text here is derived from the Scaladoc comments the author added to the entity before the entity header. Beneath the main comment are the type parameter comments, then the attribute block containing, in this case: Self Type, Source, and Since. Later you will see the full list of tags and wiki syntax you can use to directly control the content of the sections described in this paragraph.

Moving down from the attribute block you can see Linear Supertypes that show the supertypes in linearization order. Known Subclasses is self-explanatory. Type Hierarchy shows a view of the type hierarchy centered around the current entity. It shows the directly declared supertype and mixins, implicit views to other types, and some subclasses.

The boxes are clickable and will switch the content pane to the new entity. If you select a package, the Content Hierarchy will be shown. There is also a type hierarchy diagram that shows the entities contained directly in the package. Click the diagram to have it pop up in a larger window.

Filtering and Ordering Options

After the diagrams you are presented with controls for filtering and ordering the member documentation that occupies the remainder of the content pane. The first element is the query box.

Try this out:

  • Navigate to http://www.scala-lang.org/api/current/#package.
  • Use the index pane filter to filter by LL.
  • Pick LinkedList.
  • Enter head into the content pane query box. You will see method with head in the method name or description.
  • Add tail to the content page query box. The box now contains “head tail” and the listed members swells to include tail and a few other methods.
  • Replace the query box content with withFilter.

When you added tail into the query box, you saw a demonstration of the additive nature of the content pane query box. The query for withFilter included WithFilter in turn, demonstrating the case insensitivity of the content pane query. Remember, you saw that the index page search was case sensitive.

Underneath the query box are buttons controlling the ordering. This will be touched on momentarily. First a word about the Inherited buttons. Deselecting an inherited entity removes its member from display, but that's not the sum of it. There is valuable interaction with the query box to remember. For a member to show, it must satisfy the query box filter and be in an entity that is selected. Try this now:

  • Remain on LinkedList.
  • Enter ++ in the query box.
  • Note the presence of the ++ method.
  • Deselect TraversableLike.

++ is removed from view when TraversableLike is deselected.

The ordering options commonly seen are: Alphabetic, By Inheritance. There is another option that can be seen by navigating to the package documentation for scala.langauge, which is shown in Figure 8.10.

Snapshot of a box showing an option that is seen by navigating to the package documentation for scala.langauge.

Figure 8.10

You can see two groups in use: Language Features and Experimental Language Features. These groups are defined by Scaladoc tags. You will be finding out how to define your own groups later.

Entity Member Details

A member can be a constructor, a method, a type, a type alias, or a value. The documentation provided for each member will be covered in depth when you learn how to add Scaladoc yourself. Here, an important aspect of the alphabetic member ordering is described. Knowing the logic behind the default ordering will allow you to benefit more deeply from any API documentation you study.

Take a look at the documentation for Set from the Standard Library. In Alphabetic mode the members are grouped under Instance Constructors, Type Members, Abstract Value Members, Concrete Value Members, and Shadowed Implicit Value Members. Within each group the members are ordered alphabetically. If you were looking at an entity with a member for each category you would see the groups from Table 8.1.

Table 8.1 Entities by Category

Group Description
Instance Constructors Primary and auxiliary constructors.
Can included deprecated constructors.
Type Members Type aliases, traits and classes.
Can included deprecated members.
Abstract Value Members Abstract methods and values.
Can included deprecated members.
Value Members/Concrete Value Members Concrete methods and values.
Excludes shadowed implicit members and deprecated members.
When the Abstract Value Members group is not empty this group is called Concrete Value Members; otherwise it is Values Members.
Shadowed Implicit Value Members Shadowed or ambiguous implicits.
Excludes any deprecated members.
Deprecated Value Members Deprecated concrete value members.

The trait StringLike from the Standard Library uses five of the six alphabetic groups. See Figure 8.11.

Snapshot of a box showing the trait StringLike from the Standard Library using five of the six alphabetic groups.

Figure 8.11

Entity member information is included in this order: Instance Constructors, Type Members, Abstract Value Members, Value Members/Concrete Value Members, depending on presence of abstract value members, Shadowed Implicit Value Members, and Deprecated Value Members.

INVOKING THE SCALADOC TOOL

Scaladoc generation is realized at the command line by the scaladoc tool. In the following exercise you will create Scaladoc for Universe.scala, which is shown here:

package com.scalacraft.professionalscala.chapter8.cosmos

object Universe {
  type Cluster = String
  def getClusters: Seq[Cluster] = Nil
}

Create the Scaladoc for Universe.scala by following these steps:

Step 1. Open a command prompt.

Step 2. Change directory to professional-scala/src/main/scala/com/scalacraft/professionalscala/chapter8/cosmos.

Step 3. Invoke scaladoc passing the source files to process as arguments.

$ scaladoc -d output Universe.scala
model contains 7 documentable templates

Your Scaladoc is now generated and ready for viewing. List the output directory content first.

$ ls -1F output
com/
index/
index.html
index.js
lib/
package.html

Step 4. Now open index.html in a browser. You will be greeted with a complete set of Scaladoc for your one file project. This is shown in Figure 8.12.

Snapshot of open index.html in a browser. A complete set of Scaladoc for one file project is also seen.

Figure 8.12

WIKI SYNTAX

You can use wiki syntax to provide some visual flair to your documentation. The wiki syntax options are few and simple, and can be divided into two groups:

  • Inline formatting
  • Block elements

The following examples will take you through the essential techniques, leaving you with practical experience applicable to your everyday documentation tasks.

Formatting with Inline Wiki Syntax

Follow these steps to start your journey into the world of Scaladoc formatting. Start with some inline formatting examples.

If you would prefer not to enter the examples, but would still like to follow along, then you can use the source code present in the Git repo identified at the introduction section of the book.

Step 1: Create a class Galaxy in the same package as Universe,

package com.scalacraft.professionalscala.chapter8.cosmos

class Galaxy

Step 2: Add a class comment using each of the inline wiki syntax options:

/**
  * All inline styles: '''bold''', ''italic'', `monospace`, __underline__,
     ^superscript^, ,,subscript,,.
  */
class Galaxy

Step 3: Generate the Scaladoc from the command line, this time supplying a shell glob to identify all the source files in the current directory:

$ scaladoc -d output *.scala
model contains 8 documentable templates

Step 4: Load the Scaladoc for Galaxy in your browser and compare the outcome to Figure 8.13.

Illustration depicting the outcome achieved after loading the Scaladoc for Galaxy in browser.

Figure 8.13

Table 8.2 details the syntax for inline styling.

Table 8.2 Wiki Syntax and Effects

Wiki Syntax Effect
''' — three single quotes Embolden enclosed text
'' — two single quotes Italicize enclosed text
` — single backquote Monospace enclosed text
_ _ — two underscores Underline enclosed text
^ — single circumflex Superscript enclosed text
,, — two commas Subscript enclosed text

Nesting Inline Styles

Inline styles can be nested in the majority of cases as shown in Figure 8.14. One notable exception is the failure to nest bold inside italic where an extraneous single quote escapes into the page.

Snapshot of nested inline styles.

Figure 8.14

If you are interested to learn the details of Scaladoc parsing, clone the Scala GitHub repo and look at CommentFactoryBase.

The source for nested formatting examples is available from the GitHub repo as misc-examples/InlineNesting.scala.

Structuring with Block Elements

Now that you have worked with inline formatting, you can move on to the block element, which occupies the next level of the Scaladoc food chain. Block elements allow you to structure your documentation in several ways to enhance the presentation at a higher level. Again, wiki syntax is used to facilitate this (see Table 8.3). In this section you will extend Galaxy to include examples of each of the five block elements that are listed here:

  • Titles
  • Paragraphs
  • Code blocks
  • Lists
  • Horizontal rules

Table 8.3 Wiki Syntax for Block Types

Block Type Wiki Syntax Description Effect
Title =Title=
==Title==
===Title===
====Title====
Balanced equal signs surrounding text. Maximum of four equal signs. Produces a header. As more equal signs are added the header becomes smaller. Single equal signs produce a HTML h3 header, which is unfortunately hard to read, so please avoid. Use two, three, or four equal signs.
Paragraph A blank line - Starts a new paragraph.
Code {{{code example}}} Three opening and closing curly braces with code examples inside. Styles the code example to look like code using a monospace font and ignoring inline wiki syntax for the duration of the block.
List -, 1., A., a., i., I., A list item prefix that includes a trailing whitespace. This is described in Table 8.4.
Horizontal line ---- At least four hyphens on an otherwise blank line. Must be preceded by a blank line. Produces a horizontal bar.

Step 1: Return to Galaxy and extend the Scaladoc comment to match this:

package com.scalacraft.professionalscala.chapter8.cosmos

/**
  * All inline styles: '''bold''', ''italic'', `monospace`, __underline__,
      ^superscript^, ,,subscript,,.
  *
  * =Title 1: Introduction=
  *
  * Paragraph: A galaxy is a system of stars, gas and dust.
  *
  * Create a galaxy using the `new` keyword,
  * {{{
  *   /* Code example */
  *   val zeta = new Galaxy
  * }}}
  *
  * ----
  *
  * ==Title 2: Types==
  *
  * There are different types of galaxy,
  *
  *  - Elliptical
  *    A. Maffei 1
  *    A. Centaurus A
  *  - Spiral
  *    1. M100
  *    1. NGC 1365
  *    - Barred Spiral
  *      I. NGC 1300
  *      I. NGC 1073
  *  - Irregular
  *    i. PGC 18431
  *    i. IC 559
  *  - Lenticular
  *    a. Messier 84
  *    a. Cartwheel Galaxy
  */
class Galaxy

Step 2: Generate the Scaladoc from the command line:

$ scaladoc -d output *.scala
model contains 8 documentable templates

Step 3: Load the Scaladoc for Galaxy in your browser and compare the outcome to Figure 8.15.

Illustration depicting the outcome achieved after loading the Scaladoc for Galaxy in browser.

Figure 8.15

The wiki syntax options for lists deserves further explanation starting with whitespace indenting.

In the context of lists, wiki syntax whitespace is significant for lists. You should use two spaces per level. Examine the source for Galaxy and you will note there are two spaces between the asterisk and the hyphen that introduces the first item as shown here.

  *  - Elliptical

The subsequent indents also use two spaces. You can use other levels of indenting, but to avoid wasting time on a triviality, always use two spaces to indent lists.

Finally, lists can have unindexed or indexed items depending the choice of item prefix. Table 8.4 catalogs the available wiki syntax for list prefixes.

Table 8.4 Wiki Syntax for Lists

Prefix Description Result
- A hyphen followed by a space Bullets
1. The digit one, a period, and a space Numerical sequence: 1., 2., 3., …
I. The letter I, a period and a space Uppercase Roman numerals: I., II., III., iv., v., vi., …
i. The letter i, a period and a space Lowercase Roman numerals: i., ii., iii., iv., v., vi., …
A. The letter A, a period and a space Uppercase letters: A., B., C., …, Z., AA., AB., …
a. The letter a, a period and a space Lowercase letters: a., b., c., …, z., aa., ab., …
// @formatter:off
/**
 * My carefully formatted Scaladoc
 */

Linking

Scaladoc supports a compact wiki syntax for generating links. To include a link to a page anywhere on the web, you should enclose the link in square brackets followed by an optional label that the reader will see. The Scaladoc generated from the code below is shown in Figure 8.16.

/**
  * An external link: [[http://science.nasa.gov/astrophysics/]].
  *
  * An external link with a label:
    [[http://science.nasa.gov/astrophysics/ Astrophysics]].
  */
class ExternalLinks
Illustration depicting Scaladoc generated from a code.

Figure 8.16

You now have external links under your belt. Follow the next steps to learn how to link to objects, traits, classes, methods, specific overloads of methods, and types. These are known as entity links.

Step 1. Add the new class Starquake shown below. Make sure you use the correct package.

package com.scalacraft.professionalscala.chapter8.cosmos.phenom

import com.scalacraft.professionalscala.chapter8.cosmos.Magnetar
import Starquake.QuakeMagnitude

class Starquake(val magnitude: QuakeMagnitude)

object Starquake {
  /** The magnitude of a quake. */
  type QuakeMagnitude = Int
  def triggerStarquake(magnetar: Magnetar): Starquake = new Starquake(1)
}

Step 2. Add Magnetar in the package above with Scaladoc links to Starquake elements as shown here.

package com.scalacraft.professionalscala.chapter8.cosmos

/**
  * Magnetars are commonly found within a [[Galaxy]].
  *
  * Trigger a [[phenom.Starquake]] by calling
  * [[phenom.Starquake.triggerStarquake triggerStarquake on object Starquake]
  */
class Magnetar(galaxy: Option[Galaxy]

Step 3. Generate the Scaladoc and confirm that it appears as shown in Figure 8.17. Note, this time it is necessary to extend the scaladoc command arguments to include the new package phenom. Use this list of arguments for the remainder of this chapter unless otherwise advised.

$ scaladoc -d output *.scala phenom/*.scala
Illustration depicting the generated Scaladoc.

Figure 8.17

Test each link.

Step 4. Now imagine you have a requirement to allow the magnitude of the Starquake to be passed in. This results in a method overload. Add the new method on the Starquake object as shown here:

object Starquake {
  /** The magnitude of a quake. */
  type QuakeMagnitude = Int
  def triggerStarquake(magnetar: Magnetar): Starquake = new Starquake(1)
  def triggerStarquake(magnetar: Magnetar, magnitude: QuakeMagnitude): Starquake =
    new Starquake(magnitude)
}

Step 5. Generate the Scaladoc. You will encounter this warning:

Magnetar.scala:3: warning: The link target "phenom.Starquake.triggerStarquake" is
  ambiguous. Several members fit the target:
(magnetar: Magnetar, magnitude: QuakeMagnitude):
  Starquake in object Starquake [chosen
(magnetar: Magnetar): Starquake in object Starquake

The Scaladoc was created, but the method ambiguity is resolved using a strategy you were not consulted about.

Step 6. Fix this pernicious behavior by selecting the method overload precisely in Magnetar. Also add a link to the new method. See below for details.

/**
  * Magnetars are commonly found within a [[Galaxy]].
  *
  * Trigger a [[phenom.Starquake]] by calling
  * [[phenom.Starquake.triggerStarquake(magnetar:com.scalacraft.professionalscala
      .chapter8.cosmos.Magnetar)* triggerStarquake on object Starquake]] or
  * specifying the quake magnitude with
  * [[phenom.Starquake.triggerStarquake(magnetar:com.scalacraft.professionalscala
      .chapter8.cosmos.Magnetar,magnitude:com.scalacraft.professionalscala
         .chapter8
      .cosmos.phenom.Starquake.QuakeMagnitude)* triggerStarquake on object
        Starquake]
  */

Step 7. Generate the Scaladoc, confirm it resembles Figure 8.18, and check the links to the Starquake overloaded methods.

Illustration depicting the generated Scaladoc and links to the Starquake overloaded methods.

Figure 8.18

The Magnetars Scaladoc comment above requires some explanation. What is happening with those lengthy type references? You can use these rules to generate disambiguated links to your own overloaded methods,

  • Take the method signature from the source and remove all spaces.
  • Drop the result type.
  • Add an asterisk.
  • Convert the type to the fully qualified type, escaping periods with backslash.

A general theme with the syntax for links is that Scaladoc will make a best effort to find a target for a link which is convenient, but this helpfulness may have surprising outcomes. Test your Scaladoc in a browser.

You will find that this crib sheet (Table 8.5) will handle the majority of link types typically found within a Scaladoc corpus.

Table 8.5 Link types

You want to link to… Follow this format Note
A class or trait [[mypackage.Name! optional label]] The exclamation mark selects a class or trait over an object of the same name.
An object [[mypackage.Name$ optional label]] The dollar selects an object over a class or trait of the same name.
Overloaded methods on an object [[Target$.foo(z:Str* optional label]]
[[Target$.foo(z:Int* optional label]]
String and Int do not require a full package prefix. The amount of method signature prefix included can be minimized while preserving uniqueness.
Overloaded methods on a class or trait [[Target!.foo(z:Str* optional label]]
[[Target!.foo(z:Int* optional label]]
The same as the object example but showing the use of the exclamation mark for classes and traits.
A method with type parameters [[[[Target$.foo[A[_[_]]]* If square brackets are included in the method signature add additional layers of opening and closing square brackets to compensate.

Scaladoc links can be tricky to get right. To help with this, an extensive set of examples is provided in the code download for this chapter. Find the examples in misc-examples/links.scala. These examples have been adapted from a test case in the Scala source code. The original can be found at https://github.com/scala/scala/blob/2.11.x/test/scaladoc/resources/links.scala.

Locating Scaladoc

So far you have been adding and modifying Scaladoc on the top level type for the most part. Where else can Scaladoc be placed? Although Scaladoc comments can be added anywhere whitespace is allowed, comments will generate documentation if placed at these locations:

  • Before a class, trait, or object declaration
  • Before a package object declaration
  • Before a method, value, or variable declaration
  • Before an alias or abstract type declaration

See https://wiki.scala-lang.org/display/SW/Syntax for a more detailed account of this.

TAGGING

This section will take you through the documentation options realized through the use of tags and annotations. Because some tags can only apply to methods, the examples will be method-centric, although there will be exceptions.

Scaladoc tags naturally cluster into three groups that constitute the material you will explore in the following sections:

  • Everyday Tagging
  • Tagging for Groups
  • Advanced Tagging

Tags are implemented using a commercial at sign followed by a tag name. You have no doubt seen numerous usages of tags. @return is an example. You will meet the full set of tags over the course of the following sections.

Everyday Tagging

In this section you will add a class Star, apply relevant Scaladoc tags, and view the generated documentation. This will introduce you to the tags you will use most often in your day-to-day development activities.

Step 1. Add Star as shown here.

package com.scalacraft.professionalscala.chapter8.cosmos

/**
  * Luminous sphere of plasma held together by own gravity.
  * @see [[https://en.wikipedia.org/wiki/Plasma_(physics) Plasma (Wikipedia)]
  * @see Found in a [[Galaxy]
  * @author <Your Name Here>
  * @author [[https://github.com/janekdb Janek]
  * @version 13.8
  * @since 0.7
  * @todo Add `+(other: Star)` to model stellar collisions
  * @todo Add magnetic field
  * @constructor Construct a [[Star]] with the given radius
  * @param radius Initial star radius in metres
  */
class Star(var radius: Double) {

  /** @return The mass of this star in kg */
  def mass: Long = ???

  /**
    * Trigger stellar collapse.
    * @param delay Seconds to wait until collapse
    * @param blackhole If true skip white dwarf and neutron star stages
    * @throws IllegalArgumentException if `delay` is negative
    * @throws IllegalStateException if already a blackhole
    */
  def collapse(delay: Int, blackhole: Boolean): Unit = ???
}

Step 2. Generate the Scaladoc and review the output in a browser. Figure 8.19 shows the expected output. The search pane has been removed from the figure to save space.

Illustration depicting the generated Scaladoc output in a browser.

Figure 8.19

Tags fall into four groups with respect to the requirements of what must follow the tag. The simplest type of tag is the standalone tag, which is exemplified by @documentable. A standalone tag is essentially a flag. It is present or absent. You will cover an example of a standalone tag later in the form of @documentable. The next type of tag is the content tag. @since is a content tag. This type of tag expects content in the form of free text following the tag name. The penultimate type of tag is the symbol tag. This tag has a name followed by a symbol and then descriptive text. @param is an example of a symbol tag. For @param tags the expected symbol is the name of a method parameter. The last type of tag is a structured tag, exemplified by @contentDiagram. This type of tag imposes a syntax on the text that follows, which allows the effect of the tag to be controlled at a detailed level.

Table 8.6 explains the purpose of each tag you have used so far. You can use this as a quick reference.

Table 8.6 Tags and Their Purposes

Tag Type Example Purpose Cardinality
@author Content @author Janek Bogucki Identify author. Multiple
@constructor Content @constructor Construct a Star Document the primary constructor. At most one
@param Symbol @param blackhole If true skip early stages Describe the purpose of the named parameter. At most one per method parameter
@return Content @return The predicted value Document the return value. At most one
@see Content @see [[Starquake]] Point to additional material including other classes or entities, or external links. Multiple
@since Content @since 1.4.14 Version the entity was introduced in. Include @version if using this. At most one
@throws Symbol @throws IndexOutOfBoundsException when an attempt was made to index outside of the allowed range Surface the thrown exceptions a user might need to know about. The description is optional. At most one per thrown exception type
@version Content @version 1.6.18 The version of a system or API this entity is part of. At most one
@todo Content @todo Handle lower boundary case Document gaps in implementation. Multiple

In terms of deciding where to place tags, assume Scaladoc follows the principle of least surprise. Combine this with a tight review cycle on the generated Scaladoc and you won't often be surprised.

Before you learn how to group methods and other entities using the @group family of tags, there are a few more everyday tags to check over. Return to Star and follow these steps.

Step 1. Add the freeze method to the end of the class as shown here.

/**
  * Use some freezers to freeze sunspots.
  * @example
  * {{{
  *   val star = …
  *   val freezers = List.fill(63)(new Icecube)
  *   val partiallySpentFreezers = star.freezeSunspots(freezers)
  * }}}
  * @note Do not call if collapsed
  * @note Following this the radius will be reduced
  * @tparam T A type that `freeze` can use to freeze a sunspot
  * @param freezers
  * @param freeze A function to freeze a sunspot on a star given a freezer
  * @return The freezers minus any used freezing capacity
  */
@deprecated("Use SolarKit instead", "14.0")
def freezeSunspots[T](freezers: List[T], freeze: (Star, T) => T): List[T] = ???

Step 2. Generate the Scaladoc and review the output in a browser. Figure 8.20 shows the expected output. Only the new method is shown to avoid repetition.

Snaphot showing the Scaladoc output.

Figure 8.20

Notice the threefold impact of annotating with @deprecated. The method appears in the Deprecated Value Members section at the end of the page, the deprecation version and comment are shown, and as part of the generic handling of annotations, the annotation is listed in the Annotations section.

Table 8.7 explains the purpose of the newly introduced tags.

Table 8.7 Newly Introduced Tags and Their Purpose

Tag Type Example Purpose Cardinality
@example Content @example {{{val zeta = …}}} Add an example into the examples section. The wiki syntax for code blocks in example is optional, but often appropriate. Multiple
@note Content @note The option must be non empty. Document requirements, restrictions, pre and post conditions. Multiple
@tparam Symbol @tparam T Type of values handled by this pickler. Document a type parameter. At most one per type parameter

Member Permalinks

Go to any member and hover over the top right of the documentation. Right click and copy to get a deep link directly to the method. This is illustrated in Figure 8.21.

Snaphot showing a member and documentation on the top right.

Figure 8.21

Tagging for Groups

Now you have mastered the common fare of Scaladoc tagging, so it is time to ascend to more rarefied strata. In this section you will create a class that demonstrates the use of Scaladoc groups that allow related members of an entity to be collected together.

Step 1. Add the class shown here to the project.

 package com.scalacraft.professionalscala.chapter8.cosmos

/**
  * Star Types with examples.
  *
  * @groupname Type-O Star Type 0
  * @groupdesc Type-O Blue, average solar mass: 60
  * @groupprio Type-O 10
  *
  * @groupname Type-B Star Type B
  * @groupdesc Type-B Blue, average solar mass: 18
  * @groupprio Type-B 20
  *
  * @groupname Type-K Star Type K
  * @groupdesc Type-K Orange to Red, average solar mass: 0.8
  * @groupprio Type-K 30
  */
trait StarTypes {

  /** @group Type-O */
  val `10 Lacertra`: Star

  /** @group Type-B */
  val Rigel: Star

  /** @group Type-B */
  val Spica: Star

  /** @group Type-K */
  val Arcturus: Star

  /** @group Type-K */
  val Aldebaran: Star
}

Step 2. Generate the Scaladoc and review the output in a browser. To take maximum advantage of the group tags the -groups option must be supplied. Without this, the Grouped button will be missing from the Ordered section.

$ scaladoc" -d output -groups *.scala phenom/*.scala

Figure 8.22 shows the expected output. You can see vals have been listed under the group descriptions corresponding to the given @group tag. Try switching between Grouped and Alphabetic.

Snaphot showing the Scaladoc output.

Figure 8.22

Table 8.8 explains the purpose of the group tags.

Table 8.8 The Group Tags

Tag Type Example Purpose Cardinality
@group Symbol @group InfoSec Indicate the tagged entity is in the named group. At most one
@groupname Symbol @groupname InfoSec The information security API. Provide a label of the group. Appears in green bar before group description. At most one per group
@groupdesc Symbol @groupdesc InfoSec This API handles the security aspects of the system. For example: {{{ val pki = … }}} Add descriptive text to be used under group name. Can include wiki syntax and extend over several lines. At most one per group
@groupprio Symbol @groupprio InfoSec -100 Associate a relative position with a group. If group A has a lower priority value than group B, then group A appears before group B. At most one per group

Advanced Tagging

You have arrived at the advanced Scaladoc tags, some of which you will try out with a few more code additions. To start with you will see how to place a simplifying lens onto any method signature no matter how hieroglyphically rich it is, how to not repeat yourself, and how to elevate nested entities to first class citizens in the context of documentation. Following that, you will gain insight into tags that control documentation at a higher level.

Seeing, hearing, feeling, are miracles, and each part and tag of me is a miracle.

—“SONG OF MYSELF,” WALT WHITMAN

Follow these steps to get a feel for the possibilities of @define, @usecase, and @documentable.

Step 1. Add the code from the code listing below into Planet.scala. This is the Scaladoc before you fully augment it with the new tags. A macro expansion Body is defined in Terraformable and used in the @return tag. You will see the utility of this when you extend the Scaladoc with @inheritdoc.

package com.scalacraft.professionalscala.chapter8.cosmos

/**
  * @define Body Terraformable
  */
trait Terraformable[T] {

  /**
    * Create a terraformed copy of this $Body.
    * @param tfs A collection of [[Terraformer]]s to apply in order
    * @return A terraformed copy of this $Body
    */
  def terraform[P1 >: T, P2 <: T](implicit tfs: Seq[Terraformer[P1, P2]]): T
}

trait Terraformer[T, U] {
  def terraform[U <: T](body: T): U
}

class Planet extends Terraformable[Planet] {

  /**
    * A specialised kind of [[Planet]
    **/
  type SpecialisedPlanet <: Planet

  /**
    * Create a new world from this planet.
    * @note May result in mass extinction of existing life
    */
  def terraform[P1 >: Planet, SpecialisedPlanet
    (implicit tfs: Seq[Terraformer[P1, SpecialisedPlanet]]): Planet = ???
}

Step 2. Generate the Scaladoc and review the output in a browser. Figure 8.23 shows the expected output.

Illustration depicting the generated Scaladoc output in a browser.

Figure 8.23

You should make note of the following aspects of the terraform method documentation before you add the new tags, an action that will change each of these points.

  • The @return and @param tags are inherited from the Terraformable trait.
  • The @return comment mentions Terraformable.
  • The terraform method comment from Terraformable trait is missing.
  • The SpecialisedPlanet type alias is not a hyperlink.
  • The terraform method signature is very busy with implicits and type parameters—not great if you have an entire planetary system to get done.

Step 3. Edit Planet by adding a redefinition of the Body macro into the class comment, a @documentable tag on the type alias, and @inhertdoc on the terraform method as shown below.

/**
  * @define Body ''candidate'' colony world
  */
class Planet extends Terraformable[Planet] {

  /**
    * A specialised kind of [[Planet]
    * @documentable
    **/
  type SpecialisedPlanet <: Planet

  /**
    * @inheritdoc
    * Create a new world from this planet.
    * @note May result in mass extinction of existing life
    */
  def terraform[P1 >: Planet, SpecialisedPlanet
    (implicit tfs: Seq[Terraformer[P1, SpecialisedPlanet]]): Planet = ???
}

Step 4. Generate the Scaladoc. Figure 8.24 shows the expected documentation.

Illustration depicting the documentation following Scaladoc generation.

Figure 8.24

Now review the differences.

  • The inherited @return comment now mentions “candidate colony world” instead of Terraformable.
  • The terraform comment from Terraformable is now present beneath the comment defined in Planet. Remember, this was defined as “Create a terraformed copy of this $Body.” @inheritdoc contributed to this change.
  • The effect of the redefinition of the Body macro can be seen in both the @return comment and the method comment.
  • Macro definitions can contain wiki syntax.

The SpecialisedPlanet type alias is now a hyperlink.

Click SpecialisedPlanet to see that an entire page has been created as a consequence of placing @documentable tag on the type alias. The page header is shown in Figure 8.25.

Snaphot showing the page header pane.

Figure 8.25

Next, you will use @usecase to simplify the terraform method signature.

Edit Planet once more.

Step 1. Modify the comment on the terraform method as shown here.

/**
  * @inheritdoc
  * @usecase def terraform: Planet
  * Create a new world from this planet.
  * @inheritdoc
  * @note May result in mass extinction of existing life
  */
def terraform[P1 >: Planet, SpecialisedPlanet
  (implicit tfs: Seq[Terraformer[P1, SpecialisedPlanet]]): Planet = ???

Generate the Scaladoc. Figure 8.26 shows the new documentation of the terraform method.

Snapshot of new documentation of the terraform method.

Figure 8.26

The key differences are the introduction of the simplified method signature and the demotion of the full signature down into two collapsible sections. With details on demand your API documents will be simple to scan through while still providing the full signature for those sufficiently motivated to enquire more deeply.

To conclude this section you will briefly check out the diagramming related tags: @contentDiagram and @inheritanceDiagram. SVG-based inheritance and content diagrams are created by scaladoc when the -diagrams flag is supplied. You have two types of diagrams at your disposal:

  • Content for showing contained entities
  • Inheritance for showing inheritance relationships

Take a look at an example of a content diagram here: http://www.scala-lang.org/api/2.11.7/scala-reflect/index.html#scala.reflect.api.Symbols. The effects of using @contentDiagram in the main comment for Symbol are shown in Figure 8.27.

Illustration depicting the effects of using @contentDiagram in the main comment for Symbol.

Figure 8.27

The diagram shows the type aliases contained in the Symbols trait. Here is an excerpt from Symbols corresponding to the types on display in Figure 8.27.

  type Symbol >: Null <: AnyRef with SymbolApi
  type TypeSymbol >: Null <: TypeSymbolApi with Symbol
  type TermSymbol >: Null <: TermSymbolApi with Symbol
  type MethodSymbol >: Null <: MethodSymbolApi with TermSymbol
  type ModuleSymbol >: Null <: ModuleSymbolApi with TermSymbol
  type ClassSymbol >: Null <: ClassSymbolApi with TypeSymbol

By default packages and objects will get content diagrams. For traits and classes you will need to add the tag.

Inheritance diagrams are generated by default for traits and classes, but when you require fine grained control of the inheritance diagrams, @inheritanceDiagram can be added to allow exclusionary specifiers to be added. These can be used to remove distracting elements for the diagram. As an example, suppose you wanted to omit superclasses from your diagrams. You can add hideSuperclasses to the tag as shown here to achieve that.

/**
* @inheritanceDiagram hideSuperclasses
*/
class ExampleClass extends Example2 with Example3

You can use these specifiers with @contentDiagrams as well. The specifiers you can use are:

  • hideNodes
  • hideDiagram
  • hideOutgoingImplicits
  • hideSubclasses
  • hideEdges
  • hideIncomingImplicits
  • hideSuperclasses
  • hideInheritedNodes

Consult the Scala source code for examples of how to use these options.

Table 8.9 summarizes the purpose of the advanced tags.

Table 8.9 Advanced Tags

Tag Type Example Purpose Cardinality
@define Symbol @define sideEffects This method has side effects. You have been __warned__!
/** $sideEffects */
def deleteOcean: Unit
Create a named block of wiki syntax text to expand when $<name> is encountered. At most one per comment per macro name. Can be redefined closer to point of use
@inheritdoc Standalone @inheritdoc Extend the documentation inheritance that is applied by default covering certain tags to also include main comment inheritance. At most one per comment
@documentable Standalone @documentable Generate an additional documentation page for the tagged type alias. At most one per type alias
@template Standalone @template Identical to @documentable. At most one per type alias
@usecase Symbol @usecase def terraform: Planet
<Plus alternative versions of other tags>
Substitute a hand crafted, simplified account of the method signature. Nest full method definition down into method documentation body. At most once per method comment.
@contentDiagram Structured @contentDiagram hideNodes “*Api” Create content diagram for entities that do not have this type of diagram by default. Can also be used to prevent diagram creation. At most one per containing entity
@inheritanceDiagram Structured @inheritanceDiagram hideEdges(“*E” -> “*A”) Create an inheritance diagram for entities that do not have this type of diagram by default. Can also be used to prevent diagram creation. At most one per entity

INVOKING SCALADOC: ADDITIONAL OPTIONS

You have seen how to specify Scaladoc within your source code. Your users are already lauding your handsomely documented project, but that is not the end of it. There are a number of useful scaladoc command line options you can incorporate into your tool chest to provide your efforts with a fine edge (see Table 8.10). This section picks out some of those options not already covered.

Table 8.10 scaladoc Command-Line Options

Option Example Purpose
-doc-footer <footer> -doc-footer ‘Copyright 2018 – H. W. Olbers’ Add a footer to each page. By default there is no footer.
-doc-root-content <path> -doc-root-content docroot.txt Provide content for the Scaladoc landing page. Can include wiki syntax.
-doc-title <title> -doc-title ‘Cosmic Toolkit’ Set title. Visible as browser window or tab title.
-doc-version <version> -doc-version '13.8' Append the version to the title.
-skip-packages ≪package1>:…:<packageN≫ -skip-packages com.example.internal Do not include the nominated packages in the generated Scaladoc. Useful if you have packages users do not need to be aware of.

INTEGRATING SCALADOC CREATION WITH YOUR PROJECT

Although you have been generating Scaladoc by the direct execution of the scaladoc command line tool, which is fine for tutorial purposes, you can integrate documentation creation directly into your build tool or project management tool. In this section you will see how to configure Maven via a POM, and how to achieve the same thing with SBT. If you have not already studied the SBT and Maven chapters, now would be a good point to do so.

Configuring Maven

Provided you have already configured scala-maven-plugin, you can generate the Scaladoc via a Maven goal. Execute this code and then browse to target/site/scaladocs/index.html:

$ mvn scala:doc

If you need to elevate the structure around your build process, then adding a suitable plugin configuration will trigger Scaladoc generation during the Maven site phase. Take the configuration in the code below and add this into the project/build/plugins elements alongside the scala-maven-plugin configuration:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-site-plugin</artifactId>
    <version>3.4</version>
    <configuration>
        <reportPlugins>
            <plugin>
                <artifactId>maven-project-info-reports-plugin</artifactId>
                <version>2.8.1</version>
            </plugin>
            <plugin>
                <groupId>net.alchim31.maven</groupId>
                <artifactId>scala-maven-plugin</artifactId>
                <version>3.2.2</version>
                <configuration>
                    <jvmArgs>
                        <jvmArg>-Xms64m</jvmArg>
                        <jvmArg>-Xmx1024m</jvmArg>
                    </jvmArgs>
                    <args>
                        <arg>-doc-footer</arg>
                        <arg>${copyright}</arg>
                        <arg>-groups</arg>
                        <arg>-doc-title</arg>
                        <arg>Cosmic Toolkit</arg>
                    </args>
                </configuration>
            </plugin>
        </reportPlugins>
    </configuration>
</plugin>

Now you can generate your Scaladoc with Maven, either from within the comfort of your IDE, or on the CLI as shown here.

$ mvn site

As before, the root page is located at target/site/scaladocs/index.html. The site goal will also generate additional project documentation unrelated to Scaladoc.

Configuring SBT

SBT supports a doc task that generates Scaladoc from your source files. If you are new to SBT, review the SBT chapter and an introduction to SBT in general. For now it's enough to add the minimal project file shown here to the module root level (chapter-8/):

lazy val root = (project in file(".")).
  settings(
    name := "Cosmic Toolkit",
    version := "0.1.0-SNAPSHOT",
    scalaVersion := "2.11.7"
  )

val copyright = "Janek Bogucki 2015"
scalacOptions in (Compile,doc) ++=
  Seq("-doc-footer", copyright, "-groups", "-doc-title", "Cosmic Toolkit")

With that in place, call the doc task from SBT:

$ sbt doc

This will generate the same Scaladoc as the Maven configuration.

PUBLISHING SCALADOC

You have your Scaladoc sitting under target/site/scaladocs. The next step is to publish this on the web. By virtue of being a collection of static pages, there are few requirements on the web hosting solutions. If you already have a web site you can upload the pages to that. Amazon Web Services S3 is another way to publish static web sites with moderately little effort. In this section you will see how to use GitHub pages to bring your documentation to the wider world.

Step 1. Create the documentation using Maven.

$ mvn clean scala:doc
$ ls -xF target/site/scaladocs/
com/  deprecated-list.html  index/  index.html
index.js  lib/  package.html  scala/

Step 2. Create and checkout a branch called gh-pages. The --orphan option creates a branch with no parent commit, which makes for a simpler publication history.

$ git checkout --orphan gh-pages
Switched to a new branch 'gh-pages'

Step 3. Replace the top level content of the repo with the generated Scaladocs.

$ mv * /tmp
$ cp -a /tmp/target/site/scaladocs/* .

Step 4. Commit and push the documentation to the remote repo:

$ git add --all .
$ git commit -m'Publish Scaladocs'
$ git push --set-upstream origin gh-pages

Step 5. Browse your new Scaladoc site. Navigate to <username>.github.io/<project-name>. You will be greeted by the index page.

In this example you have seen a minimized version of the process that covers the primitives required to get the documentation up onto GitHub pages.

As your project develops and goes through releases, you will want to consider a longer term strategy that allows different versions of the documentation to coexist. You can also take advantage of the open ended nature of GitHub pages to attain that goal. An example that accommodates multiple versions of documentation corresponding to different releases is shown in Figure 8.28. Going beyond that there is no restriction on just publishing documentation, but that is the focus here.

Illustration depicting multiple versions of documentation corresponding to different releases.

Figure 8.28

TABLES AND CSS

Wiki markdown syntax is sufficient for many presentation purposes, and when combined with headers, paragraphs, code blocks, and bulleted lists, the structural aspects of the documentation can be lifted considerably. However, there is no support for tabular presentation of information, and with this structural workhorse missing from the stables there is a big gap to fill. So saddle up, you will shortly be solving this problem.

The solution is actually straightforward. Scaladoc defines a subset of HTML tags that are passed though unchanged. The full list of supported tags is shown in Table 8.11.

Table 8.11 Supported Tags in Scaladoc

abbr
acronym
address
area
a
bdo
big
blockquote
br
b
caption button
cite
code
col
colgroup
dd
del
dfn
fieldset
form
hr em
img
input
ins
i
kbd
label
legend
map
object
optgroup
link
option
param
pre
q
samp
small
span
strong
sub
sup select
table
tbody
td
textarea
tfoot
th
thead
tr
tt
var

Try out the tables tags by following the steps below.

Step 1. Add the StarSurvey object shown here.

package com.scalacraft.professionalscala.chapter8.cosmos

/**
  * <table style="border-collapse: collapse; border: 1px solid black">
  *   <caption>Star Data</caption>
  *   <colgroup>
  *     <col style="background-color:LemonChiffon"/>
  *     <col style="background-color:Gold"/>
  *     <col style="background-color:HoneyDew"/>
  *   </colgroup>
  *   <tr>
  *     <th style="background-color: #4CAF50; color: white">Name</th>
  *     <th style="background-color: #4CAF50; color: white">Absolute Magnitude</th>
  *     <th style="background-color: #4CAF50; color: white">Distance (parsecs)</th>
  *   </tr>
  *   <tr>
  *     <td>Arcturus</td>
  *     <td>-0.31</td>
  *     <td>11.25</td>
  *   </tr>
  *   <tr>
  *     <td>Vega</td>
  *     <td>0.58</td>
  *     <td>7.7561</td>
  *   </tr>
  *   <tr>
  *     <td colspan="3" style="background-color: #CCCCCC">
  *     Source: http://www.astronomynotes.com/starprop/s4.htm
  *     </td>
  *   </tr>
  * </table>
  */
object StarSurvey

Step 2. Build the Scaladoc.

$ mvn clean scala:doc

Step 3. Confirm your Scaladoc now includes the table shown in Figure 8.29.

Snapshot of Scaladoc with a table.

Figure 8.29

With your documentation now enriched with tables, your users will be delighted, but there is a price to pay. Your Scaladoc is now considerably noisier than when it only used markdown. This has a development cost that you should evaluate when deciding to break free from markdown.

/**
  * <img src="http://goo.gl/y7N1TH">
  */

SUMMARY

Voluminous documentation is part of the problem, not part of the solution

—Tom DeMarco

Although it is possible to produce and consume Scaladoc without a user guide, there are aspects that are not easily discovered through everyday use. Lifting the lid on Scaladoc reveals powerful features and options for both the author and the reader. There is no Scaladoc specification to peruse. Scaladoc is defined through implementation, allowing for rapid innovation but bringing the perils of never quite knowing for sure what should and should not be possible.

The Scala Language source code is the primary source of exemplar Scaladoc. You should clone it and take a look. If you are working with SBT, then ScalaTest is a project that demonstrates the levers to pull to coerce Scaladoc to your exact needs.

With out-of-the-box support for grouping methods and values, and factoring out repetition with macros, you can produce extensive documentation that is also well structured and low maintenance. By reviewing your generated Scaladoc as you author it, you can strengthen your documentation prowess and find surprising outcomes earlier rather than later. Always test your Scaladoc links.

Maven and SBT have support for Scaladoc generation. Adding a documentation generation mode to your build allows you to concentrate on the more interesting activities and avoid documenting the process for generating the documentation.

With generated Scaladoc in hand you can publish to the web with negligible effort using GitHub pages. This will expose your inline markdown outcomes to the world, or if you elected to whip out the power tools, your glorious HTML and CSS tables.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.255.87