문서화 쬐끔 번역

sarojaba authored
revision b537eb21dd77bad98867b6b26ce8c5bc3ddfd2fd
documentation
# 4.4. 문서화 (Documentation) - 1520%

문서화는 어떤 소프트웨어 프로젝트이든 중요한 부분이고, Rust에선 1등급입니다. 여러분의 프로젝트를 문서화하기위해 Rust가 제공하는 도구에 대해서 얘기해볼까요?

## `rustdoc`에 대해 (About `rustdoc`)

Rust 배포본은 `rustdoc`이라고 하는 문서를 생성해내는 도구를 포함하고 있습니다. 또한 `rustdoc`은 Cargo 명령인 `cargo doc`을 통해서 사용됩니다.

문서는 두 가지 방법으로 생성될 수 있습니다. 소스 코드로부터, 별도의 마크다운 파일로부터.

## 소스 코드 문서화 (Documenting source code)

Rust 프로젝트를 문서화하는 주된 방법은 소스 코드에 단 주석을 통해서 입니다. 이 목적을 위해 문서 주석을 사용할 수 있습니다.

```rust,ignore
/// Constructs a new `Rc`.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
pub fn new(value: T) -> Rc {
// implementation goes here
}
```

이 코드는 [다음과 같은][rc-new] 형태의 문서를 생성합니다. I've left the
implementation out, with a regular comment in its place. That's the first thing
to notice about this annotation: `//` 대신에 `///`를 사용합니다. 세 개의 슬래시는 문서 주석을 나타냅니다.

문서 주석은 마크다운으로 작성합니다.

Rust는 이런 주석들을 추적하고, 문서를 생성할 때 사용합니다. 열거형 같은 것을 문서화할 때 중요합니다.

```rust
/// The `Option` type. See [the module level documentation](../) for more.
enum Option {
/// No value
None,
/// Some value `T`
Some(T),
}
```

위 코드는 동작하지만, 다음 코드는 동작하지 않습니다.

```rust,ignore
/// The `Option` type. See [the module level documentation](../) for more.
enum Option {
None, /// No value
Some(T), /// Some value `T`
}
```

오류가 날 것입니다.

```text
hello.rs:4:1: 4:2 error: expected ident, found `}`
hello.rs:4 }
^
```

