Skip to content

Commit 27e449c

Browse files
authored
Merge pull request #31 from bkchr/bkchr-fix-multiple-crates
Fix finding crates which import itself
2 parents 2309ded + a9aa118 commit 27e449c

File tree

2 files changed

+95
-10
lines changed

2 files changed

+95
-10
lines changed

README.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# proc-macro-crate
22

33

4-
[![](https://docs.rs/proc-macro-crate/badge.svg)](https://docs.rs/proc-macro-crate) [![](https://img.shields.io/crates/v/proc-macro-crate.svg)](https://crates.io/crates/proc-macro-crate) [![](https://img.shields.io/crates/d/proc-macro-crate.svg)](https://crates.io/crates/proc-macro-crate) [![Build Status](https://travis-ci.org/bkchr/proc-macro-crate.svg?branch=master)](https://travis-ci.org/bkchr/proc-macro-crate)
4+
[![](https://docs.rs/proc-macro-crate/badge.svg)](https://docs.rs/proc-macro-crate/) [![](https://img.shields.io/crates/v/proc-macro-crate.svg)](https://crates.io/crates/proc-macro-crate) [![](https://img.shields.io/crates/d/proc-macro-crate.png)](https://crates.io/crates/proc-macro-crate) [![Build Status](https://travis-ci.org/bkchr/proc-macro-crate.png?branch=master)](https://travis-ci.org/bkchr/proc-macro-crate)
55

66
Providing support for `$crate` in procedural macros.
77

@@ -13,7 +13,7 @@ Providing support for `$crate` in procedural macros.
1313

1414
In `macro_rules!` `$crate` is used to get the path of the crate where a macro is declared in. In
1515
procedural macros there is currently no easy way to get this path. A common hack is to import the
16-
desired crate with a know name and use this. However, with Rust edition 2018 and dropping
16+
desired crate with a know name and use this. However, with rust edition 2018 and dropping
1717
`extern crate` declarations from `lib.rs`, people start to rename crates in `Cargo.toml` directly.
1818
However, this breaks importing the crate, as the proc-macro developer does not know the renamed
1919
name of the crate that should be imported.
@@ -45,6 +45,35 @@ fn import_my_crate() {
4545

4646
```
4747

48+
### Edge cases
49+
50+
There are multiple edge cases when it comes to determining the correct crate. If you for example
51+
import a crate as its own dependency, like this:
52+
53+
```toml
54+
[package]
55+
name = "my_crate"
56+
57+
[dev-dependencies]
58+
my_crate = { version = "0.1", features = [ "test-feature" ] }
59+
```
60+
61+
The crate will return `FoundCrate::Itself` and you will not be able to find the other instance
62+
of your crate in `dev-dependencies`. Other similar cases are when one crate is imported multiple
63+
times:
64+
65+
```toml
66+
[package]
67+
name = "my_crate"
68+
69+
[dependencies]
70+
some-crate = { version = "0.5" }
71+
some-crate-old = { package = "some-crate", version = "0.1" }
72+
```
73+
74+
When searching for `some-crate` in this `Cargo.toml` it will return `FoundCrate::Name("some_old_crate")`,
75+
aka the last definition of the crate in the `Cargo.toml`.
76+
4877
### License
4978

5079
Licensed under either of
@@ -55,4 +84,4 @@ Licensed under either of
5584

5685
at your option.
5786

58-
License: Apache-2.0/MIT
87+
License: MIT OR Apache-2.0

src/lib.rs

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,42 @@ fn import_my_crate() {
4545
# fn main() {}
4646
```
4747
48+
## Edge cases
49+
50+
There are multiple edge cases when it comes to determining the correct crate. If you for example
51+
import a crate as its own dependency, like this:
52+
53+
```toml
54+
[package]
55+
name = "my_crate"
56+
57+
[dev-dependencies]
58+
my_crate = { version = "0.1", features = [ "test-feature" ] }
59+
```
60+
61+
The crate will return `FoundCrate::Itself` and you will not be able to find the other instance
62+
of your crate in `dev-dependencies`. Other similar cases are when one crate is imported multiple
63+
times:
64+
65+
```toml
66+
[package]
67+
name = "my_crate"
68+
69+
[dependencies]
70+
some-crate = { version = "0.5" }
71+
some-crate-old = { package = "some-crate", version = "0.1" }
72+
```
73+
74+
When searching for `some-crate` in this `Cargo.toml` it will return `FoundCrate::Name("some_old_crate")`,
75+
aka the last definition of the crate in the `Cargo.toml`.
76+
4877
## License
4978
5079
Licensed under either of
5180
52-
* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
81+
* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
5382
54-
* [MIT license](http://opensource.org/licenses/MIT)
83+
* [MIT license](https://opensource.org/licenses/MIT)
5584
5685
at your option.
5786
*/
@@ -227,26 +256,31 @@ fn open_cargo_toml(path: &Path) -> Result<Document, Error> {
227256
/// `dev-dependencies`.
228257
fn extract_crate_names(cargo_toml: &Document) -> Result<CrateNames, Error> {
229258
let package_name = extract_package_name(cargo_toml);
230-
let root_pkg = package_name.map(|name| {
259+
let root_pkg = package_name.as_ref().map(|name| {
231260
let cr = match env::var_os("CARGO_TARGET_TMPDIR") {
232261
// We're running for a library/binary crate
233262
None => FoundCrate::Itself,
234263
// We're running for an integration test
235264
Some(_) => FoundCrate::Name(sanitize_crate_name(name)),
236265
};
237266

238-
(name.to_owned(), cr)
267+
(name.to_string(), cr)
239268
});
240269

241270
let dep_tables = dep_tables(cargo_toml).chain(target_dep_tables(cargo_toml));
242-
let dep_pkgs = dep_tables.flatten().map(|(dep_name, dep_value)| {
271+
let dep_pkgs = dep_tables.flatten().filter_map(move |(dep_name, dep_value)| {
243272
let pkg_name = dep_value
244273
.get("package")
245274
.and_then(|i| i.as_str())
246275
.unwrap_or(dep_name);
276+
277+
if package_name.as_ref().map_or(false, |n| *n == pkg_name) {
278+
return None;
279+
}
280+
247281
let cr = FoundCrate::Name(sanitize_crate_name(dep_name));
248282

249-
(pkg_name.to_owned(), cr)
283+
Some((pkg_name.to_owned(), cr))
250284
});
251285

252286
Ok(root_pkg.into_iter().chain(dep_pkgs).collect())
@@ -291,7 +325,7 @@ mod tests {
291325
fn $name() {
292326
let cargo_toml = $cargo_toml.parse::<Document>().expect("Parses `Cargo.toml`");
293327

294-
match extract_crate_names(&cargo_toml).map(|mut map| map.remove("my_crate")) {
328+
match extract_crate_names(&cargo_toml).map(|mut map| map.remove("my_crate")) {
295329
$( $result )* => (),
296330
o => panic!("Invalid result: {:?}", o),
297331
}
@@ -379,4 +413,26 @@ mod tests {
379413
"#,
380414
Ok(Some(FoundCrate::Itself))
381415
}
416+
417+
create_test! {
418+
own_crate_and_in_deps,
419+
r#"
420+
[package]
421+
name = "my_crate"
422+
423+
[dev-dependencies]
424+
my_crate = "0.1"
425+
"#,
426+
Ok(Some(FoundCrate::Itself))
427+
}
428+
429+
create_test! {
430+
multiple_times,
431+
r#"
432+
[dependencies]
433+
my_crate = { version = "0.5" }
434+
my-crate-old = { package = "my_crate", version = "0.1" }
435+
"#,
436+
Ok(Some(FoundCrate::Name(name))) if name == "my_crate_old"
437+
}
382438
}

0 commit comments

Comments
 (0)