use crate::comment::Comment;
use crate::declaration::{CustomType, Declaration, InfixDef, TypeAlias, ValueConstructor};
use crate::exposing::{ExposedItem, Exposing};
use crate::expr::{
CaseBranch, Expr, Function, FunctionImplementation, LetDeclaration, RecordSetter, Signature,
};
use crate::file::ElmModule;
use crate::import::Import;
use crate::literal::Literal;
use crate::module_header::ModuleHeader;
use crate::node::Spanned;
use crate::pattern::Pattern;
use crate::type_annotation::{RecordField, TypeAnnotation};
#[allow(unused_variables)]
pub trait VisitMut {
fn visit_module_mut(&mut self, module: &mut ElmModule) {
walk_module_mut(self, module);
}
fn visit_module_header_mut(&mut self, header: &mut Spanned<ModuleHeader>) {
walk_module_header_mut(self, header);
}
fn visit_import_mut(&mut self, import: &mut Spanned<Import>) {
walk_import_mut(self, import);
}
fn visit_exposing_mut(&mut self, exposing: &mut Spanned<Exposing>) {
walk_exposing_mut(self, exposing);
}
fn visit_exposed_item_mut(&mut self, item: &mut Spanned<ExposedItem>) {}
fn visit_declaration_mut(&mut self, decl: &mut Spanned<Declaration>) {
walk_declaration_mut(self, decl);
}
fn visit_function_mut(&mut self, func: &mut Function) {
walk_function_mut(self, func);
}
fn visit_signature_mut(&mut self, sig: &mut Spanned<Signature>) {
walk_signature_mut(self, sig);
}
fn visit_function_implementation_mut(&mut self, imp: &mut Spanned<FunctionImplementation>) {
walk_function_implementation_mut(self, imp);
}
fn visit_type_alias_mut(&mut self, alias: &mut TypeAlias) {
walk_type_alias_mut(self, alias);
}
fn visit_custom_type_mut(&mut self, ct: &mut CustomType) {
walk_custom_type_mut(self, ct);
}
fn visit_value_constructor_mut(&mut self, ctor: &mut Spanned<ValueConstructor>) {
walk_value_constructor_mut(self, ctor);
}
fn visit_infix_def_mut(&mut self, infix: &mut InfixDef) {}
fn visit_expr_mut(&mut self, expr: &mut Spanned<Expr>) {
walk_expr_mut(self, expr);
}
fn visit_pattern_mut(&mut self, pattern: &mut Spanned<Pattern>) {
walk_pattern_mut(self, pattern);
}
fn visit_type_annotation_mut(&mut self, ty: &mut Spanned<TypeAnnotation>) {
walk_type_annotation_mut(self, ty);
}
fn visit_record_field_mut(&mut self, field: &mut Spanned<RecordField>) {
walk_record_field_mut(self, field);
}
fn visit_let_declaration_mut(&mut self, decl: &mut Spanned<LetDeclaration>) {
walk_let_declaration_mut(self, decl);
}
fn visit_case_branch_mut(&mut self, branch: &mut CaseBranch) {
walk_case_branch_mut(self, branch);
}
fn visit_record_setter_mut(&mut self, setter: &mut Spanned<RecordSetter>) {
walk_record_setter_mut(self, setter);
}
fn visit_literal_mut(&mut self, lit: &mut Literal) {}
fn visit_comment_mut(&mut self, comment: &mut Spanned<Comment>) {}
fn visit_ident_mut(&mut self, name: &mut String) {}
}
pub fn walk_module_mut<V: VisitMut + ?Sized>(v: &mut V, module: &mut ElmModule) {
v.visit_module_header_mut(&mut module.header);
for import in &mut module.imports {
v.visit_import_mut(import);
}
for decl in &mut module.declarations {
v.visit_declaration_mut(decl);
}
for comment in &mut module.comments {
v.visit_comment_mut(comment);
}
}
pub fn walk_module_header_mut<V: VisitMut + ?Sized>(v: &mut V, header: &mut Spanned<ModuleHeader>) {
match &mut header.value {
ModuleHeader::Normal { exposing, .. } | ModuleHeader::Port { exposing, .. } => {
v.visit_exposing_mut(exposing);
}
ModuleHeader::Effect { exposing, .. } => {
v.visit_exposing_mut(exposing);
}
}
}
pub fn walk_import_mut<V: VisitMut + ?Sized>(v: &mut V, import: &mut Spanned<Import>) {
if let Some(exposing) = &mut import.value.exposing {
v.visit_exposing_mut(exposing);
}
}
pub fn walk_exposing_mut<V: VisitMut + ?Sized>(v: &mut V, exposing: &mut Spanned<Exposing>) {
if let Exposing::Explicit { items, .. } = &mut exposing.value {
for item in items {
v.visit_exposed_item_mut(item);
}
}
}
pub fn walk_declaration_mut<V: VisitMut + ?Sized>(v: &mut V, decl: &mut Spanned<Declaration>) {
match &mut decl.value {
Declaration::FunctionDeclaration(func) => v.visit_function_mut(func),
Declaration::AliasDeclaration(alias) => v.visit_type_alias_mut(alias),
Declaration::CustomTypeDeclaration(ct) => v.visit_custom_type_mut(ct),
Declaration::PortDeclaration(sig) => {
v.visit_ident_mut(&mut sig.name.value);
v.visit_type_annotation_mut(&mut sig.type_annotation);
}
Declaration::InfixDeclaration(infix) => v.visit_infix_def_mut(infix),
Declaration::Destructuring { pattern, body } => {
v.visit_pattern_mut(pattern);
v.visit_expr_mut(body);
}
}
}
pub fn walk_function_mut<V: VisitMut + ?Sized>(v: &mut V, func: &mut Function) {
if let Some(sig) = &mut func.signature {
v.visit_signature_mut(sig);
}
v.visit_function_implementation_mut(&mut func.declaration);
}
pub fn walk_signature_mut<V: VisitMut + ?Sized>(v: &mut V, sig: &mut Spanned<Signature>) {
v.visit_ident_mut(&mut sig.value.name.value);
v.visit_type_annotation_mut(&mut sig.value.type_annotation);
}
pub fn walk_function_implementation_mut<V: VisitMut + ?Sized>(
v: &mut V,
imp: &mut Spanned<FunctionImplementation>,
) {
v.visit_ident_mut(&mut imp.value.name.value);
for arg in &mut imp.value.args {
v.visit_pattern_mut(arg);
}
v.visit_expr_mut(&mut imp.value.body);
}
pub fn walk_type_alias_mut<V: VisitMut + ?Sized>(v: &mut V, alias: &mut TypeAlias) {
v.visit_type_annotation_mut(&mut alias.type_annotation);
}
pub fn walk_custom_type_mut<V: VisitMut + ?Sized>(v: &mut V, ct: &mut CustomType) {
for ctor in &mut ct.constructors {
v.visit_value_constructor_mut(ctor);
}
}
pub fn walk_value_constructor_mut<V: VisitMut + ?Sized>(
v: &mut V,
ctor: &mut Spanned<ValueConstructor>,
) {
for arg in &mut ctor.value.args {
v.visit_type_annotation_mut(arg);
}
}
pub fn walk_expr_mut<V: VisitMut + ?Sized>(v: &mut V, expr: &mut Spanned<Expr>) {
for c in &mut expr.comments {
v.visit_comment_mut(c);
}
match &mut expr.value {
Expr::Unit | Expr::GLSLExpression(_) | Expr::RecordAccessFunction(_) => {}
Expr::Literal(lit) => v.visit_literal_mut(lit),
Expr::FunctionOrValue { name, .. } => v.visit_ident_mut(name),
Expr::PrefixOperator(op) => v.visit_ident_mut(op),
Expr::OperatorApplication { left, right, .. } => {
v.visit_expr_mut(left);
v.visit_expr_mut(right);
}
Expr::BinOps {
operands_and_operators,
final_operand,
} => {
for (operand, _op) in operands_and_operators {
v.visit_expr_mut(operand);
}
v.visit_expr_mut(final_operand);
}
Expr::Application(args) => {
for arg in args {
v.visit_expr_mut(arg);
}
}
Expr::IfElse {
branches,
else_branch,
} => {
for branch in branches {
v.visit_expr_mut(&mut branch.condition);
v.visit_expr_mut(&mut branch.then_branch);
}
v.visit_expr_mut(else_branch);
}
Expr::Negation(inner) => v.visit_expr_mut(inner),
Expr::Tuple(elems) => {
for elem in elems {
v.visit_expr_mut(elem);
}
}
Expr::List {
elements,
element_inline_comments: _,
trailing_comments: _,
} => {
for elem in elements {
v.visit_expr_mut(elem);
}
}
Expr::Parenthesized {
expr,
trailing_comments: _,
} => v.visit_expr_mut(expr),
Expr::LetIn {
declarations,
body,
trailing_comments: _,
} => {
for decl in declarations {
v.visit_let_declaration_mut(decl);
}
v.visit_expr_mut(body);
}
Expr::CaseOf {
expr: subject,
branches,
} => {
v.visit_expr_mut(subject);
for branch in branches {
v.visit_case_branch_mut(branch);
}
}
Expr::Lambda { args, body } => {
for arg in args {
v.visit_pattern_mut(arg);
}
v.visit_expr_mut(body);
}
Expr::Record(fields) => {
for field in fields {
v.visit_record_setter_mut(field);
}
}
Expr::RecordUpdate { updates, .. } => {
for field in updates {
v.visit_record_setter_mut(field);
}
}
Expr::RecordAccess { record, .. } => {
v.visit_expr_mut(record);
}
}
}
pub fn walk_pattern_mut<V: VisitMut + ?Sized>(v: &mut V, pattern: &mut Spanned<Pattern>) {
for c in &mut pattern.comments {
v.visit_comment_mut(c);
}
match &mut pattern.value {
Pattern::Anything | Pattern::Unit | Pattern::Hex(_) => {}
Pattern::Var(name) => v.visit_ident_mut(name),
Pattern::Literal(lit) => v.visit_literal_mut(lit),
Pattern::Tuple(elems) | Pattern::List(elems) => {
for elem in elems {
v.visit_pattern_mut(elem);
}
}
Pattern::Constructor { args, .. } => {
for arg in args {
v.visit_pattern_mut(arg);
}
}
Pattern::Record(fields) => {
for field in fields {
v.visit_ident_mut(&mut field.value);
}
}
Pattern::Cons { head, tail } => {
v.visit_pattern_mut(head);
v.visit_pattern_mut(tail);
}
Pattern::As {
pattern: inner,
name,
} => {
v.visit_pattern_mut(inner);
v.visit_ident_mut(&mut name.value);
}
Pattern::Parenthesized(inner) => v.visit_pattern_mut(inner),
}
}
pub fn walk_type_annotation_mut<V: VisitMut + ?Sized>(v: &mut V, ty: &mut Spanned<TypeAnnotation>) {
match &mut ty.value {
TypeAnnotation::GenericType(_) | TypeAnnotation::Unit => {}
TypeAnnotation::Typed { args, .. } => {
for arg in args {
v.visit_type_annotation_mut(arg);
}
}
TypeAnnotation::Tupled(elems) => {
for elem in elems {
v.visit_type_annotation_mut(elem);
}
}
TypeAnnotation::Record(fields) => {
for field in fields {
v.visit_record_field_mut(field);
}
}
TypeAnnotation::GenericRecord { fields, .. } => {
for field in fields {
v.visit_record_field_mut(field);
}
}
TypeAnnotation::FunctionType { from, to } => {
v.visit_type_annotation_mut(from);
v.visit_type_annotation_mut(to);
}
}
}
pub fn walk_record_field_mut<V: VisitMut + ?Sized>(v: &mut V, field: &mut Spanned<RecordField>) {
v.visit_type_annotation_mut(&mut field.value.type_annotation);
}
pub fn walk_let_declaration_mut<V: VisitMut + ?Sized>(
v: &mut V,
decl: &mut Spanned<LetDeclaration>,
) {
for c in &mut decl.comments {
v.visit_comment_mut(c);
}
match &mut decl.value {
LetDeclaration::Function(func) => v.visit_function_mut(func),
LetDeclaration::Destructuring { pattern, body } => {
v.visit_pattern_mut(pattern);
v.visit_expr_mut(body);
}
}
}
pub fn walk_case_branch_mut<V: VisitMut + ?Sized>(v: &mut V, branch: &mut CaseBranch) {
v.visit_pattern_mut(&mut branch.pattern);
v.visit_expr_mut(&mut branch.body);
}
pub fn walk_record_setter_mut<V: VisitMut + ?Sized>(v: &mut V, setter: &mut Spanned<RecordSetter>) {
v.visit_expr_mut(&mut setter.value.value);
}