1#[cfg(feature = "std")]
2use std::{boxed::Box, path::Path};
3
4#[cfg(feature = "std")]
5use miden_assembly_syntax::debuginfo::Spanned;
6
7#[cfg(feature = "std")]
8use crate::ast::{ProjectFileError, WorkspaceFile};
9use crate::*;
10
11#[derive(Debug)]
13pub struct Package {
14 #[cfg(feature = "std")]
16 manifest_path: Option<Box<Path>>,
17 name: Span<Arc<str>>,
19 version: Span<SemVer>,
21 description: Option<Arc<str>>,
23 dependencies: Vec<Dependency>,
25 lints: MetadataSet,
29 metadata: MetadataSet,
33 lib: Option<Span<Target>>,
35 bins: Vec<Span<Target>>,
37 profiles: Vec<Profile>,
39}
40
41impl Package {
43 pub fn name(&self) -> Span<Arc<str>> {
45 self.name.clone()
46 }
47
48 pub fn version(&self) -> Span<&SemVer> {
50 self.version.as_ref()
51 }
52
53 pub fn description(&self) -> Option<Arc<str>> {
55 self.description.clone()
56 }
57
58 pub fn dependencies(&self) -> &[Dependency] {
60 &self.dependencies
61 }
62
63 pub fn num_dependencies(&self) -> usize {
65 self.dependencies.len()
66 }
67
68 pub fn lints(&self) -> &MetadataSet {
70 &self.lints
71 }
72
73 pub fn metadata(&self) -> &MetadataSet {
75 &self.metadata
76 }
77
78 pub fn profiles(&self) -> &[Profile] {
80 &self.profiles
81 }
82
83 pub fn library_target(&self) -> Option<&Span<Target>> {
85 self.lib.as_ref()
86 }
87
88 pub fn executable_targets(&self) -> &[Span<Target>] {
90 &self.bins
91 }
92
93 #[cfg(feature = "std")]
95 pub fn manifest_path(&self) -> Option<&Path> {
96 self.manifest_path.as_deref()
97 }
98}
99
100#[cfg(all(feature = "std", feature = "serde"))]
102impl Package {
103 pub fn load(source: Arc<SourceFile>) -> Result<Box<Self>, Report> {
106 Self::parse(source, None)
107 }
108
109 pub fn load_from_workspace(
112 source: Arc<SourceFile>,
113 workspace: &WorkspaceFile,
114 ) -> Result<Box<Self>, Report> {
115 Self::parse(source, Some(workspace))
116 }
117
118 fn parse(
119 source: Arc<SourceFile>,
120 workspace: Option<&WorkspaceFile>,
121 ) -> Result<Box<Self>, Report> {
122 let manifest_path = Path::new(source.uri().path());
123 let manifest_path = if manifest_path.try_exists().is_ok_and(|exists| exists) {
124 Some(manifest_path.to_path_buf().into_boxed_path())
125 } else {
126 None
127 };
128
129 let package_ast = ast::ProjectFile::parse(source.clone())?;
131
132 let version = package_ast.get_or_inherit_version(source.clone(), workspace)?;
134 let description = package_ast.get_or_inherit_description(source.clone(), workspace)?;
135
136 let mut profiles = Vec::default();
138 profiles.push(Profile::default());
139 profiles.push(Profile::release());
140 if let Some(workspace) = workspace {
141 for ast in workspace.profiles.iter() {
142 profiles.push(Profile::from_ast(ast, source.clone(), &profiles)?);
143 }
144 }
145
146 let package_profiles_start = profiles.len();
150 for ast in package_ast.profiles.iter() {
151 let profile = Profile::from_ast(ast, source.clone(), &profiles)?;
152
153 if let Some(prev_index) = profiles.iter().position(|p| p.name() == profile.name()) {
154 if prev_index < package_profiles_start {
155 profiles[prev_index].merge(&profile);
156 } else {
157 let prev = &profiles[prev_index];
158 return Err(ProjectFileError::DuplicateProfile {
159 name: prev.name().clone(),
160 source_file: source,
161 span: profile.span(),
162 prev: prev.span(),
163 }
164 .into());
165 }
166 } else {
167 profiles.push(profile);
168 }
169 }
170
171 let dependencies = package_ast.extract_dependencies(source.clone(), workspace)?;
174
175 let lib = package_ast.extract_library_target()?;
177 let bins = package_ast.extract_executable_targets();
178
179 let mut lints = workspace.map(|ws| ws.workspace.config.lints.clone()).unwrap_or_default();
180 lints.extend(package_ast.config.lints.clone());
181
182 let mut metadata =
183 workspace.map(|ws| ws.workspace.package.metadata.clone()).unwrap_or_default();
184 metadata.extend(package_ast.package.detail.metadata.clone());
185
186 Ok(Box::new(Self {
187 manifest_path,
188 name: package_ast.package.name.clone(),
189 version,
190 description,
191 dependencies,
192 lints,
193 metadata,
194 profiles,
195 lib,
196 bins,
197 }))
198 }
199}