I think we’re all annoyed with this problem: when using Google’s Android libraries (for example, material for compose) you open the source code of some compose function and see this:
When I upgraded to compose 1.7.0-beta02
(Android Studio Koala 2024.1.1 RC 1), I was pleasantly surprised: the sample’s source code is now being correctly resolved and displayed!
I immediately started 🕵️ investigating how this feature works and what Google did to correctly display the source code of their samples in Android Studio, because I wanted to add this nice feature to the design system library I’m developing.
⚙️ How it works
Basically, the requirement is that you simply need to have the declarations mentioned in @sample
tags to be present in the sources.jar
file — a file that is distributed along with .pom
, .module
, .aar
, and other files through maven.
As it turns out, there is a very easy way to do this: just add this to build.gradle.kts
of the library module that you’re publishing to maven:
tasks.withType<SourceJarTask>() {
from(file("$rootDir/samples/src/main/kotlin"))
}
assuming that all the samples are placed in the
:samples
gradle module
That’s it!
However, it is up to you to make sure that sample sources do not have the same package name and simple name as some of the declarations in the main library, as it can cause a name collision. I suggest using a unique package name for all sources that is not used anywhere else in the main library.
🔍 How Google does it
Since I first noticed working samples in Google’s material for compose library and didn’t yet know how to replicate it, I searched in the AndroidX repo’s build files for answers.
Here’s what I found:
Many (if not all) of AndroidX libs are published with 2 sources.jar
files:
Job Offers
{
"name": "sourcesElements",
"attributes": {
"org.gradle.category": "documentation",
"org.gradle.dependency.bundling": "external",
"org.gradle.docstype": "sources",
"org.gradle.usage": "java-runtime"
},
"files": [
{
"name": "haptics-1.0.0-alpha01-sources.jar"
// ...
},
{
"name": "haptics-1.0.0-alpha01-samples-sources.jar"
// ...
}
]
}
One is sources.jar
and the other is samples-sources.jar
. How they achieve this seems non-trivial. Here are some links that seem relevant to this logic: one, two, three.
The solution I suggested at the beginning of this article is different from Google’s because it packages sample sources together with the library’s sources into one sources.jar
. Seems like there’s not much difference between these two approaches except the first one is simpler to implement.
🧰 IDE Support
Compose Android plugin for Android Studio contains support for resolving KDoc links to sample code that is not present in the java byte code, but present in the sources.jar
. Here it is.
🕑 Keeping samples up-to-date
If you add your :samples
module as a dependency to the demo app module, all samples will compile every time the demo app is launched, ensuring that samples will always remain up-to-date, as opposed to just directly writing Kotlin code in KDoc.
🖼️ Samples with images
Specifically in the context of creating samples for design system libraries, I would like to recommend adding images to KDoc of samples.
If you are already using screenshot testing in your design system, it’s very easy to upload these screenshots to something like GitHub/GitLab Pages and link to them in the KDoc of the composable functions.
Like in the material library:
BTW, to see images in KDoc, you can:
- Wait for this issue in the IntelliJ IDEA to be resolved
- Install the Kelp plugin 🔌
You can do the same with your samples: just add screenshot testing to your :samples
module, upload them to the web on CI, and add links to the pictures in KDoc of samples. This way, users can see what is the result of running any sample code without actually running it. This increases developer productivity, especially when the design system is new to users.
Happy coding! 👋
This article is previously published on proandroiddev.com