이 [불행한 오류](https://github.com/rust-lang/rust/issues/22547)는 맞습니다. documentation comments apply to the thing after them, and there's no
thing after that last comment.

[rc-new]: http://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new

### 문서 주석 적기 (Writing documentation comments)

어쨋든, 주석의 각 부분을 자세히 다뤄보겠습니다.

```rust
/// Constructs a new `Rc`.
# fn foo() {}
```

문서 주석의 첫 줄은 대상의 기능을 짧게 요약하세요. 한문장으로. 기본만. 고수준으로.

```rust
///
/// Other details about constructing `Rc`s, maybe describing complicated
/// semantics, maybe additional options, all kinds of stuff.
///
# fn foo() {}
```

이 예제는 요약 줄만 가지고 있지만, 더 언급할 것이 있다면, 새 단락으로 설명을 더 추가할 수 있습니다.

#### 특별한 섹션 (Special sections)

다음은, 특별한 섹션입니다. `#`은 헤더를 의미합니다. 주로 사용되는 헤더는 세 종류가 있습니다. 현재는 특별한 문법은 아니고, 단지 관습입니다.

```rust
/// # Panics
# fn foo() {}
```

Rust에서 회복할 수 없는 함수의 오용(예를 들어, 프로그래밍 오류)은 흔히 적어도 현재 스레드 전부를 죽이는 패닉을 야기합니다. 만약 여러분의 함수가 다음과 같이 사소하지 않은 기능을 가지고 있다면, 즉, 패닉이 감지/강요된다면, 문서화는 아주 중요합니다.

```rust
/// # Failures
# fn foo() {}
```

여러분의 함수나 메소드가 `Result`을 반환한다면, `Err(E)`를 반환해서 상태를 기술하는 것은 좋습니다. 실패는 타입 시스템으로 코드화되기 때문에, 이것은 `Panics`보다 약간 덜 중요합니다. 하지만 여전히 이렇게 하는 것은 좋습니다.

```rust
/// # Safety
# fn foo() {}
```

여러분의 함수가 `unsafe`라면, you should explain which invariants the caller is
responsible for upholding.

```rust
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
# fn foo() {}
```

Third, `Examples`. Include one or more examples of using your function or
method, and your users will love you for it. These examples go inside of
code block annotations, which we'll talk about in a moment, and can have
more than one section:

```rust
/// # Examples
///
/// Simple `&str` patterns:
///
/// ```
/// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
/// ```
///
/// More complex patterns with a lambda:
///
/// ```
/// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
/// assert_eq!(v, vec!["abc", "def", "ghi"]);
/// ```
# fn foo() {}
```

Let's discuss the details of these code blocks.

#### 코드 블록 주석 (Code block annotations)

To write some Rust code in a comment, use the triple graves:주석 내에 Rust 코드를 적고 싶다면, 세 개의 역따옴표를 사용하세요.

```rust
/// ```
/// println!("Hello, world");
/// ```
# fn foo() {}
```

If you want something that's not Rust code, you can add an annotation:Rust 코드가 아니라면, 언어 이름을 표기할 수 있습니다.

```rust
/// ```c
/// printf("Hello, world¶
");
/// ```
# fn foo() {}
```

This will highlight according to whatever language you're showing off.
If you're just showing plain text, choose `text`.

It's important to choose the correct annotation here, because `rustdoc` uses it
in an interesting way:
표기한 언어에 따라 구문강조될 것입니다. 단순히 텍스트를 보여주려면, `text`를 적으세요.

`rustdoc`이 이것을 사용하기 때문에, 정확한 언어를 선택하는 것은 중요합니다.
It can be used to actually test your examples, so that
they don't get out of date. If you have some C code but `rustdoc` thinks it's
Rust because you left off the annotation, `rustdoc` will complain when trying to
generate the documentation.

## 테스트로서의 문서화 (Documentation as tests)

Let's discuss our sample example documentation:샘플 예제 문서화로 논의해봅시다.

```rust
/// ```
/// println!("Hello, world");
/// ```
# fn foo() {}
```

You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will
automatically add a main() wrapper around your code, and in the right place.
For example:

```rust
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
# fn foo() {}
```

This will end up testing:

```rust
fn main() {
use std::rc::Rc;
let five = Rc::new(5);
}
```

Here's the full algorithm rustdoc uses to postprocess examples:

1. Any leading `#![foo]` attributes are left intact as crate attributes.
2. Some common `allow` attributes are inserted, including
`unused_variables`, `unused_assignments`, `unused_mut`,
`unused_attributes`, and `dead_code`. Small examples often trigger
these lints.
3. If the example does not contain `extern crate`, then `extern crate
;` is inserted.
2. Finally, if the example does not contain `fn main`, the remainder of the
text is wrapped in `fn main() { your_code }`

Sometimes, this isn't enough, though. For example, all of these code samples
with `///` we've been talking about? The raw text:

```text
/// Some documentation.
# fn foo() {}
```

looks different than the output:

```rust
/// Some documentation.
# fn foo() {}
```

Yes, that's right: you can add lines that start with `# `, and they will
be hidden from the output, but will be used when compiling your code. You
can use this to your advantage. In this case, documentation comments need
to apply to some kind of function, so if I want to show you just a
documentation comment, I need to add a little function definition below
it. At the same time, it's just there to satisfy the compiler, so hiding
it makes the example more clear. You can use this technique to explain
longer examples in detail, while still preserving the testability of your
documentation. For example, this code:

```rust
let x = 5;
let y = 6;
println!("{}", x + y);
```

Here's an explanation, rendered:

First, we set `x` to five:

```rust
let x = 5;
# let y = 6;
# println!("{}", x + y);
```

Next, we set `y` to six:

```rust
# let x = 5;
let y = 6;
# println!("{}", x + y);
```

Finally, we print the sum of `x` and `y`:

```rust
# let x = 5;
# let y = 6;
println!("{}", x + y);
```

Here's the same explanation, in raw text:

> First, we set `x` to five:
>
> ```text
> let x = 5;
> # let y = 6;
> # println!("{}", x + y);
> ```
>
> Next, we set `y` to six:
>
> ```text
> # let x = 5;
> let y = 6;
> # println!("{}", x + y);
> ```
>
> Finally, we print the sum of `x` and `y`:
>
> ```text
> # let x = 5;
> # let y = 6;
> println!("{}", x + y);
> ```

By repeating all parts of the example, you can ensure that your example still
compiles, while only showing the parts that are relevant to that part of your
explanation.

### Documenting macros

Here’s an example of documenting a macro:

```rust
/// Panic with a given message unless an expression evaluates to true.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate foo;
/// # fn main() {
/// panic_unless!(1 + 1 == 2, “Math is broken.”);
/// # }
/// ```
///
/// ```should_panic
/// # #[macro_use] extern crate foo;
/// # fn main() {
/// panic_unless!(true == false, “I’m broken.”);
/// # }
/// ```
#[macro_export]
macro_rules! panic_unless {
($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } });
}
# fn main() {}
```

You’ll note three things: we need to add our own `extern crate` line, so that
we can add the `#[macro_use]` attribute. Second, we’ll need to add our own
`main()` as well. Finally, a judicious use of `#` to comment out those two
things, so they don’t show up in the output.

