1## Sample code in Kotlin modules
2
3### Background
4
5Public API can (and should!) have small corresponding code snippets that
6demonstrate functionality and usage of a particular API. These are often exposed
7inline in the documentation for the function / class - this causes consistency
8and correctness issues as this code is not compiled against, and the underlying
9implementation can easily change.
10
11KDoc (JavaDoc for Kotlin) supports a `@sample` tag, which allows referencing the
12body of a function from documentation. This means that code samples can be just
13written as a normal function, compiled and linted against, and reused from other
14modules such as tests! This allows for some guarantees on the correctness of a
15sample, and ensuring that it is always kept up to date.
16
17### Enforcement
18
19There are still some visibility issues here - it can be hard to tell if a
20function is a sample, and is used from public documentation - so as a result we
21have lint checks to ensure sample correctness.
22
23Primarily, there are three requirements when using sample links:
24
251.  All functions linked to from a `@sample` KDoc tag must be annotated with
26    `@Sampled`
272.  All sample functions annotated with `@Sampled` must be linked to from a
28    `@sample` KDoc tag
293.  All sample functions must live inside a separate `samples` library
30    submodule - see the section on module configuration below for more
31    information.
32
33This enforces visibility guarantees, and make it easier to know that a sample is
34a sample. This also prevents orphaned samples that aren't used, and remain
35unmaintained and outdated.
36
37### Sample usage
38
39The follow demonstrates how to reference sample functions from public API. It is
40also recommended to reuse these samples in unit tests / integration tests / test
41apps / library demos where possible to help ensure that the samples work as
42intended.
43
44**Public API:**
45
46```
47/*
48 * Fancy prints the given [string]
49 *
50 * @sample androidx.printer.samples.fancySample
51 */
52fun fancyPrint(str: String) ...
53```
54
55**Sample function:**
56
57```
58package androidx.printer.samples
59
60import androidx.printer.fancyPrint
61
62@Sampled
63fun fancySample() {
64   fancyPrint("Fancy!")
65}
66```
67
68**Generated documentation visible on d.android.com / within Android Studio**
69
70```
71fun fancyPrint(str: String)
72
73Fancy prints the given [string]
74
75<code>
76 import androidx.printer.fancyPrint
77
78 fancyPrint("Fancy!")
79<code>
80```
81
82Warning: Only the body of the function is used in generated documentation, so
83any other references to elements defined outside the body of the function (such
84as variables defined within the sample file) will not be visible. To ensure that
85samples can be easily copy and pasted without errors, make sure that any
86references are defined within the body of the function.
87
88### Module configuration
89
90The following module setups should be used for sample functions:
91
92**Per-module samples**
93
94For library groups with relatively independent sub-libraries. This is the
95recommended project setup, and should be used in most cases.
96
97Gradle project name: `:foo-library:foo-module:foo-module-samples`
98
99```
100foo-library/
101  foo-module/
102    samples/
103```
104
105**Group-level samples**
106
107For library groups with strongly related samples that want to share code and be
108reused across a library group, a singular shared samples library can be created.
109In most cases this is discouraged - samples should be small and show the usage
110of a particular API / small set of APIs, instead of more complicated usage
111combining multiple APIs from across libraries. For these cases a sample
112application is more appropriate.
113
114Gradle project name: `:foo-library:foo-library-samples`
115
116```
117foo-library/
118  foo-module/
119  bar-module/
120  samples/
121```
122
123**Samples module configuration**
124
125Samples modules are published to GMaven so that they are available to Android
126Studio, which displays referenced samples as hover-over pop-ups.
127
128To achieve this, samples modules must declare the same MavenGroup and `publish`
129as the library(s) they are samples for.
130