1use super::{FormalParameterList, FunctionBody, FunctionExpression};
2use crate::{
3 Declaration, LinearPosition, LinearSpan, LinearSpanIgnoreEq, Span, Spanned, block_to_string,
4 expression::{Expression, Identifier},
5 join_nodes,
6 operations::{ContainsSymbol, contains},
7 property::{MethodDefinitionKind, PropertyName},
8 scope::{FunctionScopes, Scope},
9 visitor::{VisitWith, Visitor, VisitorMut},
10};
11use boa_interner::{Interner, Sym, ToIndentedString, ToInternedString};
12use core::{fmt::Write as _, ops::ControlFlow};
13use std::hash::Hash;
14
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
25#[derive(Clone, Debug, PartialEq)]
26pub struct ClassDeclaration {
27 name: Identifier,
28 pub(crate) super_ref: Option<Expression>,
29 pub(crate) constructor: Option<FunctionExpression>,
30 pub(crate) elements: Box<[ClassElement]>,
31
32 #[cfg_attr(feature = "serde", serde(skip))]
33 pub(crate) name_scope: Scope,
34}
35
36impl ClassDeclaration {
37 #[inline]
39 #[must_use]
40 pub fn new(
41 name: Identifier,
42 super_ref: Option<Expression>,
43 constructor: Option<FunctionExpression>,
44 elements: Box<[ClassElement]>,
45 ) -> Self {
46 Self {
47 name,
48 super_ref,
49 constructor,
50 elements,
51 name_scope: Scope::default(),
52 }
53 }
54
55 #[inline]
57 #[must_use]
58 pub const fn name(&self) -> Identifier {
59 self.name
60 }
61
62 #[inline]
64 #[must_use]
65 pub const fn super_ref(&self) -> Option<&Expression> {
66 self.super_ref.as_ref()
67 }
68
69 #[inline]
71 #[must_use]
72 pub const fn constructor(&self) -> Option<&FunctionExpression> {
73 self.constructor.as_ref()
74 }
75
76 #[inline]
78 #[must_use]
79 pub const fn elements(&self) -> &[ClassElement] {
80 &self.elements
81 }
82
83 #[inline]
85 #[must_use]
86 pub const fn name_scope(&self) -> &Scope {
87 &self.name_scope
88 }
89}
90
91impl ToIndentedString for ClassDeclaration {
92 fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
93 let mut buf = format!("class {}", interner.resolve_expect(self.name.sym()));
94 if let Some(super_ref) = self.super_ref.as_ref() {
95 let _ = write!(buf, " extends {}", super_ref.to_interned_string(interner));
96 }
97 if self.elements.is_empty() && self.constructor().is_none() {
98 buf.push_str(" {}");
99 return buf;
100 }
101 let indentation = " ".repeat(indent_n + 1);
102 buf.push_str(" {\n");
103 if let Some(expr) = &self.constructor {
104 let _ = writeln!(
105 buf,
106 "{indentation}constructor({}) {}",
107 join_nodes(interner, expr.parameters().as_ref()),
108 block_to_string(&expr.body.statements, interner, indent_n + 1)
109 );
110 }
111 for element in &self.elements {
112 buf.push_str(&element.to_indented_string(interner, indent_n));
113 }
114 buf.push('}');
115 buf
116 }
117}
118
119impl VisitWith for ClassDeclaration {
120 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
121 where
122 V: Visitor<'a>,
123 {
124 visitor.visit_identifier(&self.name)?;
125 if let Some(expr) = &self.super_ref {
126 visitor.visit_expression(expr)?;
127 }
128 if let Some(func) = &self.constructor {
129 visitor.visit_function_expression(func)?;
130 }
131 for elem in &*self.elements {
132 visitor.visit_class_element(elem)?;
133 }
134 ControlFlow::Continue(())
135 }
136
137 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
138 where
139 V: VisitorMut<'a>,
140 {
141 visitor.visit_identifier_mut(&mut self.name)?;
142 if let Some(expr) = &mut self.super_ref {
143 visitor.visit_expression_mut(expr)?;
144 }
145 if let Some(func) = &mut self.constructor {
146 visitor.visit_function_expression_mut(func)?;
147 }
148 for elem in &mut *self.elements {
149 visitor.visit_class_element_mut(elem)?;
150 }
151 ControlFlow::Continue(())
152 }
153}
154
155impl From<ClassDeclaration> for Declaration {
156 fn from(f: ClassDeclaration) -> Self {
157 Self::ClassDeclaration(Box::new(f))
158 }
159}
160
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
170#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
171#[derive(Clone, Debug, PartialEq)]
172pub struct ClassExpression {
173 pub(crate) name: Option<Identifier>,
174 pub(crate) super_ref: Option<Expression>,
175 pub(crate) constructor: Option<FunctionExpression>,
176 pub(crate) elements: Box<[ClassElement]>,
177
178 span: Span,
179
180 #[cfg_attr(feature = "serde", serde(skip))]
181 pub(crate) name_scope: Option<Scope>,
182}
183
184impl ClassExpression {
185 #[inline]
187 #[must_use]
188 pub fn new(
189 name: Option<Identifier>,
190 super_ref: Option<Expression>,
191 constructor: Option<FunctionExpression>,
192 elements: Box<[ClassElement]>,
193 has_binding_identifier: bool,
194 span: Span,
195 ) -> Self {
196 let name_scope = if has_binding_identifier {
197 Some(Scope::default())
198 } else {
199 None
200 };
201 Self {
202 name,
203 super_ref,
204 constructor,
205 elements,
206 span,
207 name_scope,
208 }
209 }
210
211 #[inline]
213 #[must_use]
214 pub const fn name(&self) -> Option<Identifier> {
215 self.name
216 }
217
218 #[inline]
220 #[must_use]
221 pub const fn super_ref(&self) -> Option<&Expression> {
222 self.super_ref.as_ref()
223 }
224
225 #[inline]
227 #[must_use]
228 pub const fn constructor(&self) -> Option<&FunctionExpression> {
229 self.constructor.as_ref()
230 }
231
232 #[inline]
234 #[must_use]
235 pub const fn elements(&self) -> &[ClassElement] {
236 &self.elements
237 }
238
239 #[inline]
241 #[must_use]
242 pub const fn name_scope(&self) -> Option<&Scope> {
243 self.name_scope.as_ref()
244 }
245}
246
247impl Spanned for ClassExpression {
248 #[inline]
249 fn span(&self) -> Span {
250 self.span
251 }
252}
253
254impl ToIndentedString for ClassExpression {
255 fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
256 let mut buf = "class".to_string();
257 if self.name_scope.is_some()
258 && let Some(name) = self.name
259 {
260 let _ = write!(buf, " {}", interner.resolve_expect(name.sym()));
261 }
262 if let Some(super_ref) = self.super_ref.as_ref() {
263 let _ = write!(buf, " extends {}", super_ref.to_interned_string(interner));
264 }
265 if self.elements.is_empty() && self.constructor().is_none() {
266 buf.push_str(" {}");
267 return buf;
268 }
269 let indentation = " ".repeat(indent_n + 1);
270 buf.push_str(" {\n");
271 if let Some(expr) = &self.constructor {
272 let _ = writeln!(
273 buf,
274 "{indentation}constructor({}) {}",
275 join_nodes(interner, expr.parameters().as_ref()),
276 block_to_string(&expr.body.statements, interner, indent_n + 1)
277 );
278 }
279 for element in &self.elements {
280 buf.push_str(&element.to_indented_string(interner, indent_n));
281 }
282 buf.push('}');
283 buf
284 }
285}
286
287impl From<ClassExpression> for Expression {
288 fn from(expr: ClassExpression) -> Self {
289 Self::ClassExpression(Box::new(expr))
290 }
291}
292
293impl VisitWith for ClassExpression {
294 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
295 where
296 V: Visitor<'a>,
297 {
298 if let Some(ident) = &self.name {
299 visitor.visit_identifier(ident)?;
300 }
301 if let Some(expr) = &self.super_ref {
302 visitor.visit_expression(expr)?;
303 }
304 if let Some(func) = &self.constructor {
305 visitor.visit_function_expression(func)?;
306 }
307 for elem in &*self.elements {
308 visitor.visit_class_element(elem)?;
309 }
310 ControlFlow::Continue(())
311 }
312
313 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
314 where
315 V: VisitorMut<'a>,
316 {
317 if let Some(ident) = &mut self.name {
318 visitor.visit_identifier_mut(ident)?;
319 }
320 if let Some(expr) = &mut self.super_ref {
321 visitor.visit_expression_mut(expr)?;
322 }
323 if let Some(func) = &mut self.constructor {
324 visitor.visit_function_expression_mut(func)?;
325 }
326 for elem in &mut *self.elements {
327 visitor.visit_class_element_mut(elem)?;
328 }
329 ControlFlow::Continue(())
330 }
331}
332
333#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
339#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
340#[derive(Clone, Debug, PartialEq)]
341pub struct StaticBlockBody {
342 pub(crate) body: FunctionBody,
343
344 #[cfg_attr(feature = "serde", serde(skip))]
345 pub(crate) scopes: FunctionScopes,
346}
347
348impl StaticBlockBody {
349 #[inline]
351 #[must_use]
352 pub fn new(body: FunctionBody) -> Self {
353 Self {
354 body,
355 scopes: FunctionScopes::default(),
356 }
357 }
358
359 #[inline]
361 #[must_use]
362 pub const fn statements(&self) -> &FunctionBody {
363 &self.body
364 }
365
366 #[inline]
368 #[must_use]
369 pub const fn scopes(&self) -> &FunctionScopes {
370 &self.scopes
371 }
372}
373
374#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
381#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
382#[derive(Clone, Debug, PartialEq)]
383pub enum ClassElement {
384 MethodDefinition(ClassMethodDefinition),
386
387 FieldDefinition(ClassFieldDefinition),
389
390 StaticFieldDefinition(ClassFieldDefinition),
392
393 PrivateFieldDefinition(PrivateFieldDefinition),
395
396 PrivateStaticFieldDefinition(PrivateFieldDefinition),
399
400 StaticBlock(StaticBlockBody),
402}
403
404#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
411#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
412#[derive(Clone, Debug, PartialEq)]
413pub struct ClassFieldDefinition {
414 pub(crate) name: PropertyName,
415 pub(crate) initializer: Option<Expression>,
416
417 #[cfg_attr(feature = "serde", serde(skip))]
418 pub(crate) scope: Scope,
419}
420
421impl ClassFieldDefinition {
422 #[inline]
424 #[must_use]
425 pub fn new(name: PropertyName, initializer: Option<Expression>) -> Self {
426 Self {
427 name,
428 initializer,
429 scope: Scope::default(),
430 }
431 }
432
433 #[inline]
435 #[must_use]
436 pub const fn name(&self) -> &PropertyName {
437 &self.name
438 }
439
440 #[inline]
442 #[must_use]
443 pub const fn initializer(&self) -> Option<&Expression> {
444 self.initializer.as_ref()
445 }
446
447 #[inline]
449 #[must_use]
450 pub const fn scope(&self) -> &Scope {
451 &self.scope
452 }
453}
454
455#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
462#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
463#[derive(Clone, Debug, PartialEq)]
464pub struct PrivateFieldDefinition {
465 pub(crate) name: PrivateName,
466 pub(crate) initializer: Option<Expression>,
467
468 #[cfg_attr(feature = "serde", serde(skip))]
469 pub(crate) scope: Scope,
470}
471
472impl PrivateFieldDefinition {
473 #[inline]
475 #[must_use]
476 pub fn new(name: PrivateName, initializer: Option<Expression>) -> Self {
477 Self {
478 name,
479 initializer,
480 scope: Scope::default(),
481 }
482 }
483
484 #[inline]
486 #[must_use]
487 pub const fn name(&self) -> &PrivateName {
488 &self.name
489 }
490
491 #[inline]
493 #[must_use]
494 pub const fn initializer(&self) -> Option<&Expression> {
495 self.initializer.as_ref()
496 }
497
498 #[inline]
500 #[must_use]
501 pub const fn scope(&self) -> &Scope {
502 &self.scope
503 }
504}
505
506impl ToIndentedString for ClassElement {
507 fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
508 let indentation = " ".repeat(indent_n + 1);
509 match self {
510 Self::MethodDefinition(m) => m.to_indented_string(interner, indent_n),
511 Self::FieldDefinition(field) => match &field.initializer {
512 Some(expr) => {
513 format!(
514 "{indentation}{} = {};\n",
515 field.name.to_interned_string(interner),
516 expr.to_no_indent_string(interner, indent_n + 1)
517 )
518 }
519 None => {
520 format!(
521 "{indentation}{};\n",
522 field.name.to_interned_string(interner),
523 )
524 }
525 },
526 Self::StaticFieldDefinition(field) => match &field.initializer {
527 Some(expr) => {
528 format!(
529 "{indentation}static {} = {};\n",
530 field.name.to_interned_string(interner),
531 expr.to_no_indent_string(interner, indent_n + 1)
532 )
533 }
534 None => {
535 format!(
536 "{indentation}static {};\n",
537 field.name.to_interned_string(interner),
538 )
539 }
540 },
541 Self::PrivateFieldDefinition(PrivateFieldDefinition {
542 name, initializer, ..
543 }) => match initializer {
544 Some(expr) => {
545 format!(
546 "{indentation}#{} = {};\n",
547 interner.resolve_expect(name.description()),
548 expr.to_no_indent_string(interner, indent_n + 1)
549 )
550 }
551 None => {
552 format!(
553 "{indentation}#{};\n",
554 interner.resolve_expect(name.description()),
555 )
556 }
557 },
558 Self::PrivateStaticFieldDefinition(PrivateFieldDefinition {
559 name,
560 initializer,
561 ..
562 }) => match initializer {
563 Some(expr) => {
564 format!(
565 "{indentation}static #{} = {};\n",
566 interner.resolve_expect(name.description()),
567 expr.to_no_indent_string(interner, indent_n + 1)
568 )
569 }
570 None => {
571 format!(
572 "{indentation}static #{};\n",
573 interner.resolve_expect(name.description()),
574 )
575 }
576 },
577 Self::StaticBlock(block) => {
578 format!(
579 "{indentation}static {}\n",
580 block_to_string(&block.body.statements, interner, indent_n + 1)
581 )
582 }
583 }
584 }
585}
586
587impl VisitWith for ClassElement {
588 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
589 where
590 V: Visitor<'a>,
591 {
592 match self {
593 Self::MethodDefinition(m) => {
594 match &m.name {
595 ClassElementName::PropertyName(pn) => {
596 visitor.visit_property_name(pn)?;
597 }
598 ClassElementName::PrivateName(pn) => {
599 visitor.visit_private_name(pn)?;
600 }
601 }
602 visitor.visit_formal_parameter_list(&m.parameters)?;
603 visitor.visit_function_body(&m.body)
604 }
605 Self::FieldDefinition(field) | Self::StaticFieldDefinition(field) => {
606 visitor.visit_property_name(&field.name)?;
607 if let Some(expr) = &field.initializer {
608 visitor.visit_expression(expr)
609 } else {
610 ControlFlow::Continue(())
611 }
612 }
613 Self::PrivateFieldDefinition(PrivateFieldDefinition {
614 name, initializer, ..
615 })
616 | Self::PrivateStaticFieldDefinition(PrivateFieldDefinition {
617 name,
618 initializer,
619 ..
620 }) => {
621 visitor.visit_private_name(name)?;
622 if let Some(expr) = initializer {
623 visitor.visit_expression(expr)
624 } else {
625 ControlFlow::Continue(())
626 }
627 }
628 Self::StaticBlock(block) => visitor.visit_function_body(&block.body),
629 }
630 }
631
632 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
633 where
634 V: VisitorMut<'a>,
635 {
636 match self {
637 Self::MethodDefinition(m) => {
638 match m.name {
639 ClassElementName::PropertyName(ref mut pn) => {
640 visitor.visit_property_name_mut(pn)?;
641 }
642 ClassElementName::PrivateName(ref mut pn) => {
643 visitor.visit_private_name_mut(pn)?;
644 }
645 }
646 visitor.visit_formal_parameter_list_mut(&mut m.parameters)?;
647 visitor.visit_function_body_mut(&mut m.body)
648 }
649 Self::FieldDefinition(field) | Self::StaticFieldDefinition(field) => {
650 visitor.visit_property_name_mut(&mut field.name)?;
651 if let Some(expr) = &mut field.initializer {
652 visitor.visit_expression_mut(expr)
653 } else {
654 ControlFlow::Continue(())
655 }
656 }
657 Self::PrivateFieldDefinition(PrivateFieldDefinition {
658 name, initializer, ..
659 })
660 | Self::PrivateStaticFieldDefinition(PrivateFieldDefinition {
661 name,
662 initializer,
663 ..
664 }) => {
665 visitor.visit_private_name_mut(name)?;
666 if let Some(expr) = initializer {
667 visitor.visit_expression_mut(expr)
668 } else {
669 ControlFlow::Continue(())
670 }
671 }
672 Self::StaticBlock(block) => visitor.visit_function_body_mut(&mut block.body),
673 }
674 }
675}
676
677#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
687#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
688#[derive(Clone, Debug, PartialEq)]
689pub struct ClassMethodDefinition {
690 name: ClassElementName,
691 pub(crate) parameters: FormalParameterList,
692 pub(crate) body: FunctionBody,
693 pub(crate) contains_direct_eval: bool,
694 kind: MethodDefinitionKind,
695 is_static: bool,
696
697 #[cfg_attr(feature = "serde", serde(skip))]
698 pub(crate) scopes: FunctionScopes,
699 linear_span: LinearSpanIgnoreEq,
700}
701
702impl ClassMethodDefinition {
703 #[inline]
705 #[must_use]
706 pub fn new(
707 name: ClassElementName,
708 parameters: FormalParameterList,
709 body: FunctionBody,
710 kind: MethodDefinitionKind,
711 is_static: bool,
712 start_linear_pos: LinearPosition,
713 ) -> Self {
714 let contains_direct_eval = contains(¶meters, ContainsSymbol::DirectEval)
715 || contains(&body, ContainsSymbol::DirectEval);
716
717 let linear_span = LinearSpan::new(start_linear_pos, body.linear_pos_end());
718
719 Self {
720 name,
721 parameters,
722 body,
723 contains_direct_eval,
724 kind,
725 is_static,
726 scopes: FunctionScopes::default(),
727 linear_span: linear_span.into(),
728 }
729 }
730
731 #[inline]
733 #[must_use]
734 pub const fn name(&self) -> &ClassElementName {
735 &self.name
736 }
737
738 #[inline]
740 #[must_use]
741 pub const fn parameters(&self) -> &FormalParameterList {
742 &self.parameters
743 }
744
745 #[inline]
747 #[must_use]
748 pub const fn body(&self) -> &FunctionBody {
749 &self.body
750 }
751
752 #[inline]
754 #[must_use]
755 pub const fn kind(&self) -> MethodDefinitionKind {
756 self.kind
757 }
758
759 #[inline]
761 #[must_use]
762 pub const fn is_static(&self) -> bool {
763 self.is_static
764 }
765
766 #[inline]
768 #[must_use]
769 pub const fn is_private(&self) -> bool {
770 self.name.is_private()
771 }
772
773 #[inline]
775 #[must_use]
776 pub const fn scopes(&self) -> &FunctionScopes {
777 &self.scopes
778 }
779
780 #[inline]
782 #[must_use]
783 pub const fn linear_span(&self) -> LinearSpan {
784 self.linear_span.0
785 }
786
787 #[inline]
789 #[must_use]
790 pub const fn contains_direct_eval(&self) -> bool {
791 self.contains_direct_eval
792 }
793}
794
795impl ToIndentedString for ClassMethodDefinition {
796 fn to_indented_string(&self, interner: &Interner, indent_n: usize) -> String {
797 let indentation = " ".repeat(indent_n + 1);
798 let prefix = match (self.is_static, &self.kind) {
799 (true, MethodDefinitionKind::Get) => "static get ",
800 (true, MethodDefinitionKind::Set) => "static set ",
801 (true, MethodDefinitionKind::Ordinary) => "static ",
802 (true, MethodDefinitionKind::Generator) => "static *",
803 (true, MethodDefinitionKind::AsyncGenerator) => "static async *",
804 (true, MethodDefinitionKind::Async) => "static async ",
805 (false, MethodDefinitionKind::Get) => "get ",
806 (false, MethodDefinitionKind::Set) => "set ",
807 (false, MethodDefinitionKind::Ordinary) => "",
808 (false, MethodDefinitionKind::Generator) => "*",
809 (false, MethodDefinitionKind::AsyncGenerator) => "async *",
810 (false, MethodDefinitionKind::Async) => "async ",
811 };
812 let name = self.name.to_interned_string(interner);
813 let parameters = join_nodes(interner, self.parameters.as_ref());
814 let body = block_to_string(&self.body.statements, interner, indent_n + 1);
815 format!("{indentation}{prefix}{name}({parameters}) {body}\n")
816 }
817}
818
819#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
826#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
827#[derive(Clone, Debug, PartialEq)]
828pub enum ClassElementName {
829 PropertyName(PropertyName),
831
832 PrivateName(PrivateName),
834}
835
836impl ClassElementName {
837 #[inline]
839 #[must_use]
840 pub const fn is_private(&self) -> bool {
841 matches!(self, Self::PrivateName(_))
842 }
843}
844
845impl ToInternedString for ClassElementName {
846 fn to_interned_string(&self, interner: &Interner) -> String {
847 match &self {
848 Self::PropertyName(name) => name.to_interned_string(interner),
849 Self::PrivateName(name) => format!("#{}", interner.resolve_expect(name.description())),
850 }
851 }
852}
853
854#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
858#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
859#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
860pub struct PrivateName {
861 description: Sym,
863 span: Span,
864}
865
866impl PrivateName {
867 #[inline]
869 #[must_use]
870 pub const fn new(description: Sym, span: Span) -> Self {
871 Self { description, span }
872 }
873
874 #[inline]
876 #[must_use]
877 pub const fn description(&self) -> Sym {
878 self.description
879 }
880}
881
882impl Spanned for PrivateName {
883 #[inline]
884 fn span(&self) -> Span {
885 self.span
886 }
887}
888
889impl VisitWith for PrivateName {
890 fn visit_with<'a, V>(&'a self, visitor: &mut V) -> ControlFlow<V::BreakTy>
891 where
892 V: Visitor<'a>,
893 {
894 visitor.visit_sym(&self.description)
895 }
896
897 fn visit_with_mut<'a, V>(&'a mut self, visitor: &mut V) -> ControlFlow<V::BreakTy>
898 where
899 V: VisitorMut<'a>,
900 {
901 visitor.visit_sym_mut(&mut self.description)
902 }
903}