Skip to content

Avoid using the include macro to get better autocompletion on VSCode with rust-analyzer #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion jira-wip/src/koans/00_greetings/00_greetings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
/// ~ Enjoy! ~
///
#[cfg(test)]
mod greetings {
mod tests {
#[test]
/// This is your starting block!
///
Expand Down
141 changes: 69 additions & 72 deletions jira-wip/src/koans/01_ticket/01_ticket.rs
Original file line number Diff line number Diff line change
@@ -1,78 +1,75 @@
mod ticket {
/// We will begin our journey of building our own JIRA clone defining the cornerstone of
/// JIRA's experience: the ticket.
/// For now we want to limit ourselves to the essentials: each ticket will have a title
/// and a description.
/// No, not an ID yet. We will get to that in due time.
///
/// There are various ways to represent a set of related pieces of information in Rust.
/// We'll go for a `struct`: a struct is quite similar to what you would call a class or
/// an object in object-oriented programming languages.
/// It is a collection of fields, each one with its own name.
/// Given that Rust is a strongly-typed language, we also need to specify a type for each
/// of those fields.
///
/// Our definition of Ticket is incomplete - can you replace __ with what is missing to make
/// this snippet compile and the tests below succeed?
///
/// You can find more about structs in the Rust Book: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
pub struct Ticket {
title: String,
__: __
}

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

/// `cfg` stands for configuration flag.
/// The #[cfg(_)] attribute is used to mark a section of the code for conditional compilation
/// based on the value of the specified flag.
/// #[cfg(test)] is used to mark sections of our codebase that should only be compiled
/// when running `cargo test`...
/// Yes, tests!
///
/// You can put tests in different places in a Rust project, depending on what you are
/// trying to do: unit testing of private functions and methods, testing an internal API,
/// integration testing your crate from the outside, etc.
/// You can find more details on test organisation in the Rust book:
/// https://doc.rust-lang.org/book/ch11-03-test-organization.html
/// The #[test] attribute is used to mark a function as a test for the compiler.
/// Tests take no arguments: when we run `cargo test`, this function will be invoked.
/// If it runs without raising any issue, the test is considered green - it passed.
/// If it panics (raises a fatal exception), then the test is considered red - it failed.
///
/// Let it be said that tests are first-class citizens in the Rust ecosystem and you are
/// provided with a barebone test framework out of the box.
#[cfg(test)]
mod tests {
use super::*;

/// The #[test] attribute is used to mark a function as a test for the compiler.
/// Tests take no arguments: when we run `cargo test`, this function will be invoked.
/// If it runs without raising any issue, the test is considered green - it passed.
/// If it panics (raises a fatal exception), then the test is considered red - it failed.
/// `cargo test` reports on the number of failed tests at the end of each run, with some
/// associated diagnostics to make it easier to understand what went wrong exactly.
#[test]
fn your_first_ticket() {
/// `let` is used to create a variable: we are binding a new `Ticket` struct
/// to the name `ticket_one`.
///
/// `cargo test` reports on the number of failed tests at the end of each run, with some
/// associated diagnostics to make it easier to understand what went wrong exactly.
#[test]
fn your_first_ticket() {
/// `let` is used to create a variable: we are binding a new `Ticket` struct
/// to the name `ticket_one`.
///
/// We said before that Rust is strongly typed, nonetheless we haven't specified
/// a type for `ticket_one`.
/// As most modern strongly typed programming languages, Rust provides type inference:
/// the compiler is smart enough to figure out the type of variables based on
/// their usage and it won't bother you unless the type is ambiguous.
let ticket_one = Ticket {
/// This `.into()` method call is here for a reason, but give us time.
/// We'll get there when it's the right moment.
title: "A ticket title".into(),
description: "A heart-breaking description".into()
};
/// We said before that Rust is strongly typed, nonetheless we haven't specified
/// a type for `ticket_one`.
/// As most modern strongly typed programming languages, Rust provides type inference:
/// the compiler is smart enough to figure out the type of variables based on
/// their usage and it won't bother you unless the type is ambiguous.
let ticket_one = Ticket {
/// This `.into()` method call is here for a reason, but give us time.
/// We'll get there when it's the right moment.
title: "A ticket title".into(),
description: "A heart-breaking description".into()
};

/// `assert_eq` is a macro (notice the ! at the end of the name).
/// It checks that the left argument (the expected value) is identical
/// to the right argument (the computed value).
/// If they are not, it panics - Rust's (almost) non-recoverable way to terminate a program.
/// In the case of tests, this is caught by the test framework and the test is marked as failed.
assert_eq!(ticket_one.title, "A ticket title");
/// Field syntax: you use a dot to access the field of a struct.
assert_eq!(ticket_one.description, "A heart-breaking description");
}
/// `assert_eq` is a macro (notice the ! at the end of the name).
/// It checks that the left argument (the expected value) is identical
/// to the right argument (the computed value).
/// If they are not, it panics - Rust's (almost) non-recoverable way to terminate a program.
/// In the case of tests, this is caught by the test framework and the test is marked as failed.
assert_eq!(ticket_one.title, "A ticket title");
/// Field syntax: you use a dot to access the field of a struct.
assert_eq!(ticket_one.description, "A heart-breaking description");
}
}
}
124 changes: 61 additions & 63 deletions jira-wip/src/koans/01_ticket/02_status.rs
Original file line number Diff line number Diff line change
@@ -1,72 +1,70 @@
mod status {
/// Ticket have two purposes in JIRA: capturing information about a task and tracking the
/// completion of the task itself.
///
/// Let's add a new field to our `Ticket` struct, `status`.
/// For the time being, we'll work under the simplified assumption that the set of statuses
/// for a ticket is fixed and can't be customised by the user.
/// A ticket is either in the to-do column, in progress, blocked or done.
/// What is the best way to represent this information in Rust?
struct Ticket {
title: String,
description: String,
status: Status,
}
/// Ticket have two purposes in JIRA: capturing information about a task and tracking the
/// completion of the task itself.
///
/// Let's add a new field to our `Ticket` struct, `status`.
/// For the time being, we'll work under the simplified assumption that the set of statuses
/// for a ticket is fixed and can't be customised by the user.
/// A ticket is either in the to-do column, in progress, blocked or done.
/// What is the best way to represent this information in Rust?
struct Ticket {
title: String,
description: String,
status: Status,
}

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


#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
mod tests {
use super::*;

#[test]
fn a_blocked_ticket() {
// Let's create a blocked ticket.
let ticket = Ticket {
title: "A ticket title".into(),
description: "A heart-breaking description".into(),
status: __
};
#[test]
fn a_blocked_ticket() {
// Let's create a blocked ticket.
let ticket = Ticket {
title: "A ticket title".into(),
description: "A heart-breaking description".into(),
status: __
};

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