Komentar biasa // dari Chapter sebelumnya hanya terlihat oleh orang yang membuka source code. Begitu crate kita dipakai orang lain — atau bahkan dipakai diri sendiri dari proyek berbeda — catatan internal tersebut tidak pernah sampai ke pembaca: mereka melihat fungsi pub tanpa penjelasan, menebak makna parameter dari namanya, dan tidak punya contoh cara memanggilnya. Rust menjawab kebutuhan ini dengan doc comment ///, komentar yang sengaja ditulis agar diproses menjadi dokumentasi API. Materi testing sudah menunjukkan bahwa blok kode di dalam doc comment ikut dijalankan sebagai doc test; Chapter ini memperluas penggunaannya ke seluruh item publik — fungsi, struct, field, hingga modul — dan menegaskan aturan menempelnya doc comment pada item.
Aturan: /// Menempel pada Item di Bawahnya #
Doc comment dibuka dengan tiga garis miring /// dan berlaku untuk tepat satu item — item pertama yang muncul setelah komentar tersebut berakhir. Item yang layak didokumentasikan dengan /// meliputi fungsi, struct, field struct, enum, variant enum, trait, method di blok impl, hingga modul. Isi doc comment ditulis dalam format Markdown: kita bisa memakai teks tebal dengan **teks**, kode inline dengan backtick, heading dengan #, dan blok kode berpagar.
Bedanya dengan komentar biasa bersifat fundamental: // dibuang lexer dan hilang selamanya, sedangkan /// disimpan sebagai atribut #[doc = "..."] pada item oleh compiler. Karena tersimpan sebagai bagian dari item, teks tersebut dapat dikumpulkan oleh alat rustdoc — mesin pembangkit dokumentasi yang akan kita kenal lebih dekat pada Chapter rustdoc dan cargo doc. Karena /// melekat pada item, penempatannya juga dijaga ketat oleh compiler, sebagaimana akan kita lihat pada bagian penutup Chapter ini.
Mekanisme: rustdoc Mengekstrak, Markdown Menjadi HTML #
Saat cargo test atau cargo doc berjalan, rustdoc memindai seluruh atribut #[doc] hasil parsing, menggabungkan potongan /// yang berurutan menjadi satu dokumen Markdown per item, lalu memrosesnya dalam dua jalur. Jalur pertama merender Markdown menjadi halaman HTML — paragraf pertama doc comment berperan sebagai ringkasan singkat yang muncul di daftar item dan hasil pencarian. Jalur kedua mengekstrak setiap blok kode berpagar di dalam doc comment dan membungkusnya menjadi program kecil yang dikompilasi sebagai pengguna eksternal crate — inilah doc test yang sudah kita jalankan pada section testing. Dengan mekanisme ini, dokumentasi, contoh, dan test bertemu di satu tempat: contoh yang salah otomatis gagal di cargo test.
Contoh: Mendokumentasikan Struct dan Fungsinya #
Buat proyek library baru dengan cargo new gudang --lib, lalu isi src/lib.rs berikut:
/// Menyimpan data satu barang di gudang.
///
/// Struct ini dipakai untuk mencatat **nama barang**, jumlah unit, dan
/// lokasi rak penyimpanan.
pub struct Barang {
/// Nama barang, contohnya `"Kopi Arabika"`.
pub nama: String,
/// Jumlah unit barang yang tersedia di gudang.
pub jumlah: u32,
/// Kode lokasi rak, contohnya `"A-07"`.
pub rak: String,
}
/// Menghitung total nilai stok satu barang.
///
/// Nilai dihitung dengan mengalikan `jumlah` barang dengan `harga_satuan`.
///
/// # Examples
///
/// ```
/// let kopi = gudang::Barang {
/// nama: String::from("Kopi Arabika"),
/// jumlah: 10,
/// rak: String::from("A-07"),
/// };
///
/// let total = gudang::nilai_stok(&kopi, 25_000);
/// assert_eq!(total, 250_000);
/// ```
pub fn nilai_stok(barang: &Barang, harga_satuan: u32) -> u32 {
barang.jumlah * harga_satuan
}Jalankan test untuk memastikan contoh di documentation benar-benar dieksekusi:
cargo testOutput yang Dihasilkan:
Compiling gudang v0.1.0 (/tmp/w5b-dokitem)
Finished `test` profile [unoptimized + debuginfo] target(s) in 0.14s
Running unittests src/lib.rs (target/debug/deps/gudang-ca9262378e0c3a18)
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
Doc-tests gudang
running 1 test
test src/lib.rs - nilai_stok (line 22) ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
all doctests ran in 0.14s; merged doctests compilation took 0.14sLaporan Doc-tests gudang menunjukkan satu test bernama src/lib.rs - nilai_stok (line 22) lulus — contoh di doc comment terbukti hidup. Mari kita bedah kode di atas:
- Baris 1-4 (
/// Menyimpan data satu barang ...): doc comment empat baris untuk structBarang. Paragraf pertama (Menyimpan data satu barang di gudang.) menjadi ringkasan singkat yang tampil di daftar item; paragraf kedua masuk ke halaman detail. - Baris 4-5 (
pub struct Barang {): struct yang menjadi pemilik doc comment — hanya satu item di bawah komentar yang didokumentasikan. - Baris 6, 9, dan 12 (
/// Nama barang...,/// Jumlah unit...,/// Kode lokasi...): doc comment per field publik. Praktik ini penting karena setiap fieldpubadalah bagian dari API — pembaca struct perlu tahu format nilai yang diharapkan. - Baris 16-18 (
/// Menghitung total nilai stok satu barang.): doc comment fungsinilai_stokdengan penjelasan mekanisme perhitungan. Kata`jumlah`dan`harga_satuan`dalam backtick dirender sebagai kode inline di HTML. - Baris 20 (
/// # Examples): heading Markdown di dalam doc comment. rustdoc merendernya sebagai section tersendiri di halaman dokumentasi fungsi; konvensi section standar ini akan kita bahas tuntas pada Chapter Bagian Dokumentasi Standar. - Baris 22-31 (blok kode berpagar di dalam doc comment): blok ``` di dalam
///adalah doc test. Rustdoc membungkusnya menjadi program eksternal yang memanggilgudang::Barangdangudang::nilai_stoklewat nama crate — karena itu pemanggilan wajib memakai prefiksgudang::. - Baris 32 (
pub fn nilai_stok(...)): fungsi yang didokumentasikan. Karena doc test memanggilnya dari luar crate, fungsi ini wajibpub; item privat tidak akan bisa diakses oleh doc test. - Baris laporan
test src/lib.rs - nilai_stok (line 22) ... ok: angkaline 22adalah baris pembuka pagar blok contoh di file sumber — cara cepat melompat ke contoh yang gagal ketika dokumentasi berbohong.
Doc Comment yang Tidak Menempel #
Karena /// wajib menempel pada item, compiler menolak doc comment yang menggantung tanpa item di bawahnya. Kode berikut gagal dikompilasi:
fn main() {
println!("hai");
}
/// Dokumentasi untuk item yang tidak ada.
Pesan error compiler:
error: expected item after doc comment
--> src/main.rs:5:1
|
5 | /// Dokumentasi untuk item yang tidak ada.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything
error: could not compile `gudang` (bin "gudang") due to 1 previous errorPesan expected item after doc comment menyatakan masalahnya secara gamblang: ada doc comment, tetapi tidak ada item untuk menerimanya. Kasus umumnya adalah baris kosong atau komentar lain disisipkan memisahkan /// dari itemnya, atau doc comment tertinggal setelah item di bawahnya dihapus. Perbaikannya: pastikan /// berdiri tepat di atas item yang dimaksudkan.
Markdown di Dalam Doc Comment #
Rustdoc memproses Markdown standar, jadi doc comment bisa memuat daftar bertitik, tabel, heading bertingkat, dan bahkan catatan kaki. Dua hal patut diperhatikan. Pertama, heading level satu # di dalam doc comment menjadi judul section di halaman item — # Examples pada contoh kita adalah contohnya. Kedua, potongan Markdown yang terlihat seperti tautan ke item lain, misalnya [Barang], otomatis dihubungkan rustdoc ke halaman item tersebut — fitur intra-doc link yang akan kita praktikkan pada Chapter rustdoc dan cargo doc.
Ringkasan #
Doc comment /// menempel pada tepat satu item di bawahnya, tersimpan sebagai atribut item, lalu dikumpulkan rustdoc menjadi dokumentasi Markdown yang dirender ke HTML dan diuji lewat doc test. Field pub pun layak didokumentasikan sendiri, heading # Examples menjadi section standar, dan doc comment tanpa item memicu error expected item after doc comment. Ada satu posisi yang belum tercakup: bagaimana mendokumentasikan crate secara keseluruhan atau modul sebagai wadah? Untuk itu Rust menyediakan bentuk //!, materi Chapter berikutnya.