feat: add fake manifest for analyzers/IDEs (fixes #443)

This commit is contained in:
Roberto Vidal 2020-06-20 11:11:45 +02:00
parent f38f42f17d
commit 13cdc1aa69
11 changed files with 491 additions and 52 deletions

2
.cargo/config Normal file
View file

@ -0,0 +1,2 @@
[alias]
generate-manifest = "run --features maintainer -- maintainer"

1
.gitignore vendored
View file

@ -7,3 +7,4 @@ exercises/clippy/Cargo.toml
exercises/clippy/Cargo.lock exercises/clippy/Cargo.lock
.idea .idea
.vscode .vscode
exercises/Cargo.lock

66
Cargo.lock generated
View file

@ -134,7 +134,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -431,18 +431,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.4.30" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.6.12" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -602,8 +602,9 @@ dependencies = [
"notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
"predicates 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "predicates 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tooling 0.1.0",
] ]
[[package]] [[package]]
@ -639,20 +640,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.92" version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.92" version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -662,7 +663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -682,12 +683,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.15.34" version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -727,10 +728,19 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.4.10" version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tooling"
version = "0.1.0"
dependencies = [
"glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -750,7 +760,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.1.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -869,8 +879,8 @@ dependencies = [
"checksum predicates 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53e09015b0d3f5a0ec2d4428f7559bb7b3fff341b4e159fedd1d57fac8b939ff" "checksum predicates 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "53e09015b0d3f5a0ec2d4428f7559bb7b3fff341b4e159fedd1d57fac8b939ff"
"checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178" "checksum predicates-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "06075c3a3e92559ff8929e7a280684489ea27fe44805174c3ebd9328dcb37178"
"checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124" "checksum predicates-tree 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e63c4859013b38a76eca2414c64911fba30def9e3202ac461a2d22831220124"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
@ -892,22 +902,22 @@ dependencies = [
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" "checksum serde 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)" = "736aac72d1eafe8e5962d1d1c3d99b0df526015ba40915cb3c49d042e92ec243"
"checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" "checksum serde_derive 1.0.112 (registry+https://github.com/rust-lang/crates.io-index)" = "bf0343ce212ac0d3d6afd9391ac8e9c9efe06b533c8d33f660f6390cc4093f57"
"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum syn 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)" = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6"
"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea"
"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f" "checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a"
"checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" "checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"

View file

@ -4,14 +4,19 @@ version = "4.1.0"
authors = ["Marisa <mokou@posteo.de>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com>"] authors = ["Marisa <mokou@posteo.de>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com>"]
edition = "2018" edition = "2018"
[features]
# Internal tooling for maintainers
maintainer = ["tooling"]
[dependencies] [dependencies]
clap = "2.32.0" clap = "2.32.0"
indicatif = "0.10.3" indicatif = "0.10.3"
console = "0.7.7" console = "0.7.7"
notify = "4.0.15" notify = "4.0.15"
toml = "0.4.10" toml = "0.5.6"
regex = "1.1.6" regex = "1.1.6"
serde = {version = "1.0.10", features = ["derive"]} serde = {version = "1.0.10", features = ["derive"]}
tooling = { path = "./tooling", optional = true }
[[bin]] [[bin]]
name = "rustlings" name = "rustlings"
@ -21,3 +26,4 @@ path = "src/main.rs"
assert_cmd = "0.11.0" assert_cmd = "0.11.0"
predicates = "1.0.1" predicates = "1.0.1"
glob = "0.3.0" glob = "0.3.0"
tooling = { path = "./tooling" }

View file

@ -103,6 +103,17 @@ exercise:
rustlings hint myExercise1 rustlings hint myExercise1
``` ```
### Using an IDE
**TL,DR**: open the `exercises/` folder in your editor.
There are several editors and plugins that are able to analyze Rust code for a full blown IDE (or IDE-like) experience. The official language plugin of the Rust project is [rust-analyzer](rust-analyzer), but there are others, like [IntelliJ Rust](intellij) or [rls](rls).
These tools usually rely on the default structure of a Cargo project to perform their analyses. Conversely, Rustlings is conceived as a collection of isolated exercises. Nevertheless, we auto-generate a "fake" project manifest in `exercises/Cargo.toml` that should bypass this mismatch. If you open the `exercises/` folder with your Rust-enabled editor, you should be able to enjoy its capabilities.
[rust-analyzer]: https://rust-analyzer.github.io/
[rls]: https://github.com/rust-lang/rls
[intellij]: https://intellij-rust.github.io/
## Testing yourself ## Testing yourself
After every couple of sections, there will be a quiz that'll test your knowledge on a bunch of sections at once. These quizzes are found in `exercises/quizN.rs`. After every couple of sections, there will be a quiz that'll test your knowledge on a bunch of sections at once. These quizzes are found in `exercises/quizN.rs`.

286
exercises/Cargo.toml Normal file
View file

@ -0,0 +1,286 @@
# This Cargo.toml is AUTOGENERATED, you shouldn't need to edit it.
# The `rustling` commands do not rely on this manifest at all, its only purpose
# is to help editors analyze your code.
# To regenerate it, run `cargo generate-manifest`.
[package]
name = 'exercises'
version = '0.1.0'
edition = '2018'
authors = ['The Rustlings Maintainers']
publish = false
[[bin]]
name = 'clippy1'
path = 'clippy/clippy1.rs'
[[bin]]
name = 'clippy2'
path = 'clippy/clippy2.rs'
[[bin]]
name = 'as_ref_mut'
path = 'conversions/as_ref_mut.rs'
[[bin]]
name = 'from_into'
path = 'conversions/from_into.rs'
[[bin]]
name = 'from_str'
path = 'conversions/from_str.rs'
[[bin]]
name = 'try_from_into'
path = 'conversions/try_from_into.rs'
[[bin]]
name = 'using_as'
path = 'conversions/using_as.rs'
[[bin]]
name = 'enums1'
path = 'enums/enums1.rs'
[[bin]]
name = 'enums2'
path = 'enums/enums2.rs'
[[bin]]
name = 'enums3'
path = 'enums/enums3.rs'
[[bin]]
name = 'errors1'
path = 'error_handling/errors1.rs'
[[bin]]
name = 'errors2'
path = 'error_handling/errors2.rs'
[[bin]]
name = 'errors3'
path = 'error_handling/errors3.rs'
[[bin]]
name = 'errorsn'
path = 'error_handling/errorsn.rs'
[[bin]]
name = 'result1'
path = 'error_handling/result1.rs'
[[bin]]
name = 'functions1'
path = 'functions/functions1.rs'
[[bin]]
name = 'functions2'
path = 'functions/functions2.rs'
[[bin]]
name = 'functions3'
path = 'functions/functions3.rs'
[[bin]]
name = 'functions4'
path = 'functions/functions4.rs'
[[bin]]
name = 'functions5'
path = 'functions/functions5.rs'
[[bin]]
name = 'generics1'
path = 'generics/generics1.rs'
[[bin]]
name = 'generics2'
path = 'generics/generics2.rs'
[[bin]]
name = 'generics3'
path = 'generics/generics3.rs'
[[bin]]
name = 'if1'
path = 'if/if1.rs'
[[bin]]
name = 'if2'
path = 'if/if2.rs'
[[bin]]
name = 'macros1'
path = 'macros/macros1.rs'
[[bin]]
name = 'macros2'
path = 'macros/macros2.rs'
[[bin]]
name = 'macros3'
path = 'macros/macros3.rs'
[[bin]]
name = 'macros4'
path = 'macros/macros4.rs'
[[bin]]
name = 'modules1'
path = 'modules/modules1.rs'
[[bin]]
name = 'modules2'
path = 'modules/modules2.rs'
[[bin]]
name = 'move_semantics1'
path = 'move_semantics/move_semantics1.rs'
[[bin]]
name = 'move_semantics2'
path = 'move_semantics/move_semantics2.rs'
[[bin]]
name = 'move_semantics3'
path = 'move_semantics/move_semantics3.rs'
[[bin]]
name = 'move_semantics4'
path = 'move_semantics/move_semantics4.rs'
[[bin]]
name = 'option1'
path = 'option/option1.rs'
[[bin]]
name = 'option2'
path = 'option/option2.rs'
[[bin]]
name = 'primitive_types1'
path = 'primitive_types/primitive_types1.rs'
[[bin]]
name = 'primitive_types2'
path = 'primitive_types/primitive_types2.rs'
[[bin]]
name = 'primitive_types3'
path = 'primitive_types/primitive_types3.rs'
[[bin]]
name = 'primitive_types4'
path = 'primitive_types/primitive_types4.rs'
[[bin]]
name = 'primitive_types5'
path = 'primitive_types/primitive_types5.rs'
[[bin]]
name = 'primitive_types6'
path = 'primitive_types/primitive_types6.rs'
[[bin]]
name = 'quiz1'
path = 'quiz1.rs'
[[bin]]
name = 'quiz2'
path = 'quiz2.rs'
[[bin]]
name = 'quiz3'
path = 'quiz3.rs'
[[bin]]
name = 'quiz4'
path = 'quiz4.rs'
[[bin]]
name = 'arc1'
path = 'standard_library_types/arc1.rs'
[[bin]]
name = 'box1'
path = 'standard_library_types/box1.rs'
[[bin]]
name = 'iterators2'
path = 'standard_library_types/iterators2.rs'
[[bin]]
name = 'iterators3'
path = 'standard_library_types/iterators3.rs'
[[bin]]
name = 'iterators4'
path = 'standard_library_types/iterators4.rs'
[[bin]]
name = 'strings1'
path = 'strings/strings1.rs'
[[bin]]
name = 'strings2'
path = 'strings/strings2.rs'
[[bin]]
name = 'structs1'
path = 'structs/structs1.rs'
[[bin]]
name = 'structs2'
path = 'structs/structs2.rs'
[[bin]]
name = 'structs3'
path = 'structs/structs3.rs'
[[bin]]
name = 'tests1'
path = 'tests/tests1.rs'
[[bin]]
name = 'tests2'
path = 'tests/tests2.rs'
[[bin]]
name = 'tests3'
path = 'tests/tests3.rs'
[[bin]]
name = 'threads1'
path = 'threads/threads1.rs'
[[bin]]
name = 'traits1'
path = 'traits/traits1.rs'
[[bin]]
name = 'traits2'
path = 'traits/traits2.rs'
[[bin]]
name = 'variables1'
path = 'variables/variables1.rs'
[[bin]]
name = 'variables2'
path = 'variables/variables2.rs'
[[bin]]
name = 'variables3'
path = 'variables/variables3.rs'
[[bin]]
name = 'variables4'
path = 'variables/variables4.rs'
[[bin]]
name = 'variables5'
path = 'variables/variables5.rs'
[[bin]]
name = 'variables6'
path = 'variables/variables6.rs'

View file

@ -23,7 +23,7 @@ mod run;
mod verify; mod verify;
fn main() { fn main() {
let matches = App::new("rustlings") let app = App::new("rustlings")
.version(crate_version!()) .version(crate_version!())
.author("Olivia Hugger, Carol Nichols") .author("Olivia Hugger, Carol Nichols")
.about("Rustlings is a collection of small exercises to get you used to writing and reading Rust code") .about("Rustlings is a collection of small exercises to get you used to writing and reading Rust code")
@ -53,8 +53,18 @@ fn main() {
.alias("h") .alias("h")
.about("Returns a hint for the current exercise") .about("Returns a hint for the current exercise")
.arg(Arg::with_name("name").required(true).index(1)), .arg(Arg::with_name("name").required(true).index(1)),
) );
.get_matches();
let matches;
#[cfg(feature = "maintainer")]
{
let app = app.subcommand(SubCommand::with_name("maintainer"));
matches = app.get_matches();
}
#[cfg(not(feature = "maintainer"))]
{
matches = app.get_matches();
}
if matches.subcommand_name().is_none() { if matches.subcommand_name().is_none() {
println!(); println!();
@ -88,6 +98,13 @@ fn main() {
let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises; let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises;
let verbose = matches.is_present("nocapture"); let verbose = matches.is_present("nocapture");
#[cfg(feature = "maintainer")]
{
if matches.subcommand_matches("maintainer").is_some() {
maintainer();
}
}
if let Some(ref matches) = matches.subcommand_matches("run") { if let Some(ref matches) = matches.subcommand_matches("run") {
let name = matches.value_of("name").unwrap(); let name = matches.value_of("name").unwrap();
@ -217,3 +234,9 @@ fn rustc_exists() -> bool {
.map(|status| status.success()) .map(|status| status.success())
.unwrap_or(false) .unwrap_or(false)
} }
#[cfg(feature = "maintainer")]
fn maintainer() {
let manifest = tooling::generate(&Path::new("exercises"));
fs::write("exercises/Cargo.toml", manifest).unwrap();
}

View file

@ -1,8 +1,5 @@
use assert_cmd::prelude::*; use assert_cmd::prelude::*;
use glob::glob;
use predicates::boolean::PredicateBooleanExt; use predicates::boolean::PredicateBooleanExt;
use std::fs::File;
use std::io::Read;
use std::process::Command; use std::process::Command;
#[test] #[test]
@ -121,23 +118,6 @@ fn get_hint_for_single_test() {
.stdout("Hello!\n"); .stdout("Hello!\n");
} }
#[test]
fn all_exercises_require_confirmation() {
for exercise in glob("exercises/**/*.rs").unwrap() {
let path = exercise.unwrap();
let source = {
let mut file = File::open(&path).unwrap();
let mut s = String::new();
file.read_to_string(&mut s).unwrap();
s
};
source.matches("// I AM NOT DONE").next().expect(&format!(
"There should be an `I AM NOT DONE` annotation in {:?}",
path
));
}
}
#[test] #[test]
fn run_compile_exercise_does_not_prompt() { fn run_compile_exercise_does_not_prompt() {
Command::cargo_bin("rustlings") Command::cargo_bin("rustlings")

View file

@ -0,0 +1,30 @@
use glob::glob;
use std::fs;
use std::path::{Path, PathBuf};
#[test]
fn all_exercises_require_confirmation() {
for path in all_exercises() {
let source = fs::read_to_string(&path).unwrap();
source.matches("// I AM NOT DONE").next().expect(&format!(
"There should be an `I AM NOT DONE` annotation in {:?}",
path
));
}
}
#[test]
fn cargo_toml_is_up_to_date() {
let exercises_manifest = fs::read_to_string("exercises/Cargo.toml").unwrap();
let generated_manifest = tooling::generate(&Path::new("exercises"));
assert_eq!(
generated_manifest, exercises_manifest,
"exercises/Cargo.toml is not up to date, run `cargo generate-manifest`"
);
}
fn all_exercises() -> impl Iterator<Item = PathBuf> {
glob("exercises/**/*.rs")
.unwrap()
.map(|result| result.expect("Unable to traverse exercises folder"))
}

11
tooling/Cargo.toml Normal file
View file

@ -0,0 +1,11 @@
[package]
name = "tooling"
version = "0.1.0"
authors = ["The Rustlings Maintainers"]
edition = "2018"
publish = false
[dependencies]
glob = "0.3.0"
serde = { version = "1.0.112", feature = ["derive"] }
toml = "0.5.6"

79
tooling/src/lib.rs Normal file
View file

@ -0,0 +1,79 @@
use glob::glob;
use serde::Serialize;
use std::path::Path;
use toml;
pub fn generate(root: &Path) -> String {
let mut bins = vec![];
let root_glob = {
let mut p = root.to_owned();
p.push("**");
p.push("*.rs");
p
};
let mut exercise_paths: Vec<_> = glob(root_glob.to_str().unwrap())
.unwrap()
.collect::<Result<_, _>>()
.expect("Error traversing root");
exercise_paths.sort();
for path in &exercise_paths {
let name = path
.file_stem()
.expect("Malformed exercise path")
.to_str()
.expect("Invalid UTF8 in exercise path")
.to_string();
let target_path = path.strip_prefix(root).unwrap();
bins.push(Bin {
name,
path: target_path.to_str().unwrap().to_string(),
});
}
let manifest = Manifest {
package: Package {
name: "exercises",
version: "0.1.0",
authors: &["The Rustlings Maintainers"],
edition: "2018",
publish: false,
},
bin: bins,
};
format!(
"# This Cargo.toml is AUTOGENERATED, you shouldn't need to edit it.\n\
# The `rustling` commands do not rely on this manifest at all, its only purpose\n\
# is to help editors analyze your code.\n\
# To regenerate it, run `cargo generate-manifest`.\n\
{}",
toml::ser::to_string_pretty(&manifest).expect("Invalid toml")
)
}
#[derive(Serialize)]
struct Manifest {
package: Package,
bin: Vec<Bin>,
}
#[derive(Serialize)]
struct Package {
name: &'static str,
version: &'static str,
edition: &'static str,
authors: &'static [&'static str],
publish: bool,
}
#[derive(Serialize)]
struct Bin {
name: String,
path: String,
}