Merge changes from olgierd into master

sarojaba authored
revision e077688c52324f0e03aa0e53c82dce31f74af82f
documentation
# 4.4. 문서화 (Documentation) - 20%

문서화는 어떤 소프트웨어 프로젝트이든 중요한 부분이고, 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.

여기에서 확인해야 할 첫 번재 내용은 `//` 대신에 `///`를 사용한다는 것입니다. 세 개의 슬래시는 문서 주석을 나타냅니다.

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

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)는 정상적인 동작입니다. 문서 처리를 수행하면 그 뒤에 따라오는 글들을 모두 주석으로 처리하며, 주석 뒤에는 아무것도 없는 것으로 인식합니다.

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

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

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

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

여러분의 함수가 `unsafe`라면, 어떤 불변의 호출자가 책임을 지고 있는지 설명해야 할 것입니다.

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

4변째 `Examples` 입니다. 함수나 method를 사용하기 위한 하나 이상의 예제를 추가하는 것이 사용자에게 큰 도움이 될 것입니다. 이 예제들은 곧 다시 언급할 코드 블록 주석에 포함될 것이며, 그 때 더 자세하게 설명될 것입니다.

```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() {}
```

위 코드 블록 주석들에 대해 더 자세하게 알아보도록 하겠습니다.

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

주석 내에 Rust 코드를 적고 싶다면, 세 개의 역따옴표를 사용하세요.

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

Rust 코드가 아니라면, 언어 이름을 표기할 수 있습니다.

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

표기한 언어에 따라 구문이 강조될 것입니다. 단순히 텍스트를 보여주려면, `text`를 적으세요.

`rustdoc`에서 이 항목을 인식하기 때문에, 정확한 언어를 선택하는 것은 중요합니다. 적합한 값을 적용했는지 확인하기 위해 실제로 당신의 예제를 테스트하는 데 사용되기도 합니다. 만약 당신이 C code를 사용하고 이 부분을 비워놓았다면 `rustdoc`은 예제를 Rust 코드로 인식하며, 문서화 작업 중 이에 대한 complain이 발생할 것입니다.

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

샘플 예제 문서화로 논의해봅시다.

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

여기서 `fn main()`이나 다른 건 필요없다는 것을 알게될 것입니다. `rustdoc`은 자동으로 당신의 코드를 감싸는 main() 래퍼를 알맞은 곳에 추가할 것입니다.

예제를 봅시다:

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

테스팅으로 완성됩니다:

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

다음은 rustdoc이 후 처리를 하기 위해 사용하는 전체 알고리즘의 예입니다:

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 }`

가끔 이걸로 충분하지 않을 때가 있습니다. 예를 들면, 우리가 지난번에 `///`로 시작하는 모든 코드 샘플에 관해 논의한 적이 있었나요? 로우 텍스트를 봅시다:

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

출력과 달라 보입니다:

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

그렇습니다: 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 = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://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() {}
```