문서화
크레이트 수준 문서는 충실하며 예제를 포함합니다 (C-CRATE-DOC)
RFC 1687을 참고하십시오.
모든 항목에 rustdoc 예제가 있습니다 (C-EXAMPLE)
모든 공개 모듈, 트레이트, 구조체, 열거형, 함수, 메서드, 매크로, 타입 정의에는 해당 기능을 실제로 사용해 보는 예제가 있어야 합니다.
이 가이드라인은 합리적인 범위 내에서 적용해야 합니다.
다른 항목에 있는 적절한 예제로 연결하는 링크만으로도 충분할 수 있습니다. 예를 들어 특정 타입을 사용하는 함수가 정확히 하나뿐이라면, 함수나 타입 중 한쪽에만 예제를 작성하고 다른 쪽에서 그 예제로 링크하는 것이 적절할 수 있습니다.
예제의 목적이 항상 해당 항목을 사용하는 방법을 보여 주는 것은 아닙니다. 독자는 함수를 호출하는 방법, 열거형에 대해 매칭하는 방법 및 기타 기본적인 작업을 이해하고 있다고 기대할 수 있습니다. 오히려 예제는 사람들이 해당 항목을 왜 사용하려 하는지를 보여 주기 위한 경우가 많습니다.
// This would be a poor example of using clone(). It mechanically shows *how* to
// call clone(), but does nothing to show *why* somebody would want this.
fn main() {
let hello = "hello";
hello.clone();
}
예제는 try!나 unwrap이 아닌 ?를 사용합니다 (C-QUESTION-MARK)
좋든 싫든, 사용자는 예제 코드를 그대로 복사하는 경우가 많습니다. 오류를 언래핑하는 것은 사용자가 의식적으로 내려야 하는 결정이어야 합니다.
실패할 수 있는 예제 코드를 구성하는 일반적인 방법은 다음과 같습니다. #으로 시작하는 줄은 예제를 빌드할 때 cargo test에 의해 컴파일되지만, 사용자에게 보이는 rustdoc에는 나타나지 않습니다.
/// ```rust
/// # use std::error::Error;
/// #
/// # fn main() -> Result<(), Box<dyn Error>> {
/// your;
/// example?;
/// code;
/// #
/// # Ok(())
/// # }
/// ```
함수 문서에는 오류, 패닉, 안전성 관련 고려 사항이 포함됩니다 (C-FAILURE)
오류 조건은 “Errors” 섹션에 문서화해야 합니다. 이는 트레이트 메서드에도 적용됩니다. 구현이 오류를 반환하는 것이 허용되거나 예상되는 트레이트 메서드는 “Errors” 섹션으로 문서화해야 합니다.
예를 들어 표준 라이브러리에서 std::io::Read::read 트레이트 메서드의 일부 구현은 오류를 반환할 수 있습니다.
/// Pull some bytes from this source into the specified buffer, returning
/// how many bytes were read.
///
/// ... lots more info ...
///
/// # Errors
///
/// If this function encounters any form of I/O or other error, an error
/// variant will be returned. If an error is returned then it must be
/// guaranteed that no bytes were read.
패닉 조건은 “Panics” 섹션에 문서화해야 합니다. 이는 트레이트 메서드에도 적용됩니다. 구현이 패닉하는 것이 허용되거나 예상되는 트레이트 메서드는 “Panics” 섹션으로 문서화해야 합니다.
표준 라이브러리에서 Vec::insert 메서드는 패닉할 수 있습니다.
/// Inserts an element at position `index` within the vector, shifting all
/// elements after it to the right.
///
/// # Panics
///
/// Panics if `index` is out of bounds.
생각할 수 있는 모든 패닉 경우를 문서화할 필요는 없으며, 특히 호출자가 제공한 로직에서 패닉이 발생하는 경우에는 더욱 그렇습니다. 예를 들어 다음 코드에서 Display 패닉을 문서화하는 것은 지나쳐 보입니다. 하지만 확신이 서지 않을 때는 패닉 경우를 더 많이 문서화하는 쪽을 택하십시오.
#![allow(unused)]
fn main() {
/// # Panics
///
/// This function panics if `T`'s implementation of `Display` panics.
pub fn print<T: Display>(t: T) {
println!("{}", t.to_string());
}
}
unsafe 함수에는 함수를 올바르게 사용하기 위해 호출자가 지켜야 할 모든 불변 조건을 설명하는 “안전성(Safety)” 섹션을 두어 문서화해야 합니다.
unsafe std::ptr::read는 호출자에게 다음을 요구합니다.
/// Reads the value from `src` without moving it. This leaves the
/// memory in `src` unchanged.
///
/// # Safety
///
/// Beyond accepting a raw pointer, this is unsafe because it semantically
/// moves the value out of `src` without preventing further usage of `src`.
/// If `T` is not `Copy`, then care must be taken to ensure that the value at
/// `src` is not used before the data is overwritten again (e.g. with `write`,
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
/// because it will attempt to drop the value previously at `*src`.
///
/// The pointer must be aligned; use `read_unaligned` if that is not the case.
본문에는 관련 항목으로 연결되는 하이퍼링크가 포함됩니다 (C-LINK)
일반 링크는 통상적인 마크다운 문법인 [text](url)을 사용하여 인라인으로 추가할 수 있습니다. 다른 타입으로의 링크는 [`text`]로 표시한 다음, 문서 주석 끝의 새 줄에 [`text`]: <target>의 형태로 링크 대상을 추가하여 넣을 수 있습니다. 여기서 <target>은 아래에서 설명합니다.
같은 타입 안의 메서드를 가리키는 링크 대상은 보통 다음과 같습니다:
[`serialize_struct`]: #method.serialize_struct
다른 타입을 가리키는 링크 대상은 보통 다음과 같습니다:
[`Deserialize`]: trait.Deserialize.html
링크 대상은 부모 모듈이나 자식 모듈을 가리킬 수도 있습니다:
[`Value`]: ../enum.Value.html
[`DeserializeOwned`]: de/trait.DeserializeOwned.html
이 가이드라인은 RFC 1574의 “Link all the things” 항목에서 공식적으로 권장하는 사항입니다.
Cargo.toml에 모든 일반 메타데이터가 포함됩니다 (C-METADATA)
Cargo.toml의 [package] 섹션에는 다음 값들이 포함되어야 합니다:
authorsdescriptionlicenserepositorykeywordscategories
이 밖에 선택적인 메타데이터 필드가 두 가지 있습니다:
documentationhomepage
기본적으로 crates.io는 docs.rs에 있는 해당 크레이트의 문서로 링크합니다. documentation 메타데이터는 문서가 docs.rs가 아닌 다른 곳에 호스팅되는 경우에만 설정하면 됩니다. 예를 들어 크레이트가 docs.rs의 빌드 환경에서 사용할 수 없는 공유 라이브러리에 링크하는 경우가 이에 해당합니다.
homepage 메타데이터는 소스 저장소나 API 문서 외에 크레이트를 위한 별도의 웹사이트가 있는 경우에만 설정해야 합니다. homepage가 documentation 값이나 repository 값과 중복되지 않도록 하십시오. 예를 들어 Serde는 전용 웹사이트인 https://serde.rs 주소를 homepage로 설정합니다.
릴리스 노트에 모든 중요한 변경 사항이 기록됩니다 (C-RELNOTES)
크레이트 사용자는 릴리스 노트를 읽고 크레이트의 각 배포 릴리스에서 무엇이 바뀌었는지 요약을 확인할 수 있습니다. 릴리스 노트로 가는 링크나 릴리스 노트 자체를 크레이트 수준 문서와 Cargo.toml에 링크된 저장소 중 한쪽 또는 양쪽에 포함해야 합니다.
호환성을 깨뜨리는 변경(RFC 1105에서 정의한 것)은 릴리스 노트에 명확하게 표시해야 합니다.
Git으로 크레이트의 소스를 관리하는 경우, crates.io에 배포된 모든 릴리스에는 배포된 커밋을 식별하는 태그가 하나씩 있어야 합니다. Git이 아닌 VCS 도구를 사용하는 경우에도 비슷한 절차를 따라야 합니다.
# Tag the current commit
GIT_COMMITTER_DATE=$(git log -n1 --pretty=%aD) git tag -a -m "Release 0.3.0" 0.3.0
git push --tags
일부 Git 명령은 주석 태그가 하나라도 존재하면 주석이 없는 태그를 무시하므로 주석 태그를 사용하는 것이 좋습니다.
예시
rustdoc은 도움이 되지 않는 구현 세부 사항을 보여 주지 않습니다 (C-HIDDEN)
rustdoc에는 사용자가 크레이트를 온전히 사용하는 데 필요한 모든 것이 포함되어야 하며, 그 이상은 포함되지 않아야 합니다. 관련된 구현 세부 사항을 본문에서 설명하는 것은 괜찮지만, 그것이 문서의 실제 항목이 되어서는 안 됩니다.
특히 rustdoc에 어떤 impl을 보이게 할지 신중하게 고르십시오. 사용자가 크레이트를 온전히 사용하는 데 필요한 impl은 모두 보이게 하되, 그 밖의 것은 보이지 않게 하십시오. 다음 코드에서 PublicError의 rustdoc은 기본적으로 From<PrivateError> impl을 보여 줍니다. 사용자는 자신의 코드에서 PrivateError를 가질 수 없으므로 이 impl은 사용자와 전혀 관련이 없습니다. 그래서 #[doc(hidden)]으로 이를 숨기기로 합니다.
#![allow(unused)]
fn main() {
// This error type is returned to users.
pub struct PublicError { /* ... */ }
// This error type is returned by some private helper functions.
struct PrivateError { /* ... */ }
// Enable use of `?` operator.
#[doc(hidden)]
impl From<PrivateError> for PublicError {
fn from(err: PrivateError) -> PublicError {
/* ... */
}
}
}
pub(crate)는 공개 API에서 구현 세부 사항을 제거하는 또 하나의 훌륭한 도구입니다. 이를 사용하면 항목을 자신이 속한 모듈 바깥에서는 사용할 수 있지만, 같은 크레이트 바깥에서는 사용할 수 없습니다.