Skip to content

Commit 4c1ebf4

Browse files
author
Grant Wuerker
committed
ingot file resolution diagnostics
1 parent 3a3c789 commit 4c1ebf4

File tree

9 files changed

+304
-253
lines changed

9 files changed

+304
-253
lines changed

crates/driver/src/lib.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,28 @@ pub use db::DriverDataBase;
1515
use common::config::Config;
1616
use hir::hir_def::TopLevelMod;
1717
use resolver::{
18-
files::{File, FilesResolutionDiagnostic, FilesResolutionError, FilesResolver},
19-
graph::{DiGraph, GraphResolutionHandler, GraphResolver},
20-
ingot::ingot_graph_resolver,
18+
files::{FilesResource, FilesResolutionDiagnostic, FilesResolutionError, FilesResolver},
19+
graph::{DiGraph, GraphResolutionHandler, GraphResolver, GraphResolverImpl},
2120
ResolutionHandler, Resolver,
2221
};
2322
use url::Url;
2423

24+
pub type CheckIngotGraphResolver<'a> = GraphResolverImpl<FilesResolver, InputHandler<'a>, EdgeWeight>;
25+
26+
pub fn check_ingot_graph_resolver<'a>() -> CheckIngotGraphResolver<'a> {
27+
let files_resolver = FilesResolver::new()
28+
.with_required_file("fe.toml")
29+
.with_required_directory("src")
30+
.with_required_file("src/lib.fe")
31+
.with_pattern("src/**/*.fe");
32+
GraphResolverImpl::new(files_resolver)
33+
}
34+
2535
pub fn init_ingot(db: &mut DriverDataBase, ingot_url: &Url) -> Vec<IngotInitDiagnostics> {
2636
tracing::trace!(target: "resolver", "Starting workspace ingot resolution for: {}", ingot_url);
2737
let mut diagnostics: Vec<IngotInitDiagnostics> = {
28-
let mut handler = InputHandler::from_db(db);
29-
let mut ingot_graph_resolver = ingot_graph_resolver::<InputHandler>();
38+
let mut handler = InputHandler::from_db(db, ingot_url.clone());
39+
let mut ingot_graph_resolver = check_ingot_graph_resolver();
3040

3141
// Handle resolution errors gracefully instead of panicking
3242
if let Err(err) = ingot_graph_resolver.graph_resolve(&mut handler, ingot_url) {
@@ -115,6 +125,10 @@ pub enum IngotInitDiagnostics {
115125
ingot_url: Url,
116126
diagnostic: common::config::ConfigDiagnostic,
117127
},
128+
MissingRootFile {
129+
ingot_url: Url,
130+
is_main_ingot: bool,
131+
},
118132
}
119133

120134
impl std::fmt::Display for IngotInitDiagnostics {
@@ -165,6 +179,13 @@ impl std::fmt::Display for IngotInitDiagnostics {
165179
} => {
166180
write!(f, "there are issues with the local fe.toml file {ingot_url}fe.toml\n {diagnostic}")
167181
}
182+
IngotInitDiagnostics::MissingRootFile { ingot_url, is_main_ingot } => {
183+
if *is_main_ingot {
184+
write!(f, "Missing root file (src/lib.fe) in current ingot: {ingot_url}")
185+
} else {
186+
write!(f, "Missing root file (src/lib.fe) in dependency: {ingot_url}")
187+
}
188+
}
168189
}
169190
}
170191
}
@@ -173,25 +194,28 @@ pub struct InputHandler<'a> {
173194
pub db: &'a mut dyn InputDb,
174195
pub join_edges: Vec<JoinEdge>,
175196
pub diagnostics: Vec<IngotInitDiagnostics>,
197+
pub main_ingot_url: Url,
176198
}
177199

