wdl_analysis/validation/
imports.rs1use wdl_ast::AstNode;
4use wdl_ast::Diagnostic;
5use wdl_ast::Span;
6use wdl_ast::v1;
7use wdl_ast::v1::StringPart;
8
9use crate::Diagnostics;
10use crate::VisitReason;
11use crate::Visitor;
12
13fn empty_import(span: Span) -> Diagnostic {
15 Diagnostic::error("import URI cannot be empty").with_highlight(span)
16}
17
18fn placeholder_in_import(span: Span) -> Diagnostic {
20 Diagnostic::error("import URI cannot contain placeholders")
21 .with_highlight(span)
22 .with_fix("remove the placeholder")
23}
24
25fn invalid_import_namespace(span: Span) -> Diagnostic {
27 Diagnostic::error("import namespace is not a valid WDL identifier")
28 .with_label("a namespace cannot be derived from this import path", span)
29 .with_fix("add an `as` clause to the import to specify a namespace")
30}
31
32#[derive(Debug, Default)]
34pub struct ImportsVisitor;
35
36impl Visitor for ImportsVisitor {
37 fn reset(&mut self) {
38 *self = Default::default();
39 }
40
41 fn import_statement(
42 &mut self,
43 diagnostics: &mut Diagnostics,
44 reason: VisitReason,
45 stmt: &v1::ImportStatement,
46 ) {
47 if reason == VisitReason::Exit {
48 return;
49 }
50
51 let uri = stmt.uri();
52 if uri.is_empty() {
53 diagnostics.add(empty_import(uri.span()));
54 return;
55 }
56
57 if uri.text().is_none() {
58 let span = uri
59 .parts()
60 .find_map(|p| match p {
61 StringPart::Text(_) => None,
62 StringPart::Placeholder(p) => Some(p.span()),
63 })
64 .expect("should have a placeholder span");
65
66 diagnostics.add(placeholder_in_import(span));
67 return;
68 }
69
70 if stmt.namespace().is_none() {
71 diagnostics.add(invalid_import_namespace(uri.span()));
72 }
73 }
74}