Skip to content

Commit a8ff9de

Browse files
committed
fix: bug where matches inside other matches don't get replaced
1 parent 0ee5b0d commit a8ff9de

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

src/Astx.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,10 @@ export default class Astx extends ExtendableProxy implements Iterable<Astx> {
602602
const { parsePatternToNodes } = backend
603603
try {
604604
if (typeof arg0 === 'function') {
605-
for (const astx of this) {
605+
// Always replace in reverse so that if there are matches inside of
606+
// matches, the inner matches get replaced first (since they come
607+
// later in the code)
608+
for (const astx of [...this].reverse()) {
606609
const replacement = arg0(astx, parsePatternToNodes)
607610
replace(
608611
astx.match,
@@ -614,12 +617,12 @@ export default class Astx extends ExtendableProxy implements Iterable<Astx> {
614617
}
615618
} else if (typeof arg0 === 'string') {
616619
const replacement = parsePatternToNodes(arg0)
617-
for (const match of this._matches) {
618-
replace(match, replacement, this.context)
620+
for (let i = this._matches.length - 1; i >= 0; i--) {
621+
replace(this._matches[i], replacement, this.context)
619622
}
620623
} else if (isNode(arg0) || isNodeArray(arg0)) {
621-
for (const match of this._matches) {
622-
replace(match, arg0, this.context)
624+
for (let i = this._matches.length - 1; i >= 0; i--) {
625+
replace(this._matches[i], arg0, this.context)
623626
}
624627
} else {
625628
const finalPaths = parsePatternToNodes(arg0, ...quasis)

test/astx/bugs_nesting.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { TransformOptions } from '../../src'
2+
import { astxTestcase } from '../astxTestcase'
3+
import dedent from 'dedent-js'
4+
5+
astxTestcase({
6+
file: __filename,
7+
input: dedent`
8+
const validator = t.ref(() => t.object({
9+
a: t.ref(() => Foo)
10+
}))
11+
`,
12+
parsers: ['babel', 'babel/tsx'],
13+
astx: ({ astx }: TransformOptions): void => {
14+
astx.find`t.ref(() => $x)`().replace`z.lazy(() => $x)`()
15+
},
16+
expected: dedent`
17+
const validator = z.lazy(() => t.object({
18+
a: z.lazy(() => Foo)
19+
}));
20+
`,
21+
})

0 commit comments

Comments
 (0)