### Running documentation tests

To run the tests, either

```bash
$ rustdoc --test path/to/my/crate/root.rs
# or
$ cargo test
```

That's right, `cargo test` tests embedded documentation too. However,
`cargo test` will not test binary crates, only library ones. This is
due to the way `rustdoc` works: it links against the library to be tested,
but with a binary, there’s nothing to link to.

There are a few more annotations that are useful to help `rustdoc` do the right
thing when testing your code:

```rust
/// ```ignore
/// fn foo() {
/// ```
# fn foo() {}
```

The `ignore` directive tells Rust to ignore your code. This is almost never
what you want, as it's the most generic. Instead, consider annotating it
with `text` if it's not code, or using `#`s to get a working example that
only shows the part you care about.

```rust
/// ```should_panic
/// assert!(false);
/// ```
# fn foo() {}
```

`should_panic` tells `rustdoc` that the code should compile correctly, but
not actually pass as a test.

```rust
/// ```no_run
/// loop {
/// println!("Hello, world");
/// }
/// ```
# fn foo() {}
```

The `no_run` attribute will compile your code, but not run it. This is
important for examples such as "Here's how to start up a network service,"
which you would want to make sure compile, but might run in an infinite loop!

### Documenting modules

Rust has another kind of doc comment, `//!`. This comment doesn't document the next item, but the enclosing item. In other words:

```rust
mod foo {
//! This is documentation for the `foo` module.
//!
//! # Examples

// ...
}
```

This is where you'll see `//!` used most often: for module documentation. If
you have a module in `foo.rs`, you'll often open its code and see this:

```rust
//! A module for using `foo`s.
//!
//! The `foo` module contains a lot of useful functionality blah blah blah
```

### Documentation comment style

Check out [RFC 505][rfc505] for full conventions around the style and format of
documentation.

[rfc505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md

## Other documentation

All of this behavior works in non-Rust source files too. Because comments
are written in Markdown, they're often `.md` files.

When you write documentation in Markdown files, you don't need to prefix
the documentation with comments. For example:

```rust
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5);
/// ```
# fn foo() {}
```

is just

~~~markdown
# Examples

```rust
use std::rc::Rc;

let five = Rc::new(5);
```
~~~

when it's in a Markdown file. There is one wrinkle though: Markdown files need
to have a title like this:

```markdown
% The title

This is the example documentation.
```

This `%` line needs to be the very first line of the file.

## `doc` attributes

At a deeper level, documentation comments are sugar for documentation attributes:

```rust
/// this
# fn foo() {}

#[doc="this"]
# fn bar() {}
```

are the same, as are these:

```rust
//! this

#![doc="/// this"]
```

You won't often see this attribute used for writing documentation, but it
can be useful when changing some options, or when writing a macro.

### Re-exports

`rustdoc` will show the documentation for a public re-export in both places:

```ignore
extern crate foo;

pub use foo::bar;
```

This will create documentation for bar both inside the documentation for the
crate `foo`, as well as the documentation for your crate. It will use the same
documentation in both places.

This behavior can be suppressed with `no_inline`:

```ignore
extern crate foo;

#[doc(no_inline)]
pub use foo::bar;
```

### Controlling HTML

You can control a few aspects of the HTML that `rustdoc` generates through the
`#![doc]` version of the attribute:

```rust
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
```

This sets a few different options, with a logo, favicon, and a root URL.

## Generation options

`rustdoc` also contains a few other options on the command line, for further customization:

- `--html-in-header FILE`: includes the contents of FILE at the end of the
`...` section.
- `--html-before-content FILE`: includes the contents of FILE directly after
``, before the rendered content (including the search bar).
- `--html-after-content FILE`: includes the contents of FILE after all the rendered content.

## Security note

The Markdown in documentation comments is placed without processing into
the final webpage. Be careful with literal HTML:

```rust
///
# fn foo() {}
```