wdl_cli/analysis/
results.rs1use std::rc::Rc;
4use std::sync::Arc;
5
6use anyhow::Error;
7use nonempty::NonEmpty;
8use wdl_analysis::AnalysisResult;
9use wdl_ast::AstNode as _;
10use wdl_ast::Diagnostic;
11
12use crate::analysis::Source;
13
14#[derive(Debug)]
19pub struct AnalysisResults(Vec<AnalysisResult>);
20
21impl AnalysisResults {
22 pub fn try_new(
27 results: Vec<AnalysisResult>,
28 ) -> std::result::Result<Self, NonEmpty<Arc<Error>>> {
29 let mut errors = results.iter().flat_map(|result| result.error().cloned());
30
31 if let Some(error) = errors.next() {
32 let mut results = NonEmpty::new(error);
33 results.extend(errors);
34 Err(results)
35 } else {
36 Ok(Self(results))
37 }
38 }
39
40 pub fn into_inner(self) -> Vec<AnalysisResult> {
42 self.0
43 }
44
45 pub fn filter(&self, sources: &[&Source]) -> impl Iterator<Item = &AnalysisResult> {
48 self.0.iter().filter(|r| {
49 let mut path = None;
50 sources.iter().any(|s| match s {
51 Source::Remote(url) | Source::File(url) => url == r.document().uri().as_ref(),
52 Source::Directory(dir) => path
53 .get_or_insert_with(|| r.document().uri().to_file_path())
54 .as_ref()
55 .map(|p| p.starts_with(dir))
56 .unwrap_or(false),
57 })
58 })
59 }
60
61 pub fn diagnostics(&self) -> impl Iterator<Item = (Rc<String>, Rc<String>, &Diagnostic)> {
70 self.0.iter().flat_map(|result| {
71 let path = Rc::new(result.document().path().to_string());
72 let source = Rc::new(result.document().root().text().to_string());
73
74 result
75 .document()
76 .diagnostics()
77 .iter()
78 .map(move |diagnostic| (path.clone(), source.clone(), diagnostic))
79 })
80 }
81}
82
83impl IntoIterator for AnalysisResults {
84 type IntoIter = std::vec::IntoIter<AnalysisResult>;
85 type Item = AnalysisResult;
86
87 fn into_iter(self) -> Self::IntoIter {
88 self.into_inner().into_iter()
89 }
90}