Skip to content

Commit f64e726

Browse files
author
yourname
committed
feat: Add clippy lints
- adds a new 'clippy' category for exercises - clippy exercises should throw no warnings - install script now also installs clippy is related to rust-lang/rust-clippy#2604
1 parent 2d9f2b2 commit f64e726

File tree

10 files changed

+110
-15
lines changed

10 files changed

+110
-15
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
target/
33
**/*.rs.bk
44
.DS_Store
5-
*.pdb
5+
*.pdb
6+
exercises/clippy/Cargo.toml
7+
exercises/clippy/Cargo.lock

exercises/clippy/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
### Clippy
2+
3+
The Clippy tool is a collection of lints to analyze your code so you can catch common mistakes and improve your Rust code.
4+
5+
If you used the installation script for Rustlings, Clippy should be already installed.
6+
If not you can install it manually via `rustup component add clippy`.
7+
8+
For more information about Clippy lints, please see [their documentation page](https://rust-lang.github.io/rust-clippy/master/).

exercises/clippy/clippy1.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// clippy1.rs
2+
// The Clippy tool is a collection of lints to analyze your code
3+
// so you can catch common mistakes and improve your Rust code.
4+
//
5+
// Execute `rustlings hint clippy1` for hints :)
6+
7+
// I AM NOT DONE
8+
9+
fn main() {
10+
let x = 1.2331f64;
11+
let y = 1.2332f64;
12+
if y != x {
13+
println!("Success!");
14+
}
15+
}

exercises/clippy/clippy2.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// clippy2.rs
2+
// Make me compile! Execute `rustlings hint clippy2` for hints :)
3+
4+
// I AM NOT DONE
5+
6+
fn main() {
7+
let mut res = 42;
8+
let option = Some(12);
9+
for x in option {
10+
res += x;
11+
}
12+
println!("{}", res);
13+
}

info.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,22 @@ hint = """
529529
It should be doing some checking, returning an `Err` result if those checks fail, and only
530530
returning an `Ok` result if those checks determine that everything is... okay :)"""
531531

532+
# CLIPPY
533+
534+
[[exercises]]
535+
name = "clippy1"
536+
path = "exercises/clippy/clippy1.rs"
537+
mode = "clippy"
538+
hint = """
539+
Floating point calculations are usually imprecise, so asking if two values are exactly equal is asking for trouble"""
540+
541+
[[exercises]]
542+
name = "clippy2"
543+
path = "exercises/clippy/clippy2.rs"
544+
mode = "clippy"
545+
hint = """
546+
`for` loops over Option values are more clearly expressed as an `if let`"""
547+
532548
# STANDARD LIBRARY TYPES
533549

534550
[[exercises]]

install.ps1

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,19 @@ if (!($LASTEXITCODE -eq 0)) {
7272
# but anyone running pwsh 5 will have to pass the argument.
7373
$version = Invoke-WebRequest -UseBasicParsing https://api.github.com/repos/rust-lang/rustlings/releases/latest `
7474
| ConvertFrom-Json | Select-Object -ExpandProperty tag_name
75-
Write-Host "Checking out version $version..."
76-
Set-Location $path
77-
git checkout -q tags/$version
7875

7976
Write-Host "Installing the 'rustlings' executable..."
80-
cargo install --force --path .
77+
cargo install --force --git https://github.com/rust-lang/rustlings --tag $version
8178
if (!(Get-Command rustlings -ErrorAction SilentlyContinue)) {
8279
Write-Host "WARNING: Please check that you have '~/.cargo/bin' in your PATH environment variable!"
8380
}
8481

82+
# Checking whether Clippy is installed.
83+
# Due to a bug in Cargo, this must be done with Rustup: https://github.com/rust-lang/rustup/issues/1514
84+
$clippy = (rustup component list | Select-String "clippy" | Select-String "installed") | Out-String
85+
if (!$clippy) {
86+
Write-Host "Installing the 'cargo-clippy' executable..."
87+
rustup component add clippy
88+
}
89+
8590
Write-Host "All done! Run 'rustlings' to get started."

install.sh

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,24 @@ else
8282
echo "SUCCESS: Rust is up to date"
8383
fi
8484

85-
Path=${1:-rustlings/}
86-
echo "Cloning Rustlings at $Path..."
87-
git clone -q https://github.com/rust-lang/rustlings $Path
88-
8985
Version=$(curl -s https://api.github.com/repos/rust-lang/rustlings/releases/latest | python -c "import json,sys;obj=json.load(sys.stdin);print(obj['tag_name']);")
90-
echo "Checking out version $Version..."
91-
cd $Path
92-
git checkout -q tags/$Version
86+
CargoBin="${CARGO_HOME:-$HOME/.cargo}/bin"
9387

9488
echo "Installing the 'rustlings' executable..."
95-
cargo install --force --path .
89+
cargo install --force --git https://github.com/rust-lang/rustlings --tag $Version
9690

9791
if ! [ -x "$(command -v rustlings)" ]
9892
then
99-
echo "WARNING: Please check that you have '~/.cargo/bin' in your PATH environment variable!"
93+
echo "WARNING: Please check that you have '$CargoBin' in your PATH environment variable!"
94+
fi
95+
96+
# Checking whether Clippy is installed.
97+
# Due to a bug in Cargo, this must be done with Rustup: https://github.com/rust-lang/rustup/issues/1514
98+
Clippy=$(rustup component list | grep "clippy" | grep "installed")
99+
if [ -z "$Clippy" ]
100+
then
101+
echo "Installing the 'cargo-clippy' executable..."
102+
rustup component add clippy
100103
fi
101104

102105
echo "All done! Run 'rustlings' to get started."

src/exercise.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use regex::Regex;
22
use serde::Deserialize;
33
use std::fmt::{self, Display, Formatter};
4-
use std::fs::{remove_file, File};
4+
use std::fs::{self, remove_file, File};
55
use std::io::Read;
66
use std::path::PathBuf;
77
use std::process::{self, Command};
88

99
const RUSTC_COLOR_ARGS: &[&str] = &["--color", "always"];
1010
const I_AM_DONE_REGEX: &str = r"(?m)^\s*///?\s*I\s+AM\s+NOT\s+DONE";
1111
const CONTEXT: usize = 2;
12+
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/clippy/Cargo.toml";
1213

