use indexmap::IndexMap;
use miette::{Diagnostic, SourceSpan};
use wac_parser::Document;
mod fs;
#[cfg(feature = "registry")]
mod registry;
mod visitor;
pub use fs::*;
#[cfg(feature = "registry")]
pub use registry::*;
pub use visitor::*;
use wac_types::BorrowedPackageKey;
#[derive(thiserror::Error, Diagnostic, Debug)]
#[diagnostic(code("failed to resolve document"))]
pub enum Error {
#[error("failed to create registry client: {0:#}")]
RegistryClientFailed(anyhow::Error),
#[error("unknown package `{name}`")]
UnknownPackage {
name: String,
#[label(primary, "unknown package `{name}`")]
span: SourceSpan,
},
#[error("invalid package name `{name}`")]
InvalidPackageName {
name: String,
#[label(primary, "invalid package name `{name}`")]
span: SourceSpan,
},
#[cfg(feature = "registry")]
#[error("version {version} of package `{name}` does not exist")]
UnknownPackageVersion {
name: String,
version: semver::Version,
#[label(primary, "unknown package version `{version}`")]
span: SourceSpan,
},
#[error("cannot instantiate the package being defined")]
CannotInstantiateSelf {
#[label(primary, "cannot instantiate self")]
span: SourceSpan,
},
#[error("package `{name}` does not exist in the registry")]
PackageDoesNotExist {
name: String,
#[label(primary, "package `{name}` does not exist")]
span: SourceSpan,
},
#[cfg(feature = "registry")]
#[error("version {version} of package `{name}` does not exist")]
PackageVersionDoesNotExist {
name: String,
version: semver::Version,
#[label(primary, "{version} does not exist")]
span: SourceSpan,
},
#[cfg(feature = "registry")]
#[error("package `{name}` has no releases")]
PackageNoReleases {
name: String,
#[label(primary, "package `{name}` has no releases")]
span: SourceSpan,
},
#[cfg(feature = "registry")]
#[error("failed to update registry logs")]
RegistryUpdateFailure {
#[source]
source: anyhow::Error,
},
#[cfg(feature = "registry")]
#[error("failed to download content from the registry")]
RegistryDownloadFailure {
#[source]
source: anyhow::Error,
},
#[cfg(feature = "registry")]
#[error("failed to read content path `{path}`", path = .path.display())]
RegistryContentFailure {
path: std::path::PathBuf,
#[source]
source: anyhow::Error,
},
#[error("failed to resolve package `{name}`")]
PackageResolutionFailure {
name: String,
#[label(primary, "package `{name}` failed to resolve")]
span: SourceSpan,
#[source]
source: anyhow::Error,
},
}
pub fn packages<'a>(
document: &'a Document<'a>,
) -> Result<IndexMap<BorrowedPackageKey<'a>, SourceSpan>, Error> {
let mut keys = IndexMap::new();
let mut visitor = PackageVisitor::new(|name, version, span| {
if name == document.directive.package.name {
return true;
}
if keys
.insert(
BorrowedPackageKey::from_name_and_version(name, version),
span,
)
.is_none()
{
if let Some(version) = version {
log::debug!("discovered reference to package `{name}` ({version})");
} else {
log::debug!("discovered reference to package `{name}`");
}
}
true
});
visitor.visit(document)?;
Ok(keys)
}