mod masm;
use alloc::borrow::Cow;
use core::ops::ControlFlow;
use miden_assembly_syntax::debuginfo::SourceManager;
use miden_package_registry::PackageRegistryAndProvider;
use miden_project::ProjectDependencyGraph;
pub use self::masm::MasmSourceProvider;
use super::*;
pub struct TargetAssemblyContext<'a> {
pub package: Arc<ProjectPackage>,
pub manifest_path: &'a std::path::Path,
pub project_root: Cow<'a, std::path::Path>,
pub resolved_target_root: Box<std::path::Path>,
pub target: &'a Target,
pub profile: &'a Profile,
pub dependency_graph: &'a ProjectDependencyGraph,
pub source_manager: Arc<dyn SourceManager>,
pub package_registry: &'a dyn PackageRegistryAndProvider,
pub warnings_as_errors: bool,
}
impl<'a> TargetAssemblyContext<'a> {
pub fn new(
package: Arc<ProjectPackage>,
manifest_path: &'a std::path::Path,
target: &'a Target,
profile: &'a Profile,
dependency_graph: &'a ProjectDependencyGraph,
package_registry: &'a dyn PackageRegistryAndProvider,
source_manager: Arc<dyn SourceManager>,
) -> Result<Self, Report> {
let project_root = manifest_path.parent().ok_or_else(|| {
Report::msg(format!("manifest '{}' has no parent directory", manifest_path.display()))
})?;
let target_path = target.path.to_path().ok_or_else(|| {
Report::msg(format!(
"invalid target '{}': '{}' is not a valid file path",
target.name.inner(),
target.path
))
})?;
let root_path = project_root.join(&target_path);
let root_path = root_path.canonicalize().map_err(|error| {
Report::msg(format!(
"failed to resolve target source '{}': {error}",
root_path.display()
))
})?;
Ok(TargetAssemblyContext {
package,
manifest_path,
project_root: project_root.into(),
resolved_target_root: root_path.into_boxed_path(),
target,
profile,
dependency_graph,
source_manager,
package_registry,
warnings_as_errors: false,
})
}
pub fn new_virtual(
package: Arc<ProjectPackage>,
target: &'a Target,
profile: &'a Profile,
dependency_graph: &'a ProjectDependencyGraph,
package_registry: &'a dyn PackageRegistryAndProvider,
source_manager: Arc<dyn SourceManager>,
) -> Result<Self, Report> {
let target_path = target.path.to_path().ok_or_else(|| {
Report::msg(format!(
"invalid target '{}': '{}' is not a valid file path",
target.name.inner(),
target.path
))
})?;
let target_path = target_path.canonicalize().unwrap_or(target_path.clone());
let resolved_target_root = target_path.clone().into_boxed_path();
let project_root = target_path
.parent()
.map(std::path::Path::to_path_buf)
.unwrap_or(PathBuf::from("."));
Ok(TargetAssemblyContext {
package,
manifest_path: std::path::Path::new(""),
project_root: project_root.into(),
resolved_target_root,
target,
profile,
dependency_graph,
source_manager,
package_registry,
warnings_as_errors: false,
})
}
#[inline]
pub fn with_warnings_as_errors(&mut self, yes: bool) -> &mut Self {
self.warnings_as_errors = yes;
self
}
}
pub trait ProjectSourceProvider {
fn file_type(&self) -> &'static str;
fn provide_sources(
&self,
context: &TargetAssemblyContext<'_>,
) -> Result<ProjectSourceInputs, Report>;
fn provide_sources_interruptible(
&self,
context: &TargetAssemblyContext<'_>,
) -> Result<ControlFlow<(), ProjectSourceInputs>, Report> {
self.provide_sources(context).map(ControlFlow::Continue)
}
fn provide_source_provenance(
&self,
context: &TargetAssemblyContext<'_>,
) -> Result<ProjectSourceProvenanceInputs, Report>;
#[allow(unused_variables)]
fn post_process_package(
&self,
package: &mut MastPackage,
context: &TargetAssemblyContext<'_>,
) -> Result<(), Report> {
Ok(())
}
}