Skip to content

Commit caec4fd

Browse files
Avoid using the include macro to get better autocompletion on VSCode. (#34)
1 parent 50f90bf commit caec4fd

23 files changed

+2213
-2242
lines changed

jira-wip/src/koans/00_greetings/00_greetings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
/// ~ Enjoy! ~
2929
///
3030
#[cfg(test)]
31-
mod greetings {
31+
mod tests {
3232
#[test]
3333
/// This is your starting block!
3434
///
+69-72
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,75 @@
1-
mod ticket {
1+
/// We will begin our journey of building our own JIRA clone defining the cornerstone of
2+
/// JIRA's experience: the ticket.
3+
/// For now we want to limit ourselves to the essentials: each ticket will have a title
4+
/// and a description.
5+
/// No, not an ID yet. We will get to that in due time.
6+
///
7+
/// There are various ways to represent a set of related pieces of information in Rust.
8+
/// We'll go for a `struct`: a struct is quite similar to what you would call a class or
9+
/// an object in object-oriented programming languages.
10+
/// It is a collection of fields, each one with its own name.
11+
/// Given that Rust is a strongly-typed language, we also need to specify a type for each
12+
/// of those fields.
13+
///
14+
/// Our definition of Ticket is incomplete - can you replace __ with what is missing to make
15+
/// this snippet compile and the tests below succeed?
16+
///
17+
/// You can find more about structs in the Rust Book: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
18+
pub struct Ticket {
19+
title: String,
20+
__: __
21+
}
222

3-
/// We will begin our journey of building our own JIRA clone defining the cornerstone of
4-
/// JIRA's experience: the ticket.
5-
/// For now we want to limit ourselves to the essentials: each ticket will have a title
6-
/// and a description.
7-
/// No, not an ID yet. We will get to that in due time.
8-
///
9-
/// There are various ways to represent a set of related pieces of information in Rust.
10-
/// We'll go for a `struct`: a struct is quite similar to what you would call a class or
11-
/// an object in object-oriented programming languages.
12-
/// It is a collection of fields, each one with its own name.
13-
/// Given that Rust is a strongly-typed language, we also need to specify a type for each
14-
/// of those fields.
15-
///
16-
/// Our definition of Ticket is incomplete - can you replace __ with what is missing to make
17-
/// this snippet compile and the tests below succeed?
18-
///
19-
/// You can find more about structs in the Rust Book: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
20-
pub struct Ticket {
21-
title: String,
22-
__
23-
}
23+
/// `cfg` stands for configuration flag.
24+
/// The #[cfg(_)] attribute is used to mark a section of the code for conditional compilation
25+
/// based on the value of the specified flag.
26+
/// #[cfg(test)] is used to mark sections of our codebase that should only be compiled
27+
/// when running `cargo test`...
28+
/// Yes, tests!
29+
///
30+
/// You can put tests in different places in a Rust project, depending on what you are
31+
/// trying to do: unit testing of private functions and methods, testing an internal API,
32+
/// integration testing your crate from the outside, etc.
33+
/// You can find more details on test organisation in the Rust book:
34+
/// https://doc.rust-lang.org/book/ch11-03-test-organization.html
35+
///
36+
/// Let it be said that tests are first-class citizens in the Rust ecosystem and you are
37+
/// provided with a barebone test framework out of the box.
38+
#[cfg(test)]
39+
mod tests {
40+
use super::*;
2441

25-
/// `cfg` stands for configuration flag.
26-
/// The #[cfg(_)] attribute is used to mark a section of the code for conditional compilation
27-
/// based on the value of the specified flag.
28-
/// #[cfg(test)] is used to mark sections of our codebase that should only be compiled
29-
/// when running `cargo test`...
30-
/// Yes, tests!
31-
///
32-
/// You can put tests in different places in a Rust project, depending on what you are
33-
/// trying to do: unit testing of private functions and methods, testing an internal API,
34-
/// integration testing your crate from the outside, etc.
35-
/// You can find more details on test organisation in the Rust book:
36-
/// https://doc.rust-lang.org/book/ch11-03-test-organization.html
42+
/// The #[test] attribute is used to mark a function as a test for the compiler.
43+
/// Tests take no arguments: when we run `cargo test`, this function will be invoked.
44+
/// If it runs without raising any issue, the test is considered green - it passed.
45+
/// If it panics (raises a fatal exception), then the test is considered red - it failed.
3746
///
38-
/// Let it be said that tests are first-class citizens in the Rust ecosystem and you are
39-
/// provided with a barebone test framework out of the box.
40-
#[cfg(test)]
41-
mod tests {
42-
use super::*;
43-
44-
/// The #[test] attribute is used to mark a function as a test for the compiler.
45-
/// Tests take no arguments: when we run `cargo test`, this function will be invoked.
46-
/// If it runs without raising any issue, the test is considered green - it passed.
47-
/// If it panics (raises a fatal exception), then the test is considered red - it failed.
47+
/// `cargo test` reports on the number of failed tests at the end of each run, with some
48+
/// associated diagnostics to make it easier to understand what went wrong exactly.
49+
#[test]
50+
fn your_first_ticket() {
51+
/// `let` is used to create a variable: we are binding a new `Ticket` struct
52+
/// to the name `ticket_one`.
4853
///
49-
/// `cargo test` reports on the number of failed tests at the end of each run, with some
50-
/// associated diagnostics to make it easier to understand what went wrong exactly.
51-
#[test]
52-
fn your_first_ticket() {
53-
/// `let` is used to create a variable: we are binding a new `Ticket` struct
54-
/// to the name `ticket_one`.
55-
///
56-
/// We said before that Rust is strongly typed, nonetheless we haven't specified
57-
/// a type for `ticket_one`.
58-
/// As most modern strongly typed programming languages, Rust provides type inference:
59-
/// the compiler is smart enough to figure out the type of variables based on
60-
/// their usage and it won't bother you unless the type is ambiguous.
61-
let ticket_one = Ticket {
62-
/// This `.into()` method call is here for a reason, but give us time.
63-
/// We'll get there when it's the right moment.
64-
title: "A ticket title".into(),
65-
description: "A heart-breaking description".into()
66-
};
54+
/// We said before that Rust is strongly typed, nonetheless we haven't specified
55+
/// a type for `ticket_one`.
56+
/// As most modern strongly typed programming languages, Rust provides type inference:
57+
/// the compiler is smart enough to figure out the type of variables based on
58+
/// their usage and it won't bother you unless the type is ambiguous.
59+
let ticket_one = Ticket {
60+
/// This `.into()` method call is here for a reason, but give us time.
61+
/// We'll get there when it's the right moment.
62+
title: "A ticket title".into(),
63+
description: "A heart-breaking description".into()
64+
};
6765

68-
/// `assert_eq` is a macro (notice the ! at the end of the name).
69-
/// It checks that the left argument (the expected value) is identical
70-
/// to the right argument (the computed value).
71-
/// If they are not, it panics - Rust's (almost) non-recoverable way to terminate a program.
72-
/// In the case of tests, this is caught by the test framework and the test is marked as failed.
73-
assert_eq!(ticket_one.title, "A ticket title");
74-
/// Field syntax: you use a dot to access the field of a struct.
75-
assert_eq!(ticket_one.description, "A heart-breaking description");
76-
}
66+
/// `assert_eq` is a macro (notice the ! at the end of the name).
67+
/// It checks that the left argument (the expected value) is identical
68+
/// to the right argument (the computed value).
69+
/// If they are not, it panics - Rust's (almost) non-recoverable way to terminate a program.
70+
/// In the case of tests, this is caught by the test framework and the test is marked as failed.
71+
assert_eq!(ticket_one.title, "A ticket title");
72+
/// Field syntax: you use a dot to access the field of a struct.
73+
assert_eq!(ticket_one.description, "A heart-breaking description");
7774
}
78-
}
75+
}
+61-63
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,70 @@
1-
mod status {
2-
/// Ticket have two purposes in JIRA: capturing information about a task and tracking the
3-
/// completion of the task itself.
4-
///
5-
/// Let's add a new field to our `Ticket` struct, `status`.
6-
/// For the time being, we'll work under the simplified assumption that the set of statuses
7-
/// for a ticket is fixed and can't be customised by the user.
8-
/// A ticket is either in the to-do column, in progress, blocked or done.
9-
/// What is the best way to represent this information in Rust?
10-
struct Ticket {
11-
title: String,
12-
description: String,
13-
status: Status,
14-
}
1+
/// Ticket have two purposes in JIRA: capturing information about a task and tracking the
2+
/// completion of the task itself.
3+
///
4+
/// Let's add a new field to our `Ticket` struct, `status`.
5+
/// For the time being, we'll work under the simplified assumption that the set of statuses
6+
/// for a ticket is fixed and can't be customised by the user.
7+
/// A ticket is either in the to-do column, in progress, blocked or done.
8+
/// What is the best way to represent this information in Rust?
9+
struct Ticket {
10+
title: String,
11+
description: String,
12+
status: Status,
13+
}
1514

16-
/// Rust's enums are perfect for this usecase.
17-
/// Enum stands for enumeration: a type encoding the constraint that only a finite set of
18-
/// values is possible.
19-
/// Enums are great to encode semantic information in your code: making domain constraints
20-
/// explicit.
21-
///
22-
/// Each possible value of an enum is called a variant. By convention, they are Pascal-cased.
23-
/// Check out the Rust book for more details on enums:
24-
/// https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html
25-
///
26-
/// Let's create a variant for each of the allowed statuses of our tickets.
27-
pub enum Status {
28-
ToDo,
29-
__
30-
}
15+
/// Rust's enums are perfect for this usecase.
16+
/// Enum stands for enumeration: a type encoding the constraint that only a finite set of
17+
/// values is possible.
18+
/// Enums are great to encode semantic information in your code: making domain constraints
19+
/// explicit.
20+
///
21+
/// Each possible value of an enum is called a variant. By convention, they are Pascal-cased.
22+
/// Check out the Rust book for more details on enums:
23+
/// https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html
24+
///
25+
/// Let's create a variant for each of the allowed statuses of our tickets.
26+
pub enum Status {
27+
ToDo,
28+
__
29+
}
3130

3231

33-
#[cfg(test)]
34-
mod tests {
35-
use super::*;
32+
#[cfg(test)]
33+
mod tests {
34+
use super::*;
3635

37-
#[test]
38-
fn a_blocked_ticket() {
39-
// Let's create a blocked ticket.
40-
let ticket = Ticket {
41-
title: "A ticket title".into(),
42-
description: "A heart-breaking description".into(),
43-
status: __
44-
};
36+
#[test]
37+
fn a_blocked_ticket() {
38+
// Let's create a blocked ticket.
39+
let ticket = Ticket {
40+
title: "A ticket title".into(),
41+
description: "A heart-breaking description".into(),
42+
status: __
43+
};
4544

46-
// Let's check that the status corresponds to what we expect.
47-
// We can use pattern matching to take a different course of action based on the enum
48-
// variant we are looking at.
49-
// The Rust compiler will make sure that the match statement is exhaustive: it has to
50-
// handle all variants in our enums.
51-
// If not, the compiler will complain and reject our program.
52-
//
53-
// This is extremely useful when working on evolving codebases: if tomorrow we decide
54-
// that tickets can also have `Backlog` as their status, the Rust compiler will
55-
// highlight all code locations where we need to account for the new variant.
56-
// No way to forget!
45+
// Let's check that the status corresponds to what we expect.
46+
// We can use pattern matching to take a different course of action based on the enum
47+
// variant we are looking at.
48+
// The Rust compiler will make sure that the match statement is exhaustive: it has to
49+
// handle all variants in our enums.
50+
// If not, the compiler will complain and reject our program.
51+
//
52+
// This is extremely useful when working on evolving codebases: if tomorrow we decide
53+
// that tickets can also have `Backlog` as their status, the Rust compiler will
54+
// highlight all code locations where we need to account for the new variant.
55+
// No way to forget!
56+
//
57+
// Checkout the Rust Book for more details:
58+
// https://doc.rust-lang.org/book/ch06-02-match.html
59+
match ticket.status {
60+
// Variant => Expression
61+
Status::Blocked => println!("Great, as expected!"),
62+
// If we want to take the same action for multiple variants, we can use a | to list them.
63+
// Variant | Variant | ... | Variant => Expression
5764
//
58-
// Checkout the Rust Book for more details:
59-
// https://doc.rust-lang.org/book/ch06-02-match.html
60-
match ticket.status {
61-
// Variant => Expression
62-
Status::Blocked => println!("Great, as expected!"),
63-
// If we want to take the same action for multiple variants, we can use a | to list them.
64-
// Variant | Variant | ... | Variant => Expression
65-
//
66-
// We are panicking in this case, thus making the test fail if this branch of our
67-
// match statement gets executed.
68-
Status::ToDo | Status::InProgress | Status::Done => panic!("The ticket is not blocked!")
69-
}
65+
// We are panicking in this case, thus making the test fail if this branch of our
66+
// match statement gets executed.
67+
Status::ToDo | Status::InProgress | Status::Done => panic!("The ticket is not blocked!")
7068
}
7169
}
7270
}

0 commit comments

Comments
 (0)