178200
impl<'a> InputHandler<'a> {
179-
pub fn from_db(db: &'a mut dyn InputDb) -> Self {
201+
pub fn from_db(db: &'a mut dyn InputDb, main_ingot_url: Url) -> Self {
180202
Self {
181203
db,
182204
join_edges: vec![],
183205
diagnostics: vec![],
206+
main_ingot_url,
184207
}
185208
}
186209
}
187210

188211
impl<'a> ResolutionHandler<FilesResolver> for InputHandler<'a> {
189212
type Item = Vec<(Url, EdgeWeight)>;
190213

191-
fn handle_resolution(&mut self, ingot_url: &Url, files: Vec<File>) -> Self::Item {
214+
fn handle_resolution(&mut self, ingot_url: &Url, resource: FilesResource) -> Self::Item {
192215
let mut config = None;
193216

194-
for file in files {
217+
218+
for file in resource.files {
195219
if file.path.ends_with("fe.toml") {
196220
self.db.workspace().touch(
197221
self.db,
@@ -231,6 +255,8 @@ impl<'a> ResolutionHandler<FilesResolver> for InputHandler<'a> {
231255
});
232256
}
233257

258+
// Missing src/lib.fe file is now handled by the FilesResolver diagnostics
259+
234260
// let weights: HashSet<Url> = self.db.graph().node_weights().cloned().collect();
235261

236262
config
@@ -259,10 +285,7 @@ impl<'a> ResolutionHandler<FilesResolver> for InputHandler<'a> {
259285
})
260286
.collect()
261287
} else {
262-
// No fe.toml file found - record this as a diagnostic
263-
self.diagnostics.push(IngotInitDiagnostics::MissingFeToml {
264-
ingot_url: ingot_url.clone(),
265-
});
288+
// No fe.toml file found - this will be reported by the FilesResolver as a diagnostic
266289
vec![]
267290
}
268291
}

crates/fe/src/tree.rs

Lines changed: 123 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ use std::collections::{HashMap, HashSet};
33
use camino::Utf8PathBuf;
44
use common::{config::Config, graph::EdgeWeight, urlext::canonical_url};
55
use resolver::{
6-
graph::{petgraph, DiGraph, GraphResolver, NodeIndex},
7-
ingot::BasicIngotNodeHandler,
6+
files::{FilesResource, FilesResolver},
7+
graph::{petgraph, DiGraph, GraphResolver, GraphResolutionHandler, NodeIndex},
8+
ResolutionHandler,
89
};
910
use url::Url;
1011

1112
pub fn print_tree(path: &Utf8PathBuf) {
12-
let mut graph_resolver = resolver::ingot::basic_ingot_graph_resolver();
13-
let mut node_handler = BasicIngotNodeHandler::default();
13+
let mut graph_resolver = basic_ingot_graph_resolver();
14+
let mut node_handler = TreeIngotNodeHandler::default();
1415
let ingot_url = match canonical_url(path) {
1516
Ok(url) => url,
1617
Err(_) => {
@@ -21,12 +22,36 @@ pub fn print_tree(path: &Utf8PathBuf) {
2122

2223
match graph_resolver.graph_resolve(&mut node_handler, &ingot_url) {
2324
Ok(ingot_graph) => {
25+
// Report diagnostics from graph resolution first
26+
let graph_diagnostics = graph_resolver.take_diagnostics();
27+
for diagnostic in &graph_diagnostics {
28+
eprintln!("⚠️ {}", diagnostic);
29+
}
30+
31+
// Report diagnostics from node handler
32+
let node_diagnostics = node_handler.diagnostics();
33+
for diagnostic in node_diagnostics {
34+
eprintln!("⚠️ {}", diagnostic);
35+
}
36+
37+
// Print tree after diagnostics
2438
print!(
2539
"{}",
2640
print_tree_impl(&ingot_graph, &ingot_url, &node_handler.configs)
2741
);
2842
}
2943
Err(err) => {
44+
// Even if resolution failed, show available diagnostics first
45+
let graph_diagnostics = graph_resolver.take_diagnostics();
46+
for diagnostic in &graph_diagnostics {
47+
eprintln!("⚠️ {}", diagnostic);
48+
}
49+
50+
let node_diagnostics = node_handler.diagnostics();
51+
for diagnostic in node_diagnostics {
52+
eprintln!("⚠️ {}", diagnostic);
53+
}
54+
3055
println!("❌ Failed to resolve dependency tree: {err}");
3156
}
3257
}
@@ -199,3 +224,97 @@ fn find_cycle_nodes<N, E>(graph: &DiGraph<N, E>) -> HashSet<NodeIndex> {
199224
}
200225
cycles
201226
}
227+
228+
// Tree-specific ingot resolution types and functions
229+
230+
pub type TreeIngotGraphResolver = resolver::graph::GraphResolverImpl<FilesResolver, TreeIngotNodeHandler, EdgeWeight>;
231+
232+
pub fn basic_ingot_graph_resolver() -> TreeIngotGraphResolver {
233+
let files_resolver = FilesResolver::new()
234+
.with_required_file("fe.toml");
235+
resolver::graph::GraphResolverImpl::new(files_resolver)
236+
}
237+
238+
#[derive(Debug)]
239+
pub enum IngotResolutionDiagnostic {
240+
ConfigParseWarning(Url, String),
241+
}
242+
243+
impl std::fmt::Display for IngotResolutionDiagnostic {
244+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245+
match self {
246+
IngotResolutionDiagnostic::ConfigParseWarning(url, msg) => {
247+
write!(f, "Warning parsing config at {url}: {msg}")
248+
}
249+
}
250+
}
251+
}
252+
253+
#[derive(Default)]
254+
pub struct TreeIngotNodeHandler {
255+
pub configs: HashMap<Url, Config>,
256+
pub diagnostics: Vec<IngotResolutionDiagnostic>,
257+
}
258+
259+
impl TreeIngotNodeHandler {
260+
pub fn diagnostics(&self) -> &[IngotResolutionDiagnostic] {
261+
&self.diagnostics
262+
}
263+
}
264+
265+
impl ResolutionHandler<FilesResolver> for TreeIngotNodeHandler {
266+
type Item = Vec<(Url, EdgeWeight)>;
267+
268+
fn handle_resolution(&mut self, ingot_url: &Url, resource: FilesResource) -> Self::Item {
269+
tracing::trace!(target: "resolver", "Handling ingot resolution for: {}", ingot_url);
270+
271+
// Look for fe.toml file
272+
if let Some(config_file) = resource.files.iter().find(|f| f.path.file_name() == Some("fe.toml")) {
273+
match Config::parse(&config_file.content) {
274+
Ok(config) => {
275+
tracing::trace!(target: "resolver", "Successfully parsed config for ingot: {}", ingot_url);
276+
self.configs.insert(ingot_url.clone(), config.clone());
277+
let dependencies = config
278+
.based_dependencies(ingot_url)
279+
.into_iter()
280+
.map(|based_dependency| {
281+
tracing::trace!(target: "resolver", "Found dependency: {} -> {}", ingot_url, based_dependency.url);
282+
(
283+
based_dependency.url,
284+
EdgeWeight {
285+
alias: based_dependency.alias,
286+
arguments: based_dependency.parameters,
287+
},
288+
)
289+
})
290+
.collect();
291+
dependencies
292+
}
293+
Err(err) => {
294+
tracing::warn!(target: "resolver", "Failed to parse config for ingot {}: {}", ingot_url, err);
295+
self.diagnostics
296+
.push(IngotResolutionDiagnostic::ConfigParseWarning(
297+
ingot_url.clone(),
298+
err.to_string(),
299+
));
300+
vec![]
301+
}
302+
}
303+
} else {
304+
// This case should not happen since we require fe.toml, but handle it gracefully
305+
vec![]
306+
}
307+
}
308+
}
309+
310+
impl GraphResolutionHandler<Url, DiGraph<Url, EdgeWeight>> for TreeIngotNodeHandler {
311+
type Item = DiGraph<Url, EdgeWeight>;
312+
313+
fn handle_graph_resolution(
314+
&mut self,
315+
_ingot_url: &Url,
316+
graph: DiGraph<Url, EdgeWeight>,
317+
) -> Self::Item {
318+
graph
319+
}
320+
}

crates/fe/tests/fixtures/cli_output/ingots/missing_dep/missing_dep.snap

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ source: crates/fe/tests/cli_output.rs
33
expression: output
44
---
55
=== STDERR ===
6-
there are issues with the local fe.toml file file://<project>/crates/fe/tests/fixtures/cli_output/ingots/missing_dep/fe.toml
7-
dependencies are not yet supported
8-
Failed to resolve ingot dependency 'file://<project>/crates/fe/tests/fixtures/cli_output/ingots/nonexistent/': File URL does not exist: file://<project>/crates/fe/tests/fixtures/cli_output/ingots/nonexistent/
6+
Failed to resolve ingot dependency 'file://<project>/crates/fe/tests/fixtures/cli_output/ingots/nonexistent/': Directory does not exist: file://<project>/crates/fe/tests/fixtures/cli_output/ingots/nonexistent/
97

108
=== EXIT CODE: 1 ===
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
source: crates/fe/tests/cli_output.rs
3-
assertion_line: 78
43
expression: output
54
---
65
=== STDERR ===
7-
source files resolution error: `src` folder does not exist in the ingot directory
6+
File resolution error: Missing required directory 'src' in ingot at file://<project>/crates/fe/tests/fixtures/cli_output/ingots/missing_src/
7+
File resolution error: Missing required file 'src/lib.fe' in ingot at file://<project>/crates/fe/tests/fixtures/cli_output/ingots/missing_src/
88

99
=== EXIT CODE: 1 ===

0 commit comments

Comments
 (0)