Ideally, this would get cached on the node factory so there's only ever one set of closures made per factory
(f *NodeFactory, syntheticLocation bool)
| 4 | |
| 5 | // Ideally, this would get cached on the node factory so there's only ever one set of closures made per factory |
| 6 | func getDeepCloneVisitor(f *NodeFactory, syntheticLocation bool) *NodeVisitor { |
| 7 | var visitor *NodeVisitor |
| 8 | visitor = NewNodeVisitor( |
| 9 | func(node *Node) *Node { |
| 10 | visited := visitor.VisitEachChild(node) |
| 11 | if visited != node { |
| 12 | if syntheticLocation { |
| 13 | visited.Loc = core.NewTextRange(-1, -1) |
| 14 | } |
| 15 | return visited |
| 16 | } |
| 17 | c := node.Clone(f) // forcibly clone leaf nodes, which will then cascade new nodes/arrays upwards via `update` calls |
| 18 | // In strada, `factory.cloneNode` was dynamic and did _not_ clone positions for any "special cases", meanwhile |
| 19 | // Node.Clone in corsa reliably uses `Update` calls for all nodes and so copies locations by default. |
| 20 | // Deep clones are done to copy a node across files, so here, we explicitly make the location range synthetic on all cloned nodes |
| 21 | if syntheticLocation { |
| 22 | c.Loc = core.NewTextRange(-1, -1) |
| 23 | } |
| 24 | return c |
| 25 | }, |
| 26 | f, |
| 27 | NodeVisitorHooks{ |
| 28 | VisitNodes: func(nodes *NodeList, v *NodeVisitor) *NodeList { |
| 29 | if nodes == nil { |
| 30 | return nil |
| 31 | } |
| 32 | visited := v.VisitNodes(nodes) |
| 33 | var newList *NodeList |
| 34 | if visited != nodes { |
| 35 | newList = visited |
| 36 | } else { |
| 37 | newList = nodes.Clone(v.Factory) |
| 38 | } |
| 39 | if syntheticLocation { |
| 40 | newList.Loc = core.NewTextRange(-1, -1) |
| 41 | if nodes.HasTrailingComma() { |
| 42 | newList.Nodes[len(newList.Nodes)-1].Loc = core.NewTextRange(-2, -2) |
| 43 | } |
| 44 | } |
| 45 | return newList |
| 46 | }, |
| 47 | VisitModifiers: func(nodes *ModifierList, v *NodeVisitor) *ModifierList { |
| 48 | if nodes == nil { |
| 49 | return nil |
| 50 | } |
| 51 | visited := v.VisitModifiers(nodes) |
| 52 | var newList *ModifierList |
| 53 | if visited != nodes { |
| 54 | newList = visited |
| 55 | } else { |
| 56 | newList = nodes.Clone(v.Factory) |
| 57 | } |
| 58 | if syntheticLocation { |
| 59 | newList.Loc = core.NewTextRange(-1, -1) |
| 60 | if nodes.HasTrailingComma() { |
| 61 | newList.Nodes[len(newList.Nodes)-1].Loc = core.NewTextRange(-2, -2) |
| 62 | } |
| 63 | } |
no test coverage detected