Scenario

Build either a small static analysis tool (a focused linter checking for one or two specific, genuinely useful patterns) or a codemod (an automated refactor applied across a codebase) — your choice, built on a real AST parse/transform/generate pipeline, not text matching.

Requirements

Core

  • A genuine AST-based pipeline (recall AST Fundamentals) — parses real source code, analyzes or transforms the AST, and (for a codemod) generates valid code back out.
  • For a linter: at least two distinct, genuinely useful checks, each producing a diagnostic (recall API Design for Libraries) with a precise source location, a stable code, and a clear, actionable message — not a vague “issue found here.”
  • For a codemod: the transformation is tested against fixtures (before/after file pairs, recall Codemods) covering at least three distinct realistic input variations, and verified idempotent (running it twice produces the same result as once).
  • Editor-friendly output: results in a format usable by a human at a glance (clear terminal output with file:line:column) and, ideally, a machine-parseable format (JSON) an editor integration could consume.
  • A documented list of known limitations — cases the tool deliberately doesn’t handle, or handles incorrectly, stated honestly rather than discovered by a confused user.

Stretch

  • A property-based or fuzz test (recall Property-Based Testing) that generates varied valid JavaScript snippets and confirms the tool never crashes on syntactically valid input, even if it produces no useful diagnostic.
  • A rollback mechanism for a codemod (or clear instructions for reverting via version control).

Reflect

  • What’s the trickiest real-world code pattern your tool has to handle correctly (or explicitly decline to handle) — and why was it harder than the common case?
  • If you built a linter, what would change about your check design if it needed to run on every keystroke in an editor rather than as a batch command-line tool?

Suggested milestones

  1. Get the AST parse/traverse pipeline working against a single hard-coded example first.
  2. Implement the core check or transform logic against that one example.
  3. Generalize it against a handful of real, varied source files from an actual codebase.
  4. Build the fixture-based test suite (and idempotency test, if a codemod).
  5. Polish the diagnostic/output format and write the known-limitations documentation.

Acceptance checks

  • Running the tool against a small real codebase (not just your own test fixtures) produces sensible, non-crashing results.
  • Every fixture test passes, and (for a codemod) the idempotency check passes.
  • A diagnostic’s reported location, when opened in an editor, actually points at the relevant code.
  • The known-limitations documentation accurately reflects at least one real case you deliberately chose not to (or couldn’t yet) handle.