|
| 1 | +import { describe, test, expect } from 'vitest' |
| 2 | +import { parseSync, type ESTree } from 'rolldown/utils' |
| 3 | +import { extractBindingNames } from './bindingNames.ts' |
| 4 | + |
| 5 | +function parse(code: string) { |
| 6 | + return parseSync('test.js', code).program |
| 7 | +} |
| 8 | + |
| 9 | +describe('extractBindingNames', () => { |
| 10 | + function extractFromParam(code: string): string[] { |
| 11 | + const program = parse(`function f(${code}) {}`) |
| 12 | + // oxlint-disable-next-line typescript/no-unsafe-type-assertion |
| 13 | + const fn = program.body[0] as ESTree.Function |
| 14 | + const names: string[] = [] |
| 15 | + for (const param of fn.params) { |
| 16 | + extractBindingNames(param, names) |
| 17 | + } |
| 18 | + return names |
| 19 | + } |
| 20 | + |
| 21 | + function extractFromDecl(code: string): string[] { |
| 22 | + const program = parse(code) |
| 23 | + // oxlint-disable-next-line typescript/no-unsafe-type-assertion |
| 24 | + const decl = program.body[0] as ESTree.VariableDeclaration |
| 25 | + const names: string[] = [] |
| 26 | + for (const declarator of decl.declarations) { |
| 27 | + extractBindingNames(declarator.id, names) |
| 28 | + } |
| 29 | + return names |
| 30 | + } |
| 31 | + |
| 32 | + test('simple identifier', () => { |
| 33 | + expect(extractFromParam('a')).toEqual(['a']) |
| 34 | + }) |
| 35 | + |
| 36 | + test('multiple params', () => { |
| 37 | + expect(extractFromParam('a, b, c')).toEqual(['a', 'b', 'c']) |
| 38 | + }) |
| 39 | + |
| 40 | + test('rest param', () => { |
| 41 | + expect(extractFromParam('a, ...rest')).toEqual(['a', 'rest']) |
| 42 | + }) |
| 43 | + |
| 44 | + test('array destructuring', () => { |
| 45 | + expect(extractFromDecl('const [a, b] = arr')).toEqual(['a', 'b']) |
| 46 | + }) |
| 47 | + |
| 48 | + test('array destructuring with holes', () => { |
| 49 | + expect(extractFromDecl('const [a, , b] = arr')).toEqual(['a', 'b']) |
| 50 | + }) |
| 51 | + |
| 52 | + test('object destructuring', () => { |
| 53 | + expect(extractFromDecl('const { a, b } = obj')).toEqual(['a', 'b']) |
| 54 | + }) |
| 55 | + |
| 56 | + test('renamed object destructuring', () => { |
| 57 | + expect(extractFromDecl('const { x: a, y: b } = obj')).toEqual(['a', 'b']) |
| 58 | + }) |
| 59 | + |
| 60 | + test('rest element in array', () => { |
| 61 | + expect(extractFromDecl('const [a, ...rest] = arr')).toEqual(['a', 'rest']) |
| 62 | + }) |
| 63 | + |
| 64 | + test('rest element in object', () => { |
| 65 | + expect(extractFromDecl('const { a, ...rest } = obj')).toEqual(['a', 'rest']) |
| 66 | + }) |
| 67 | + |
| 68 | + test('assignment pattern', () => { |
| 69 | + expect(extractFromParam('a = 1, b = 2')).toEqual(['a', 'b']) |
| 70 | + }) |
| 71 | + |
| 72 | + test('nested destructuring', () => { |
| 73 | + expect(extractFromDecl('const { a: { b, c }, d } = obj')).toEqual(['b', 'c', 'd']) |
| 74 | + }) |
| 75 | + |
| 76 | + test('deeply nested mixed destructuring', () => { |
| 77 | + expect(extractFromDecl('const { a: [b, { c: d }], ...e } = obj')).toEqual(['b', 'd', 'e']) |
| 78 | + }) |
| 79 | +}) |
0 commit comments