forked from bytecodealliance/wasm-tools
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable omitting versions in world selection
Similar to how if a name isn't provided and a package only has one world, if a name is provided and it looks like an "id" and there's only one package with that name/namespace combo then the package version can be omitted.
- Loading branch information
1 parent
722b599
commit 53b9c6f
Showing
1 changed file
with
91 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -570,13 +570,34 @@ impl Resolve { | |
.with_context(|| format!("failed to parse world specifier `{world}`"))?; | ||
let (pkg, world) = match path { | ||
AstUsePath::Name(name) => (pkg, name), | ||
AstUsePath::Package(pkg, interface) => ( | ||
*self | ||
.package_names | ||
.get(&pkg) | ||
.ok_or_else(|| anyhow!("unknown package `{pkg}`"))?, | ||
interface, | ||
), | ||
AstUsePath::Package(pkg, interface) => { | ||
let pkg = match self.package_names.get(&pkg) { | ||
Some(pkg) => *pkg, | ||
None => { | ||
let mut candidates = self.package_names.iter().filter(|(name, _)| { | ||
pkg.version.is_none() | ||
&& pkg.name == name.name | ||
&& pkg.namespace == name.namespace | ||
&& name.version.is_some() | ||
}); | ||
let candidate = candidates.next(); | ||
if let Some((c2, _)) = candidates.next() { | ||
let (c1, _) = candidate.unwrap(); | ||
bail!( | ||
"package name `{pkg}` is available at both \ | ||
versions {} and {} but which is not specified", | ||
c1.version.as_ref().unwrap(), | ||
c2.version.as_ref().unwrap(), | ||
); | ||
} | ||
match candidate { | ||
Some((_, id)) => *id, | ||
None => bail!("unknown package `{pkg}`"), | ||
} | ||
} | ||
}; | ||
(pkg, interface) | ||
} | ||
}; | ||
let pkg = &self.packages[pkg]; | ||
pkg.worlds | ||
|
@@ -1781,3 +1802,66 @@ impl<'a> MergeMap<'a> { | |
Ok(()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::{PackageId, Resolve}; | ||
|
||
#[test] | ||
fn select_world() { | ||
let mut resolve = Resolve::default(); | ||
parse_into( | ||
&mut resolve, | ||
r#" | ||
package foo:[email protected] | ||
world foo {} | ||
"#, | ||
); | ||
parse_into( | ||
&mut resolve, | ||
r#" | ||
package foo:[email protected] | ||
world foo {} | ||
"#, | ||
); | ||
parse_into( | ||
&mut resolve, | ||
r#" | ||
package foo:[email protected] | ||
world foo {} | ||
"#, | ||
); | ||
|
||
let dummy = parse_into( | ||
&mut resolve, | ||
r#" | ||
package foo:dummy | ||
world foo {} | ||
"#, | ||
); | ||
|
||
assert!(resolve.select_world(dummy, None).is_ok()); | ||
assert!(resolve.select_world(dummy, Some("xx")).is_err()); | ||
assert!(resolve.select_world(dummy, Some("")).is_err()); | ||
assert!(resolve.select_world(dummy, Some("foo:bar/foo")).is_ok()); | ||
assert!(resolve | ||
.select_world(dummy, Some("foo:bar/[email protected]")) | ||
.is_ok()); | ||
assert!(resolve.select_world(dummy, Some("foo:baz/foo")).is_err()); | ||
assert!(resolve | ||
.select_world(dummy, Some("foo:baz/[email protected]")) | ||
.is_ok()); | ||
assert!(resolve | ||
.select_world(dummy, Some("foo:baz/[email protected]")) | ||
.is_ok()); | ||
} | ||
|
||
fn parse_into(resolve: &mut Resolve, wit: &str) -> PackageId { | ||
let pkg = crate::UnresolvedPackage::parse("input.wit".as_ref(), wit).unwrap(); | ||
resolve.push(pkg).unwrap() | ||
} | ||
} |