1314
fn temp_file() -> String {
1415
format!("./temp_{}", process::id())
@@ -19,6 +20,7 @@ fn temp_file() -> String {
1920
pub enum Mode {
2021
Compile,
2122
Test,
23+
Clippy,
2224
}
2325

2426
#[derive(Deserialize)]
@@ -83,6 +85,34 @@ impl Exercise {
8385
.args(&["--test", self.path.to_str().unwrap(), "-o", &temp_file()])
8486
.args(RUSTC_COLOR_ARGS)
8587
.output(),
88+
Mode::Clippy => {
89+
let cargo_toml = format!(
90+
r#"[package]
91+
name = "{}"
92+
version = "0.0.1"
93+
edition = "2018"
94+
[[bin]]
95+
name = "{}"
96+
path = "{}.rs""#,
97+
self.name, self.name, self.name
98+
);
99+
fs::write(CLIPPY_CARGO_TOML_PATH, cargo_toml)
100+
.expect("Failed to write 📎 Clippy 📎 Cargo.toml file.");
101+
// Due to an issue with Clippy, a cargo clean is required to catch all lints.
102+
// See https://github.com/rust-lang/rust-clippy/issues/2604
103+
// This is already fixed on master branch. See this issue to track merging into Cargo:
104+
// https://github.com/rust-lang/rust-clippy/issues/3837
105+
Command::new("cargo")
106+
.args(&["clean", "--manifest-path", CLIPPY_CARGO_TOML_PATH])
107+
.args(RUSTC_COLOR_ARGS)
108+
.output()
109+
.expect("Failed to run 'cargo clean'");
110+
Command::new("cargo")
111+
.args(&["clippy", "--manifest-path", CLIPPY_CARGO_TOML_PATH])
112+
.args(RUSTC_COLOR_ARGS)
113+
.args(&["--", "-D", "warnings"])
114+
.output()
115+
}
86116
}
87117
.expect("Failed to run 'compile' command.");
88118

src/run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub fn run(exercise: &Exercise) -> Result<(), ()> {
66
match exercise.mode {
77
Mode::Test => test(exercise)?,
88
Mode::Compile => compile_and_run(exercise)?,
9+
Mode::Clippy => compile_and_run(exercise)?,
910
}
1011
Ok(())
1112
}

src/verify.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<()
77
let compile_result = match exercise.mode {
88
Mode::Test => compile_and_test(&exercise, RunMode::Interactive),
99
Mode::Compile => compile_only(&exercise),
10+
Mode::Clippy => compile_only(&exercise),
1011
};
1112
if !compile_result.unwrap_or(false) {
1213
return Err(exercise);
@@ -99,6 +100,7 @@ fn prompt_for_completion(exercise: &Exercise) -> bool {
99100
let success_msg = match exercise.mode {
100101
Mode::Compile => "The code is compiling!",
101102
Mode::Test => "The code is compiling, and the tests pass!",
103+
Mode::Clippy => "The code is compiling, and 📎 Clippy 📎 is happy!",
102104
};
103105

104106
println!("");

0 commit comments

Comments
 (0)