pedant_core/resolution/rust/snapshot/
resolution.rs1use std::path::Path;
9use std::sync::Arc;
10
11use crate::resolution::rust::identity::{TargetId, index_of, position};
12use crate::resolution::rust::limits::ResolutionLimits;
13use crate::resolution::rust::project::RustProject;
14use crate::resolution::rust::warning::{self, RustResolutionWarning};
15
16use super::authority;
17use super::closure::{self, ClosureEntry};
18use super::error::{RustSnapshotError, SourceClosureFailure};
19use super::selection::{self, EdgeDraft, Selection, UnitDraft};
20use super::source::{self, RustSource};
21use super::store::{SourceStore, refuse};
22use super::unit::{RustResolutionUnit, RustSnapshotEdge, RustSnapshotUnitId};
23
24#[derive(Debug)]
27pub struct RustResolutionSnapshot {
28 root: Box<Path>,
29 root_target: TargetId,
30 limits: ResolutionLimits,
31 root_unit: RustSnapshotUnitId,
32 units: Box<[RustResolutionUnit]>,
33 edges: Box<[RustSnapshotEdge]>,
34 sources: Box<[RustSource]>,
35 warnings: Box<[RustResolutionWarning]>,
36}
37
38impl RustResolutionSnapshot {
39 pub fn root(&self) -> &Path {
43 &self.root
44 }
45
46 pub fn root_target(&self) -> TargetId {
48 self.root_target
49 }
50
51 pub fn root_unit(&self) -> RustSnapshotUnitId {
53 self.root_unit
54 }
55
56 pub fn limits(&self) -> ResolutionLimits {
58 self.limits
59 }
60
61 pub fn units(&self) -> &[RustResolutionUnit] {
63 &self.units
64 }
65
66 pub fn unit(&self, id: RustSnapshotUnitId) -> Option<&RustResolutionUnit> {
68 self.units.get(index_of(id.index()))
69 }
70
71 pub fn edges(&self) -> &[RustSnapshotEdge] {
73 &self.edges
74 }
75
76 pub fn sources(&self) -> &[RustSource] {
78 &self.sources
79 }
80
81 pub fn warnings(&self) -> &[RustResolutionWarning] {
84 &self.warnings
85 }
86
87 pub fn source(&self, path: &str) -> Option<&RustSource> {
89 source::find(&self.sources, path)
90 }
91}
92
93pub(in crate::resolution::rust) fn build(
95 project: &RustProject,
96 id: TargetId,
97) -> Result<RustResolutionSnapshot, RustSnapshotError> {
98 let root = authority::validated_target(project, id)?;
99 let selection = selection::select(project, root)?;
100 let mut store = SourceStore::new(project.root(), project.limits());
101 let mut failures = Vec::new();
102 let units = build_units(&selection, &mut store, &mut failures);
103 match failures.is_empty() {
104 false => Err(refuse(&store, failures)),
105 true => {
106 let warnings = warning::shared_sources(&units);
107 Ok(RustResolutionSnapshot {
108 root: Box::from(project.root()),
109 root_target: id,
110 limits: project.limits(),
111 root_unit: RustSnapshotUnitId::new(selection.root),
112 edges: build_edges(&selection.edges),
113 sources: store.finish(),
114 units,
115 warnings,
116 })
117 }
118 }
119}
120
121fn build_units(
122 selection: &Selection,
123 store: &mut SourceStore,
124 failures: &mut Vec<SourceClosureFailure>,
125) -> Box<[RustResolutionUnit]> {
126 let mut units = Vec::new();
127 for (index, draft) in selection.units.iter().enumerate() {
128 let seen = failures.len();
129 units.extend(build_unit((draft, index), store, failures));
130 if failures
131 .iter()
132 .skip(seen)
133 .any(SourceClosureFailure::is_fatal)
134 {
135 break;
136 }
137 }
138 units.into_boxed_slice()
139}
140
141fn build_unit(
142 draft: (&UnitDraft, usize),
143 store: &mut SourceStore,
144 failures: &mut Vec<SourceClosureFailure>,
145) -> Option<RustResolutionUnit> {
146 let (unit, index) = draft;
147 let entry = ClosureEntry {
148 target_name: &unit.target_name,
149 entry_path: &unit.entry,
150 edition: unit.edition,
151 };
152 let closure = closure::walk_unit(store, &entry, failures)?;
153 Some(RustResolutionUnit {
154 id: RustSnapshotUnitId::new(position(index)),
155 package: unit.package,
156 target: unit.target,
157 name: Arc::clone(&unit.target_name),
158 manifest: Arc::clone(&unit.manifest),
159 kind: unit.kind,
160 activation: unit.predicate.activation(),
161 crate_root: Arc::clone(&unit.entry),
162 modules: closure.modules,
163 sources: closure.sources,
164 })
165}
166
167fn build_edges(drafts: &[EdgeDraft]) -> Box<[RustSnapshotEdge]> {
168 drafts
169 .iter()
170 .map(|draft| RustSnapshotEdge {
171 source: RustSnapshotUnitId::new(draft.source),
172 target: RustSnapshotUnitId::new(draft.target),
173 name: Arc::clone(&draft.name),
174 kind: draft.kind,
175 activation: draft.predicate.activation(),
176 })
177 .collect()
178}