use rowan::WalkEvent;
use crate::v1::BoundDecl;
use crate::v1::CallStatement;
use crate::v1::CommandSection;
use crate::v1::CommandText;
use crate::v1::ConditionalStatement;
use crate::v1::Expr;
use crate::v1::HintsSection;
use crate::v1::ImportStatement;
use crate::v1::InputSection;
use crate::v1::MetadataArray;
use crate::v1::MetadataObject;
use crate::v1::MetadataObjectItem;
use crate::v1::MetadataSection;
use crate::v1::OutputSection;
use crate::v1::ParameterMetadataSection;
use crate::v1::Placeholder;
use crate::v1::RequirementsSection;
use crate::v1::RuntimeItem;
use crate::v1::RuntimeSection;
use crate::v1::ScatterStatement;
use crate::v1::StringText;
use crate::v1::StructDefinition;
use crate::v1::TaskDefinition;
use crate::v1::UnboundDecl;
use crate::v1::WorkflowDefinition;
use crate::AstNode;
use crate::AstToken as _;
use crate::Comment;
use crate::Document;
use crate::SupportedVersion;
use crate::SyntaxKind;
use crate::SyntaxNode;
use crate::VersionStatement;
use crate::VisitReason;
use crate::Whitespace;
#[allow(unused_variables)]
pub trait Visitor {
type State;
fn document(
&mut self,
state: &mut Self::State,
reason: VisitReason,
doc: &Document,
version: SupportedVersion,
);
fn whitespace(&mut self, state: &mut Self::State, whitespace: &Whitespace) {}
fn comment(&mut self, state: &mut Self::State, comment: &Comment) {}
fn version_statement(
&mut self,
state: &mut Self::State,
reason: VisitReason,
stmt: &VersionStatement,
) {
}
fn import_statement(
&mut self,
state: &mut Self::State,
reason: VisitReason,
stmt: &ImportStatement,
) {
}
fn struct_definition(
&mut self,
state: &mut Self::State,
reason: VisitReason,
def: &StructDefinition,
) {
}
fn task_definition(
&mut self,
state: &mut Self::State,
reason: VisitReason,
task: &TaskDefinition,
) {
}
fn workflow_definition(
&mut self,
state: &mut Self::State,
reason: VisitReason,
workflow: &WorkflowDefinition,
) {
}
fn input_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &InputSection,
) {
}
fn output_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &OutputSection,
) {
}
fn command_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &CommandSection,
) {
}
fn command_text(&mut self, state: &mut Self::State, text: &CommandText) {}
fn requirements_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &RequirementsSection,
) {
}
fn hints_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &HintsSection,
) {
}
fn runtime_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &RuntimeSection,
) {
}
fn runtime_item(&mut self, state: &mut Self::State, reason: VisitReason, item: &RuntimeItem) {}
fn metadata_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &MetadataSection,
) {
}
fn parameter_metadata_section(
&mut self,
state: &mut Self::State,
reason: VisitReason,
section: &ParameterMetadataSection,
) {
}
fn metadata_object(
&mut self,
state: &mut Self::State,
reason: VisitReason,
object: &MetadataObject,
) {
}
fn metadata_object_item(
&mut self,
state: &mut Self::State,
reason: VisitReason,
item: &MetadataObjectItem,
) {
}
fn metadata_array(
&mut self,
state: &mut Self::State,
reason: VisitReason,
item: &MetadataArray,
) {
}
fn unbound_decl(&mut self, state: &mut Self::State, reason: VisitReason, decl: &UnboundDecl) {}
fn bound_decl(&mut self, state: &mut Self::State, reason: VisitReason, decl: &BoundDecl) {}
fn expr(&mut self, state: &mut Self::State, reason: VisitReason, expr: &Expr) {}
fn string_text(&mut self, state: &mut Self::State, text: &StringText) {}
fn placeholder(
&mut self,
state: &mut Self::State,
reason: VisitReason,
placeholder: &Placeholder,
) {
}
fn conditional_statement(
&mut self,
state: &mut Self::State,
reason: VisitReason,
stmt: &ConditionalStatement,
) {
}
fn scatter_statement(
&mut self,
state: &mut Self::State,
reason: VisitReason,
stmt: &ScatterStatement,
) {
}
fn call_statement(
&mut self,
state: &mut Self::State,
reason: VisitReason,
stmt: &CallStatement,
) {
}
}
pub(crate) fn visit<V: Visitor>(root: &SyntaxNode, state: &mut V::State, visitor: &mut V) {
for event in root.preorder_with_tokens() {
let (reason, element) = match event {
WalkEvent::Enter(node) => (VisitReason::Enter, node),
WalkEvent::Leave(node) => (VisitReason::Exit, node),
};
match element.kind() {
SyntaxKind::RootNode => {
let document = Document(element.into_node().unwrap());
let version = document
.version_statement()
.and_then(|s| s.version().as_str().parse::<SupportedVersion>().ok())
.expect("only WDL documents with supported versions can be visited");
visitor.document(state, reason, &document, version)
}
SyntaxKind::VersionStatementNode => visitor.version_statement(
state,
reason,
&VersionStatement(element.into_node().unwrap()),
),
SyntaxKind::ImportStatementNode => visitor.import_statement(
state,
reason,
&ImportStatement(element.into_node().unwrap()),
),
SyntaxKind::ImportAliasNode => {
}
SyntaxKind::StructDefinitionNode => visitor.struct_definition(
state,
reason,
&StructDefinition(element.into_node().unwrap()),
),
SyntaxKind::TaskDefinitionNode => visitor.task_definition(
state,
reason,
&TaskDefinition(element.into_node().unwrap()),
),
SyntaxKind::WorkflowDefinitionNode => visitor.workflow_definition(
state,
reason,
&WorkflowDefinition(element.into_node().unwrap()),
),
SyntaxKind::UnboundDeclNode => {
visitor.unbound_decl(state, reason, &UnboundDecl(element.into_node().unwrap()))
}
SyntaxKind::BoundDeclNode => {
visitor.bound_decl(state, reason, &BoundDecl(element.into_node().unwrap()))
}
SyntaxKind::PrimitiveTypeNode
| SyntaxKind::MapTypeNode
| SyntaxKind::ArrayTypeNode
| SyntaxKind::PairTypeNode
| SyntaxKind::ObjectTypeNode
| SyntaxKind::TypeRefNode => {
}
SyntaxKind::InputSectionNode => {
visitor.input_section(state, reason, &InputSection(element.into_node().unwrap()))
}
SyntaxKind::OutputSectionNode => {
visitor.output_section(state, reason, &OutputSection(element.into_node().unwrap()))
}
SyntaxKind::CommandSectionNode => visitor.command_section(
state,
reason,
&CommandSection(element.into_node().unwrap()),
),
SyntaxKind::RequirementsSectionNode => visitor.requirements_section(
state,
reason,
&RequirementsSection(element.into_node().unwrap()),
),
SyntaxKind::HintsSectionNode => {
visitor.hints_section(state, reason, &HintsSection(element.into_node().unwrap()))
}
SyntaxKind::RequirementsItemNode => {
}
SyntaxKind::RuntimeSectionNode => visitor.runtime_section(
state,
reason,
&RuntimeSection(element.into_node().unwrap()),
),
SyntaxKind::RuntimeItemNode => {
visitor.runtime_item(state, reason, &RuntimeItem(element.into_node().unwrap()))
}
SyntaxKind::MetadataSectionNode => visitor.metadata_section(
state,
reason,
&MetadataSection(element.into_node().unwrap()),
),
SyntaxKind::ParameterMetadataSectionNode => visitor.parameter_metadata_section(
state,
reason,
&ParameterMetadataSection(element.into_node().unwrap()),
),
SyntaxKind::MetadataObjectNode => visitor.metadata_object(
state,
reason,
&MetadataObject(element.into_node().unwrap()),
),
SyntaxKind::MetadataObjectItemNode => visitor.metadata_object_item(
state,
reason,
&MetadataObjectItem(element.into_node().unwrap()),
),
SyntaxKind::MetadataArrayNode => {
visitor.metadata_array(state, reason, &MetadataArray(element.into_node().unwrap()))
}
SyntaxKind::LiteralNullNode => {
}
k if Expr::can_cast(k) => visitor.expr(
state,
reason,
&Expr::cast(element.into_node().unwrap()).expect("node should cast"),
),
SyntaxKind::LiteralMapItemNode
| SyntaxKind::LiteralObjectItemNode
| SyntaxKind::LiteralStructItemNode
| SyntaxKind::LiteralHintsItemNode
| SyntaxKind::LiteralInputItemNode
| SyntaxKind::LiteralOutputItemNode => {
}
k @ (SyntaxKind::LiteralIntegerNode
| SyntaxKind::LiteralFloatNode
| SyntaxKind::LiteralBooleanNode
| SyntaxKind::LiteralNoneNode
| SyntaxKind::LiteralStringNode
| SyntaxKind::LiteralPairNode
| SyntaxKind::LiteralArrayNode
| SyntaxKind::LiteralMapNode
| SyntaxKind::LiteralObjectNode
| SyntaxKind::LiteralStructNode
| SyntaxKind::LiteralHintsNode
| SyntaxKind::LiteralInputNode
| SyntaxKind::LiteralOutputNode
| SyntaxKind::ParenthesizedExprNode
| SyntaxKind::NameRefNode
| SyntaxKind::IfExprNode
| SyntaxKind::LogicalNotExprNode
| SyntaxKind::NegationExprNode
| SyntaxKind::LogicalOrExprNode
| SyntaxKind::LogicalAndExprNode
| SyntaxKind::EqualityExprNode
| SyntaxKind::InequalityExprNode
| SyntaxKind::LessExprNode
| SyntaxKind::LessEqualExprNode
| SyntaxKind::GreaterExprNode
| SyntaxKind::GreaterEqualExprNode
| SyntaxKind::AdditionExprNode
| SyntaxKind::SubtractionExprNode
| SyntaxKind::MultiplicationExprNode
| SyntaxKind::DivisionExprNode
| SyntaxKind::ModuloExprNode
| SyntaxKind::CallExprNode
| SyntaxKind::IndexExprNode
| SyntaxKind::AccessExprNode) => {
unreachable!("`{k:?}` should be handled by `Expr::can_cast`")
}
SyntaxKind::PlaceholderNode => {
visitor.placeholder(state, reason, &Placeholder(element.into_node().unwrap()))
}
SyntaxKind::PlaceholderSepOptionNode
| SyntaxKind::PlaceholderDefaultOptionNode
| SyntaxKind::PlaceholderTrueFalseOptionNode => {
}
SyntaxKind::ConditionalStatementNode => visitor.conditional_statement(
state,
reason,
&ConditionalStatement(element.into_node().unwrap()),
),
SyntaxKind::ScatterStatementNode => visitor.scatter_statement(
state,
reason,
&ScatterStatement(element.into_node().unwrap()),
),
SyntaxKind::CallStatementNode => {
visitor.call_statement(state, reason, &CallStatement(element.into_node().unwrap()))
}
SyntaxKind::CallTargetNode
| SyntaxKind::CallAliasNode
| SyntaxKind::CallAfterNode
| SyntaxKind::CallInputItemNode => {
}
SyntaxKind::Abandoned | SyntaxKind::MAX => {
unreachable!("node should not exist in the tree")
}
SyntaxKind::Whitespace if reason == VisitReason::Enter => {
visitor.whitespace(state, &Whitespace(element.into_token().unwrap()))
}
SyntaxKind::Comment if reason == VisitReason::Enter => {
visitor.comment(state, &Comment(element.into_token().unwrap()))
}
SyntaxKind::LiteralStringText if reason == VisitReason::Enter => {
visitor.string_text(state, &StringText(element.into_token().unwrap()))
}
SyntaxKind::LiteralCommandText if reason == VisitReason::Enter => {
visitor.command_text(state, &CommandText(element.into_token().unwrap()))
}
_ => {
}
}
}
}