Skip to content
Back to skills

Ast Codegen Patterns

ASecurity

Code generation from AST back to source text. esotope-style compact code output, format-preserving reprint, and round-trip AST → source pipelines for codemods and refactoring tools. Sources: glaynge/esotope (BSD-2-Clause).

  • 10 stars
  • 0 votes
  • 0 copies
  • 6 views
  • Added September 9, 2026
ai-agentsjavascripttypescriptjavanoderefactoring

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add yanacuti1121/Yana-AI --skill ast-codegen-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ast Codegen Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ast Codegen Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yanacuti1121-ast-codegen-patterns/badge)](https://www.skillsdirectory.com/skills/yanacuti1121-ast-codegen-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ast-codegen-patterns
description: Code generation from AST back to source text. esotope-style compact code output, format-preserving reprint, and round-trip AST → source pipelines for codemods and refactoring tools. Sources: glaynge/esotope (BSD-2-Clause).
origin: yana-ai — synthesized from glaynge/esotope (BSD-2-Clause), escodegen (BSD-2-Clause)
license: Apache-2.0
version: 1.0.0
compatibility: yana-ai >= 1.3.49
---

# /ast-codegen-patterns

## When to Use

- Regenerate source from a modified AST (after [[babel-ast-transform]] or [[estree-ast-spec]] walker)
- Format-preserving reprints: preserve whitespace/comments in unmodified subtrees
- Round-trip pipelines: parse → mutate → generate → diff
- Custom code generation: emit domain-specific patterns from data models

## Do NOT use for

- Full Babel transform pipelines (use [[babel-ast-transform]] which includes generate)
- TypeScript codegen from scratch (use [[ts-morph-refactor]] for type-safe generation)

---

## ESTree → source (escodegen)

```javascript
import escodegen from 'escodegen'
import { parse }  from 'acorn'

const source = `
const arr = [1, 2, 3]
const doubled = arr.map(x => x * 2)
`

const ast = parse(source, { ecmaVersion: 2022, sourceType: 'module' })

// Mutate AST: rename 'doubled' → 'multiplied'
function rename(node, from, to) {
  if (!node || typeof node !== 'object') return
  if (node.type === 'Identifier' && node.name === from) node.name = to
  for (const key of Object.keys(node)) rename(node[key], from, to)
}
rename(ast, 'doubled', 'multiplied')

const output = escodegen.generate(ast, {
  format: {
    indent:    { style: '  ' },
    quotes:    'single',
    semicolons: true,
  },
  comment: true,   // preserve comments from original
})

console.log(output)
// const arr = [1, 2, 3];
// const multiplied = arr.map(x => x * 2);
```

---

## Source map–aware generation

```javascript
import escodegen from 'escodegen'
import { SourceMapConsumer } from 'source-map'

const { code, map } = escodegen.generate(ast, {
  sourceMap:         'input.js',
  sourceMapWithCode: true,
  format: { compact: false },
})

// map is a SourceMapGenerator — serialize for output
const sourceMapString = map.toString()
const codeWithMap = code + '\n//# sourceMappingURL=data:application/json;base64,'
                       + Buffer.from(sourceMapString).toString('base64')
```

---

## Manual AST builder (no parser needed)

```javascript
// Build `export const VERSION = "1.0.0"` from scratch
function buildVersionExport(version: string) {
  return {
    type: 'ExportNamedDeclaration',
    declaration: {
      type: 'VariableDeclaration',
      kind: 'const',
      declarations: [{
        type: 'VariableDeclarator',
        id:   { type: 'Identifier', name: 'VERSION' },
        init: { type: 'Literal',    value: version, raw: JSON.stringify(version) },
      }],
    },
    specifiers: [],
    source: null,
  }
}

const program = {
  type: 'Program',
  body: [buildVersionExport('1.0.0')],
  sourceType: 'module',
}

console.log(escodegen.generate(program))
// export const VERSION = '1.0.0';
```

---

## Round-trip codemod helper

```typescript
import { parse }   from 'acorn'
import escodegen   from 'escodegen'

export function codemod(
  source:  string,
  mutate:  (ast: any) => void,
  options: escodegen.GenerateOptions = {}
): string {
  const ast = parse(source, {
    ecmaVersion: 2022,
    sourceType:  'module',
    onComment:   (block, text, start, end) => {
      // attach comments to nearest node for escodegen to reprint
    },
  })
  mutate(ast)
  return escodegen.generate(ast, {
    comment: true,
    format: { indent: { style: '  ' }, ...options },
  })
}
```

---

## Anti-Fake-Pass Checklist

```
❌ escodegen.generate on Babel AST → Babel adds non-ESTree nodes; strip them first
❌ comment: false → all comments lost in round-trip
❌ Mutating raw node.loc values → code generation uses loc for source maps; corruption
❌ compact: true in a codemod → diffs become unreadable one-liners
❌ Manual AST missing 'raw' field on Literal → some generators produce undefined
❌ sourceMap: 'filename' must match the original filename exactly or stack traces break
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.