[
  {
    "path": ".changeset/README.md",
    "content": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works\nwith multi-package repos, or single-package repos to help you version and publish your code. You can\nfind the full documentation for it [in our repository](https://github.com/changesets/changesets)\n\nWe have a quick list of common questions to get you started engaging with this project in\n[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@3.0.3/schema.json\",\n  \"changelog\": \"@changesets/cli/changelog\",\n  \"commit\": false,\n  \"fixed\": [],\n  \"linked\": [],\n  \"access\": \"public\",\n  \"baseBranch\": \"main\",\n  \"updateInternalDependencies\": \"patch\",\n  \"ignore\": []\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": ".eslintignore",
    "content": "/dist/\n/docs/\n/sample/__testfixtures__/\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"extends\": \"eslint:recommended\",\n  \"parser\": \"@babel/eslint-parser\",\n  \"rules\": {\n    \"comma-dangle\": 0,\n    \"no-underscore-dangle\": 0,\n    \"quotes\": [2, \"single\", \"avoid-escape\"],\n    \"strict\": 0\n  },\n  \"env\": {\n    \"jest\": true,\n    \"node\": true,\n    \"es6\": true\n  },\n  \"globals\": {\n    \"Promise\": true\n  }\n}\n"
  },
  {
    "path": ".gitattributes",
    "content": "bin/jscodeshift.js eol=lf\n"
  },
  {
    "path": ".github/workflows/cr.yml",
    "content": "name: Continuous Releases\n\non:\n  push:\n  pull_request:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions/checkout@v2\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v3\n        with:\n          node-version: 20.x\n          cache: yarn\n      - name: Install dependencies\n        run: yarn --frozen-lockfile\n      - name: Preview\n        run: npx pkg-pr-new@0.0.24 publish --compact\n"
  },
  {
    "path": ".github/workflows/pull_request.yml",
    "content": "name: pull_request\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  call-test:\n    uses: ./.github/workflows/test.yml\n"
  },
  {
    "path": ".github/workflows/push.yml",
    "content": "name: push\n\non:\n  push:\n    branches: [main]\n\njobs:\n  call-test:\n    uses: ./.github/workflows/test.yml\n  release:\n    needs: call-test\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n      id-token: write\n      pull-requests: write\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          cache: yarn\n\n      - run: yarn\n\n      - name: Create Release Pull Request or Publish to npm\n        id: changesets\n        uses: changesets/action@v1\n        with:\n          publish: yarn release\n          title: Publish <version>\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: test\n\non:\n  workflow_call:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: [16.x, 18.x, 20.x]\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: yarn\n      - name: Install dependencies\n        run: yarn --frozen-lockfile\n      - name: Run test\n        run: yarn test\n"
  },
  {
    "path": ".gitignore",
    "content": "/dist\nnode_modules/\n"
  },
  {
    "path": ".node-version",
    "content": "16.20.2\n"
  },
  {
    "path": ".npmignore",
    "content": "/docs/\n/test/\n/sample/\n/recipes/\n.gitignore\n.eslintrc\n.eslintrc.yaml\n.jshintrc\n.module-cache\n__tests__\nyarn.lock\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## 17.3.0\n\n### Minor Changes\n\n- 6c2ff57: Bumps recast to allow parsing of Typescript type arguments on tagged template literals\n\n## 17.2.0\n\n### Minor Changes\n\n- e5fe5be: Bumps recast to resolve a bug where JSX elements are wrapped in two pairs of parenthesis\n\n## 17.1.2\n\n### Patch Changes\n\n- 8f60fbf: Enable async tranformers in test utils.\n  All notable changes to this project will be documented in this file.\n\n## [17.1.1] 2024-10-31\n\n### Fixed\n\n- Republished with `temp` dependency properly removed (#638, thanks @trivikr for reporting)\n\n## [17.1.0] 2024-10-30\n\n### Added\n\n- `pkg.pr.new` will now be used to build an npm pakage for each commit to the repo, allowing you to more easily test changes or use new features before an official release is cut. (#622, @Aslemammad)\n\n### Changed\n\n- Replaced `temp` library with `tmp` (#633, @r4zendev)\n\n### Fixed\n\n- Removed old `docs` command from `package.json` since the new docs are in the `website` folder, which has instructions in its README.\n\n## [17.0.0] 2024-08-06\n\nWe needed to go [from v0.x to a major release](https://github.com/facebook/jscodeshift/issues/593), and it may as well happen now. jscodeshift has been around for nine years though, so going to v1.0.0 didn't feel quite right. I've instead promoted the minor version number to a major version number, similar to what React did when it went from 0.14 to 15.0.\n\n### Fixed\n\n- Node.js 16 is now explicitly specified as the minimum required version. It was _already_ implicitly required due to some dependencies requiring it, but this wasn't explicitly specified until now. (#607, @trivikr)\n\n### Added\n\n- A new [jscodeshift website](https://jscodeshift.com/) has launched, thanks to the team at [Codemod](https://codemod.com/). (#592, @mohab-sameh with some tweaks by @morinokami)\n- Added collection functions for import declarations, including finding imports and inserting new imports (#617, @danieldelcore)\n\n### Changed\n\n- Enabled TypeScript `importAttributes` (#585, @benasher44) and `decoratorAutoAccessors` (#594, @syi0808) plugins\n- Removed or replaced various outdated and unused dependencies (#601, #605, #609, #613, @trivikr)\n- Started using Corepack to manage Yarn version (#599, @trivikr)\n\n## [0.16.1] 2024-06-25\n\n### Fixed\n\n- Removed old `babel-core` dependency that was unused but caused security scanners to flag vulnerabilities.\n\n## [0.16.0] 2024-06-18\n\n### Added\n\n- Added a `--gitignore` flag to avoid transforming any files listed in `.gitignore` (#508, @ElonVolo)\n\n### Changed\n\n- Updated various dependencies to latest version (#588, @ElonVolo)\n\n## [0.15.2] 2024-02-21\n\n### Fixed\n\n- Process all supported extensions by default (#584, @trivikr)\n\n## [0.15.1] 2023-10-28\n\n### Changed\n\n- Upgraded to recast 0.23.3 (#564, @ashsearle)\n- Enable `@babel/plugin-proposal-private-methods` in worker (#568, @sibelius)\n- Upgraded Babel packages (#570, @dartess)\n\n### Fixed\n\n- Respect extensions cli option when filtering individual files (#562, @robcmills)\n- Fixed unit test after #562 broke them (#575, @ElonVolo)\n\n## [0.15.0] 2023-05-07\n\n### Changed\n\n- Upgraded to recast 0.23.1 (#544, @ryanrhee)\n- Make @babel/preset-env optional (#480, @SimenB)\n\n### Fixed\n\n- Force LF line ending in bin/jscodeshift.sh (#555, @jakeboone02)\n- Use transform's exported parser in testUitls (#528, @CrispyBacon12)\n- Ensure jscodeshift doesn't load Babel config file (#460, @raon0211)\n\n## [0.14.0] 2022-10-04\n\n### Added\n\n- Added a `defineSnapshotTestFromFixture` test util (#471, @shriuken)\n- Added `renameTo` filters for Babel 6+ node types (#412 and #504, @elonvolo and @henryqdineen)\n- Added `childNodesOfType` to JSX traversal methods (#415, @j13huang)\n\n### Changed\n\n- Bumped dependency versions\n- Allow arguments in `--help` to be listed in an order other than alphabetically, so they can instead be grouped thematically (#507, @elonvolo)\n- Allow the `j` shortcut in test utils (#515, @no23reason)\n\n## [0.13.1] 2022-01-10\n\n### Changed\n\n- Switched from `colors` to `chalk` to mitigate a security vulnerability in `colors@1.4.1`.\n\n## [0.13.0] 2021-06-26\n\n### Added\n\n- Added a `--fail-on-error` flag to return a `1` error code when errors were found (#416, @marcodejongh)\n- Created `template.asyncExpression` (#405, @jedwards1211)\n\n### Changed\n\n- Removed lodash dependency from tsx parser (#432, @JHilker and @robyoder)\n\n## [0.12.0] 2021-04-21\n\n### Changed\n\n- Allow transform to be a Promise (#237, @rektide)\n- Support newer TypeScript syntax by upgrading to newer Babel parser (#410, @wdoug and @mfeckie)\n\n## [0.11.0] 2020-09-01\n\n### Changed\n\n- Updated `recast` to latest\n\n## [0.10.0] 2020-06-01\n\n### Changed\n\n- Updated `flow-parser` to latest, and enabled Flow Enums parsing by default when using Flow parser\n\n## [0.8.0] 2020-05-03\n\n### Changed\n\n- Dropped support for Node versions 6 and 8\n\n## [0.7.0] 2019-12-11\n\n## Added\n\n- Added jest snapshot utils (#297, @dogoku)\n\n### Changed\n\n- Moved from BSD to MIT license\n\n### Fixed\n\n- No longer throw an error when calling jscodeshift on a non-existent path (#334, @threepointone)\n- Preserve the original file extension in remote files (#317, @samselikoff)\n\n## [0.6.4] 2019-04-30\n\n### Changed\n\n- Allow writing tests in TypeScript ([PR #308](https://github.com/facebook/jscodeshift/pull/308))\n- Better handling of `.gitingore` files: Ignore comments and support `\\r\\n` line breaks ([PR #306](https://github.com/facebook/jscodeshift/pull/306))\n\n## [0.6.3] 2019-01-18\n\n### Fixed\n\n- Don't throw an error when jscodeshift processes an empty set of files (#295,\n  @skovhus).\n- `renameTo` should not rename class properties (#296, @henryqdineen).\n- Custom/unknown CLI parameters are parsed as JSON, just like nomnom used to\n  do.\n\n## [0.6.2] 2018-12-05\n\n### Changed\n\n- `@babel/register`/`@babel/preset-env` is configured to not transpile any\n  language features that the running Node process supports. That means if you use\n  features in your transform code supported by the Node version you are running,\n  they will be left as is. Most of ES2015 is actually supported since Node v6.\n- Do not transpile object rest/spread in transform code if supported by running\n  Node version.\n\n### Fixed\n\n- Presets and plugins passed to `@babel/register` are now properly named and\n  loaded.\n\n## [0.6.1] 2018-12-04\n\n### Added\n\n- Tranform files can be written in Typescript. If the file extension of the\n  transform file is `.ts` or `.tsx`, `@babel/preset-typescript` is used to\n  convert them. This requires the `--babel` option to be set (which it is by\n  default). ( #287 , @brieb )\n\n### Changed\n\n- The preset and plugins for converting the transform file itself via babeljs\n  have been updated to work with babel v7. This included removing\n  `babel-preset-es2015` and `babel-preset-stage-1` in favor of\n  `@babel/preset-env`. Only `@babel/proposal-class-properties` and\n  `@babel/proposal-object-rest-spread` are enabled as experimental features. If\n  you want to use other's in your transform file, please create a PR.\n\n### Fixed\n\n- Typescript parses use `@babel/parser` instead of Babylon ( #291, @elliottsj )\n\n### Bumped\n\n- `micromatch` => v3.1.10, which doesn't (indirectly) depend on `randomatic` <\n  v3 anymore (see #292).\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct\n\nFacebook has adopted a Code of Conduct that we expect project participants to adhere to. Please [read the full text](https://code.facebook.com/codeofconduct) so that you can understand what actions will and will not be tolerated.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to jscodeshift\nWe want to make contributing to this project as easy and transparent as\npossible.\n\n## Code of Conduct\nThe code of conduct is described in [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md)\n\n## Our Development Process\nThe majority of development on jscodeshift will occur through GitHub. Accordingly,\nthe process for contributing will follow standard GitHub protocol.\n\n## Pull Requests\nWe actively welcome your pull requests.\n\n1. Fork the repo and create your branch from `main`.\n1. Run `corepack enable` to set up `yarn` package manager.\n1. If you've added code that should be tested, add tests.\n1. If you've changed APIs, update the documentation.\n1. Ensure the test suite passes.\n1. Make sure your code lints.\n1. If you haven't already, complete the Contributor License Agreement (\"CLA\").\n\n## Contributor License Agreement (\"CLA\")\nIn order to accept your pull request, we need you to submit a CLA. You only need\nto do this once to work on any of Facebook's open source projects.\n\nComplete your CLA here: <https://code.facebook.com/cla>\n\n## Issues\nWe use GitHub issues to track public bugs. Please ensure your description is\nclear and has sufficient instructions to be able to reproduce the issue.\n\nFacebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe\ndisclosure of security bugs. In those cases, please go through the process\noutlined on that page and do not file a public issue.\n\n## Coding Style\n* Use semicolons;\n* Commas last,\n* 2 spaces for indentation (no tabs)\n* Prefer `'` over `\"`\n* `'use strict';`\n* 80 character line length\n* \"Attractive\"\n\n### License\n\njscodeshift is [MIT licensed](./LICENSE).\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) Facebook, Inc. and its affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# [jscodeshift](https://jscodeshift.com/) [![Support Ukraine](https://img.shields.io/badge/Support-Ukraine-FFD500?style=flat&labelColor=005BBB)](https://opensource.fb.com/support-ukraine) [![Build Status](https://img.shields.io/github/checks-status/facebook/jscodeshift/main?label=build)](https://github.com/facebook/jscodeshift/actions/workflows/test.yml?query=branch%3Amain)\n\n\njscodeshift is a toolkit for running codemods over multiple JavaScript or\nTypeScript files.\nIt provides:\n\n- A runner, which executes the provided transform for each file passed to it.\n  It also outputs a summary of how many files have (not) been transformed.\n- A wrapper around [recast][], providing a different API.  Recast is an\n  AST-to-AST transform tool and also tries to preserve the style of original code\n  as much as possible.\n\n## Install\n\nGet jscodeshift from [npm](https://www.npmjs.com/package/jscodeshift):\n\n```\n$ npm install -g jscodeshift\n```\n\nThis will install the runner as `jscodeshift`.\n\n## VSCode Debugger\n\n[Configure VSCode to debug codemods](#vscode-debugging)\n\n## Usage (CLI)\n\nSee [the website](https://jscodeshift.com/) for full documentation.\n\nThe CLI provides the following options:\n\n```\n$ jscodeshift --help\n\nUsage: jscodeshift [OPTION]... PATH...\n  or:  jscodeshift [OPTION]... -t TRANSFORM_PATH PATH...\n  or:  jscodeshift [OPTION]... -t URL PATH...\n  or:  jscodeshift [OPTION]... --stdin < file_list.txt\n\nApply transform logic in TRANSFORM_PATH (recursively) to every PATH.\nIf --stdin is set, each line of the standard input is used as a path.\n\nOptions:\n\"...\" behind an option means that it can be supplied multiple times.\nAll options are also passed to the transformer, which means you can supply custom options that are not listed here.\n\n      --(no-)babel              apply babeljs to the transform file\n                                (default: true)\n  -c, --cpus=N                  start at most N child processes to process source files\n                                (default: max(all - 1, 1))\n  -d, --(no-)dry                dry run (no changes are made to files)\n                                (default: false)\n      --extensions=EXT          transform files with these file extensions (comma separated list)\n                                (default: js)\n  -h, --help                    print this help and exit\n      --ignore-config=FILE ...  ignore files if they match patterns sourced from a configuration file (e.g. a .gitignore)\n      --ignore-pattern=GLOB ...  ignore files that match a provided glob expression\n      --(no-)gitignore          adds entries the current directory's .gitignore file\n                                (default: false)\n      --parser=babel|babylon|flow|ts|tsx  the parser to use for parsing the source files\n                                          (default: babel)\n      --parser-config=FILE      path to a JSON file containing a custom parser configuration for flow or babylon\n  -p, --(no-)print              print transformed files to stdout, useful for development\n                                (default: false)\n      --(no-)run-in-band        run serially in the current process\n                                (default: false)\n  -s, --(no-)silent             do not write to stdout or stderr\n                                (default: false)\n      --(no-)stdin              read file/directory list from stdin\n                                (default: false)\n  -t, --transform=FILE          path to the transform file. Can be either a local path or url\n                                (default: ./transform.js)\n  -v, --verbose=0|1|2           show more information about the transform process\n                                (default: 0)\n      --version                 print version and exit\n      --fail-on-error           return a 1 exit code when errors were found during execution of codemods\n```\n\nThis passes the source of all passed through the transform module specified\nwith `-t` or `--transform` (defaults to `transform.js` in the current\ndirectory). The next section explains the structure of the transform module.\n\n## Usage (JS)\n\n```js\nconst {run: jscodeshift} = require('jscodeshift/src/Runner')\nconst path = require('node:path');\n\nconst transformPath = path.resolve('transform.js')\nconst paths = ['foo.js', 'bar']\nconst options = {\n  dry: true,\n  print: true,\n  verbose: 1,\n  // ...\n}\n\nconst res = await jscodeshift(transformPath, paths, options)\nconsole.log(res)\n/*\n{\n  stats: {},\n  timeElapsed: '0.001',\n  error: 0,\n  ok: 0,\n  nochange: 0,\n  skip: 0\n}\n*/\n```\n\n## Transform module\n\nThe transform is simply a module that exports a function of the form:\n\n```js\nmodule.exports = function(fileInfo, api, options) {\n  // transform `fileInfo.source` here\n  // ...\n  // return changed source\n  return source;\n};\n```\n\nAs of v0.6.1, this module can also be written in TypeScript.\n\n### Arguments\n\n#### `fileInfo`\n\nHolds information about the currently processed file.\n\nProperty    | Description\n------------|------------\npath        | File path\nsource      | File content\n\n#### `api`\n\nThis object exposes the `jscodeshift` library and helper functions from the\nrunner.\n\nProperty    | Description\n------------|------------\njscodeshift | A reference to the jscodeshift library\nstats       | A function to collect statistics during `--dry` runs\nreport      | Prints the passed string to stdout\n\n`jscodeshift` is a reference to the wrapper around recast and provides a\njQuery-like API to navigate and transform the AST. Here is a quick example,\na more detailed description can be found below.\n\n```js\n/**\n * This replaces every occurrence of variable \"foo\".\n */\nmodule.exports = function(fileInfo, api, options) {\n  return api.jscodeshift(fileInfo.source)\n    .findVariableDeclarators('foo')\n    .renameTo('bar')\n    .toSource();\n}\n```\n\n**Note:** This API is exposed for convenience, but you don't have to use it.\nYou can use any tool to modify the source.\n\n`stats` is a function that only works when the `--dry` options is set. It accepts\na string, and will simply count how often it was called with that value.\n\nAt the end, the CLI will report those values. This can be useful while\ndeveloping the transform, e.g. to find out how often a certain construct\nappears in the source(s).\n\n**`report`** allows you to print arbitrary strings to stdout. This can be\nuseful when other tools consume the output of jscodeshift. The reason to not\ndirectly use `process.stdout` in transform code is to avoid mangled output when\nmany files are processed.\n\n#### `options`\n\nContains all options that have been passed to runner. This allows you to pass\nadditional options to the transform. For example, if the CLI is called with\n\n```\n$ jscodeshift -t myTransforms fileA fileB --foo=bar\n```\n\n`options` would contain `{foo: 'bar'}`.\n\n### Return value\n\nThe return value of the function determines the status of the transformation:\n\n- If a string is returned and it is different from passed source, the\n  transform is considered to be successful.\n- If a string is returned but it's the same as the source, the transform\n  is considered to be unsuccessful.\n- If nothing is returned, the file is not supposed to be transformed (which is\n  ok).\n\nThe CLI provides a summary of the transformation at the end. You can get more\ndetailed information by setting the `-v` option to `1` or `2`.\n\nYou can collect even more stats via the `stats` function as explained above.\n\n### Parser\n\nThe transform file can let jscodeshift know with which parser to parse the source files (and features like templates).\n\nTo do that, the transform module can export `parser`, which can either be one\nof the strings `\"babel\"`, `\"babylon\"`, `\"flow\"`, `\"ts\"`, or `\"tsx\"`,\nor it can be a parser object that is compatible with recast and follows the estree spec.\n\n__Example: specifying parser type string in the transform file__\n\n```js\n\nmodule.exports = function transformer(file, api, options) {\n  const j = api.jscodeshift;\n  const rootSource = j(file.source);\n\n  // whatever other code...\n\n  return rootSource.toSource();\n}\n\n// use the flow parser\nmodule.exports.parser = 'flow';\n```\n\n__Example: specifying a custom parser object in the transform file__\n\n```js\n\nmodule.exports = function transformer(file, api, options) {\n  const j = api.jscodeshift;\n  const rootSource = j(file.source);\n\n  // whatever other code...\n\n  return rootSource.toSource();\n}\n\nmodule.exports.parser = {\n  parse: function(source) {\n    // return estree compatible AST\n  },\n};\n```\n\n### Example output\n\n```text\n$ jscodeshift -t myTransform.js src\nProcessing 10 files...\nSpawning 2 workers with 5 files each...\nAll workers done.\nResults: 0 errors 2 unmodified 3 skipped 5 ok\n```\n\n## The jscodeshift API\n\nAs already mentioned, jscodeshift also provides a wrapper around [recast][].\nIn order to properly use the jscodeshift API, one has to understand the basic\nbuilding blocks of recast (and ASTs) as well.\n\n### Core Concepts\n\n#### AST nodes\n\nAn AST node is a plain JavaScript object with a specific set of fields, in\naccordance with the [Mozilla Parser API][]. The primary way to identify nodes\nis via their `type`.\n\nFor example, string literals are represented via `Literal` nodes, which\nhave the structure\n\n```js\n// \"foo\"\n{\n  type: 'Literal',\n  value: 'foo',\n  raw: '\"foo\"'\n}\n```\n\nIt's OK to not know the structure of every AST node type.\nThe [(esprima) AST explorer][ast-explorer] is an online tool to inspect the AST\nfor a given piece of JS code.\n\n#### Path objects\n\nRecast itself relies heavily on [ast-types][] which defines methods to traverse\nthe AST, access node fields and build new nodes. ast-types wraps every AST node\ninto a *path object*. Paths contain meta-information and helper methods to\nprocess AST nodes.\n\nFor example, the child-parent relationship between two nodes is not explicitly\ndefined. Given a plain AST node, it is not possible to traverse the tree *up*.\nGiven a path object however, the parent can be traversed to via `path.parent`.\n\nFor more information about the path object API, please have a look at\n[ast-types][].\n\n#### Builders\n\nTo make creating AST nodes a bit simpler and \"safer\", ast-types defines a couple\nof *builder methods*, which are also exposed on `jscodeshift`.\n\nFor example, the following creates an AST equivalent to `foo(bar)`:\n\n```js\n// inside a module transform\nvar j = jscodeshift;\n// foo(bar);\nvar ast = j.callExpression(\n  j.identifier('foo'),\n  [j.identifier('bar')]\n);\n```\n\nThe signature of each builder function is best learned by having a look at the\n[definition files](https://github.com/benjamn/ast-types/tree/master/src/def)\nor in the babel/types [docs](https://babeljs.io/docs/en/babel-types).\n\n### Collections and Traversal\n\nIn order to transform the AST, you have to traverse it and find the nodes that\nneed to be changed. jscodeshift is built around the idea of **collections** of\npaths and thus provides a different way of processing an AST than recast or\nast-types.\n\nA collection has methods to process the nodes inside a collection, often\nresulting in a new collection. This results in a fluent interface, which can\nmake the transform more readable.\n\nCollections are \"typed\" which means that the type of a collection is the\n\"lowest\" type all AST nodes in the collection have in common. That means you\ncannot call a method for a `FunctionExpression` collection on an `Identifier`\ncollection.\n\nHere is an example of how one would find/traverse all `Identifier` nodes with\njscodeshift and with recast:\n\n```js\n// recast\nvar ast = recast.parse(src);\nrecast.visit(ast, {\n  visitIdentifier: function(path) {\n    // do something with path\n    return false;\n  }\n});\n\n// jscodeshift\njscodeshift(src)\n  .find(jscodeshift.Identifier)\n  .forEach(function(path) {\n    // do something with path\n  });\n```\n\nTo learn about the provided methods, have a look at the\n[Collection.js](src/Collection.js) and its [extensions](src/collections/).\n\n### Extensibility\n\njscodeshift provides an API to extend collections. By moving common operators\ninto helper functions (which can be stored separately in other modules), a\ntransform can be made more readable.\n\nThere are two types of extensions: generic extensions and type-specific\nextensions. **Generic extensions** are applicable to all collections. As such,\nthey typically don't access specific node data, but rather traverse the AST from\nthe nodes in the collection. **Type-specific** extensions work only on specific\nnode types and are not callable on differently typed collections.\n\n#### Examples\n\n```js\n// Adding a method to all Identifiers\njscodeshift.registerMethods({\n  logNames: function() {\n    return this.forEach(function(path) {\n      console.log(path.node.name);\n    });\n  }\n}, jscodeshift.Identifier);\n\n// Adding a method to all collections\njscodeshift.registerMethods({\n  findIdentifiers: function() {\n    return this.find(jscodeshift.Identifier);\n  }\n});\n\njscodeshift(ast).findIdentifiers().logNames();\njscodeshift(ast).logNames(); // error, unless `ast` only consists of Identifier nodes\n```\n\n### Ignoring files and directories\n\n\nSometimes there are files and directories that you want to avoid running transforms on. For example, the node_modules/ directory, where the project's installed local npm packages reside, can introduce bugs if any files in it are accidentally transformed by jscodeshift.\n\nThe simplest way to avoid many of these unwanted transforms is to pass jscodeshift the __--gitignore__ flag, which uses the glob patterns specified in your project’s .gitignore file to avoid transforming anything in directories such as node_modules/, dist/, etc. In most cases anything you want git to ignore you proabably are also going to want jscodeshift to ignore as well. _Please note that the .gitignore file use will be taken from the current working directory from which jscodeshift is being run._\n\n```\njscodeshift --gitignore mytransform.js\n```\n\nFor more custom ignore functionality, the __--ignore-pattern__ and the __--ignore-config__ arguments can be used.\n\n\n__--ignore-pattern__  takes a [.gitignore format](https://git-scm.com/docs/gitignore#_pattern_format) glob pattern that specifies file and directory patterns to ignore\n\n```\njscodeshift --ignore-pattern=\"js_configuration_files/**/*” mytransform.js\n\n// More than one ignore\njscodeshift --ignore-pattern=\"first_ignored_dir/**/*” -—ignore-pattern=\"second_ignored_dir/**/*” mytransform.js\n```\n\n__--ignore-config__ takes one or more paths to files containing lines with [.gitignore format](https://git-scm.com/docs/gitignore#_pattern_format) glob patterns.\n```\n\n// note: .gitignore is a random made-up filename extension for this example\n\njscodeshift --ignore-config=\"MyIgnoreFile.gitignore\" mytransform.js\n\n// More than one ignore file\njscodeshift --ignore-pattern=\"first_ignore_file.gitignore” --ignore-pattern=\"second_ignore_file.gitignore” mytransform.js\n```\n\n### Passing options to [recast]\n\nYou may want to change some of the output settings (like setting `'` instead of `\"` or \nchanging the end-of-line terminator to `\\r\\n` for Windows files).\nThis can be done by passing config options to [recast].\n\n```js\n.toSource({quote: 'single'}); // sets strings to use single quotes in transformed code.\n// or\n.toSource({lineTerminator: '\\r\\n'}); // sets EOL to use CRLF.\n```\n\nYou can also pass options to recast's `parse` method by passing an object to\njscodeshift as second argument:\n\n```js\njscodeshift(source, {...})\n```\n\nFor more details on recast config options, see [here](https://github.com/benjamn/recast/blob/master/lib/options.ts).\n\n### Unit Testing\n\njscodeshift comes with a simple utility to allow easy unit testing with [Jest](https://facebook.github.io/jest/), without having to write a lot of boilerplate code. This utility makes some assumptions in order to reduce the amount of configuration required:\n\n - The test is located in a subdirectory under the directory the transform itself is located in (eg. `__tests__`)\n - Test fixtures are located in a `__testfixtures__` directory\n\nThis results in a directory structure like this:\n\n```\n/MyTransform.js\n/__tests__/MyTransform-test.js\n/__testfixtures__/MyTransform.input.js\n/__testfixtures__/MyTransform.output.js\n```\n\nA simple example of unit tests is bundled in the [sample directory](sample).\n\nThe `testUtils` module exposes a number of useful helpers for unit testing.\n\n#### `defineTest`\n\nDefines a Jest/Jasmine test for a jscodeshift transform which depends on fixtures\n\n```js\njest.autoMockOff();\nconst defineTest = require('jscodeshift/dist/testUtils').defineTest;\ndefineTest(__dirname, 'MyTransform');\n```\n\nAn alternate fixture filename can be provided as the fourth argument to `defineTest`.\nThis also means that multiple test fixtures can be provided:\n\n```js\ndefineTest(__dirname, 'MyTransform', null, 'FirstFixture');\ndefineTest(__dirname, 'MyTransform', null, 'SecondFixture');\n```\n\nThis will run two tests:\n- `__testfixtures__/FirstFixture.input.js`\n- `__testfixtures__/SecondFixture.input.js`\n\n#### `defineInlineTest`\n\nDefines a Jest/Jasmine test suite for a jscodeshift transform which accepts inline values\n\nThis is a more flexible alternative to `defineTest`, as this allows to also provide options to your transform\n\n```js\nconst defineInlineTest = require('jscodeshift/dist/testUtils').defineInlineTest;\nconst transform = require('../myTransform');\nconst transformOptions = {};\ndefineInlineTest(transform, transformOptions, 'input', 'expected output', 'test name (optional)');\n```\n\n#### `defineSnapshotTest`\n\nSimilar to `defineInlineTest` but instead of requiring an output value, it uses Jest's `toMatchSnapshot()`\n\n```js\nconst defineSnapshotTest = require('jscodeshift/dist/testUtils').defineSnapshotTest;\nconst transform = require('../myTransform');\nconst transformOptions = {};\ndefineSnapshotTest(transform, transformOptions, 'input', 'test name (optional)');\n```\n\nFor more information on snapshots, check out [Jest's docs](https://jestjs.io/docs/en/snapshot-testing)\n\n#### `defineSnapshotTestFromFixture`\n\nSimilar to `defineSnapshotTest` but will load the file using same file-directory defaults as `defineTest`\n\n```js\nconst defineSnapshotTestDefault = require('jscodeshift/dist/testUtils').defineSnapshotTestDefault;\nconst transform = require('../myTransform');\nconst transformOptions = {};\ndefineSnapshotTestFromFixture(__dirname, transform, transformOptions, 'FirstFixture', 'test name (optional)');\n```\n\n#### `applyTransform`\n\nExecutes your transform using the options and the input given and returns the result.\nThis function is used internally by the other helpers, but it can prove useful in other cases.\n(bear in mind the `transform` module can be asynchronous. In that case, `applyTransform` will return a `Promise` with the transformed code. Otherwise, it will directly return the transformed code as a `string`).\n\n```js\nconst applyTransform = require('jscodeshift/dist/testUtils').applyTransform;\nconst transform = require('../myTransform');\nconst transformOptions = {};\nconst output = applyTransform(transform, transformOptions, 'input');\n```\n\n#### ES modules\n\nIf you're authoring your transforms and tests using ES modules, make sure to import the transform's parser (if specified) in your tests:\n\n```js\n// MyTransform.js\nexport const parser = 'flow'\nexport default function MyTransform(fileInfo, api, options) {\n  // ...\n}\n```\n```js\n// __tests__/MyTransform-test.js\nimport { defineInlineTest } from 'jscodeshift/dist/testUtils\nimport * as transform from '../MyTransform\n\nconsole.log(transform.parser) // 'flow'\n\ndefineInlineTest(transform, /* ... */)\n```\n\n### Example Codemods\n\n- [react-codemod](https://github.com/reactjs/react-codemod) - React codemod scripts to update React APIs.\n- [js-codemod](https://github.com/cpojer/js-codemod/) - Codemod scripts to transform code to next generation JS.\n- [js-transforms](https://github.com/jhgg/js-transforms) - Some documented codemod experiments to help you learn.\n- [fix-js](https://github.com/anshckr/fix-js) - Codemods to fix some ESLint issues\n\n### Local Documentation Server\n\n To update docs in `/docs`, use `npm run docs`.\n\n To view these docs locally, use `npx http-server ./docs`\n\n## VSCode Debugging\n\nIt's recommended that you set up your codemod project to all debugging via the VSCode IDE. When you open your project in VSCode, add the following configuration to your launch.json debugging configuration.\n\n```jsonc\n{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"type\": \"pwa-node\",\n            \"request\": \"launch\",\n            \"name\": \"Debug Transform\",\n            \"skipFiles\": [\n                \"<node_internals>/**\"\n            ],\n            \"program\": \"${workspaceRoot}/node_modules/.bin/jscodeshift\",\n            \"stopOnEntry\": false,\n            \"args\": [\"--dry\", \"--print\", \"-t\", \"${input:transformFile}\", \"--parser\", \"${input:parser}\", \"--run-in-band\", \"${file}\"],\n            \"preLaunchTask\": null,\n            \"runtimeExecutable\": null,\n            \"runtimeArgs\": [\n                \"--nolazy\"\n            ],\n            \"console\": \"internalConsole\",\n            \"sourceMaps\": true,\n            \"outFiles\": []\n        },\n        {\n            \"name\": \"Debug All JSCodeshift Jest Tests\",\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"runtimeArgs\": [\n                \"--inspect-brk\",\n                \"${workspaceRoot}/node_modules/jest/bin/jest.js\",\n                \"--runInBand\",\n                \"--testPathPattern=${fileBasenameNoExtension}\"\n            ],\n            \"console\": \"integratedTerminal\",\n            \"internalConsoleOptions\": \"neverOpen\",\n            \"port\": 9229\n        }\n    ],\n    \"inputs\": [\n        {\n          \"type\": \"pickString\",\n          \"id\": \"parser\",\n          \"description\": \"jscodeshift parser\",\n          \"options\": [\n            \"babel\",\n            \"babylon\",\n            \"flow\",\n            \"ts\",\n            \"tsx\",\n          ],\n          \"default\": \"babel\"\n        },\n        {\n            \"type\": \"promptString\",\n            \"id\": \"transformFile\",\n            \"description\": \"jscodeshift transform file\",\n            \"default\": \"transform.js\"\n        }\n    ]\n}\n```\n\nOnce this has been added to the configuration\n\n1. Install jscodeshift as a package if you haven't done so already by running the command  **npm install --save jscodeshift**. The debug configuration will not work otherwise.\n2. Once the jscodeshift local package has been installed, go to the VSCode file tree and select the file on which you want to run the transform. For example, if you wanted to run codemod transforms of foo.js file, you would click on the entry for foo.js file in your project tree.\n3. Select \"Debug Transform\" from the debugging menu's options menu.\n4. Click the **\"Start Debugging\"** button on the VSCode debugger.\n5. You will be then prompted for the name of jscodeshift transform file. Enter in the name of the transform file to use. If no name is given it will default to **transform.js**\n6. Select the parser to use from the presented selection list of parsers. The transform will otherwise default to using the **babel** parser.\n7. The transform will then be run, stopping at any breakpoints that have been set.\n8. If there are no errors and the transform is complete, then the results of the transform will be printed in the VSCode debugging console. The file with the contents that have been transformed will not be changed, as the debug configuration makes use the jscodeshift **--dry** option.\n\n\n### Recipes\n\n- [Retain leading comment(s) in file when replacing/removing first statement](recipes/retain-first-comment.md)\n\n[npm]: https://www.npmjs.com/\n[Mozilla Parser API]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API\n[recast]: https://github.com/benjamn/recast\n[ast-types]: https://github.com/benjamn/ast-types\n[ast-explorer]: http://astexplorer.net/\n"
  },
  {
    "path": "bin/__tests__/jscodeshift-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/*global jest, jasmine, xdescribe, it, expect, beforeEach*/\n/*eslint camelcase: 0, no-unused-vars: 0*/\n\njest.autoMockOff();\n\n// Increase default timeout (5000ms) for Travis\njest.setTimeout(600000); // 10 minutes\n\nconst child_process = require('child_process');\nconst fs = require('fs');\nconst path = require('path');\nconst testUtils = require('../../utils/testUtils');\n\nconst createTransformWith = testUtils.createTransformWith;\nconst createTempFileWith = testUtils.createTempFileWith;\n\nfunction readFile(path) {\n  return fs.readFileSync(path).toString();\n}\n\nfunction run(args, stdin, cwd) {\n  return new Promise(resolve => {\n    const jscodeshift = child_process.spawn(\n      path.join(__dirname, '../jscodeshift.sh'),\n      args,\n      {\n        cwd,\n      }\n    );\n    let stdout = '';\n    let stderr = '';\n    jscodeshift.stdout.on('data', data => stdout += data);\n    jscodeshift.stderr.on('data', data => stderr += data);\n    jscodeshift.on('close', () => resolve([stdout, stderr]));\n    if (stdin) {\n      jscodeshift.stdin.write(stdin);\n    }\n    jscodeshift.stdin.end();\n  });\n}\n\ndescribe('jscodeshift CLI', () => {\n\n  it('calls the transform and file information', () => {\n    const sourceA = createTempFileWith('a', 'sourceA', '.js');\n    const sourceB = createTempFileWith('b\\n', 'sourceB', '.js');\n    const sourceC = createTempFileWith('c', 'sourceC', '.js');\n    const transformA = createTransformWith(\n      'return \"transform\" + fileInfo.source;'\n    );\n    const transformB = createTransformWith(\n      'return fileInfo.path;'\n    );\n\n    return Promise.all([\n      run(['-t', transformA, sourceA, sourceB]).then(\n        out => {\n          expect(out[1]).toBe('');\n          expect(readFile(sourceA)).toBe('transforma');\n          expect(readFile(sourceB)).toBe('transformb\\n');\n        }\n      ),\n      run(['-t', transformB, sourceC]).then(\n        out => {\n          expect(out[1]).toBe('');\n          expect(readFile(sourceC)).toBe(sourceC);\n        }\n      )\n    ]);\n  });\n\n  it('takes file list from stdin if --stdin is set', () => {\n    const sourceA = createTempFileWith('a', 'sourceA', '.js');\n    const sourceB = createTempFileWith('b\\n', 'sourceB', '.js');\n    const sourceC = createTempFileWith('c', 'sourceC', '.js');\n    const transformA = createTransformWith(\n      'return \"transform\" + fileInfo.source;'\n    );\n\n    return run(['--stdin', '-t', transformA], [sourceA, sourceB, sourceC].join('\\n')).then(\n      out => {\n        expect(out[1]).toBe('');\n        expect(readFile(sourceA)).toBe('transforma');\n        expect(readFile(sourceB)).toBe('transformb\\n');\n        expect(readFile(sourceC)).toBe('transformc');\n      }\n    );\n  });\n\n  it('does not transform files in a dry run', () => {\n    const sourceA = createTempFileWith('a', 'sourceA', '.js');\n    const transform = createTransformWith(\n      'return \"transform\" + fileInfo.source;'\n    );\n    return run(['-t', transform, '-d', sourceA]).then(\n      () => {\n        expect(readFile(sourceA).toString()).toBe('a');\n      }\n    );\n  });\n\n  describe('Babel', () => {\n\n    // Verifiers that ES6 features are supported either natively or via Babel\n    it('supports ES6 features in transform files', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith(\n        'const a = 42; return a;'\n      );\n      return Promise.all([\n        run(['-t', transform, sourceA]).then(\n          () => {\n            expect(readFile(sourceA).toString())\n              .toEqual('42');\n          }\n        ),\n      ]);\n    });\n\n    // Verifies that spread is supported, either natively over via Babel\n    it('supports property spread in transform files', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith(\n        'const a = {...{foo: 42}, bar: 21}; return a.foo;'\n      );\n      return Promise.all([\n        run(['-t', transform, sourceA]).then(\n          () => {\n            expect(readFile(sourceA).toString())\n              .toEqual('42');\n          }\n        ),\n      ]);\n    });\n\n    it('supports class properties in transform files', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith(`\n        return (class {\n          x = 42;\n        }).toString();\n      `);\n      return Promise.all([\n        run(['-t', transform, sourceA]).then(\n          () => {\n            expect(readFile(sourceA).toString())\n              .toMatch(/\\(this,\\s*['\"]x['\"]/);\n          }\n        ),\n      ]);\n    });\n\n    it('supports flow type annotations in transform files', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith(\n        'return (function() { \"use strict\"; const a: number = 42; }).toString();'\n      );\n      return Promise.all([\n        run(['-t', transform, sourceA]).then(\n          () => {\n            expect(readFile(sourceA).toString())\n              .toMatch(/a\\s*=\\s*42/);\n          }\n        ),\n      ]);\n    });\n\n    it('supports Typescript type annotations in transform files', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith(\n        'return (function() { \"use strict\"; function foo(x: string): x is string {}}).toString();',\n        '.ts'\n      );\n      return Promise.all([\n        run(['-t', transform, sourceA]).then(\n          args => {\n            expect(readFile(sourceA).toString())\n              .toMatch(/function\\s+foo\\(x\\)\\s*{}/);\n          }\n        ),\n      ]);\n    });\n\n    it('transpiles imported Typescript files in transform files', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const helper = createTempFileWith(\n        'module.exports = function(x: string): x is string {};',\n        undefined,\n        '.ts'\n      );\n      const transform = createTransformWith(\n        `return require('${helper}').toString();`,\n        '.ts'\n      );\n      return Promise.all([\n        run(['-t', transform, sourceA]).then(\n          args => {\n            expect(readFile(sourceA).toString())\n              .toMatch(/function\\s*\\(x\\)\\s*{}/);\n          }\n        ),\n      ]);\n    });\n\n  });\n\n  it('passes jscodeshift and stats the transform function', () => {\n    const sourceA = createTempFileWith('a', 'sourceA', '.js');\n    const transform = createTransformWith([\n      '  return String(',\n      '    typeof api.jscodeshift === \"function\" &&',\n      '    typeof api.stats === \"function\"',\n      '  );',\n    ].join('\\n'));\n    return run(['-t', transform, sourceA]).then(\n      () => {\n        expect(readFile(sourceA).toString()).toBe('true');\n      }\n    );\n  });\n\n  it('passes options along to the transform', () => {\n    const sourceA = createTempFileWith('a', 'sourceA', '.js');\n    const transform = createTransformWith('return options.foo;');\n    return run(['-t', transform, '--foo=42', sourceA]).then(\n      () => {\n        expect(readFile(sourceA).toString()).toBe('42');\n      }\n    );\n  });\n  it('does not stall with too many files', () => {\n    const sources = [];\n    for (let i = 0; i < 100; i++) {\n      sources.push(createTempFileWith('a'));\n    }\n    const transform = createTransformWith('');\n    return run(['-t', transform, '--foo=42'].concat(sources)).then(\n      () => {\n        expect(true).toBe(true);\n      }\n    );\n  });\n\n  describe('ignoring', () => {\n    const transform = createTransformWith(\n      'return \"transform\" + fileInfo.source;'\n    );\n    let sources = [];\n\n    beforeEach(() => {\n      sources = [];\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const testIgnoreFile = createTempFileWith('a', 'a-test', '.js');\n      sources.push(sourceA);\n      sources.push(testIgnoreFile);\n      // sources.push(createTempFileWith('b', 'src/lib/b.js'));\n    });\n\n    it('supports basic glob', () => {\n      const pattern = '*-test.js';\n      return run(['-t', transform, '--ignore-pattern', pattern].concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('transforma');\n          expect(readFile(sources[1]).toString()).toBe('a');\n        }\n      );\n    });\n\n    it('supports filename match', () => {\n      const pattern = 'sourceA.js';\n      return run(['-t', transform, '--ignore-pattern', pattern].concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('a');\n          expect(readFile(sources[1]).toString()).toBe('transforma');\n        }\n      );\n    });\n\n    it('accepts a list of patterns', () => {\n      const patterns = ['--ignore-pattern', 'sourceA.js', '--ignore-pattern', '*-test.js'];\n      return run(['-t', transform].concat(patterns).concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('a');\n          expect(readFile(sources[1]).toString()).toBe('a');\n        }\n      );\n    });\n\n    it('sources ignore patterns from configuration file', () => {\n      const patterns = ['sub/dir/', '*-test.js'];\n      const gitignore = createTempFileWith(patterns.join('\\n'), '.gitignore');\n      sources.push(createTempFileWith('subfile', 'sub/dir/file.js'));\n\n      return run(['-t', transform, '--ignore-config', gitignore].concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('transforma');\n          expect(readFile(sources[1]).toString()).toBe('a');\n          expect(readFile(sources[2]).toString()).toBe('subfile');\n        }\n      );\n    });\n\n    it('sources ignore patterns from configuration file', () => {\n      const patterns = ['sub/dir/', '*-test.js'];\n      const gitignore = createTempFileWith(patterns.join('\\n'), '.gitignore');\n      sources.push(createTempFileWith('subfile', 'sub/dir/file.js'));\n\n      return run(['-t', transform, '--ignore-config', gitignore].concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('transforma');\n          expect(readFile(sources[1]).toString()).toBe('a');\n          expect(readFile(sources[2]).toString()).toBe('subfile');\n        }\n      );\n    });\n\n    it('sources ignore patterns from a root directory\\'s .gitignore file', () => {\n      // This test is a little different from the one above only in that we have\n      // to simulate automatically hitting up the .gitignore file from the current\n      // directory that the codeshift process is running from\n      const patterns = ['sub/dir/', '*-test.js'];\n      const gitignore = createTempFileWith(patterns.join('\\n'), '.gitignore');\n      sources.push(createTempFileWith('subfile', 'sub/dir/file.js'));\n\n      // Make the temp directory with our test files the current working directory\n      let currPath = process.cwd();\n      let tempDirPath = path.dirname(sources[0]);\n      process.chdir(tempDirPath);;\n\n      return run(['-t', transform, '--gitignore'].concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('transforma');\n          expect(readFile(sources[1]).toString()).toBe('a');\n          expect(readFile(sources[2]).toString()).toBe('subfile');\n        }\n      )\n      .catch((err) => {\n        console.log(err);\n      })\n      .finally(() => {\n        process.chdir(currPath);\n      })\n    });\n\n    it('accepts a list of configuration files', () => {\n      const gitignore = createTempFileWith(['sub/dir/'].join('\\n'), '.gitignore');\n      const eslintignore = createTempFileWith(['**/*test.js', 'sourceA.js'].join('\\n'), '.eslintignore');\n      const configs = ['--ignore-config', gitignore, '--ignore-config', eslintignore];\n      sources.push(createTempFileWith('subfile', 'sub/dir/file.js'));\n\n      return run(['-t', transform].concat(configs).concat(sources)).then(\n        () => {\n          expect(readFile(sources[0]).toString()).toBe('a');\n          expect(readFile(sources[1]).toString()).toBe('a');\n          expect(readFile(sources[2]).toString()).toBe('subfile');\n        }\n      );\n    });\n  });\n\n  describe('output', () => {\n    it('shows workers info and stats at the end by default', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith('return null;');\n      return run(['-t', transform, sourceA]).then(\n        out => {\n          expect(out[0]).toContain('Processing 1 files...');\n          expect(out[0]).toContain('Spawning 1 workers...');\n          expect(out[0]).toContain('Sending 1 files to free worker...');\n          expect(out[0]).toContain('All done.');\n          expect(out[0]).toContain('Results: ');\n          expect(out[0]).toContain('Time elapsed: ');\n        }\n      );\n    });\n\n    it('does not ouput anything in silent mode', () => {\n      const sourceA = createTempFileWith('a', 'sourceA', '.js');\n      const transform = createTransformWith('return null;');\n      return run(['-t', transform, '-s', sourceA]).then(\n        out => {\n          expect(out[0]).toEqual('');\n        }\n      );\n    });\n  });\n\n  xdescribe('--parser=ts', () => {\n    it('parses TypeScript sources', () => {\n      const source = createTempFileWith('type Foo = string | string[];', 'source', '.ts');\n\n      const transform = createTransformWith(\n        'api.jscodeshift(fileInfo.source)\\n { return \"changed\" };'\n      );\n      return run([\n        '-t', transform,\n        '--parser', 'ts',\n        '--run-in-band',\n        source,\n      ]).then(\n        out => {\n          expect(out[0]).not.toContain('Transformation error');\n          expect(readFile(source)).toEqual('changed');\n        }\n      );\n    });\n  });\n\n  describe('--parser-config', () => {\n    it('allows custom parser settings to be passed', () => {\n      // @decorators before export are not supported in the current default\n      // config\n      const source = createTempFileWith('@foo\\nexport class Bar {}', 'source', '.js');\n      const parserConfig = createTempFileWith(JSON.stringify({\n        sourceType: 'module',\n        tokens: true,\n        plugins: [\n          ['decorators', {decoratorsBeforeExport: true}],\n        ],\n      }));\n      const transform = createTransformWith(\n        'api.jscodeshift(fileInfo.source)\\n { return \"changed\" };'\n      );\n      return run([\n        '-t', transform,\n        '--parser-config', parserConfig,\n        '--parser', 'babylon',\n        '--run-in-band',\n        source,\n      ]).then(\n        out => {\n          expect(out[0]).not.toContain('Transformation error');\n          expect(readFile(source)).toEqual('changed');\n        }\n      );\n    });\n  });\n\n});\n"
  },
  {
    "path": "bin/jscodeshift.js",
    "content": "#!/usr/bin/env node\n\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst Runner = require('../src/Runner.js');\n\nconst fs = require('fs');\nconst path = require('path');\nconst pkg = require('../package.json');\n\nconst { DEFAULT_EXTENSIONS } = require('@babel/core');\nconst defaultExtensions = DEFAULT_EXTENSIONS.concat(['ts', 'tsx']).map(\n  (ext) => (ext.startsWith('.') ? ext.substring(1) : ext)\n).sort().join(',');\n\nconst parser = require('../src/argsParser')\n  .options({\n    transform: {\n      display_index: 15,\n      abbr: 't',\n      default: './transform.js',\n      help: 'path to the transform file. Can be either a local path or url',\n      metavar: 'FILE',\n      required: true\n    },\n    cpus: {\n      display_index: 1,\n      abbr: 'c',\n      help: 'start at most N child processes to process source files',\n      defaultHelp: 'max(all - 1, 1)',\n      metavar: 'N',\n      process: Number,\n    },\n    verbose: {\n      display_index: 16,\n      abbr: 'v',\n      choices: [0, 1, 2],\n      default: 0,\n      help: 'show more information about the transform process',\n      metavar: 'N',\n      process: Number,\n    },\n    dry: {\n      display_index: 2,\n      abbr: 'd',\n      flag: true,\n      default: false,\n      help: 'dry run (no changes are made to files)'\n    },\n    print: {\n      display_index: 11,\n      abbr: 'p',\n      flag: true,\n      default: false,\n      help: 'print transformed files to stdout, useful for development'\n    },\n    babel: {\n      display_index: 0,\n      flag: true,\n      default: true,\n      help: 'apply babeljs to the transform file'\n    },\n    extensions: {\n      display_index: 3,\n      default: defaultExtensions,\n      help: 'transform files with these file extensions (comma separated list)',\n      metavar: 'EXT',\n    },\n    ignorePattern: {\n      display_index: 7,\n      full: 'ignore-pattern',\n      list: true,\n      help: 'ignore files that match a provided glob expression',\n      metavar: 'GLOB',\n    },\n    ignoreConfig: {\n      display_index: 6,\n      full: 'ignore-config',\n      list: true,\n      help: 'ignore files if they match patterns sourced from a configuration file (e.g. a .gitignore)',\n      metavar: 'FILE'\n    },\n    gitignore: {\n      display_index: 8,\n      flag: true,\n      default: false,\n      help: 'adds entries the current directory\\'s .gitignore file',\n    },\n    runInBand: {\n      display_index: 12,\n      flag: true,\n      default: false,\n      full: 'run-in-band',\n      help: 'run serially in the current process'\n    },\n    silent: {\n      display_index: 13,\n      abbr: 's',\n      flag: true,\n      default: false,\n      help: 'do not write to stdout or stderr'\n    },\n    parser: {\n      display_index: 9,\n      choices: ['babel', 'babylon', 'flow', 'ts', 'tsx'],\n      default: 'babel',\n      help: 'the parser to use for parsing the source files'\n    },\n    parserConfig: {\n      display_index: 10,\n      full: 'parser-config',\n      help: 'path to a JSON file containing a custom parser configuration for flow or babylon',\n      metavar: 'FILE',\n      process: file => JSON.parse(fs.readFileSync(file)),\n    },\n    failOnError: {\n      display_index: 4,\n      flag: true,\n      help: 'Return a non-zero code when there are errors',\n      full: 'fail-on-error',\n      default: false,\n    },\n    version: {\n      display_index: 17,\n      help: 'print version and exit',\n      callback: function() {\n        const requirePackage = require('../utils/requirePackage');\n        return [\n          `jscodeshift: ${pkg.version}`,\n          ` - babel: ${require('@babel/core').version}`,\n          ` - babylon: ${requirePackage('@babel/parser').version}`,\n          ` - flow: ${requirePackage('flow-parser').version}`,\n          ` - recast: ${requirePackage('recast').version}\\n`,\n        ].join('\\n');\n      },\n    },\n    stdin: {\n      display_index: 14,\n      help: 'read file/directory list from stdin',\n      flag: true,\n      default: false,\n    },\n  });\n\nlet options, positionalArguments;\ntry {\n  ({options, positionalArguments} = parser.parse());\n  if (positionalArguments.length === 0 && !options.stdin) {\n    process.stderr.write(\n      'Error: You have to provide at least one file/directory to transform.' +\n      '\\n\\n---\\n\\n' +\n      parser.getHelpText()\n    );\n    process.exit(1);\n  }\n} catch(e) {\n  const exitCode = e.exitCode === undefined ? 1 : e.exitCode;\n  (exitCode ? process.stderr : process.stdout).write(e.message);\n  process.exit(exitCode);\n}\nfunction run(paths, options) {\n  Runner.run(\n    /^https?/.test(options.transform) ? options.transform : path.resolve(options.transform),\n    paths,\n    options\n  );\n}\n\nif (options.stdin) {\n  let buffer = '';\n  process.stdin.on('data', data => buffer += data);\n  process.stdin.on('end', () => run(buffer.split('\\n'), options));\n} else {\n  run(positionalArguments, options);\n}\n"
  },
  {
    "path": "bin/jscodeshift.sh",
    "content": "#!/usr/bin/env node\n\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nrequire('./jscodeshift.js');\n"
  },
  {
    "path": "index.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = require('./src/core');\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"jscodeshift\",\n  \"version\": \"17.3.0\",\n  \"description\": \"A toolkit for JavaScript codemods\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/facebook/jscodeshift.git\"\n  },\n  \"bugs\": \"https://github.com/facebook/jscodeshift/issues\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"clean\": \"rm -rf dist/\",\n    \"prepare\": \"yarn clean && cp -R src/ dist/\",\n    \"test\": \"jest --bail\",\n    \"release\": \"changeset publish\"\n  },\n  \"bin\": {\n    \"jscodeshift\": \"./bin/jscodeshift.js\"\n  },\n  \"keywords\": [\n    \"codemod\",\n    \"recast\",\n    \"babel\"\n  ],\n  \"author\": \"Felix Kling\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@babel/core\": \"^7.24.7\",\n    \"@babel/parser\": \"^7.24.7\",\n    \"@babel/plugin-transform-class-properties\": \"^7.24.7\",\n    \"@babel/plugin-transform-modules-commonjs\": \"^7.24.7\",\n    \"@babel/plugin-transform-nullish-coalescing-operator\": \"^7.24.7\",\n    \"@babel/plugin-transform-optional-chaining\": \"^7.24.7\",\n    \"@babel/plugin-transform-private-methods\": \"^7.24.7\",\n    \"@babel/preset-flow\": \"^7.24.7\",\n    \"@babel/preset-typescript\": \"^7.24.7\",\n    \"@babel/register\": \"^7.24.6\",\n    \"flow-parser\": \"0.*\",\n    \"graceful-fs\": \"^4.2.4\",\n    \"micromatch\": \"^4.0.7\",\n    \"neo-async\": \"^2.5.0\",\n    \"picocolors\": \"^1.0.1\",\n    \"recast\": \"^0.23.11\",\n    \"tmp\": \"^0.2.3\",\n    \"write-file-atomic\": \"^5.0.1\"\n  },\n  \"peerDependencies\": {\n    \"@babel/preset-env\": \"^7.1.6\"\n  },\n  \"peerDependenciesMeta\": {\n    \"@babel/preset-env\": {\n      \"optional\": true\n    }\n  },\n  \"devDependencies\": {\n    \"@babel/eslint-parser\": \"^7.24.7\",\n    \"@changesets/cli\": \"^2.27.8\",\n    \"eslint\": \"8.56.0\",\n    \"jest\": \"^29.7.0\",\n    \"jsdoc\": \"^4.0.3\"\n  },\n  \"jest\": {\n    \"roots\": [\n      \"src\",\n      \"bin\",\n      \"parser\",\n      \"sample\"\n    ]\n  },\n  \"engines\": {\n    \"node\": \">=16\"\n  },\n  \"packageManager\": \"yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e\"\n}\n"
  },
  {
    "path": "parser/__tests__/.eslintrc",
    "content": "{\n  \"globals\": {\n    \"jest\": true\n  },\n  \"env\": {\n    \"jasmine\": true\n  }\n}\n"
  },
  {
    "path": "parser/__tests__/__snapshots__/tsx-test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`tsxParser parse extends the ts config with jsx support 1`] = `\n[\n  \"\"mock content\";\",\n  {\n    \"allowImportExportEverywhere\": true,\n    \"allowReturnOutsideFunction\": true,\n    \"plugins\": [\n      \"jsx\",\n      \"asyncGenerators\",\n      \"decoratorAutoAccessors\",\n      \"bigInt\",\n      \"classPrivateMethods\",\n      \"classPrivateProperties\",\n      \"classProperties\",\n      \"decorators-legacy\",\n      \"doExpressions\",\n      \"dynamicImport\",\n      \"exportDefaultFrom\",\n      \"exportExtensions\",\n      \"exportNamespaceFrom\",\n      \"functionBind\",\n      \"functionSent\",\n      \"importAttributes\",\n      \"importMeta\",\n      \"nullishCoalescingOperator\",\n      \"numericSeparator\",\n      \"objectRestSpread\",\n      \"optionalCatchBinding\",\n      \"optionalChaining\",\n      [\n        \"pipelineOperator\",\n        {\n          \"proposal\": \"minimal\",\n        },\n      ],\n      \"throwExpressions\",\n      \"typescript\",\n    ],\n    \"sourceType\": \"module\",\n    \"startLine\": 1,\n    \"tokens\": true,\n  },\n]\n`;\n"
  },
  {
    "path": "parser/__tests__/tsx-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/*global jest, describe, it, expect*/\n\n'use strict';\n\njest.mock('@babel/parser')\nconst babylon = require('@babel/parser');\n\nconst tsxParser = require('../tsx');\n\ndescribe('tsxParser', function() {\n  describe('parse', function() {\n    it('extends the ts config with jsx support', function() {\n      const parser = tsxParser();\n      parser.parse('\"mock content\";');\n\n      expect(babylon.parse).toHaveBeenCalledTimes(1);\n      expect(babylon.parse.mock.calls[0]).toMatchSnapshot();\n    });\n  });\n});\n"
  },
  {
    "path": "parser/babel5Compat.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst babylon = require('@babel/parser');\n\n// These are the options that were the default of the Babel5 parse function\n// see https://github.com/babel/babel/blob/5.x/packages/babel/src/api/node.js#L81\nconst options = {\n  sourceType: 'module',\n  allowHashBang: true,\n  ecmaVersion: Infinity,\n  allowImportExportEverywhere: true,\n  allowReturnOutsideFunction: true,\n  startLine: 1,\n  tokens: true,\n  plugins: [\n    'estree',\n    'jsx',\n    'asyncGenerators',\n    'classProperties',\n    'doExpressions',\n    'exportExtensions',\n    'functionBind',\n    'functionSent',\n    'objectRestSpread',\n    'dynamicImport',\n    'nullishCoalescingOperator',\n    'optionalChaining',\n    ['decorators', {decoratorsBeforeExport: false}],\n  ],\n};\n\n/**\n * Wrapper to set default options. Doesn't accept custom options because in that\n * case babylon should be used instead.\n */\nmodule.exports = function() {\n  return {\n    parse(code) {\n      return babylon.parse(code, options);\n    },\n  };\n};\n"
  },
  {
    "path": "parser/babylon.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst babylon = require('@babel/parser');\n\nconst defaultOptions = {\n  sourceType: 'module',\n  allowImportExportEverywhere: true,\n  allowReturnOutsideFunction: true,\n  startLine: 1,\n  tokens: true,\n  plugins: [\n    ['flow', {all: true}],\n    'flowComments',\n    'jsx',\n\n    'asyncGenerators',\n    'bigInt',\n    'classProperties',\n    'classPrivateProperties',\n    'classPrivateMethods',\n    ['decorators', {decoratorsBeforeExport: false}],\n    'doExpressions',\n    'dynamicImport',\n    'exportDefaultFrom',\n    'exportNamespaceFrom',\n    'functionBind',\n    'functionSent',\n    'importMeta',\n    'logicalAssignment',\n    'nullishCoalescingOperator',\n    'numericSeparator',\n    'objectRestSpread',\n    'optionalCatchBinding',\n    'optionalChaining',\n    ['pipelineOperator', {proposal: 'minimal'}],\n    'throwExpressions',\n  ],\n};\n\n/**\n * Wrapper to set default options\n */\nmodule.exports = function(options=defaultOptions) {\n  return {\n    parse(code) {\n      return babylon.parse(code, options);\n    },\n  };\n};\n"
  },
  {
    "path": "parser/flow.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst flowParser = require('flow-parser');\n\nconst defaultOptions = {\n  enums: true,\n  esproposal_class_instance_fields: true,\n  esproposal_class_static_fields: true,\n  esproposal_decorators: true,\n  esproposal_export_star_as: true,\n  esproposal_optional_chaining: true,\n  esproposal_nullish_coalescing: true,\n  tokens: true,\n  types: true,\n};\n\n/**\n * Wrapper to set default options\n */\nmodule.exports = function(options=defaultOptions) {\n  return {\n    parse(code) {\n      return flowParser.parse(code, options);\n    },\n  };\n};\n"
  },
  {
    "path": "parser/ts.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst babylon = require('@babel/parser');\nconst options = require('./tsOptions');\n\n/**\n * Doesn't accept custom options because babylon should be used directly in\n * that case.\n */\nmodule.exports = function() {\n  return {\n    parse(code) {\n      return babylon.parse(code, options);\n    },\n  };\n};\n"
  },
  {
    "path": "parser/tsOptions.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n/**\n * Options shared by the TypeScript and TSX parsers.\n */\nmodule.exports = {\n  sourceType: 'module',\n  allowImportExportEverywhere: true,\n  allowReturnOutsideFunction: true,\n  startLine: 1,\n  tokens: true,\n  plugins: [\n    'asyncGenerators',\n    'decoratorAutoAccessors',\n    'bigInt',\n    'classPrivateMethods',\n    'classPrivateProperties',\n    'classProperties',\n    'decorators-legacy',\n    'doExpressions',\n    'dynamicImport',\n    'exportDefaultFrom',\n    'exportExtensions',\n    'exportNamespaceFrom',\n    'functionBind',\n    'functionSent',\n    'importAttributes',\n    'importMeta',\n    'nullishCoalescingOperator',\n    'numericSeparator',\n    'objectRestSpread',\n    'optionalCatchBinding',\n    'optionalChaining',\n    ['pipelineOperator', { proposal: 'minimal' }],\n    'throwExpressions',\n    'typescript'\n  ],\n};\n"
  },
  {
    "path": "parser/tsx.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst babylon = require('@babel/parser');\nconst baseOptions = require('./tsOptions');\n\nconst options = Object.assign({}, baseOptions);\noptions.plugins = ['jsx'].concat(baseOptions.plugins);\n\n/**\n * Doesn't accept custom options because babylon should be used directly in\n * that case.\n */\nmodule.exports = function() {\n  return {\n    parse(code) {\n      return babylon.parse(code, options);\n    },\n  };\n};\n"
  },
  {
    "path": "recipes/retain-first-comment.md",
    "content": "# Retain comment on first line\n\n## Problem\n\nWhen removing or replacing the first statement in a file, it is possible for [leading comments at the top of the file to be removed](https://github.com/facebook/jscodeshift/issues/44).\n\n## Solution\n\nTo retain the leading comments during a transformation, the `comments` array on the statement's `node` _must_ be copied to the next statement's `node` that will be at the top of the file.\n\n## Examples\n\n#### Bad\n\n##### Transform\n```javascript\nexport default function transformer(file, api) {\n  const j = api.jscodeshift;\n\n  return j(file.source)\n    .find(j.VariableDeclaration)\n    .replaceWith(\n        j.expressionStatement(j.callExpression(\n                j.identifier('foo'), []\n            )\n        )\n    )\n    .toSource();\n};\n```\n\n##### In\n```javascript\n// Comment on first line\nconst firstStatement = require('some-module');\n```\n\n##### Out\n```javascript\nfoo();\n```\n\n#### Good\n\n##### Transform\n```javascript\nexport default function transformer(file, api) {\n  const j = api.jscodeshift;\n  const root = j(file.source);\n\n  const getFirstNode = () => root.find(j.Program).get('body', 0).node;\n\n  // Save the comments attached to the first node\n  const firstNode = getFirstNode();\n  const { comments } = firstNode;\n\n  root.find(j.VariableDeclaration).replaceWith(\n    j.expressionStatement(j.callExpression(\n        j.identifier('foo'),\n        []\n    ))\n  );\n\n  // If the first node has been modified or deleted, reattach the comments\n  const firstNode2 = getFirstNode();\n  if (firstNode2 !== firstNode) {\n    firstNode2.comments = comments;\n  }\n\n  return root.toSource();\n};\n```\n\n##### In\n```javascript\n// Comment on first line\nconst firstStatement = require('some-module');\n```\n\n##### Out\n```javascript\n// Comment on first line\nfoo();\n```\n\n"
  },
  {
    "path": "sample/__testfixtures__/reverse-identifiers.input.js",
    "content": "var firstWord = 'Hello ';\nvar secondWord = 'world';\nvar message = firstWord + secondWord;\n\nclass Foo {\n  @decorated\n  *bar() { }\n}\n"
  },
  {
    "path": "sample/__testfixtures__/reverse-identifiers.output.js",
    "content": "var droWtsrif = 'Hello ';\nvar droWdnoces = 'world';\nvar egassem = droWtsrif + droWdnoces;\n\nclass ooF {\n  @detaroced\n  *rab() { }\n}\n"
  },
  {
    "path": "sample/__testfixtures__/typescript/reverse-identifiers.input.ts",
    "content": "import type { Stream } from 'stream';\n\nconst firstWord = 'Hello ';\nconst secondWord = 'world';\nconst message = firstWord + secondWord;\n\nconst getMessage = (): string => message\n"
  },
  {
    "path": "sample/__testfixtures__/typescript/reverse-identifiers.output.ts",
    "content": "import type { maertS } from 'stream';\n\nconst droWtsrif = 'Hello ';\nconst droWdnoces = 'world';\nconst egassem = droWtsrif + droWdnoces;\n\nconst egasseMteg = (): string => egassem\n"
  },
  {
    "path": "sample/__tests__/__snapshots__/reverse-identifiers-test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`transforms correctly 1`] = `\n\"var droWtsrif = 'Hello ';\nvar droWdnoces = 'world';\nvar egassem = droWtsrif + droWdnoces;\n\nclass ooF {\n  @detaroced\n  *rab() { }\n}\"\n`;\n"
  },
  {
    "path": "sample/__tests__/reverse-identifiers-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * An example of writing a unit test for a jscodeshift script using the\n * `defineTest` helper bundled with jscodeshift. This will run the\n * reverse-identifiers.js transform with the input specified in the\n * reverse-identifiers-input file, and expect the output to be the same as that\n * in reverse-identifiers-output.\n */\n\n'use strict';\n\njest.autoMockOff();\nconst defineTest = require('../../src/testUtils').defineTest;\nconst defineInlineTest = require('../../src/testUtils').defineInlineTest;\nconst defineSnapshotTestFromFixture = require('../../src/testUtils').defineSnapshotTestFromFixture;\nconst transform = require('../reverse-identifiers');\n\ndefineTest(__dirname, 'reverse-identifiers');\n\ndefineTest(__dirname, 'reverse-identifiers', null, 'typescript/reverse-identifiers', { parser: 'ts' });\n\ndescribe('reverse-identifiers', () => {\n  defineInlineTest(transform, {}, `\nvar firstWord = 'Hello ';\nvar secondWord = 'world';\nvar message = firstWord + secondWord;`,`\nvar droWtsrif = 'Hello ';\nvar droWdnoces = 'world';\nvar egassem = droWtsrif + droWdnoces;\n  `);\n  defineInlineTest(transform, {},\n    'function aFunction() {};',\n    'function noitcnuFa() {};',\n    'Reverses function names'\n  );\n});\n\n// the snapshot output of this file should be the same as reverse-identifiers.output.js\ndefineSnapshotTestFromFixture(__dirname, transform, {}, 'reverse-identifiers');\n"
  },
  {
    "path": "sample/reverse-identifiers.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * Example jscodeshift transformer. Simply reverses the names of all\n * identifiers.\n */\nfunction transformer(file, api) {\n  const j = api.jscodeshift;\n\n  return j(file.source)\n    .find(j.Identifier)\n    .replaceWith(\n      p => j.identifier(p.node.name.split('').reverse().join(''))\n    )\n    .toSource();\n}\n\nmodule.exports = transformer;\n"
  },
  {
    "path": "src/Collection.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst assert = require('assert');\nconst intersection = require('./utils/intersection');\nconst recast = require('recast');\nconst union = require('./utils/union');\n\nconst astTypes = recast.types;\nvar types = astTypes.namedTypes;\nconst NodePath = astTypes.NodePath;\nconst Node = types.Node;\n\n/**\n * This represents a generic collection of node paths. It only has a generic\n * API to access and process the elements of the list. It doesn't know anything\n * about AST types.\n *\n * @mixes traversalMethods\n * @mixes mutationMethods\n * @mixes transformMethods\n * @mixes globalMethods\n */\nclass Collection {\n\n  /**\n   * @param {Array} paths An array of AST paths\n   * @param {Collection} parent A parent collection\n   * @param {Array} types An array of types all the paths in the collection\n   *  have in common. If not passed, it will be inferred from the paths.\n   * @return {Collection}\n   */\n  constructor(paths, parent, types) {\n    assert.ok(Array.isArray(paths), 'Collection is passed an array');\n    assert.ok(\n      paths.every(p => p instanceof NodePath),\n      'Array contains only paths'\n    );\n    this._parent = parent;\n    this.__paths = paths;\n    if (types && !Array.isArray(types)) {\n      types = _toTypeArray(types);\n    } else if (!types || Array.isArray(types) && types.length === 0) {\n      types = _inferTypes(paths);\n    }\n    this._types = types.length === 0 ? _defaultType : types;\n  }\n\n  /**\n   * Returns a new collection containing the nodes for which the callback\n   * returns true.\n   *\n   * @param {function} callback\n   * @return {Collection}\n   */\n  filter(callback) {\n    return new this.constructor(this.__paths.filter(callback), this);\n  }\n\n  /**\n   * Executes callback for each node/path in the collection.\n   *\n   * @param {function} callback\n   * @return {Collection} The collection itself\n   */\n  forEach(callback) {\n    this.__paths.forEach(\n      (path, i, paths) => callback.call(path, path, i, paths)\n    );\n    return this;\n  }\n\n  /**\n   * Tests whether at-least one path passes the test implemented by the provided callback.\n   *\n   * @param {function} callback\n   * @return {boolean}\n   */\n  some(callback) {\n    return this.__paths.some(\n      (path, i, paths) => callback.call(path, path, i, paths)\n    );\n  }\n\n  /**\n   * Tests whether all paths pass the test implemented by the provided callback.\n   *\n   * @param {function} callback\n   * @return {boolean}\n   */\n  every(callback) {\n    return this.__paths.every(\n      (path, i, paths) => callback.call(path, path, i, paths)\n    );\n  }\n\n  /**\n   * Executes the callback for every path in the collection and returns a new\n   * collection from the return values (which must be paths).\n   *\n   * The callback can return null to indicate to exclude the element from the\n   * new collection.\n   *\n   * If an array is returned, the array will be flattened into the result\n   * collection.\n   *\n   * @param {function} callback\n   * @param {Type} type Force the new collection to be of a specific type\n   */\n  map(callback, type) {\n    const paths = [];\n    this.forEach(function(path) {\n      /*jshint eqnull:true*/\n      let result = callback.apply(path, arguments);\n      if (result == null) return;\n      if (!Array.isArray(result)) {\n        result = [result];\n      }\n      for (let i = 0; i < result.length; i++) {\n        if (paths.indexOf(result[i]) === -1) {\n          paths.push(result[i]);\n        }\n      }\n    });\n    return fromPaths(paths, this, type);\n  }\n\n  /**\n   * Returns the number of elements in this collection.\n   *\n   * @return {number}\n   */\n  size() {\n    return this.__paths.length;\n  }\n\n  /**\n   * Returns the number of elements in this collection.\n   *\n   * @return {number}\n   */\n  get length() {\n    return this.__paths.length;\n  }\n\n  /**\n   * Returns an array of AST nodes in this collection.\n   *\n   * @return {Array}\n   */\n  nodes() {\n    return this.__paths.map(p => p.value);\n  }\n\n  paths() {\n    return this.__paths;\n  }\n\n  getAST() {\n    if (this._parent) {\n      return this._parent.getAST();\n    }\n    return this.__paths;\n  }\n\n  toSource(options) {\n    if (this._parent) {\n      return this._parent.toSource(options);\n    }\n    if (this.__paths.length === 1) {\n      return recast.print(this.__paths[0], options).code;\n    } else {\n      return this.__paths.map(p => recast.print(p, options).code);\n    }\n  }\n\n  /**\n   * Returns a new collection containing only the element at position index.\n   *\n   * In case of a negative index, the element is taken from the end:\n   *\n   *   .at(0)  - first element\n   *   .at(-1) - last element\n   *\n   * @param {number} index\n   * @return {Collection}\n   */\n  at(index) {\n    return fromPaths(\n      this.__paths.slice(\n        index,\n        index === -1 ? undefined : index + 1\n      ),\n      this\n    );\n  }\n\n  /**\n   * Proxies to NodePath#get of the first path.\n   *\n   * @param {string|number} ...fields\n   */\n  get() {\n    const path = this.__paths[0];\n    if (!path) {\n      throw Error(\n        'You cannot call \"get\" on a collection with no paths. ' +\n        'Instead, check the \"length\" property first to verify at least 1 path exists.'\n      );\n    }\n    return path.get.apply(path, arguments);\n  }\n\n  /**\n   * Returns the type(s) of the collection. This is only used for unit tests,\n   * I don't think other consumers would need it.\n   *\n   * @return {Array<string>}\n   */\n  getTypes() {\n    return this._types;\n  }\n\n  /**\n   * Returns true if this collection has the type 'type'.\n   *\n   * @param {Type} type\n   * @return {boolean}\n   */\n  isOfType(type) {\n    return !!type && this._types.indexOf(type.toString()) > -1;\n  }\n}\n\n/**\n * Given a set of paths, this infers the common types of all paths.\n * @private\n * @param {Array} paths An array of paths.\n * @return {Type} type An AST type\n */\nfunction _inferTypes(paths) {\n  let _types = [];\n\n  if (paths.length > 0 && Node.check(paths[0].node)) {\n    const nodeType = types[paths[0].node.type];\n    const sameType = paths.length === 1 ||\n      paths.every(path => nodeType.check(path.node));\n\n    if (sameType) {\n      _types = [nodeType.toString()].concat(\n        astTypes.getSupertypeNames(nodeType.toString())\n      );\n    } else {\n      // try to find a common type\n      _types = intersection(\n        paths.map(path => astTypes.getSupertypeNames(path.node.type))\n      );\n    }\n  }\n\n  return _types;\n}\n\nfunction _toTypeArray(value) {\n  value = !Array.isArray(value) ? [value] : value;\n  value = value.map(v => v.toString());\n  if (value.length > 1) {\n    return union(\n      [value].concat(intersection(value.map(_getSupertypeNames)))\n    );\n  } else {\n    return value.concat(_getSupertypeNames(value[0]));\n  }\n}\n\nfunction _getSupertypeNames(type) {\n  try {\n    return astTypes.getSupertypeNames(type);\n  } catch(error) {\n    if (error.message === '') {\n      // Likely the case that the passed type wasn't found in the definition\n      // list. Maybe a typo. ast-types doesn't throw a useful error in that\n      // case :(\n      throw new Error(\n        '\"' + type + '\" is not a known AST node type. Maybe a typo?'\n      );\n    }\n    throw error;\n  }\n}\n\n/**\n * Creates a new collection from an array of node paths.\n *\n * If type is passed, it will create a typed collection if such a collection\n * exists. The nodes or path values must be of the same type.\n *\n * Otherwise it will try to infer the type from the path list. If every\n * element has the same type, a typed collection is created (if it exists),\n * otherwise, a generic collection will be created.\n *\n * @ignore\n * @param {Array} paths An array of paths\n * @param {Collection} parent A parent collection\n * @param {Type} type An AST type\n * @return {Collection}\n */\nfunction fromPaths(paths, parent, type) {\n  assert.ok(\n    paths.every(n => n instanceof NodePath),\n    'Every element in the array should be a NodePath'\n  );\n\n  return new Collection(paths, parent, type);\n}\n\n/**\n * Creates a new collection from an array of nodes. This is a convenience\n * method which converts the nodes to node paths first and calls\n *\n *    Collections.fromPaths(paths, parent, type)\n *\n * @ignore\n * @param {Array} nodes An array of AST nodes\n * @param {Collection} parent A parent collection\n * @param {Type} type An AST type\n * @return {Collection}\n */\nfunction fromNodes(nodes, parent, type) {\n  assert.ok(\n    nodes.every(n => Node.check(n)),\n    'Every element in the array should be a Node'\n  );\n  return fromPaths(\n    nodes.map(n => new NodePath(n)),\n    parent,\n    type\n  );\n}\n\nconst CPt = Collection.prototype;\n\n/**\n * This function adds the provided methods to the prototype of the corresponding\n * typed collection. If no type is passed, the methods are added to\n * Collection.prototype and are available for all collections.\n *\n * @param {Object} methods Methods to add to the prototype\n * @param {Type=} type Optional type to add the methods to\n */\nfunction registerMethods(methods, type) {\n  for (const methodName in methods) {\n    if (!methods.hasOwnProperty(methodName)) {\n      return;\n    }\n    if (hasConflictingRegistration(methodName, type)) {\n      let msg = `There is a conflicting registration for method with name \"${methodName}\".\\nYou tried to register an additional method with `;\n\n      if (type) {\n        msg += `type \"${type.toString()}\".`\n      } else {\n        msg += 'universal type.'\n      }\n\n      msg += '\\nThere are existing registrations for that method with ';\n\n      const conflictingRegistrations = CPt[methodName].typedRegistrations;\n\n      if (conflictingRegistrations) {\n        msg += `type ${Object.keys(conflictingRegistrations).join(', ')}.`;\n      } else {\n        msg += 'universal type.';\n      }\n\n      throw Error(msg);\n    }\n    if (!type) {\n      CPt[methodName] = methods[methodName];\n    } else {\n      type = type.toString();\n      if (!CPt.hasOwnProperty(methodName)) {\n        installTypedMethod(methodName);\n      }\n      var registrations = CPt[methodName].typedRegistrations;\n      registrations[type] = methods[methodName];\n      astTypes.getSupertypeNames(type).forEach(function (name) {\n        registrations[name] = false;\n      });\n    }\n  }\n}\n\nfunction installTypedMethod(methodName) {\n  if (CPt.hasOwnProperty(methodName)) {\n    throw new Error(`Internal Error: \"${methodName}\" method is already installed`);\n  }\n\n  const registrations = {};\n\n  function typedMethod() {\n    const types = Object.keys(registrations);\n\n    for (let i = 0; i < types.length; i++) {\n      const currentType = types[i];\n      if (registrations[currentType] && this.isOfType(currentType)) {\n        return registrations[currentType].apply(this, arguments);\n      }\n    }\n\n    throw Error(\n      `You have a collection of type [${this.getTypes()}]. ` +\n      `\"${methodName}\" is only defined for one of [${types.join('|')}].`\n    );\n  }\n\n  typedMethod.typedRegistrations = registrations;\n\n  CPt[methodName] = typedMethod;\n}\n\nfunction hasConflictingRegistration(methodName, type) {\n  if (!type) {\n    return CPt.hasOwnProperty(methodName);\n  }\n\n  if (!CPt.hasOwnProperty(methodName)) {\n    return false;\n  }\n\n  const registrations = CPt[methodName] && CPt[methodName].typedRegistrations;\n\n  if (!registrations) {\n    return true;\n  }\n\n  type = type.toString();\n\n  if (registrations.hasOwnProperty(type)) {\n    return true;\n  }\n\n  return astTypes.getSupertypeNames(type.toString()).some(function (name) {\n    return !!registrations[name];\n  });\n}\n\nvar _defaultType = [];\n\n/**\n * Sets the default collection type. In case a collection is created form an\n * empty set of paths and no type is specified, we return a collection of this\n * type.\n *\n * @ignore\n * @param {Type} type\n */\nfunction setDefaultCollectionType(type) {\n  _defaultType = _toTypeArray(type);\n}\n\nexports.fromPaths = fromPaths;\nexports.fromNodes = fromNodes;\nexports.registerMethods = registerMethods;\nexports.hasConflictingRegistration = hasConflictingRegistration;\nexports.setDefaultCollectionType = setDefaultCollectionType;\n"
  },
  {
    "path": "src/Runner.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst child_process = require('child_process');\nconst pc = require('picocolors');\nconst fs = require('graceful-fs');\nconst path = require('path');\nconst http = require('http');\nconst https = require('https');\nconst ignores = require('./ignoreFiles');\n\nconst tmp = require('tmp');\ntmp.setGracefulCleanup();\n\nconst availableCpus = Math.max(require('os').cpus().length - 1, 1);\nconst CHUNK_SIZE = 50;\n\nfunction lineBreak(str) {\n  return /\\n$/.test(str) ? str : str + '\\n';\n}\n\nconst bufferedWrite = (function() {\n  const buffer = [];\n  let buffering = false;\n\n  process.stdout.on('drain', () => {\n    if (!buffering) return;\n    while (buffer.length > 0 && process.stdout.write(buffer.shift()) !== false);\n    if (buffer.length === 0) {\n      buffering = false;\n    }\n  });\n  return function write(msg) {\n    if (buffering) {\n      buffer.push(msg);\n    }\n    if (process.stdout.write(msg) === false) {\n      buffering = true;\n    }\n  };\n}());\n\nconst log = {\n  ok(msg, verbose) {\n    verbose >= 2 && bufferedWrite(pc.bgGreen(pc.white(' OKK ')) + msg);\n  },\n  nochange(msg, verbose) {\n    verbose >= 1 && bufferedWrite(pc.bgYellow(pc.white(' NOC ')) + msg);\n  },\n  skip(msg, verbose) {\n    verbose >= 1 && bufferedWrite(pc.bgYellow(pc.white(' SKIP ')) + msg);\n  },\n  error(msg, verbose) {\n    verbose >= 0 && bufferedWrite(pc.bgRed(pc.white(' ERR ')) + msg);\n  },\n};\n\nfunction report({file, msg}) {\n  bufferedWrite(lineBreak(`${pc.bgBlue(pc.white(' REP '))}${file} ${msg}`));\n}\n\nfunction concatAll(arrays) {\n  const result = [];\n  for (const array of arrays) {\n    for (const element of array) {\n      result.push(element);\n    }\n  }\n  return result;\n}\n\nfunction showFileStats(fileStats) {\n  process.stdout.write(\n    'Results: \\n'+\n    pc.red(fileStats.error + ' errors\\n')+\n    pc.yellow(fileStats.nochange + ' unmodified\\n')+\n    pc.yellow(fileStats.skip + ' skipped\\n')+\n    pc.green(fileStats.ok + ' ok\\n')\n  );\n}\n\nfunction showStats(stats) {\n  const names = Object.keys(stats).sort();\n  if (names.length) {\n    process.stdout.write(pc.blue('Stats: \\n'));\n  }\n  names.forEach(name => process.stdout.write(name + ': ' + stats[name] + '\\n'));\n}\n\nfunction dirFiles (dir, callback, acc) {\n  // acc stores files found so far and counts remaining paths to be processed\n  acc = acc || { files: [], remaining: 1 };\n\n  function done() {\n    // decrement count and return if there are no more paths left to process\n    if (!--acc.remaining) {\n      callback(acc.files);\n    }\n  }\n\n  fs.readdir(dir, (err, files) => {\n    // if dir does not exist or is not a directory, bail\n    // (this should not happen as long as calls do the necessary checks)\n    if (err) throw err;\n\n    acc.remaining += files.length;\n    files.forEach(file => {\n      let name = path.join(dir, file);\n      fs.stat(name, (err, stats) => {\n        if (err) {\n          // probably a symlink issue\n          process.stdout.write(\n            'Skipping path \"' + name + '\" which does not exist.\\n'\n          );\n          done();\n        } else if (ignores.shouldIgnore(name)) {\n          // ignore the path\n          done();\n        } else if (stats.isDirectory()) {\n          dirFiles(name + '/', callback, acc);\n        } else {\n          acc.files.push(name);\n          done();\n        }\n      });\n    });\n    done();\n  });\n}\n\nfunction getAllFiles(paths, filter) {\n  return Promise.all(\n    paths.map(file => new Promise(resolve => {\n      fs.lstat(file, (err, stat) => {\n        if (err) {\n          process.stderr.write('Skipping path ' + file + ' which does not exist. \\n');\n          resolve([]);\n          return;\n        }\n\n        if (stat.isDirectory()) {\n          dirFiles(\n            file,\n            list => resolve(list.filter(filter))\n          );\n        } else if (!filter(file) || ignores.shouldIgnore(file)) {\n          // ignoring the file\n          resolve([]);\n        } else {\n          resolve([file]);\n        }\n      })\n    }))\n  ).then(concatAll);\n}\n\nfunction run(transformFile, paths, options) {\n  const cpus = options.cpus ? Math.min(availableCpus, options.cpus) : availableCpus;\n  const extensions =\n    options.extensions && options.extensions.split(',').map(ext => '.' + ext);\n  const fileCounters = {error: 0, ok: 0, nochange: 0, skip: 0};\n  const statsCounter = {};\n  const startTime = process.hrtime();\n\n  ignores.add(options.ignoreSet);\n  ignores.add(options.ignorePattern);\n  ignores.addFromFile(options.ignoreConfig);\n\n  if (options.gitignore) {\n    let currDirectory = process.cwd();\n    let gitIgnorePath = path.join(currDirectory, '.gitignore');\n    ignores.addFromFile(gitIgnorePath);\n  }\n\n  if (/^http/.test(transformFile)) {\n    return new Promise((resolve, reject) => {\n      // call the correct `http` or `https` implementation\n      (transformFile.indexOf('https') !== 0 ?  http : https).get(transformFile, (res) => {\n        let contents = '';\n        res\n          .on('data', (d) => {\n            contents += d.toString();\n          })\n          .on('end', () => {\n            const ext = path.extname(transformFile);\n            tmp.file({ prefix: 'jscodeshift', postfix: ext }, (err, path, fd) => {\n              if (err) return reject(err);\n              fs.write(fd, contents, function (err) {\n                if (err) return reject(err);\n                fs.close(fd, function(err) {\n                  if (err) return reject(err);\n                  transform(path).then(resolve, reject);\n                });\n              });\n            });\n        })\n      })\n      .on('error', (e) => {\n        reject(e);\n      });\n    });\n  } else if (!fs.existsSync(transformFile)) {\n    process.stderr.write(\n      pc.bgRed(pc.white('ERROR')) + ' Transform file ' + transformFile + ' does not exist \\n'\n    );\n    return;\n  } else {\n    return transform(transformFile);\n  }\n\n  function transform(transformFile) {\n    return getAllFiles(\n      paths,\n      name => !extensions || extensions.indexOf(path.extname(name)) != -1\n    ).then(files => {\n        const numFiles = files.length;\n\n        if (numFiles === 0) {\n          process.stdout.write('No files selected, nothing to do. \\n');\n          return [];\n        }\n\n        const processes = options.runInBand ? 1 : Math.min(numFiles, cpus);\n        const chunkSize = processes > 1 ?\n          Math.min(Math.ceil(numFiles / processes), CHUNK_SIZE) :\n          numFiles;\n\n        let index = 0;\n        // return the next chunk of work for a free worker\n        function next() {\n          if (!options.silent && !options.runInBand && index < numFiles) {\n            process.stdout.write(\n              'Sending ' +\n              Math.min(chunkSize, numFiles-index) +\n              ' files to free worker...\\n'\n            );\n          }\n          return files.slice(index, index += chunkSize);\n        }\n\n        if (!options.silent) {\n          process.stdout.write('Processing ' + files.length + ' files... \\n');\n          if (!options.runInBand) {\n            process.stdout.write(\n              'Spawning ' + processes +' workers...\\n'\n            );\n          }\n          if (options.dry) {\n            process.stdout.write(\n              pc.green('Running in dry mode, no files will be written! \\n')\n            );\n          }\n        }\n\n        const args = [transformFile, options.babel ? 'babel' : 'no-babel'];\n\n        const workers = [];\n        for (let i = 0; i < processes; i++) {\n          workers.push(options.runInBand ?\n            require('./Worker')(args) :\n            child_process.fork(require.resolve('./Worker'), args)\n          );\n        }\n\n        return workers.map(child => {\n          child.send({files: next(), options});\n          child.on('message', message => {\n            switch (message.action) {\n              case 'status':\n                fileCounters[message.status] += 1;\n                log[message.status](lineBreak(message.msg), options.verbose);\n                break;\n              case 'update':\n                if (!statsCounter[message.name]) {\n                  statsCounter[message.name] = 0;\n                }\n                statsCounter[message.name] += message.quantity;\n                break;\n              case 'free':\n                child.send({files: next(), options});\n                break;\n              case 'report':\n                report(message);\n                break;\n            }\n          });\n          return new Promise(resolve => child.on('disconnect', resolve));\n        });\n      })\n      .then(pendingWorkers =>\n        Promise.all(pendingWorkers).then(() => {\n          const endTime = process.hrtime(startTime);\n          const timeElapsed = (endTime[0] + endTime[1]/1e9).toFixed(3);\n          if (!options.silent) {\n            process.stdout.write('All done. \\n');\n            showFileStats(fileCounters);\n            showStats(statsCounter);\n            process.stdout.write(\n              'Time elapsed: ' + timeElapsed + 'seconds \\n'\n            );\n\n            if (options.failOnError && fileCounters.error > 0) {\n              process.exit(1);\n            }\n          }\n          return Object.assign({\n            stats: statsCounter,\n            timeElapsed: timeElapsed\n          }, fileCounters);\n        })\n      );\n  }\n}\n\nexports.run = run;\n"
  },
  {
    "path": "src/Worker.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst EventEmitter = require('events').EventEmitter;\n\nconst async = require('neo-async');\nconst fs = require('graceful-fs');\nconst writeFileAtomic = require('write-file-atomic');\nconst { DEFAULT_EXTENSIONS } = require('@babel/core');\nconst getParser = require('./getParser');\n\nconst jscodeshift = require('./core');\n\nlet presetEnv;\ntry {\n  presetEnv = require('@babel/preset-env');\n} catch (_) {}\n\nlet emitter;\nlet finish;\nlet notify;\nlet transform;\nlet parserFromTransform;\n\nif (module.parent) {\n  emitter = new EventEmitter();\n  emitter.send = (data) => { run(data); };\n  finish = () => { emitter.emit('disconnect'); };\n  notify = (data) => { emitter.emit('message', data); };\n  module.exports = (args) => {\n    setup(args[0], args[1]);\n    return emitter;\n  };\n} else {\n  finish = () => setImmediate(() => process.disconnect());\n  notify = (data) => { process.send(data); };\n  process.on('message', (data) => { run(data); });\n  setup(process.argv[2], process.argv[3]);\n}\n\nfunction prepareJscodeshift(options) {\n  const parser = parserFromTransform ||\n    getParser(options.parser, options.parserConfig);\n  return jscodeshift.withParser(parser);\n}\n\nfunction setup(tr, babel) {\n  if (babel === 'babel') {\n    const presets = [];\n    if (presetEnv) {\n      presets.push([\n        presetEnv.default,\n        {targets: {node: true}},\n      ]);\n    }\n    presets.push(\n      /\\.tsx?$/.test(tr) ?\n        require('@babel/preset-typescript').default :\n        require('@babel/preset-flow').default\n    );\n\n    require('@babel/register')({\n      configFile: false,\n      babelrc: false,\n      presets,\n      plugins: [\n        require('@babel/plugin-transform-class-properties').default,\n        require('@babel/plugin-transform-nullish-coalescing-operator').default,\n        require('@babel/plugin-transform-optional-chaining').default,\n        require('@babel/plugin-transform-modules-commonjs').default,\n        require('@babel/plugin-transform-private-methods').default,\n      ],\n      extensions: [...DEFAULT_EXTENSIONS, '.ts', '.tsx'],\n      // By default, babel register only compiles things inside the current working directory.\n      // https://github.com/babel/babel/blob/2a4f16236656178e84b05b8915aab9261c55782c/packages/babel-register/src/node.js#L140-L157\n      ignore: [\n        // Ignore parser related files\n        /@babel\\/parser/,\n        /\\/flow-parser\\//,\n        /\\/recast\\//,\n        /\\/ast-types\\//,\n      ],\n    });\n  }\n\n  const module = require(tr);\n  transform = typeof module.default === 'function' ?\n    module.default :\n    module;\n  if (module.parser) {\n    parserFromTransform = typeof module.parser === 'string' ?\n      getParser(module.parser) :\n      module.parser;\n  }\n}\n\nfunction free() {\n  notify({action: 'free'});\n}\n\nfunction updateStatus(status, file, msg) {\n  msg = msg ? file + ' ' + msg : file;\n  notify({action: 'status', status: status, msg: msg});\n}\n\nfunction report(file, msg) {\n  notify({action: 'report', file, msg});\n}\n\nfunction empty() {}\n\nfunction stats(name, quantity) {\n  quantity = typeof quantity !== 'number' ? 1 : quantity;\n  notify({action: 'update', name: name, quantity: quantity});\n}\n\nfunction trimStackTrace(trace) {\n  if (!trace) {\n    return '';\n  }\n  // Remove this file from the stack trace of an error thrown in the transformer\n  const lines = trace.split('\\n');\n  const result = [];\n  lines.every(function(line) {\n    if (line.indexOf(__filename) === -1) {\n      result.push(line);\n      return true;\n    }\n  });\n  return result.join('\\n');\n}\n\nfunction run(data) {\n  const files = data.files;\n  const options = data.options || {};\n  if (!files.length) {\n    finish();\n    return;\n  }\n  async.each(\n    files,\n    function(file, callback) {\n      fs.readFile(file, async function(err, source) {\n        if (err) {\n          updateStatus('error', file, 'File error: ' + err);\n          callback();\n          return;\n        }\n        source = source.toString();\n        try {\n          const jscodeshift = prepareJscodeshift(options);\n          const out = await transform(\n            {\n              path: file,\n              source: source,\n            },\n            {\n              j: jscodeshift,\n              jscodeshift: jscodeshift,\n              stats: options.dry ? stats : empty,\n              report: msg => report(file, msg),\n            },\n            options\n          );\n          if (!out || out === source) {\n            updateStatus(out ? 'nochange' : 'skip', file);\n            callback();\n            return;\n          }\n          if (options.print) {\n            console.log(out); // eslint-disable-line no-console\n          }\n          if (!options.dry) {\n            writeFileAtomic(file, out, function(err) {\n              if (err) {\n                updateStatus('error', file, 'File writer error: ' + err);\n              } else {\n                updateStatus('ok', file);\n              }\n              callback();\n            });\n          } else {\n            updateStatus('ok', file);\n            callback();\n          }\n        } catch(err) {\n          updateStatus(\n            'error',\n            file,\n            'Transformation error ('+ err.message.replace(/\\n/g, ' ') + ')\\n' + trimStackTrace(err.stack)\n          );\n          callback();\n        }\n      });\n    },\n    function(err) {\n      if (err) {\n        updateStatus('error', '', 'This should never be shown!');\n      }\n      free();\n    }\n  );\n}\n"
  },
  {
    "path": "src/__testfixtures__/test-async-transform.input.js",
    "content": "export const sum = (a, b) => a + b;\n"
  },
  {
    "path": "src/__testfixtures__/test-async-transform.js",
    "content": "const synchronousTestTransform = (fileInfo, api, options) => {\n  return new Promise(resolve => {\n    setTimeout(() => {\n      resolve(api.jscodeshift(fileInfo.source)\n        .findVariableDeclarators('sum')\n        .renameTo('addition')\n        .toSource());\n    }, 100);\n  });\n}\nmodule.exports = synchronousTestTransform;\n"
  },
  {
    "path": "src/__testfixtures__/test-async-transform.output.js",
    "content": "export const addition = (a, b) => a + b;\n"
  },
  {
    "path": "src/__testfixtures__/test-sync-transform.input.js",
    "content": "export const sum = (a, b) => a + b;\n"
  },
  {
    "path": "src/__testfixtures__/test-sync-transform.js",
    "content": "const synchronousTestTransform = (fileInfo, api, options) => {\n  return api.jscodeshift(fileInfo.source)\n    .findVariableDeclarators('sum')\n    .renameTo('addition')\n    .toSource();\n}\nmodule.exports = synchronousTestTransform;\n"
  },
  {
    "path": "src/__testfixtures__/test-sync-transform.output.js",
    "content": "export const addition = (a, b) => a + b;\n"
  },
  {
    "path": "src/__tests__/.eslintrc",
    "content": "{\n  \"globals\": {\n    \"jest\": true\n  },\n  \"env\": {\n    \"jasmine\": true\n  }\n}\n"
  },
  {
    "path": "src/__tests__/Collection-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n\ndescribe('Collection API', function() {\n  let nodes;\n  let Collection;\n  let recast;\n  let NodePath;\n  let types;\n  let b;\n\n  beforeEach(function() {\n    jest.resetModules();\n\n    Collection = require('../Collection');\n    recast = require('recast');\n\n    NodePath = recast.types.NodePath;\n    types = recast.types.namedTypes;\n    b = recast.types.builders;\n\n    nodes = [b.identifier('foo'), b.identifier('bar')];\n  });\n\n  describe('Instantiation', function() {\n\n    it('should create a collection from an array of nodes', function() {\n      expect(Collection.fromNodes(nodes).getTypes()).toContain('Identifier');\n    });\n\n    it('should create a collection from an array of paths', function() {\n      const paths = [\n        new NodePath(b.identifier('foo')),\n        new NodePath(b.identifier('bar')),\n      ];\n      expect(Collection.fromPaths(paths).getTypes()).toContain('Identifier');\n    });\n\n    it('accepts an empty array as input', function() {\n      const values = [];\n      expect(() => Collection.fromPaths(values)).not.toThrow();\n      expect(() => Collection.fromNodes(values)).not.toThrow();\n    });\n\n    it('throws if it is passed an array of mixed values', function() {\n      const values = [\n        new NodePath(b.identifier('foo')),\n        b.identifier('bar'),\n      ];\n      expect(() => Collection.fromPaths(values)).toThrow();\n      expect(() => Collection.fromNodes(values)).toThrow();\n    });\n\n    it('returns a collection of the closest common type', function() {\n      let nodes = [\n        b.identifier('foo'),\n        b.sequenceExpression([]),\n      ];\n      expect(Collection.fromNodes(nodes).getTypes())\n        .toContain('Expression');\n\n      nodes = [\n        b.identifier('foo'),\n        b.blockStatement([]),\n      ];\n      expect(Collection.fromNodes(nodes).getTypes())\n        .toContain('Node');\n    });\n  });\n\n  describe('Method extensions', function() {\n    it('handles method extensions for types', function() {\n      const Collection = require('../Collection');\n      const getNames = jest.fn(function() {\n        expect(this.nodes()).toEqual(nodes);\n      });\n      Collection.registerMethods({getNames: getNames}, types.Identifier);\n\n      const collection = Collection.fromNodes(nodes);\n\n      expect(collection.getNames).toBeDefined();\n      collection.getNames();\n      expect(getNames).toBeCalled();\n    });\n\n    it('throws if a method is called for the wrong node type', function() {\n      const Collection = require('../Collection');\n      const getNames = jest.fn();\n      Collection.registerMethods({getNames: getNames}, types.Identifier);\n\n      const collection = Collection.fromNodes([\n        b.blockStatement([])\n      ]);\n\n      expect(() => collection.getNames()).toThrow();\n    });\n\n    it('adds \"global\" methods to all types', function() {\n      const Collection = require('../Collection');\n      const getNames = jest.fn();\n      Collection.registerMethods({getNames: getNames});\n\n      expect(Collection.fromNodes([b.blockStatement([])]).getNames).toBeDefined();\n      expect(Collection.fromNodes(nodes).getNames).toBeDefined();\n      expect(Collection.fromNodes([]).getNames).toBeDefined();\n    });\n\n    it('handles type inheritance chains', function() {\n      const Collection = require('../Collection');\n      const nodeMethod = function() {};\n      const identifierMethod = function() {};\n      Collection.registerMethods({nodeMethod: nodeMethod}, types.Node);\n      Collection.registerMethods(\n        {identifierMethod: identifierMethod},\n        types.Identifier\n      );\n\n      const collection = Collection.fromNodes([b.identifier('foo')]);\n\n      expect(() => collection.identifierMethod()).not.toThrow();\n      expect(() => collection.nodeMethod()).not.toThrow();\n    });\n\n    it('handles type inheritance with multiple parents', function() {\n      Collection.registerMethods(\n        {expressionMethod: function() {}},\n        types.Expression\n      );\n      const collection = Collection.fromNodes([\n        b.functionExpression(null, [], b.blockStatement([]))\n      ]);\n      expect(() => collection.expressionMethod()).not.toThrow();\n    });\n\n    it('allows multiple registrations for non-conflicting types', function () {\n      Collection.registerMethods(\n        {foo: function () {}},\n        types.FunctionExpression\n      );\n\n      Collection.registerMethods(\n        {foo: function () {}},\n        types.BinaryExpression\n      );\n\n      const collection = Collection.fromNodes([\n        b.functionExpression(null, [], b.blockStatement([])),\n        b.functionExpression(null, [], b.blockStatement([])),\n        b.binaryExpression('+', b.identifier('a'), b.identifier('b'))\n      ]);\n\n      function typeFilter(type) {\n        return function (path) {\n          return type.check(path.value);\n        };\n      }\n\n      // allowed if collection contents match one of the registered types.\n      collection.filter(typeFilter(types.BinaryExpression)).foo();\n      collection.filter(typeFilter(types.FunctionExpression)).foo();\n\n      // not allowed if there is mixed types (even though all types match one function or the other).\n      expect(function () {\n        collection.foo();\n      }).toThrow();\n    });\n\n    describe('hasConflictingRegistration', function () {\n      function register(methodName, type) {\n        const methods = {};\n        methods[methodName] = function () {};\n        if (!types[type]) {\n          throw new Error(type + ' is not a valid type');\n        }\n        Collection.registerMethods(methods, types[type]);\n      }\n\n      it('true if supertype is registered', function () {\n        register('supertypeIsRegistered', 'Expression');\n        expect(Collection.hasConflictingRegistration('supertypeIsRegistered', 'FunctionExpression')).toBe(true);\n      });\n\n      it('true if subtype is registered', function () {\n        register('subtypeIsRegistered', 'FunctionExpression');\n        expect(Collection.hasConflictingRegistration('subtypeIsRegistered', 'Expression')).toBe(true);\n      });\n\n      it('false if only a sibling type is registered', function () {\n        register('siblingIsRegistered', 'FunctionExpression');\n        expect(Collection.hasConflictingRegistration('siblingIsRegistered', 'BinaryExpression')).toBe(false);\n      });\n    });\n  });\n\n  describe('Processing functions', function() {\n    describe('filter', function() {\n      it('lets you filter with custom logic', function() {\n        const filter = jest.fn(function(path) {\n          return path.value.name === 'foo';\n        });\n        const fooVariables = Collection.fromNodes(nodes).filter(filter);\n\n        expect(filter.mock.calls.length).toBe(2);\n        expect(fooVariables.length).toBe(1);\n      });\n\n    });\n\n    describe('forEach', function() {\n      it('lets you iterate over each element of an collection', function() {\n        const each = jest.fn();\n        Collection.fromNodes(nodes).forEach(each);\n\n        expect(each.mock.calls.length).toBe(2);\n        expect(each.mock.calls[0][0].value).toBe(nodes[0]);\n        expect(each.mock.calls[1][0].value).toBe(nodes[1]);\n      });\n\n      it('returns the collection itself', function() {\n        const fVariables = Collection.fromNodes(nodes);\n        const result = fVariables.forEach(function(){});\n\n        expect(result).toBe(fVariables);\n      });\n    });\n\n    describe('some', function() {\n      it('lets you test each element of a collection and stops when one passes the test', function() {\n        const each = jest.fn().mockImplementation(() => true);\n        Collection.fromNodes(nodes).some(each);\n\n        expect(each.mock.calls.length).toBe(1);\n        expect(each.mock.calls[0][0].value).toBe(nodes[0]);\n      });\n\n      it('returns true if at least one element passes the test', function() {\n        const result = Collection.fromNodes(nodes).some((_, i) => i === 1);\n        expect(result).toBe(true);\n      });\n\n      it('returns false if no elements pass the test', function() {\n        const result = Collection.fromNodes(nodes).some(() => false);\n        expect(result).toBe(false);\n      });\n    });\n\n    describe('every', function() {\n      it('lets you test each element of a collection and stops when one fails the test', function() {\n        const each = jest.fn().mockImplementation(() => false);\n        Collection.fromNodes(nodes).every(each);\n\n        expect(each.mock.calls.length).toBe(1);\n        expect(each.mock.calls[0][0].value).toBe(nodes[0]);\n      });\n\n      it('returns true if all elements pass the test', function() {\n        const result = Collection.fromNodes(nodes).every(() => true);\n        expect(result).toBe(true);\n      });\n\n      it('returns false if at least one element does not pass the test', function() {\n        const result = Collection.fromNodes(nodes).every((_, i) => i === 1);\n        expect(result).toBe(false);\n      });\n    });\n\n    describe('map', function() {\n      it('returns a new collection with mapped values', function() {\n        const root = Collection.fromNodes(nodes);\n        const mapped = root.map((_, i) => new NodePath(nodes[+!i]));\n\n        expect(root).not.toBe(mapped);\n        expect(mapped.length).toBe(2);\n        expect(mapped.nodes()[0]).toBe(nodes[1]);\n        expect(mapped.nodes()[1]).toBe(nodes[0]);\n      });\n\n      it('dedupes elements', function() {\n        const path = new NodePath(nodes[0]);\n        const root = Collection.fromNodes(nodes);\n        const mapped = root.map(() => path);\n\n        expect(root).not.toBe(mapped);\n        expect(mapped.length).toBe(1);\n        expect(mapped.paths()[0]).toBe(path);\n      });\n    });\n\n    describe('at', function() {\n      it('should work with positive indecies', function() {\n        const root = Collection.fromNodes(nodes);\n        expect(root.at(0).nodes()[0]).toEqual(nodes[0]);\n        expect(root.at(1).nodes()[0]).toEqual(nodes[1]);\n      });\n\n      it('should work with negative indecies', function() {\n        const root = Collection.fromNodes(nodes);\n        expect(root.at(-1).nodes()[0]).toEqual(nodes[nodes.length - 1]);\n        expect(root.at(-2).nodes()[0]).toEqual(nodes[nodes.length - 2]);\n      });\n    });\n\n    describe('get', function() {\n      it('should throw descriptive error when no paths are present', function() {\n        const root = Collection.fromNodes([]);\n        expect(() => root.get()).toThrowError(/cannot call \"get\" on a collection with no paths/);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/__tests__/Worker-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst testUtils = require('../../utils/testUtils');\n\nconst createTransformWith = testUtils.createTransformWith;\nconst createTempFileWith = testUtils.createTempFileWith;\nconst getFileContent = testUtils.getFileContent;\n\ndescribe('Worker API', () => {\n  it('transforms files', done => {\n    const worker = require('../Worker');\n    const transformPath =\n      createTransformWith('return fileInfo.source + \" changed\";');\n    const sourcePath = createTempFileWith('foo');\n    const emitter = worker([transformPath]);\n\n    emitter.send({files: [sourcePath]});\n    emitter.once('message', (data) => {\n      expect(data.status).toBe('ok');\n      expect(data.msg).toBe(sourcePath);\n      expect(getFileContent(sourcePath)).toBe('foo changed');\n      done();\n    });\n  });\n\n  it('passes j as argument', done => {\n    const worker = require('../Worker');\n    const transformPath = createTempFileWith(\n      `module.exports = function (file, api) {\n        return api.j(file.source).toSource() + ' changed';\n       }`\n    );\n    const sourcePath = createTempFileWith('const x = 10;');\n\n    const emitter = worker([transformPath]);\n    emitter.send({files: [sourcePath]});\n    emitter.once('message', (data) => {\n      expect(data.status).toBe('ok');\n      expect(getFileContent(sourcePath)).toBe(\n        'const x = 10;' + ' changed'\n      );\n      done();\n    });\n  });\n\n  describe('custom parser', () => {\n    function getTransformForParser(parser) {\n      return createTempFileWith(\n        `function transform(fileInfo, api) {\n          api.jscodeshift(fileInfo.source);\n          return \"changed\";\n         }\n         ${parser ? `transform.parser = '${parser}';` : ''}\n         module.exports = transform;\n        `\n      );\n    }\n    function getSourceFile() {\n      // This code cannot be parsed by Babel v5\n      return createTempFileWith(\n         'const x = (a: Object, b: string): void => {}'\n      );\n    }\n\n    it('errors if new flow type code is parsed with babel v5', done => {\n      const worker = require('../Worker');\n      const transformPath = createTransformWith(\n        'api.jscodeshift(fileInfo.source); return \"changed\";'\n      );\n      const sourcePath = getSourceFile();\n      const emitter = worker([transformPath]);\n\n      emitter.send({files: [sourcePath]});\n      emitter.once('message', (data) => {\n        expect(data.status).toBe('error');\n        expect(data.msg).toMatch('SyntaxError');\n        done();\n      });\n    });\n\n    ['flow', 'babylon'].forEach(parser => {\n      it(`uses ${parser} if configured as such`, done => {\n        const worker = require('../Worker');\n        const transformPath = getTransformForParser(parser);\n        const sourcePath = getSourceFile();\n        const emitter = worker([transformPath]);\n\n        emitter.send({files: [sourcePath]});\n        emitter.once('message', (data) => {\n          expect(data.status).toBe('ok');\n          expect(getFileContent(sourcePath)).toBe('changed');\n          done();\n        });\n      });\n    });\n\n    ['babylon', 'flow', 'tsx'].forEach(parser => {\n      it(`can parse JSX with ${parser}`, done => {\n        const worker = require('../Worker');\n        const transformPath = getTransformForParser(parser);\n        const sourcePath = createTempFileWith(\n          'var component = <div>{foobar}</div>;'\n        );\n        const emitter = worker([transformPath]);\n\n        emitter.send({files: [sourcePath]});\n        emitter.once('message', (data) => {\n          expect(data.status).toBe('ok');\n          expect(getFileContent(sourcePath)).toBe('changed');\n          done();\n        });\n      });\n    });\n\n    it('can parse enums with flow', done => {\n      const worker = require('../Worker');\n      const transformPath = getTransformForParser('flow');\n      const sourcePath = createTempFileWith(\n        'enum E {A, B}'\n      );\n      const emitter = worker([transformPath]);\n\n      emitter.send({files: [sourcePath]});\n      emitter.once('message', (data) => {\n        expect(data.status).toBe('ok');\n        expect(getFileContent(sourcePath)).toBe('changed');\n        done();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/__tests__/__snapshots__/testUtils-test.js.snap",
    "content": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`testUtils async should run async defineSnapshotTest 1`] = `\"export const addition = (a, b) => a + b;\"`;\n\nexports[`testUtils async should run async defineSnapshotTestFromFixture 1`] = `\"export const addition = (a, b) => a + b;\"`;\n\nexports[`testUtils async should run snapshot test 1`] = `\"export const addition = (a, b) => a + b;\"`;\n\nexports[`testUtils synchronous should run snapshot test 1`] = `\"export const addition = (a, b) => a + b;\"`;\n\nexports[`testUtils synchronous should run sync defineSnapshotTest 1`] = `\"export const addition = (a, b) => a + b;\"`;\n\nexports[`testUtils synchronous should run sync defineSnapshotTestFromFixture 1`] = `\"export const addition = (a, b) => a + b;\"`;\n"
  },
  {
    "path": "src/__tests__/argsParser-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/*global jest, describe, it, expect, beforeEach*/\n\n'use strict';\n\nconst argsParser = require('../argsParser');\n\ndescribe('argsParser', function() {\n  it('prints the help text', function() {\n    const parser = argsParser.options({});\n    let exception;\n    try {\n      parser.parse(['--help']);\n    } catch(e) {\n      exception = e;\n    }\n    expect(exception.exitCode).toEqual(0);\n    expect(exception.message).toEqual(parser.getHelpText());\n  });\n\n  it('parsers positional arguments', function() {\n    const parser = argsParser.options({});\n    const {positionalArguments} = parser.parse(['foo', 'bar']);\n    expect(positionalArguments).toEqual(['foo', 'bar']);\n  });\n\n  it('parsers mixed options, flags and positional arguments', function() {\n    const parser = argsParser.options({\n      foo: {},\n      bar: {\n        flag: true,\n      },\n      bay: {\n        flag: true,\n      },\n      baz: {\n        default: 'zab',\n      },\n    });\n    expect(parser.parse(['arg1', '--foo=1', 'arg2', '--bar', '--bay=1', 'arg3', 'arg4']))\n      .toEqual({\n        options: {\n          foo: '1',\n          bar: true,\n          bay: true,\n          baz: 'zab',\n        },\n        positionalArguments: ['arg1', 'arg2', 'arg3', 'arg4'],\n      });\n  });\n\n  describe('options', function() {\n    function test(testCases) {\n      for (const testName in testCases) {\n        const testCase = testCases[testName];\n\n        const parser = argsParser.options(testCase.options);\n\n        it(testName + ' (space separated values)', function() {\n          const parse = () => parser.parse(\n            Array.prototype.concat.apply([], testCase.args)\n          );\n\n          if (typeof testCase.expected === 'string') {\n            expect(parse).toThrowError(testCase.expected);\n          } else {\n            expect(parse()).toEqual(testCase.expected);\n          }\n        });\n\n        it(testName + ' (= separated values)', function() {\n          const parse = () => parser.parse(\n            testCase.args.map(args => args.join('='))\n          );\n          if (typeof testCase.expected === 'string') {\n            expect(parse).toThrowError(testCase.expected);\n          } else {\n            expect(parse()).toEqual(testCase.expected);\n          }\n        });\n\n      }\n    }\n\n    test({\n      'understands separate arg name and short option names': {\n        options: {\n          foo: {\n            full: 'another-foo',\n          },\n          bar: {\n            abbr: 'b',\n          },\n        },\n        args: [['--another-foo', 'oof'], ['-b', 'rab']],\n        expected: {\n          options: {\n            foo: 'oof',\n            bar: 'rab',\n          },\n          positionalArguments: []\n        },\n      },\n\n      'understands default values': {\n        options: {\n          foo: {},\n          bar: {\n            default: 'rab',\n          },\n          baz: {\n            abbr: 'b',\n            default: 'zab',\n          },\n        },\n        args: [['--foo', 'oof']],\n        expected: {\n          options: {\n            foo: 'oof',\n            bar: 'rab',\n            baz: 'zab',\n          },\n          positionalArguments: []\n        },\n      },\n\n      'allows preprocessing values': {\n        options: {\n          foo: {},\n          bar: {\n            default: 456,\n          },\n          bay: {\n            process: Number,\n          },\n          baz: {\n            abbr: 'b',\n            process: v => v+v,\n          },\n        },\n        args: [['--foo', '123'], ['--bay', '789'], ['-b', 'zab']],\n        expected: {\n          options: {\n            foo: '123',\n            bar: 456,\n            bay: 789,\n            baz: 'zabzab',\n          },\n          positionalArguments: []\n        },\n      },\n\n      'understands lists': {\n        options: {\n          foo: {\n            list: true,\n          },\n          bar: {\n            list: true,\n          },\n          baz: {},\n        },\n        args: [\n          ['--foo', 'oof1'],\n          ['--baz', 'zab1'],\n          ['--foo', 'oof2'],\n          ['--baz', 'zab2'],\n        ],\n        expected: {\n          options: {\n            foo: ['oof1', 'oof2'],\n            bar: [],\n            baz: 'zab2',\n          },\n          positionalArguments: []\n        },\n      },\n\n      'errors when an option does not have a value (1)': {\n        options: {\n          foo: {},\n          bar: {\n            abbr: 'b',\n          },\n          baz: {},\n        },\n        args: [\n          ['--foo', 'oof'],\n          ['-b'],\n          ['--baz', 'zab'],\n        ],\n        expected: '--bar requires a value',\n      },\n\n      'errors when an option does not have a value (2)': {\n        options: {\n          foo: {},\n          bar: {\n            abbr: 'b',\n          },\n          baz: {},\n        },\n        args: [\n          ['--foo', 'oof'],\n          ['--bar'],\n          ['--baz', 'zab'],\n        ],\n        expected: '--bar requires a value',\n      },\n\n      'errors when an option does not have a value (3)': {\n        options: {\n          foo: {\n            default: 'oof',\n          },\n        },\n        args: [['--foo']],\n        expected: '--foo requires a value',\n      },\n\n      'understands choices': {\n        options: {\n          foo: {\n            choices: ['oof'],\n          },\n        },\n        args: [\n          ['--foo', 'oof'],\n        ],\n        expected: {\n          options: {\n            foo: 'oof',\n          },\n          positionalArguments: []\n        },\n      },\n\n      'errors if choice does not match': {\n        options: {\n          foo: {\n            choices: ['oof'],\n          },\n          bar: {\n            choices: ['rab1', 'rab2'],\n          },\n        },\n        args: [\n          ['--foo', 'oof'],\n          ['--bar', 'rab'],\n        ],\n        expected: '--bar must be one of the values rab1,rab2',\n      },\n\n      'accepts unkown options': {\n        options: {},\n        args: [\n          ['--foo'],\n          ['--bar'],\n          ['--bay', 'yab'],\n          ['foo'],\n          ['--b', 'zab1'],\n          ['--foo', 'oof'],\n          ['--b', 'zab2'],\n          ['bar'],\n        ],\n        expected: {\n          options: {\n            foo: 'oof',\n            bar: true,\n            bay: 'yab',\n            b: ['zab1', 'zab2'],\n          },\n          positionalArguments: ['foo', 'bar'],\n        },\n      },\n\n      'parses unkown options as JSON': {\n        options: {},\n        args: [\n          ['--foo', '{\"foo\": \"bar\"}'],\n        ],\n        expected: {\n          options: {\n            foo: {foo: 'bar'},\n          },\n          positionalArguments: [],\n        },\n      },\n    });\n  });\n\n  describe('flags', function() {\n    const parser = argsParser.options({\n      foo: {\n        abbr: 'f',\n        full: 'foo',\n        flag: true,\n      },\n      bar: {\n        full: 'another-bar',\n        flag: true,\n        default: false,\n      },\n    });\n\n    it('sets values to true of specified', function() {\n      expect(parser.parse(['--foo', '--another-bar', 'foo', 'bar']))\n        .toEqual({\n          options: {\n            foo: true,\n            bar: true,\n          },\n          positionalArguments: ['foo', 'bar'],\n        });\n    });\n\n    it('understands short options', function() {\n      expect(parser.parse(['-f', '--another-bar', 'f', 'bar']))\n        .toEqual({\n          options: {\n            foo: true,\n            bar: true,\n          },\n          positionalArguments: ['f', 'bar'],\n        });\n    });\n\n    it('sets default value if not specified', function() {\n      expect(parser.parse(['f', 'bar']))\n        .toEqual({\n          options: {\n            bar: false,\n          },\n          positionalArguments: ['f', 'bar'],\n        });\n    });\n\n    it('accepts flag=0 and flag=1 (undocumented)', function() {\n      expect(parser.parse(['--foo=0', '--another-bar=1']))\n        .toEqual({\n          options: {\n            foo: false,\n            bar: true,\n          },\n          positionalArguments: [],\n        });\n      expect(parser.parse(['-f=0']))\n        .toEqual({\n          options: {\n            foo: false,\n            bar: false,\n          },\n          positionalArguments: [],\n        });\n    });\n\n    it('understands --no-prefixes', function() {\n      expect(parser.parse(['--no-foo', '--no-another-bar']))\n        .toEqual({\n          options: {\n            foo: false,\n            bar: false,\n          },\n          positionalArguments: [],\n        });\n    });\n  });\n\n});\n\n"
  },
  {
    "path": "src/__tests__/core-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n/*global jest, describe, it, expect*/\n\nconst core = require('../core');\nconst recast = require('recast');\nconst b = recast.types.builders;\nconst NodePath = recast.types.NodePath;\n\ndescribe('core API', function() {\n  it('returns a Collection from a source string', function() {\n    expect(core('var foo;').constructor.name ).toContain('Collection');\n  });\n\n  it('returns a Collection from an AST node', function() {\n    const node = b.identifier('foo');\n    expect(core(node).constructor.name).toContain('Collection');\n  });\n\n  it('returns a Collection from an array of AST nodes', function() {\n    const node = b.identifier('foo');\n    expect(core([node]).constructor.name).toContain('Collection');\n  });\n\n  it('returns a Collection from a path', function() {\n    const path = new NodePath(b.identifier('foo'));\n    expect(core(path).constructor.name).toContain('Collection');\n  });\n\n  it('returns a Collection from an array of paths', function() {\n    const path = new NodePath(b.identifier('foo'));\n    expect(core([path]).constructor.name).toContain('Collection');\n  });\n\n  it('returns a Collection from an empty array', function() {\n    expect(core([]).constructor.name).toContain('Collection');\n  });\n\n  it('throws if it gets an invalid value', function() {\n    expect(() => core(42)).toThrow();\n    expect(() => core({})).toThrow();\n  });\n\n  it('returns the source as is if nothing was modified', function () {\n    const source = '\\nvar foo;\\n';\n    expect(core(source).toSource()).toEqual(source);\n  });\n\n  it('plugins are called with core', function (done) {\n    core.use(function (j) {\n      expect(j).toBe(core);\n      done();\n    });\n  });\n\n  it('plugins are only registered once', function () {\n    let ct = 0;\n\n    function plugin() {\n      ct++;\n    }\n\n    core.use(plugin);\n    core.use(plugin);\n\n    expect(ct).toBe(1);\n  });\n\n});\n"
  },
  {
    "path": "src/__tests__/matchNode-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/*global jest, describe, it, expect, beforeEach*/\n\n'use strict';\n\nconst matchNode = require('../matchNode');\n\ndescribe('matchNode', function() {\n  beforeEach(function() {\n    expect.extend({\n      toMatchNode: function(haystack, needle) {\n        const result = {};\n        result.pass = matchNode(haystack, needle);\n        return result;\n      }\n    });\n  })\n\n  it('matches null and undefined', function() {\n    expect(null).toMatchNode(null);\n    expect(null).not.toMatchNode(undefined);\n\n    expect(undefined).toMatchNode(undefined);\n    expect(undefined).not.toMatchNode(null);\n  });\n\n  it('matches scalars', function() {\n    expect('foo').toMatchNode('foo');\n    expect('foo').not.toMatchNode('bar');\n    expect('123').not.toMatchNode(123);\n\n    expect(123).toMatchNode(123);\n    expect(123).not.toMatchNode(456);\n    expect(123).not.toMatchNode('123');\n\n    expect(true).toMatchNode(true);\n    expect(true).not.toMatchNode(false);\n    expect(true).not.toMatchNode('true');\n  });\n\n  it('matches arrays', function() {\n    expect([1, 2, 3]).toMatchNode([1, 2, 3]);\n    expect([1, 2, 3]).not.toMatchNode([4, 5, 6]);\n\n    expect([[1, 2, 3], 'foo']).toMatchNode([[1, 2, 3], 'foo']);\n    expect([[1, 2, 3], 'foo']).not.toMatchNode([[456], 'foo']);\n    expect([[1, 2, 3], 'foo']).not.toMatchNode([[1, 2, 3], 'bar']);\n\n    expect([1, 2, 3, 4]).toMatchNode([1, 2, 3]);\n    expect([1, 2, 3]).not.toMatchNode([1, 2, 3, 4]);\n  });\n\n  it('matches objects', function() {\n    expect({}).toMatchNode({});\n    expect({name: 'foo'}).toMatchNode({name: 'foo'});\n    expect({name: 'foo'}).not.toMatchNode({name: 'bar'});\n\n    expect({name: 'foo', value: {name: 'bar'}})\n      .toMatchNode({name: 'foo', value: {name: 'bar'}});\n    expect({name: 'foo', value: {name: 'bar'}})\n      .not.toMatchNode({name: 'foo', value: {name: 'baz'}});\n\n    expect({name: 'foo', value: 'bar'}).toMatchNode({name: 'foo'});\n    expect({name: 'foo'}).not.toMatchNode({name: 'foo', value: 'bar'});\n\n    expect(Object.create({name: 'foo'})).not.toMatchNode({name: 'foo'});\n    expect({}).toMatchNode(Object.create({name: 'foo'}));\n  });\n\n  it('matches with a function', function() {\n    const haystack = {name: 'foo'};\n    const needle = jest.fn();\n\n    needle.mockReturnValue(true);\n    expect(haystack).toMatchNode(needle);\n    expect(needle).toBeCalledWith(haystack);\n\n    needle.mockReturnValue(false);\n    expect(haystack).not.toMatchNode(needle);\n  });\n\n  it('matches nested value with a function', function() {\n    const haystack = {name: 'foo', value: 'bar'};\n    const needle = {\n      name: jest.fn(),\n      value: jest.fn(),\n    };\n\n    needle.name.mockReturnValue(true);\n    needle.value.mockReturnValue(true);\n    expect(haystack).toMatchNode(needle);\n    expect(needle.name).toBeCalledWith(haystack.name);\n    expect(needle.value).toBeCalledWith(haystack.value);\n\n    needle.name.mockReturnValue(false);\n    needle.value.mockReturnValue(true);\n    expect(haystack).not.toMatchNode(needle);\n\n    needle.name.mockReturnValue(true);\n    needle.value.mockReturnValue(false);\n    expect(haystack).not.toMatchNode(needle);\n  });\n});\n"
  },
  {
    "path": "src/__tests__/template-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\n/*global jest, describe, it, expect, beforeEach*/\n\n\ndescribe('Templates', () => {\n  let statements;\n  let statement;\n  let expression;\n  let jscodeshift;\n\n  beforeEach(() => {\n    jest.resetModules();\n\n    jscodeshift = require('../core');\n    const template = jscodeshift.template;\n    expression = template.expression;\n    statement = template.statement;\n    statements = template.statements;\n  });\n\n  it('interpolates expression nodes with source code', () => {\n\n    let input =\n`var foo = bar;\nif(bar) {\n  console.log(42);\n}`;\n\n    let expected =\n`var foo = alert(bar);\nif(alert(bar)) {\n  console.log(42);\n}`;\n\n    expect(\n      jscodeshift(input)\n        .find('Identifier', {name: 'bar'})\n        .replaceWith(path => expression`alert(${path.node})`)\n        .toSource()\n    ).toEqual(expected);\n  });\n\n  it('interpolates statement nodes with source code', () => {\n    let input =\n`for (var i = 0; i < 10; i++) {\n  console.log(i);\n  console.log(i / 2);\n}`;\n\n    let expected =\n`var i = 0;\nwhile (i < 10) {\n  console.log(i);\n  console.log(i / 2);\n  i++;\n}`;\n\n    expect(\n      jscodeshift(input)\n        .find('ForStatement')\n        .replaceWith(\n          p => statements`\n            ${p.node.init};\n            while (${p.node.test}) {\n              ${p.node.body.body}\n              ${p.node.update};\n            }`\n        )\n        .toSource()\n    ).toEqual(expected);\n  });\n\n  it('can be used with a different parser', () => {\n    const parser = require('../../parser/flow')();\n    const template = require('../template')(parser);\n    const node = {type: 'Literal', value: 41};\n\n    expect(\n      jscodeshift(template.expression`1 + ${node}`, {parser}).toSource()\n    ).toEqual('1 + 41');\n  });\n\n  it('handles out-of-order traversal', () => {\n    const input = 'var x';\n    const expected = 'class X extends a {f(b) {}}';\n\n    const a = jscodeshift.identifier('a');\n    const b = jscodeshift.identifier('b');\n\n    const classDecl = statement`\n      class X extends ${a} {f(${b}) {}}\n    `;\n\n    expect(\n      jscodeshift(input)\n        .find('VariableDeclaration')\n        .replaceWith(classDecl)\n        .toSource()\n    )\n    .toEqual(expected);\n  });\n  it('correctly parses expressions without any interpolation', () => {\n    const expected = 'function() {}';\n\n    expect(\n      jscodeshift(\n        expression`function() {}`\n      )\n      .toSource()\n    )\n    .toEqual(expected);\n  });\n\n  for (const parser of ['babel', 'babylon', 'flow', 'ts', 'tsx']) {\n    it(`asyncExpression correctly parses expressions with await -- ${parser}`, () => {\n      const expected = '{\\n  bar: await baz\\n}'\n      const j = jscodeshift.withParser(parser)\n\n      expect(j(j.template.asyncExpression`{\\n  bar: await baz\\n}`).toSource()).toEqual(expected)\n    })\n  }\n\n  describe('explode arrays', () => {\n\n    it('explodes arrays in function definitions', () => {\n      let input = 'var foo = [a, b];';\n      let expected = 'var foo = function foo(a, b, c) {};';\n\n      expect(\n        jscodeshift(input)\n          .find('ArrayExpression')\n          .replaceWith(\n            p => expression`function foo(${p.node.elements}, c) {}`\n          )\n          .toSource()\n      )\n      .toEqual(expected);\n\n      expected = 'var foo = function(a, b, c) {};';\n\n      expect(\n        jscodeshift(input)\n          .find('ArrayExpression')\n          .replaceWith(\n            p => expression`function(${p.node.elements}, c) {}`\n          )\n          .toSource()\n      )\n      .toEqual(expected);\n\n      expected = 'var foo = (a, b) => {};';\n\n      expect(\n        jscodeshift(input)\n          .find('ArrayExpression')\n          .replaceWith(\n            p => expression`${p.node.elements} => {}`\n          )\n          .toSource()\n      )\n      .toEqual(expected);\n\n      expected = 'var foo = (a, b, c) => {};';\n\n      expect(\n        jscodeshift(input)\n          .find('ArrayExpression')\n          .replaceWith(\n            p => expression`(${p.node.elements}, c) => {}`\n          )\n          .toSource()\n      )\n      .toEqual(expected);\n    });\n\n    it('explodes arrays in variable declarations', () => {\n      let input = 'var foo = [a, b];';\n      let expected = 'var foo, a, b;';\n      expect(\n        jscodeshift(input)\n          .find('VariableDeclaration')\n          // Need to use a block here because the arrow doesn't seem to be\n          // compiled with a line break after the return statement. Can't repro\n          // outside here though\n          .replaceWith(p => {\n            const node = p.node.declarations[0];\n            return statement`var ${node.id}, ${node.init.elements};`;\n          })\n          .toSource()\n      )\n      .toEqual(expected);\n    });\n\n    it('explodes arrays in array expressions', () => {\n      let input = 'var foo = [a, b];';\n      let expected = 'var foo = [a, b, c];';\n      expect(\n        jscodeshift(input)\n          .find('ArrayExpression')\n          .replaceWith(p => expression`[${p.node.elements}, c]`)\n          .toSource()\n      )\n      .toEqual(expected);\n    });\n\n    it('explodes arrays in object expressions', () => {\n      let input = 'var foo = {a, b};';\n      let expected = /var foo = \\{\\s*a,\\s*b,\\s*c: 42\\s*};/;\n      expect(\n        jscodeshift(input)\n          .find('ObjectExpression')\n          .replaceWith(p => expression`{${p.node.properties}, c: 42}`)\n          .toSource()\n      )\n      .toMatch(expected);\n    });\n\n    it('explodes arrays in call expressions', () => {\n      let input = 'var foo = [a, b];';\n      let expected = 'var foo = bar(a, b, c);';\n\n      expect(\n        jscodeshift(input)\n          .find('ArrayExpression')\n          .replaceWith(\n            p => expression`bar(${p.node.elements}, c)`\n          )\n          .toSource()\n      )\n      .toEqual(expected);\n    });\n\n  });\n\n});\n"
  },
  {
    "path": "src/__tests__/testUtils-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst testSyncTransform = require('../__testfixtures__/test-sync-transform');\nconst testAsyncTransform = require('../__testfixtures__/test-async-transform');\n\nconst testUtils = require('../testUtils');\n\nconst testInputSource = 'export const sum = (a, b) => a + b;';\nconst expectedInlineOutput = 'export const addition = (a, b) => a + b;';\n\nconst getModuleToTransform = () => {\n  const moduleToTransformPath = path.join(__dirname, '..', '__testfixtures__', 'test-sync-transform.input.js');\n  const source = fs.readFileSync(moduleToTransformPath, 'utf8');\n  return {\n    path: moduleToTransformPath,\n    source,\n  }\n}\n\ndescribe('testUtils', () => {\n  describe('synchronous', () => {\n    it('should apply transformation', () => {\n      const moduleToTransform = getModuleToTransform();\n      const transformedCode = testUtils.applyTransform(testSyncTransform, null, moduleToTransform);\n\n      expect(transformedCode).not.toMatch(/sum/);\n      expect(transformedCode).toMatch(/addition/);\n    });\n\n    it('should run test', () => {\n      testUtils.runTest(\n        __dirname,\n        path.join('__testfixtures__',\n        'test-sync-transform'),\n        null,\n        'test-sync-transform'\n      );\n    });\n\n    it ('should run snapshot test', () => {\n      const moduleToTransform = getModuleToTransform();\n      testUtils.runSnapshotTest(testSyncTransform, null, moduleToTransform);\n    });\n\n    it('should run inline test', () => {\n      const moduleToTransform = getModuleToTransform();\n      testUtils.runInlineTest(testSyncTransform, null, moduleToTransform, expectedInlineOutput);\n    });\n\n    testUtils.defineTest(\n      __dirname,\n      path.join('__testfixtures__', 'test-sync-transform'),\n      null,\n      'test-sync-transform'\n    );\n\n    testUtils.defineInlineTest(\n      testSyncTransform,\n      null,\n      testInputSource,\n      expectedInlineOutput,\n      'should run sync defineInlineTest'\n    );\n\n    testUtils.defineSnapshotTest(\n      testSyncTransform,\n      null,\n      testInputSource,\n      'should run sync defineSnapshotTest'\n    );\n\n    testUtils.defineSnapshotTestFromFixture(\n      __dirname,\n      testSyncTransform,\n      null,\n      'test-sync-transform',\n      'should run sync defineSnapshotTestFromFixture'\n    );\n  });\n\n  describe('async', () => {\n    it('should apply transformation', async () => {\n      const moduleToTransform = getModuleToTransform();\n      const transformedCode = await testUtils.applyTransform(testAsyncTransform, null, moduleToTransform);\n\n      expect(transformedCode).not.toMatch(/sum/);\n      expect(transformedCode).toMatch(/addition/);\n    });\n\n    it('should run test', () => {\n      return testUtils.runTest(__dirname, path.join('__testfixtures__', 'test-async-transform'), null, 'test-async-transform');\n    });\n\n    it ('should run snapshot test', () => {\n      const moduleToTransform = getModuleToTransform();\n      return testUtils.runSnapshotTest(testAsyncTransform, null, moduleToTransform);\n    });\n\n    it('should run inline test', () => {\n      const moduleToTransform = getModuleToTransform();\n      return testUtils.runInlineTest(testAsyncTransform, null, moduleToTransform, expectedInlineOutput);\n    });\n\n    testUtils.defineTest(\n      __dirname,\n      path.join('__testfixtures__', 'test-async-transform'),\n      null,\n      'test-async-transform'\n    );\n\n    testUtils.defineInlineTest(\n      testAsyncTransform,\n      null,\n      testInputSource,\n      expectedInlineOutput,\n      'should run async defineInlineTest'\n    );\n\n    testUtils.defineSnapshotTest(\n      testAsyncTransform,\n      null,\n      testInputSource,\n      'should run async defineSnapshotTest'\n    );\n\n    testUtils.defineSnapshotTestFromFixture(\n      __dirname,\n      testSyncTransform,\n      null,\n      'test-async-transform',\n      'should run async defineSnapshotTestFromFixture'\n    );\n  });\n});\n"
  },
  {
    "path": "src/__tests__/ts-decorator-auto-accessor-test.js",
    "content": "'use strict';\n\nfunction transformer(file, api) {\n  const j = api.jscodeshift;\n\n  return j(file.source).toSource();\n}\n\ntransformer.parser = 'ts';\n\njest.autoMockOff();\nconst defineInlineTest = require('../../src/testUtils').defineInlineTest;\n\ndescribe('should be parse typescript decoratorAutoAccessors correctly', function () {\n  defineInlineTest(\n    transformer,\n    {},\n    'export class Test {\\n' +\n    '  public accessor myValue = 10;\\n' +\n    '}\\n',\n    'export class Test {\\n' +\n    '  public accessor myValue = 10;\\n' +\n    '}',\n    'ts-decorator-auto-accessor',\n  );\n});\n"
  },
  {
    "path": "src/argsParser.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nfunction throwError(exitCode, message, helpText) {\n  const error = new Error(\n    helpText ?  `${message}\\n\\n---\\n\\n${helpText}` : message\n  );\n  error.exitCode = exitCode;\n  throw error;\n}\n\nfunction formatOption(option) {\n  let text = '  ';\n  text += option.abbr ? `-${option.abbr}, ` : '    ';\n  text += `--${option.flag ? '(no-)' : ''}${option.full}`;\n  if (option.choices) {\n    text += `=${option.choices.join('|')}`;\n  } else if (option.metavar) {\n    text += `=${option.metavar}`;\n  }\n  if (option.list) {\n    text += ' ...';\n  }\n  if (option.defaultHelp || option.default !== undefined || option.help) {\n    text += '  ';\n    if (text.length < 32) {\n      text += ' '.repeat(32 - text.length);\n    }\n    const textLength = text.length;\n    if (option.help) {\n      text += option.help;\n    }\n    if (option.defaultHelp || option.default !== undefined) {\n      if (option.help) {\n        text += '\\n';\n      }\n      text += `${' '.repeat(textLength)}(default: ${option.defaultHelp || option.default})`;\n    }\n  }\n\n  return text;\n}\n\nfunction getHelpText(options) {\n  const opts = Object.keys(options)\n    .map(k => options[k])\n    .sort((a,b) => a.display_index - b.display_index);\n\n  const text = `\nUsage: jscodeshift [OPTION]... PATH...\n  or:  jscodeshift [OPTION]... -t TRANSFORM_PATH PATH...\n  or:  jscodeshift [OPTION]... -t URL PATH...\n  or:  jscodeshift [OPTION]... --stdin < file_list.txt\n\nApply transform logic in TRANSFORM_PATH (recursively) to every PATH.\nIf --stdin is set, each line of the standard input is used as a path.\n\nOptions:\n\"...\" behind an option means that it can be supplied multiple times.\nAll options are also passed to the transformer, which means you can supply custom options that are not listed here.\n\n${opts.map(formatOption).join('\\n')}\n`;\n  return text.trimLeft();\n}\n\nfunction validateOptions(parsedOptions, options) {\n  const errors = [];\n  for (const optionName in options) {\n    const option = options[optionName];\n    if (option.choices && !option.choices.includes(parsedOptions[optionName])) {\n      errors.push(\n        `Error: --${option.full} must be one of the values ${option.choices.join(',')}`\n      );\n    }\n  }\n  if (errors.length > 0) {\n    throwError(\n      1,\n      errors.join('\\n'),\n      getHelpText(options)\n    );\n  }\n}\n\nfunction prepareOptions(options) {\n  options.help = {\n    display_index: 5,\n    abbr: 'h',\n    help: 'print this help and exit',\n    callback() {\n      return getHelpText(options);\n    },\n  };\n\n  const preparedOptions = {};\n\n  for (const optionName of Object.keys(options)) {\n    const option = options[optionName];\n    if (!option.full) {\n      option.full = optionName;\n    }\n    option.key = optionName;\n\n    preparedOptions['--'+option.full] = option;\n    if (option.abbr) {\n      preparedOptions['-'+option.abbr] = option;\n    }\n    if (option.flag) {\n      preparedOptions['--no-'+option.full] = option;\n    }\n  }\n\n  return preparedOptions;\n}\n\nfunction isOption(value) {\n  return /^--?/.test(value);\n}\n\nfunction parse(options, args=process.argv.slice(2)) {\n  const missingValue = Symbol();\n  const preparedOptions = prepareOptions(options);\n\n  const parsedOptions = {};\n  const positionalArguments = [];\n\n  for (const optionName in options) {\n    const option = options[optionName];\n    if (option.default !== undefined) {\n      parsedOptions[optionName] = option.default;\n    } else if (option.list) {\n      parsedOptions[optionName] = [];\n    }\n  }\n\n  for (let i = 0; i < args.length; i++) {\n    const arg = args[i];\n    if (isOption(arg)) {\n      let optionName = arg;\n      let value = null;\n      let option = null;\n      if (optionName.includes('=')) {\n        const index = arg.indexOf('=');\n        optionName = arg.slice(0, index);\n        value = arg.slice(index+1);\n      }\n      if (preparedOptions.hasOwnProperty(optionName)) {\n        option = preparedOptions[optionName];\n      } else {\n        // Unknown options are just \"passed along\".\n        // The logic is as follows:\n        // - If an option is encountered without a value, it's treated\n        //   as a flag\n        // - If the option has a value, it's initialized with that value\n        // - If the option has been seen before, it's converted to a list\n        //   If the previous value was true (i.e. a flag), that value is\n        //   discarded.\n        const realOptionName = optionName.replace(/^--?(no-)?/, '');\n        const isList = parsedOptions.hasOwnProperty(realOptionName) &&\n          parsedOptions[realOptionName] !== true;\n        option = {\n          key: realOptionName,\n          full: realOptionName,\n          flag: !parsedOptions.hasOwnProperty(realOptionName) &&\n                value === null &&\n                isOption(args[i+1]),\n          list: isList,\n          process(value) {\n            // Try to parse values as JSON to be compatible with nomnom\n            try {\n              return JSON.parse(value);\n            } catch(_e) {}\n            return value;\n          },\n        };\n\n        if (isList) {\n          const currentValue = parsedOptions[realOptionName];\n          if (!Array.isArray(currentValue)) {\n            parsedOptions[realOptionName] = currentValue === true ?\n              [] :\n              [currentValue];\n          }\n        }\n      }\n\n      if (option.callback) {\n        throwError(0, option.callback());\n      } else if (option.flag) {\n        if (optionName.startsWith('--no-')) {\n          value = false;\n        } else if (value !== null) {\n          value = value === '1';\n        } else {\n          value = true;\n        }\n        parsedOptions[option.key] = value;\n      } else {\n        if (value === null && i <  args.length - 1 && !isOption(args[i+1])) {\n          // consume next value\n          value = args[i+1];\n          i += 1;\n        }\n        if (value !== null) {\n          if (option.process) {\n            value = option.process(value);\n          }\n          if (option.list) {\n            parsedOptions[option.key].push(value);\n          } else {\n            parsedOptions[option.key] = value;\n          }\n        } else {\n          parsedOptions[option.key] = missingValue;\n        }\n      }\n    } else {\n      positionalArguments.push(/^\\d+$/.test(arg) ? Number(arg) : arg);\n    }\n  }\n\n  for (const optionName in parsedOptions) {\n    if (parsedOptions[optionName] === missingValue) {\n      throwError(\n        1,\n        `Missing value: --${options[optionName].full} requires a value`,\n        getHelpText(options)\n      );\n    }\n  }\n\n  const result = {\n    positionalArguments,\n    options: parsedOptions,\n  };\n\n  validateOptions(parsedOptions, options);\n\n  return result;\n}\n\nmodule.exports = {\n  /**\n   * `options` is an object of objects. Each option can have the following\n   * properties:\n   *\n   *   - full: The name of the option to be used in the command line (if\n   *           different than the property name.\n   *   - abbr: The short version of the option, a single character\n   *   - flag: Whether the option takes an argument or not.\n   *   - default: The default value to use if option is not supplied\n   *   - choices: Restrict possible values to these values\n   *   - help: The help text to print\n   *   - metavar: Value placeholder to use in the help\n   *   - callback: If option is supplied, call this function and exit\n   *   - process: Pre-process value before returning it\n   */\n  options(options) {\n    return {\n      parse(args) {\n        return parse(options, args);\n      },\n      getHelpText() {\n        return getHelpText(options);\n      },\n    };\n  },\n};\n"
  },
  {
    "path": "src/collections/ImportDeclaration.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\nconst Collection = require(\"../Collection\");\nconst NodeCollection = require(\"./Node\");\n\nconst assert = require(\"assert\");\nconst once = require(\"../utils/once\");\nconst recast = require(\"recast\");\n\nconst types = recast.types.namedTypes;\n\nconst globalMethods = {\n  /**\n   * Inserts an ImportDeclaration at the top of the AST\n   *\n   * @param {string} sourcePath\n   * @param {Array} specifiers\n   */\n  insertImportDeclaration: function (sourcePath, specifiers) {\n    assert.ok(\n      sourcePath && typeof sourcePath === \"string\",\n      \"insertImportDeclaration(...) needs a source path\"\n    );\n\n    assert.ok(\n      specifiers && Array.isArray(specifiers),\n      \"insertImportDeclaration(...) needs an array of specifiers\"\n    );\n\n    if (this.hasImportDeclaration(sourcePath)) {\n      return this;\n    }\n\n    const importDeclaration = recast.types.builders.importDeclaration(\n      specifiers,\n      recast.types.builders.stringLiteral(sourcePath)\n    );\n\n    return this.forEach((path) => {\n      if (path.value.type === \"Program\") {\n        path.value.body.unshift(importDeclaration);\n      }\n    });\n  },\n  /**\n   * Finds all ImportDeclarations optionally filtered by name\n   *\n   * @param {string} sourcePath\n   * @return {Collection}\n   */\n  findImportDeclarations: function (sourcePath) {\n    assert.ok(\n      sourcePath && typeof sourcePath === \"string\",\n      \"findImportDeclarations(...) needs a source path\"\n    );\n\n    return this.find(types.ImportDeclaration, {\n      source: { value: sourcePath },\n    });\n  },\n\n  /**\n   * Determines if the collection has an ImportDeclaration with the given sourcePath\n   *\n   * @param {string} sourcePath\n   * @returns {boolean}\n   */\n  hasImportDeclaration: function (sourcePath) {\n    assert.ok(\n      sourcePath && typeof sourcePath === \"string\",\n      \"findImportDeclarations(...) needs a source path\"\n    );\n\n    return this.findImportDeclarations(sourcePath).length > 0;\n  },\n\n  /**\n   * Renames all ImportDeclarations with the given name\n   *\n   * @param {string} sourcePath\n   * @param {string} newSourcePath\n   * @return {Collection}\n   */\n  renameImportDeclaration: function (sourcePath, newSourcePath) {\n    assert.ok(\n      sourcePath && typeof sourcePath === \"string\",\n      \"renameImportDeclaration(...) needs a name to look for\"\n    );\n\n    assert.ok(\n      newSourcePath && typeof newSourcePath === \"string\",\n      \"renameImportDeclaration(...) needs a new name to rename to\"\n    );\n\n    return this.findImportDeclarations(sourcePath).forEach((path) => {\n      path.value.source.value = newSourcePath;\n    });\n  },\n};\n\nfunction register() {\n  NodeCollection.register();\n  Collection.registerMethods(globalMethods, types.Node);\n}\n\nexports.register = once(register);\n"
  },
  {
    "path": "src/collections/JSXElement.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst Collection = require('../Collection');\nconst NodeCollection = require('./Node');\n\nconst assert = require('assert');\nconst once = require('../utils/once');\nconst recast = require('recast');\nconst requiresModule = require('./VariableDeclarator').filters.requiresModule;\n\nconst types = recast.types.namedTypes;\nconst JSXElement = types.JSXElement;\nconst JSXAttribute = types.JSXAttribute;\nconst Literal = types.Literal;\n\n/**\n * Contains filter methods and mutation methods for processing JSXElements.\n * @mixin\n */\nconst globalMethods = {\n  /**\n   * Finds all JSXElements optionally filtered by name\n   *\n   * @param {string} name\n   * @return {Collection}\n   */\n  findJSXElements: function(name) {\n    const nameFilter = name && {openingElement: {name: {name: name}}};\n    return this.find(JSXElement, nameFilter);\n  },\n\n  /**\n   * Finds all JSXElements by module name. Given\n   *\n   *     var Bar = require('Foo');\n   *     <Bar />\n   *\n   * findJSXElementsByModuleName('Foo') will find <Bar />, without having to\n   * know the variable name.\n   */\n  findJSXElementsByModuleName: function(moduleName) {\n    assert.ok(\n      moduleName && typeof moduleName === 'string',\n      'findJSXElementsByModuleName(...) needs a name to look for'\n    );\n\n    return this.find(types.VariableDeclarator)\n      .filter(requiresModule(moduleName))\n      .map(function(path) {\n        const id = path.value.id.name;\n        if (id) {\n          return Collection.fromPaths([path])\n            .closestScope()\n            .findJSXElements(id)\n            .paths();\n        }\n      });\n  }\n};\n\nconst filterMethods = {\n\n  /**\n   * Filter method for attributes.\n   *\n   * @param {Object} attributeFilter\n   * @return {function}\n   */\n  hasAttributes: function(attributeFilter) {\n    const attributeNames = Object.keys(attributeFilter);\n    return function filter(path) {\n      if (!JSXElement.check(path.value)) {\n        return false;\n      }\n      const elementAttributes = Object.create(null);\n      path.value.openingElement.attributes.forEach(function(attr) {\n        if (!JSXAttribute.check(attr) ||\n          !(attr.name.name in attributeFilter)) {\n          return;\n        }\n        elementAttributes[attr.name.name] = attr;\n      });\n\n      return attributeNames.every(function(name) {\n        if (!(name in elementAttributes) ){\n          return false;\n        }\n\n        const value = elementAttributes[name].value;\n        const expected = attributeFilter[name];\n\n        // Only when value is truthy access it's properties\n        const actual = !value\n          ? value\n          : Literal.check(value)\n          ? value.value\n          : value.expression;\n\n        if (typeof expected === 'function') {\n          return expected(actual);\n        }\n\n         // Literal attribute values are always strings\n        return String(expected) === actual;\n      });\n    };\n  },\n\n  /**\n   * Filter elements which contain a specific child type\n   *\n   * @param {string} name\n   * @return {function}\n   */\n  hasChildren: function(name) {\n    return function filter(path) {\n      return JSXElement.check(path.value) &&\n        path.value.children.some(\n          child => JSXElement.check(child) &&\n                   child.openingElement.name.name === name\n        );\n    };\n  }\n};\n\n/**\n* @mixin\n*/\nconst traversalMethods = {\n\n  /**\n   * Returns all child nodes, including literals and expressions.\n   *\n   * @return {Collection}\n   */\n  childNodes: function() {\n    const paths = [];\n    this.forEach(function(path) {\n      const children = path.get('children');\n      const l = children.value.length;\n      for (let i = 0; i < l; i++) {\n        paths.push(children.get(i));\n      }\n    });\n    return Collection.fromPaths(paths, this);\n  },\n\n  /**\n   * Returns all children that are JSXElements.\n   *\n   * @return {JSXElementCollection}\n   */\n  childElements: function() {\n    const paths = [];\n    this.forEach(function(path) {\n      const children = path.get('children');\n      const l = children.value.length;\n      for (let i = 0; i < l; i++) {\n        if (types.JSXElement.check(children.value[i])) {\n          paths.push(children.get(i));\n        }\n      }\n    });\n    return Collection.fromPaths(paths, this, JSXElement);\n  },\n\n  /**\n   * Returns all children that are of jsxElementType.\n   *\n   * @return {Collection<jsxElementType>}\n   */\n  childNodesOfType: function(jsxChildElementType) {\n    const paths = [];\n    this.forEach(function(path) {\n      const children = path.get('children');\n      const l = children.value.length;\n      for (let i = 0; i < l; i++) {\n        if (jsxChildElementType.check(children.value[i])) {\n          paths.push(children.get(i));\n        }\n      }\n    });\n    return Collection.fromPaths(paths, this, jsxChildElementType);\n  },\n};\n\nconst mappingMethods = {\n  /**\n   * Given a JSXElement, returns its \"root\" name. E.g. it would return \"Foo\" for\n   * both <Foo /> and <Foo.Bar />.\n   *\n   * @param {NodePath} path\n   * @return {string}\n   */\n  getRootName: function(path) {\n    let name = path.value.openingElement.name;\n    while (types.JSXMemberExpression.check(name)) {\n      name = name.object;\n    }\n\n    return name && name.name || null;\n  }\n};\n\nfunction register() {\n  NodeCollection.register();\n  Collection.registerMethods(globalMethods, types.Node);\n  Collection.registerMethods(traversalMethods, JSXElement);\n}\n\nexports.register = once(register);\nexports.filters = filterMethods;\nexports.mappings = mappingMethods;\n"
  },
  {
    "path": "src/collections/Node.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst Collection = require('../Collection');\n\nconst matchNode = require('../matchNode');\nconst once = require('../utils/once');\nconst recast = require('recast');\n\nconst Node = recast.types.namedTypes.Node;\nvar types = recast.types.namedTypes;\n\n/**\n* @mixin\n*/\nconst traversalMethods = {\n\n  /**\n   * Find nodes of a specific type within the nodes of this collection.\n   *\n   * @param {type}\n   * @param {filter}\n   * @return {Collection}\n   */\n  find: function(type, filter) {\n    const paths = [];\n    const visitorMethodName = 'visit' + type;\n\n    const visitor = {};\n    function visit(path) {\n      /*jshint validthis:true */\n      if (!filter || matchNode(path.value, filter)) {\n        paths.push(path);\n      }\n      this.traverse(path);\n    }\n    this.__paths.forEach(function(p, i) {\n      const self = this;\n      visitor[visitorMethodName] = function(path) {\n        if (self.__paths[i] === path) {\n          this.traverse(path);\n        } else {\n          return visit.call(this, path);\n        }\n      };\n      recast.visit(p, visitor);\n    }, this);\n\n    return Collection.fromPaths(paths, this, type);\n  },\n\n  /**\n   * Returns a collection containing the paths that create the scope of the\n   * currently selected paths. Dedupes the paths.\n   *\n   * @return {Collection}\n   */\n  closestScope: function() {\n    return this.map(path => path.scope && path.scope.path);\n  },\n\n  /**\n   * Traverse the AST up and finds the closest node of the provided type.\n   *\n   * @param {Collection}\n   * @param {filter}\n   * @return {Collection}\n   */\n  closest: function(type, filter) {\n    return this.map(function(path) {\n      let parent = path.parent;\n      while (\n        parent &&\n        !(\n          type.check(parent.value) &&\n          (!filter || matchNode(parent.value, filter))\n        )\n      ) {\n        parent = parent.parent;\n      }\n      return parent || null;\n    });\n  },\n\n  /**\n   * Finds the declaration for each selected path. Useful for member expressions\n   * or JSXElements. Expects a callback function that maps each path to the name\n   * to look for.\n   *\n   * If the callback returns a falsey value, the element is skipped.\n   *\n   * @param {function} nameGetter\n   *\n   * @return {Collection}\n   */\n  getVariableDeclarators: function(nameGetter) {\n    return this.map(function(path) {\n      /*jshint curly:false*/\n      let scope = path.scope;\n      if (!scope) return;\n      const name = nameGetter.apply(path, arguments);\n      if (!name) return;\n      scope = scope.lookup(name);\n      if (!scope) return;\n      const bindings = scope.getBindings()[name];\n      if (!bindings) return;\n      const decl = Collection.fromPaths(bindings)\n        .closest(types.VariableDeclarator);\n      if (decl.length === 1) {\n        return decl.paths()[0];\n      }\n    }, types.VariableDeclarator);\n  },\n};\n\nfunction toArray(value) {\n  return Array.isArray(value) ? value : [value];\n}\n\n/**\n* @mixin\n*/\nconst mutationMethods = {\n  /**\n   * Simply replaces the selected nodes with the provided node. If a function\n   * is provided it is executed for every node and the node is replaced with the\n   * functions return value.\n   *\n   * @param {Node|Array<Node>|function} nodes\n   * @return {Collection}\n   */\n  replaceWith: function(nodes) {\n    return this.forEach(function(path, i) {\n      const newNodes =\n        (typeof nodes === 'function') ? nodes.call(path, path, i) : nodes;\n      path.replace.apply(path, toArray(newNodes));\n    });\n  },\n\n  /**\n   * Inserts a new node before the current one.\n   *\n   * @param {Node|Array<Node>|function} insert\n   * @return {Collection}\n   */\n  insertBefore: function(insert) {\n    return this.forEach(function(path, i) {\n      const newNodes =\n        (typeof insert === 'function') ? insert.call(path, path, i) : insert;\n      path.insertBefore.apply(path, toArray(newNodes));\n    });\n  },\n\n  /**\n   * Inserts a new node after the current one.\n   *\n   * @param {Node|Array<Node>|function} insert\n   * @return {Collection}\n   */\n  insertAfter: function(insert) {\n    return this.forEach(function(path, i) {\n      const newNodes =\n        (typeof insert === 'function') ? insert.call(path, path, i) : insert;\n      path.insertAfter.apply(path, toArray(newNodes));\n    });\n  },\n\n  remove: function() {\n    return this.forEach(path => path.prune());\n  }\n\n};\n\nfunction register() {\n  Collection.registerMethods(traversalMethods, Node);\n  Collection.registerMethods(mutationMethods, Node);\n  Collection.setDefaultCollectionType(Node);\n}\n\nexports.register = once(register);\n"
  },
  {
    "path": "src/collections/VariableDeclarator.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst Collection = require('../Collection');\nconst NodeCollection = require('./Node');\nconst once = require('../utils/once');\nconst recast = require('recast');\n\nconst astNodesAreEquivalent = recast.types.astNodesAreEquivalent;\nconst b = recast.types.builders;\nvar types = recast.types.namedTypes;\n\nconst VariableDeclarator = recast.types.namedTypes.VariableDeclarator;\n\n/**\n* @mixin\n*/\nconst globalMethods = {\n  /**\n   * Finds all variable declarators, optionally filtered by name.\n   *\n   * @param {string} name\n   * @return {Collection}\n   */\n  findVariableDeclarators: function(name) {\n    const filter = name ? {id: {name: name}} : null;\n    return this.find(VariableDeclarator, filter);\n  }\n};\n\nconst filterMethods = {\n  /**\n   * Returns a function that returns true if the provided path is a variable\n   * declarator and requires one of the specified module names.\n   *\n   * @param {string|Array} names A module name or an array of module names\n   * @return {Function}\n   */\n  requiresModule: function(names) {\n    if (names && !Array.isArray(names)) {\n      names = [names];\n    }\n    const requireIdentifier = b.identifier('require');\n    return function(path) {\n      const node = path.value;\n      if (!VariableDeclarator.check(node) ||\n          !types.CallExpression.check(node.init) ||\n          !astNodesAreEquivalent(node.init.callee, requireIdentifier)) {\n        return false;\n      }\n      return !names ||\n        names.some(\n          n => astNodesAreEquivalent(node.init.arguments[0], b.literal(n))\n        );\n    };\n  }\n};\n\n/**\n* @mixin\n*/\nconst transformMethods = {\n  /**\n   * Renames a variable and all its occurrences.\n   *\n   * @param {string} newName\n   * @return {Collection}\n   */\n  renameTo: function(newName) {\n    // TODO: Include JSXElements\n    return this.forEach(function(path) {\n      const node = path.value;\n      const oldName = node.id.name;\n      const rootScope = path.scope;\n      const rootPath = rootScope.path;\n      Collection.fromPaths([rootPath])\n        .find(types.Identifier, {name: oldName})\n        .filter(function(path) { // ignore non-variables\n          const parent = path.parent.node;\n\n          if (\n            types.MemberExpression.check(parent) &&\n            parent.property === path.node &&\n            !parent.computed\n          ) {\n            // obj.oldName\n            return false;\n          }\n\n          if (\n            types.Property.check(parent) &&\n            parent.key === path.node &&\n            !parent.computed\n          ) {\n            // { oldName: 3 }\n            return false;\n          }\n\n          if (\n            types.ObjectProperty.check(parent) &&\n            parent.key === path.node &&\n            !parent.computed\n          ) {\n            // { oldName: 3 }\n            return false;\n          }\n\n          if (\n            types.ObjectMethod.check(parent) &&\n            parent.key === path.node &&\n            !parent.computed\n          ) {\n            // { oldName() {} }\n            return false;\n          }\n\n          if (\n            types.MethodDefinition.check(parent) &&\n            parent.key === path.node &&\n            !parent.computed\n          ) {\n            // class A { oldName() {} }\n            return false;\n          }\n\n          if (\n            types.ClassMethod.check(parent) &&\n            parent.key === path.node &&\n            !parent.computed\n          ) {\n            // class A { oldName() {} }\n            return false;\n          }\n\n          if (\n            types.ClassProperty.check(parent) &&\n            parent.key === path.node &&\n            !parent.computed\n          ) {\n            // class A { oldName = 3 }\n            return false;\n          }\n\n          if (\n            types.JSXAttribute.check(parent) &&\n            parent.name === path.node &&\n            !parent.computed\n          ) {\n            // <Foo oldName={oldName} />\n            return false;\n          }\n\n          if (\n            (types.JSXOpeningElement.check(parent) || types.JSXClosingElement.check(parent)) &&\n            parent.name === path.node &&\n            /^[a-z]/.test(path.node.name)\n          ) {\n            // <oldName></oldName>\n            return false;\n          }\n\n          return true;\n        })\n        .forEach(function(path) {\n          let scope = path.scope;\n          while (scope && scope !== rootScope) {\n            if (scope.declares(oldName)) {\n              return;\n            }\n            scope = scope.parent;\n          }\n          if (scope) { // identifier must refer to declared variable\n\n            // It may look like we filtered out properties,\n            // but the filter only ignored property \"keys\", not \"value\"s\n            // In shorthand properties, \"key\" and \"value\" both have an\n            // Identifier with the same structure.\n            const parent = path.parent.node;\n            if (\n              types.Property.check(parent) &&\n              parent.shorthand &&\n              !parent.method\n            )  {\n\n              path.parent.get('shorthand').replace(false);\n            }\n\n            path.get('name').replace(newName);\n          }\n        });\n    });\n  }\n};\n\n\nfunction register() {\n  NodeCollection.register();\n  Collection.registerMethods(globalMethods);\n  Collection.registerMethods(transformMethods, VariableDeclarator);\n}\n\nexports.register = once(register);\nexports.filters = filterMethods;\n"
  },
  {
    "path": "src/collections/__tests__/.eslintrc",
    "content": "{\n  \"globals\": {\n    \"jest\": true\n  },\n  \"env\": {\n    \"jasmine\": true\n  }\n}\n"
  },
  {
    "path": "src/collections/__tests__/.jshintrc",
    "content": "{\n  \"predef\": [\"jest\", \"describe\", \"beforeEach\" , \"xit\", \"it\", \"expect\"],\n  \"node\": true,\n  \"esnext\": true\n}\n"
  },
  {
    "path": "src/collections/__tests__/ImportDeclaration-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\nconst getParser = require(\"./../../getParser\");\n\ndescribe(\"ImportDeclaration API\", function () {\n  let nodes;\n  let Collection;\n  let ImportDeclarationCollection;\n  let recast;\n  let types;\n  let b;\n\n  beforeEach(function () {\n    jest.resetModules();\n\n    Collection = require(\"../../Collection\");\n    ImportDeclarationCollection = require(\"../ImportDeclaration\");\n    recast = require(\"recast\");\n    types = recast.types.namedTypes;\n    b = recast.types.builders;\n\n    ImportDeclarationCollection.register();\n\n    nodes = [\n      recast.parse(\n        [\n          'import FooBar from \"XYZ\";',\n          'import Foo, { Bar, Baz } from \"@meta/foo\";',\n          'import { Bar as Burger } from \"@meta/bar\";',\n        ].join(\"\\n\"),\n        { parser: getParser() }\n      ).program,\n    ];\n  });\n\n  describe(\"Traversal\", function () {\n    describe(\"hasImportDeclaration\", function () {\n      it(\"returns true if an ImportDeclaration exists\", function () {\n        const hasImport =\n          Collection.fromNodes(nodes).hasImportDeclaration(\"XYZ\");\n\n        expect(hasImport).toBe(true);\n      });\n\n      it(\"returns false if an ImportDeclaration does not exist\", function () {\n        const hasImport =\n          Collection.fromNodes(nodes).hasImportDeclaration(\"ABC\");\n\n        expect(hasImport).toBe(false);\n      });\n    });\n\n    describe(\"findImportDeclarations\", function () {\n      it(\"lets us find ImportDeclarations by source path conveniently\", function () {\n        const imports =\n          Collection.fromNodes(nodes).findImportDeclarations(\"XYZ\");\n\n        expect(imports.length).toBe(1);\n      });\n\n      it(\"returns an empty ImportDeclarationCollection if no ImportDeclarations are found\", function () {\n        const imports =\n          Collection.fromNodes(nodes).findImportDeclarations(\"Foo\");\n\n        expect(imports.length).toBe(0);\n      });\n    });\n\n    describe(\"renameImportDeclaration\", function () {\n      it(\"renames an ImportDeclaration with the given sourcePath\", function () {\n        Collection.fromNodes(nodes).renameImportDeclaration(\"XYZ\", \"ABC\");\n\n        {\n          const imports =\n            Collection.fromNodes(nodes).findImportDeclarations(\"ABC\");\n\n          expect(imports.length).toBe(1);\n        }\n        {\n          const imports =\n            Collection.fromNodes(nodes).findImportDeclarations(\"XYZ\");\n          expect(imports.length).toBe(0);\n        }\n      });\n\n      it(\"throws if sourcePath is not provided\", function () {\n        expect(function () {\n          Collection.fromNodes(nodes).renameImportDeclaration();\n        }).toThrow();\n      });\n\n      it(\"throws if newSourcePath is not provided\", function () {\n        expect(function () {\n          Collection.fromNodes(nodes).renameImportDeclaration(\"XYZ\");\n        }).toThrow();\n      });\n    });\n\n    describe(\"insertImportDeclaration\", function () {\n      it(\"inserts an ImportDeclaration into the AST\", function () {\n        Collection.fromNodes(nodes).insertImportDeclaration(\"@foo/bar\", [\n          b.importDefaultSpecifier(b.identifier(\"Foo\")),\n          b.importSpecifier(b.identifier(\"ABC\")),\n          b.importSpecifier(b.identifier(\"123\")),\n        ]);\n\n        const imports =\n          Collection.fromNodes(nodes).findImportDeclarations(\"@foo/bar\");\n\n        expect(imports.length).toBe(1);\n\n        const importSpecifiers = imports.paths()[0].value.specifiers;\n        expect(importSpecifiers.length).toBe(3);\n      });\n\n      it(\"does not insert duplicate ImportDeclarations\", function () {\n        Collection.fromNodes(nodes).insertImportDeclaration(\"@foo/baz\", [\n          b.importDefaultSpecifier(b.identifier(\"Foo\")),\n          b.importSpecifier(b.identifier(\"ABC\")),\n        ]);\n\n        Collection.fromNodes(nodes).insertImportDeclaration(\"@foo/baz\", [\n          b.importDefaultSpecifier(b.identifier(\"Foo\")),\n          b.importSpecifier(b.identifier(\"ABC\")),\n        ]);\n\n        const imports =\n          Collection.fromNodes(nodes).findImportDeclarations(\"@foo/baz\");\n\n        expect(imports.length).toBe(1);\n      });\n\n      it(\"throws if importDeclaration is not provided\", function () {\n        expect(function () {\n          Collection.fromNodes(nodes).insertImportDeclaration();\n        }).toThrow();\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/collections/__tests__/JSXElement-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst getParser = require('./../../getParser');\n\ndescribe('JSXCollection API', function() {\n  let nodes;\n  let Collection;\n  let JSXElementCollection;\n  let recast;\n  let types;\n  let b;\n\n  beforeEach(function() {\n    jest.resetModules();\n\n    Collection = require('../../Collection');\n    JSXElementCollection = require('../JSXElement');\n    recast = require('recast');\n    types = recast.types.namedTypes;\n    b = recast.types.builders;\n\n    JSXElementCollection.register();\n\n    nodes = [recast.parse([\n      'var FooBar = require(\"XYZ\");',\n      '<FooBar foo=\"bar\" bar=\"foo\">',\n      '  <Child id=\"1\" foo=\"bar\" baz>',\n      '     <Child />',\n      '     <Baz.Bar />',\n      '  </Child>',\n      '  <Child id=\"2\" foo=\"baz\" baz/>',\n      '  {\"foo\"}',\n      '</FooBar>'\n    ].join('\\n'), {parser: getParser()}).program];\n  });\n\n  describe('Traversal', function() {\n    it('returns a non empty JSXCollection', function() {\n      const jsx = Collection.fromNodes(nodes).find(types.JSXElement);\n      expect(jsx.getTypes()).toContain('JSXElement');\n      expect(jsx.length).toBeGreaterThan(0);\n    });\n\n    it('lets us find JSXElements by name conveniently', function() {\n      const jsx = Collection.fromNodes(nodes).findJSXElements('Child');\n\n      expect(jsx.length).toBe(3);\n    });\n\n    it('finds JSXElements by module name', function() {\n      const jsx = Collection.fromNodes(nodes).findJSXElementsByModuleName('XYZ');\n\n      expect(jsx.length).toBe(1);\n    });\n\n    it('returns the child nodes of an JSXElement', function() {\n      const children =\n        Collection.fromNodes(nodes)\n        .findJSXElements('FooBar')\n        .childNodes();\n      expect(children.length).toBe(7);\n      expect(children.getTypes()).toContain('Expression');\n    });\n\n    it('returns the child JSXElements of an JSXElement', function() {\n      const children =\n        Collection.fromNodes(nodes)\n        .findJSXElements('FooBar')\n        .childElements();\n\n      expect(children.length).toBe(2);\n      expect(children.getTypes()).toContain('JSXElement');\n    });\n\n    it('returns the child element types of an JSXElement', function() {\n      const children =\n        Collection.fromNodes(nodes)\n        .findJSXElements('FooBar')\n        .childNodesOfType(types.JSXExpressionContainer);\n\n      expect(children.length).toBe(1);\n      expect(children.getTypes()).toContain('JSXExpressionContainer');\n    });\n\n    it('returns a properly typed collection even if empty', function() {\n      const children =\n        Collection.fromNodes([])\n        .findJSXElements('Foo')\n        .childElements();\n\n      expect(children.length).toBe(0);\n      expect(children.getTypes()).toContain('JSXElement');\n    });\n  });\n\n  describe('Filtering', function() {\n    it('filters elements by attributes', function() {\n      const jsx = Collection.fromNodes(nodes)\n        .findJSXElements()\n        .filter(JSXElementCollection.filters.hasAttributes({foo: 'bar'}));\n      expect(jsx.length).toBe(2);\n    });\n\n    it('accepts callback functions as attribute filters', function() {\n      const jsx = Collection.fromNodes(nodes)\n        .findJSXElements()\n        .filter(JSXElementCollection.filters.hasAttributes(\n            {\n              foo: v => ['bar', 'baz'].indexOf(v) > -1,\n              baz: v => v === null\n            }\n        ));\n      expect(jsx.length).toBe(2);\n    });\n\n    it('filters elements by children', function() {\n      const jsx = Collection.fromNodes(nodes)\n        .findJSXElements()\n        .filter(JSXElementCollection.filters.hasChildren('Child'));\n      expect(jsx.length).toBe(2);\n    });\n  });\n\n  describe('Mappings', function() {\n    it('gets the root names of JSXElements', function() {\n      const names = Collection.fromNodes(nodes)\n        .findJSXElements()\n        .paths().map(JSXElementCollection.mappings.getRootName);\n\n      expect(names.indexOf('FooBar') > -1).toBe(true);\n      expect(names.indexOf('Child') > -1).toBe(true);\n      expect(names.indexOf('Baz') > -1).toBe(true);\n    });\n  });\n\n  describe('Mutation', function() {\n    it('handles insertions before children correctly', function() {\n      const childElement = b.jsxElement(\n        b.jsxOpeningElement(b.jsxIdentifier('Bar'), [], true)\n      );\n      const newChildElement = b.jsxElement(\n        b.jsxOpeningElement(b.jsxIdentifier('Baz'), [], true)\n      );\n      const literal = b.literal('\\n  ');\n      const ast = b.jsxElement(\n        b.jsxOpeningElement(b.jsxIdentifier('Foo')),\n        b.jsxClosingElement(b.jsxIdentifier('Foo')),\n        [literal, childElement, literal, childElement, b.literal('\\n')]\n      );\n\n      Collection.fromNodes([ast])\n        .childElements().at(1).insertBefore(newChildElement);\n\n      expect(ast.children.length).toBe(6);\n      expect(ast.children[3]).toBe(newChildElement);\n    });\n\n  });\n});\n"
  },
  {
    "path": "src/collections/__tests__/Node-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\ndescribe('Collection API', function() {\n  let ast;\n  let Collection;\n  let NodeCollection;\n  let recast;\n  let types;\n  let b;\n\n  beforeEach(function() {\n    jest.resetModules();\n\n    Collection = require('../../Collection');\n    NodeCollection = require('../Node');\n    recast = require('recast');\n\n    types = recast.types.namedTypes;\n    b = recast.types.builders;\n\n    NodeCollection.register();\n\n    ast = b.program([\n      b.variableDeclaration(\n        'var',\n        [b.variableDeclarator(b.identifier('foo'), null)]\n      ),\n      b.functionDeclaration(\n        b.identifier('f'),\n        [],\n        b.blockStatement([\n          b.variableDeclaration(\n            'var',\n            [b.variableDeclarator(b.identifier('bar'), null)]\n          ),\n          b.variableDeclaration(\n            'var',\n            [b.variableDeclarator(b.identifier('baz'), null)]\n          )\n        ])\n      ),\n    ]);\n  });\n\n  describe('Traversal', function() {\n    describe('find', function() {\n      it('finds nodes by type', function() {\n        const ast = b.sequenceExpression([ // eslint-disable-line no-shadow\n          b.identifier('foo'),\n          b.literal('asd'),\n          b.identifier('bar'),\n        ]);\n        const vars = Collection.fromNodes([ast]).find(types.Identifier);\n\n        expect(vars.length).toBe(2);\n      });\n\n      it('doesn\\'t find the nodes in the collection itself', function() {\n        const nodes = [\n          b.identifier('foo'),\n          b.literal('asd'),\n          b.identifier('bar'),\n        ];\n        const vars = Collection.fromNodes(nodes).find(types.Identifier);\n\n        expect(vars.length).toBe(0);\n      });\n\n      it('finds nodes by type and properties', function() {\n        const ast = b.sequenceExpression([ // eslint-disable-line no-shadow\n          b.identifier('foo'),\n          b.literal('asd'),\n          b.identifier('bar'),\n        ]);\n        const vars = Collection.fromNodes([ast])\n          .find(types.Identifier, {name: 'bar'});\n\n        expect(vars.length).toBe(1);\n        expect(vars.nodes()[0]).toBe(ast.expressions[2]);\n      });\n\n      it('handles chained find calls properly', function() {\n        const vars = Collection.fromNodes([ast])\n          .find(types.FunctionDeclaration)\n          .find(types.VariableDeclarator, {id: {name: 'bar'}});\n\n        expect(vars.length).toBe(1);\n        expect(vars.nodes()[0]).toBe(\n          ast.body[1].body.body[0].declarations[0]\n        );\n      });\n\n      it('handles multi chain find calls properly', function() {\n        const functionBody = ast.body[1].body.body;\n        const functionDeclarations = Collection.fromNodes([ast])\n          .find(types.FunctionDeclaration);\n\n        const bar = functionDeclarations\n          .find(types.VariableDeclarator, {id: {name: 'bar'}});\n        const baz = functionDeclarations\n          .find(types.VariableDeclarator, {id: {name: 'baz'}});\n\n        expect(bar.length).toBe(1);\n        expect(bar.nodes()[0]).toBe(functionBody[0].declarations[0]);\n        expect(baz.length).toBe(1);\n        expect(baz.nodes()[0]).toBe(functionBody[1].declarations[0]);\n      });\n    });\n\n    describe('closestScope', function() {\n      it('gets the closest scope', function() {\n        const functionDeclaration = ast.body[1];\n        const scopes = Collection.fromNodes([ast])\n          .find(types.Identifier)\n          .closestScope();\n\n        expect(scopes.nodes()[0]).toBe(ast);\n        expect(scopes.nodes()[1]).toBe(functionDeclaration);\n      });\n    });\n\n    describe('closest', function() {\n      let decl;\n      beforeEach(()=> {\n        decl = b.functionDeclaration(\n          b.identifier('foo'),\n          [],\n          b.blockStatement([\n            b.functionDeclaration(\n              b.identifier('bar'),\n              [],\n              b.blockStatement([\n                b.returnStatement(\n                  b.literal(3)\n                )\n              ])\n            ),\n          ])\n        );\n      });\n\n      it('finds closest node (up the tree) of the given type', function() {\n        const functionDeclaration = ast.body[1];\n        decl = Collection.fromNodes([ast])\n          .find(types.Identifier)\n          .closest(types.FunctionDeclaration);\n\n        expect(decl.length).toBe(1);\n        expect(decl.nodes()[0]).toBe(functionDeclaration);\n      });\n\n      it('allows to filter nodes by pattern', function() {\n        const literals = Collection.fromNodes([decl])\n          .find(types.Literal);\n        expect(literals.get(0).node.value).toBe(3);\n        const closest = literals.closest(\n          types.FunctionDeclaration,\n          {id: {name: 'foo'}}\n        );\n        expect(closest.get(0).node.id.name).toBe('foo');\n      });\n\n      it('allows to filter nodes with a filter function', function() {\n        const literals = Collection.fromNodes([decl])\n          .find(types.Literal);\n        expect(literals.get(0).node.value).toBe(3);\n        const closest = literals.closest(\n          types.FunctionDeclaration,\n          (node) => node.id && node.id.name === 'foo'\n        );\n        expect(closest.get(0).node.id.name).toBe('foo');\n      });\n\n      it('fails when filter evaluates as false', function() {\n        const literals = Collection.fromNodes([decl])\n          .find(types.Literal);\n        expect(literals.get(0).node.value).toBe(3);\n        const closest = literals.closest(\n          types.FunctionDeclaration,\n          (node) => node.id && node.id.name === 'blue'\n        );\n        expect(closest.nodes().length).toBe(0);\n      });\n    });\n\n    describe('getVariableDeclarators', function() {\n      it('gets the variable declarators for each selected path', function() {\n        const variableDeclarator =\n          b.variableDeclarator(b.identifier('foo'), null);\n        const program = b.program([\n          b.variableDeclaration('var', [variableDeclarator]),\n          b.expressionStatement(b.identifier('foo')),\n          b.expressionStatement(b.identifier('bar'))\n        ]);\n\n        const decl = Collection.fromNodes([program])\n          .find(types.Identifier)\n          .getVariableDeclarators(p => p.value.name);\n        expect(decl.length).toBe(1);\n        expect(decl.nodes()[0]).toBe(variableDeclarator);\n      });\n    });\n  });\n\n  describe('Mutation', function() {\n    describe('replaceWith', function() {\n      it('handles simple AST node replacement', function() {\n        const ast = b.sequenceExpression([ // eslint-disable-line no-shadow\n          b.identifier('foo'),\n          b.literal('asd'),\n          b.identifier('bar'),\n        ]);\n        const newNode = b.identifier('xyz');\n\n        const S = Collection.fromNodes([ast]);\n        S.find(types.Identifier, {name: 'bar'})\n          .replaceWith(newNode);\n\n        expect(S.nodes()[0].expressions[2]).toBe(newNode);\n      });\n\n      it('accepts an array as replacement', function() {\n        const ast = b.sequenceExpression([   // eslint-disable-line no-shadow\n          b.identifier('foo'),\n          b.literal('asd'),\n          b.identifier('bar'),\n        ]);\n        const newNode1 = b.identifier('xyz');\n        const newNode2 = b.identifier('jkl');\n\n        const S = Collection.fromNodes([ast]);\n        S.find(types.Identifier, {name: 'bar'})\n          .replaceWith([newNode1, newNode2]);\n\n        expect(S.nodes()[0].expressions[2]).toBe(newNode1);\n        expect(S.nodes()[0].expressions[3]).toBe(newNode2);\n      });\n\n      it('accepts a function as replacement ', function() {\n        const ast = b.sequenceExpression([ // eslint-disable-line no-shadow\n          b.identifier('foo'),\n          b.literal('asd'),\n          b.identifier('bar'),\n        ]);\n\n        const expectedArgs = [b.identifier('foo'), b.identifier('bar')];\n        const receivedArgs = [];\n        const replaceFunction =\n          jest.fn(function(path, i) {\n            // We have to keep a reference to the argument before it gets\n            // replaced\n            receivedArgs.push(path.value);\n            return b.identifier(path.value.name + i);\n          });\n\n        const S = Collection.fromNodes([ast]);\n        S.find(types.Identifier)\n         .replaceWith(replaceFunction);\n\n        expect(replaceFunction.mock.calls.length).toBe(2);\n        expect(receivedArgs).toEqual(expectedArgs);\n        // baz is properly replaced\n        expect(S.nodes()[0].expressions[0]).toEqual(b.identifier('foo0'));\n        // baz1 is properly replaced\n        expect(S.nodes()[0].expressions[2]).toEqual(b.identifier('bar1'));\n      });\n    });\n\n    describe('insertBefore', function() {\n      it('inserts a new node before the current one', function() {\n        const ast = b.variableDeclaration( // eslint-disable-line no-shadow\n          'var',\n          [b.variableDeclarator(b.identifier('foo'), null)]\n        );\n        const one = b.variableDeclarator(b.identifier('one'), null);\n\n        Collection.fromNodes([ast])\n          .find(types.VariableDeclarator)\n          .insertBefore(one);\n\n        expect(ast.declarations.length).toBe(2);\n        expect(ast.declarations[0]).toBe(one);\n      });\n\n      it('accepts an array of nodes', function() {\n        const ast = b.variableDeclaration( // eslint-disable-line no-shadow\n          'var',\n          [b.variableDeclarator(b.identifier('foo'), null)]\n        );\n        const one = b.variableDeclarator(b.identifier('one'), null);\n        const two = b.variableDeclarator(b.identifier('two'), null);\n\n        Collection.fromNodes([ast])\n          .find(types.VariableDeclarator)\n          .insertBefore([one, two]);\n\n        expect(ast.declarations.length).toBe(3);\n        expect(ast.declarations[0]).toBe(one);\n        expect(ast.declarations[1]).toBe(two);\n      });\n\n      it('accepts a function', function() {\n        const x = b.identifier('x');\n        const foo = b.identifier('foo');\n        const bar = b.identifier('bar');\n        const ast = b.sequenceExpression([foo, bar]); // eslint-disable-line no-shadow\n\n        Collection.fromNodes([ast])\n          .find(types.Identifier)\n          .insertBefore(function() {\n            return x;\n          });\n\n        expect(ast.expressions.length).toBe(4);\n        expect(ast.expressions).toEqual([x, foo, x, bar]);\n        expect(ast.expressions[0]).toBe(x);\n        expect(ast.expressions[2]).toBe(x);\n      });\n    });\n\n    describe('insertAfter', function() {\n      it('inserts a new node after the current one', function() {\n        const ast = b.variableDeclaration( // eslint-disable-line no-shadow\n          'var',\n          [b.variableDeclarator(b.identifier('foo'), null)]\n        );\n        const one = b.variableDeclarator(b.identifier('one'), null);\n\n        Collection.fromNodes([ast])\n          .find(types.VariableDeclarator)\n          .insertAfter(one);\n\n        expect(ast.declarations.length).toBe(2);\n        expect(ast.declarations[1]).toBe(one);\n      });\n\n      it('accepts an array of nodes', function() {\n        const ast = b.variableDeclaration( // eslint-disable-line no-shadow\n          'var',\n          [b.variableDeclarator(b.identifier('foo'), null)]\n        );\n        const one = b.variableDeclarator(b.identifier('one'), null);\n        const two = b.variableDeclarator(b.identifier('two'), null);\n\n        Collection.fromNodes([ast])\n          .find(types.VariableDeclarator)\n          .insertAfter([one, two]);\n\n        expect(ast.declarations.length).toBe(3);\n        expect(ast.declarations[1]).toBe(one);\n        expect(ast.declarations[2]).toBe(two);\n      });\n\n      it('accepts a function', function() {\n        const x = b.identifier('x');\n        const foo = b.identifier('foo');\n        const bar = b.identifier('bar');\n        const ast = b.sequenceExpression([foo, bar]); // eslint-disable-line no-shadow\n\n        Collection.fromNodes([ast])\n          .find(types.Identifier)\n          .insertAfter(function() {\n            return x;\n          });\n\n        expect(ast.expressions.length).toBe(4);\n        expect(ast.expressions).toEqual([foo, x, bar, x]);\n        expect(ast.expressions[1]).toBe(x);\n        expect(ast.expressions[3]).toBe(x);\n      });\n    });\n\n    describe('removes', function() {\n      it('removes a node if it is part of the body of a statement', function() {\n        const x = b.expressionStatement(b.identifier('x'));\n        const y = b.expressionStatement(b.identifier('y'));\n        const ast = b.program([x, y]); // eslint-disable-line no-shadow\n\n        Collection.fromNodes([ast])\n          .find(types.Identifier, {name: 'x'})\n          .remove();\n\n        expect(ast.body.length).toBe(1);\n        expect(ast.body[0]).toBe(y);\n      });\n\n      it('removes a node if it is a function param', function() {\n        const x = b.identifier('x');\n        const y = b.identifier('y');\n        const ast = b.arrowFunctionExpression( // eslint-disable-line no-shadow\n          [x, b.identifier('z')],\n          y\n        );\n\n        Collection.fromNodes([ast])\n          .find(types.Identifier, {name: 'z'})\n          .remove();\n        expect(ast.params.length).toBe(1);\n        expect(ast.params[0]).toBe(x);\n        expect(ast.body).toBe(y);\n      });\n    });\n  });\n});\n"
  },
  {
    "path": "src/collections/__tests__/VariableDeclarator-test.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst getParser = require('./../../getParser');\n\nconst recast = require('recast');\nconst types = recast.types.namedTypes;\n\ndescribe('VariableDeclarators', function() {\n  let nodes;\n  let Collection;\n  let VariableDeclaratorCollection;\n\n  beforeEach(function() {\n    jest.resetModules();\n\n    Collection = require('../../Collection');\n    VariableDeclaratorCollection =  require('../VariableDeclarator');\n    VariableDeclaratorCollection.register();\n\n    nodes = [recast.parse([\n      'var foo = 42;',\n      'var bar = require(\"module\");',\n      'var baz = require(\"module2\");',\n      'function first() {',\n      '  var x = bar;',\n      '  bar.someMethod();',\n      '  func1(bar);',\n      '}',\n      'function func1(bar) {',\n      '  var bar = 21;',\n      '}',\n      'foo.bar();',\n      'foo[bar]();',\n      'bar.foo();',\n      'function second() {',\n      '  var blah;',\n      '  var obj = {',\n      '    blah: 4,',\n      '    blah() {},',\n      '  };',\n      '  obj.blah = 3;',\n      '  class A {',\n      '    blah = 10',\n      '    blah() {}',\n      '  }',\n      '}',\n      'class Foo { @decorator\\n*stuff() {} }',\n      '<Component foo={foo} />',\n    ].join('\\n'), {parser: getParser()}).program];\n  });\n\n  describe('Traversal', function() {\n    it('adds a root method to find variable declarators', function() {\n      expect(Collection.fromNodes([]).findVariableDeclarators).toBeDefined();\n    });\n\n    it('finds all variable declarators', function() {\n      const declarators = Collection.fromNodes(nodes).findVariableDeclarators();\n      expect(declarators.getTypes()).toContain('VariableDeclarator');\n      expect(declarators.length).toBe(7);\n    });\n\n    it('finds variable declarators by name', function() {\n      const declarators = Collection.fromNodes(nodes)\n        .findVariableDeclarators('bar');\n      expect(declarators.length).toBe(2);\n    });\n  });\n\n  describe('Filters', function() {\n    it('finds module imports (require)', function() {\n      const declarators = Collection.fromNodes(nodes)\n        .findVariableDeclarators()\n        .filter(VariableDeclaratorCollection.filters.requiresModule());\n\n      expect(declarators.length).toBe(2);\n    });\n\n    it('finds module imports (require) by module name', function() {\n      const declarators = Collection.fromNodes(nodes)\n        .findVariableDeclarators()\n        .filter(VariableDeclaratorCollection.filters.requiresModule('module'));\n\n      expect(declarators.length).toBe(1);\n    });\n\n    it('accepts multiple module names', function() {\n      const declarators = Collection.fromNodes(nodes)\n        .findVariableDeclarators()\n        .filter(VariableDeclaratorCollection.filters.requiresModule(\n          ['module', 'module2']\n        ));\n\n      expect(declarators.length).toBe(2);\n    });\n  });\n\n  describe('Transform', function() {\n    it('renames variable declarations considering scope', function() {\n      Collection.fromNodes(nodes)\n        .findVariableDeclarators()\n        .filter(VariableDeclaratorCollection.filters.requiresModule('module'))\n        .renameTo('xyz');\n\n      const identifiers =\n        Collection.fromNodes(nodes)\n        .find(types.Identifier, {name: 'xyz'});\n\n      expect(identifiers.length).toBe(6);\n    });\n\n    it('does not rename things that are not variables', function() {\n      Collection.fromNodes(nodes)\n        .findVariableDeclarators('blah')\n        .renameTo('blarg');\n\n      const identifiers =\n        Collection.fromNodes(nodes)\n        .find(types.Identifier, {name: 'blarg'});\n\n      expect(identifiers.length).toBe(1);\n    });\n\n    it('properly renames a shorthand property that was using the old variable name', function() {\n      nodes = [recast.parse([\n        'var foo = 42;',\n        'var obj2 = {',\n        '  foo,',\n        '};',\n      ].join('\\n'), {parser: getParser()}).program];\n\n      // Outputs:\n      // var newFoo = 42;\n      // var obj2 = {\n      //   foo: newFoo,\n      // };\n      Collection.fromNodes(nodes)\n        .findVariableDeclarators('foo').renameTo('newFoo');\n\n      expect(\n        Collection.fromNodes(nodes).find(types.Identifier, { name: 'newFoo' }).length\n      ).toBe(2);\n      expect(\n        Collection.fromNodes(nodes).find(types.Identifier, { name: 'foo' }).length\n      ).toBe(1);\n\n      expect(\n        Collection.fromNodes(nodes).find(types.Property).filter(prop => !prop.value.shorthand).length\n      ).toBe(1);\n      expect(\n        Collection.fromNodes(nodes).find(types.Property).filter(prop => prop.value.shorthand).length\n      ).toBe(0);\n    });\n\n    it('does not rename React component prop name', function () {\n      Collection.fromNodes(nodes)\n        .findVariableDeclarators('foo')\n        .renameTo('xyz');\n\n      const identifiers = Collection.fromNodes(nodes)\n        .find(types.JSXIdentifier, { name: 'foo' });\n\n      expect(identifiers.length).toBe(1);\n    });\n\n    it('does not rename JSX open and closing tags that start with a lowercase letter', function () {\n      nodes = [recast.parse([\n        'var span = useRef(null);',\n        'var element = <span ref={span}></span>;',\n      ].join('\\n'), {parser: getParser()}).program];\n\n      Collection.fromNodes(nodes)\n        .findVariableDeclarators('span')\n        .renameTo('spanRef');\n\n      const identifiers = Collection.fromNodes(nodes)\n        .find(types.JSXIdentifier, { name: 'spanRef' });\n\n      expect(identifiers.length).toBe(0);\n    });\n\n    it('does rename JSX open and closing tags that are capitalized', function () {\n      nodes = [recast.parse([\n        'var Span = require(\"./Span\");',\n        'var span = useRef(null);',\n        'var element = <Span ref={span}></Span>;',\n      ].join('\\n'), {parser: getParser()}).program];\n\n      Collection.fromNodes(nodes)\n        .findVariableDeclarators('Span')\n        .renameTo('SpanComponent');\n\n      const identifiers = Collection.fromNodes(nodes)\n        .find(types.JSXIdentifier, { name: 'SpanComponent' });\n\n      expect(identifiers.length).toBe(2);\n    });\n\n    describe('parsing with bablylon', function() {\n      it('does not rename object property', function () {\n        nodes = [\n          recast.parse('var foo = 42; var obj = { foo: null };', {\n            parser: getParser('babylon'),\n          }).program\n        ];\n        Collection\n          .fromNodes(nodes)\n          .findVariableDeclarators('foo').renameTo('newFoo');\n\n        expect(\n          Collection.fromNodes(nodes).find(types.Identifier, { name: 'newFoo' }).length\n        ).toBe(1);\n        expect(\n          Collection.fromNodes(nodes).find(types.Identifier, { name: 'foo' }).length\n        ).toBe(1);\n      })\n\n      it('does not rename object method', function () {\n        nodes = [\n          recast.parse('var foo = 42; var obj = { foo() {} };', {\n            parser: getParser('babylon'),\n          }).program\n        ];\n        Collection\n          .fromNodes(nodes)\n          .findVariableDeclarators('foo').renameTo('newFoo');\n\n        expect(\n          Collection.fromNodes(nodes).find(types.Identifier, { name: 'newFoo' }).length\n        ).toBe(1);\n        expect(\n          Collection.fromNodes(nodes).find(types.Identifier, { name: 'foo' }).length\n        ).toBe(1);\n      })\n\n      it('does not rename class method', function () {\n        nodes = [\n          recast.parse('var foo = 42; class A { foo() {} }', {\n            parser: getParser('babylon'),\n          }).program\n        ];\n        Collection\n          .fromNodes(nodes)\n          .findVariableDeclarators('foo').renameTo('newFoo');\n\n        expect(\n          Collection.fromNodes(nodes).find(types.Identifier, { name: 'newFoo' }).length\n        ).toBe(1);\n        expect(\n          Collection.fromNodes(nodes).find(types.Identifier, { name: 'foo' }).length\n        ).toBe(1);\n      })\n    });\n  });\n\n});\n"
  },
  {
    "path": "src/collections/index.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = {\n  Node: require('./Node'),\n  JSXElement: require('./JSXElement'),\n  VariableDeclarator: require('./VariableDeclarator'),\n  ImportDeclaration: require('./ImportDeclaration'),\n};\n"
  },
  {
    "path": "src/core.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\nconst Collection = require('./Collection');\n\nconst collections = require('./collections');\nconst getParser = require('./getParser');\nconst matchNode = require('./matchNode');\nconst recast = require('recast');\nconst template = require('./template');\n\nconst Node = recast.types.namedTypes.Node;\nconst NodePath = recast.types.NodePath;\n\n// Register all built-in collections\nfor (var name in collections) {\n  collections[name].register();\n}\n\n/**\n * Main entry point to the tool. The function accepts multiple different kinds\n * of arguments as a convenience. In particular the function accepts either\n *\n * - a string containing source code\n *   The string is parsed with Recast\n * - a single AST node\n * - a single node path\n * - an array of nodes\n * - an array of node paths\n *\n * @exports jscodeshift\n * @param {Node|NodePath|Array|string} source\n * @param {Object} options Options to pass to Recast when passing source code\n * @return {Collection}\n */\nfunction core(source, options) {\n  return typeof source === 'string' ?\n    fromSource(source, options) :\n    fromAST(source);\n}\n\n/**\n * Returns a collection from a node, node path, array of nodes or array of node\n * paths.\n *\n * @ignore\n * @param {Node|NodePath|Array} source\n * @return {Collection}\n */\nfunction fromAST(ast) {\n  if (Array.isArray(ast)) {\n    if (ast[0] instanceof NodePath || ast.length === 0) {\n      return Collection.fromPaths(ast);\n    } else if (Node.check(ast[0])) {\n      return Collection.fromNodes(ast);\n    }\n  } else {\n    if (ast instanceof NodePath) {\n      return Collection.fromPaths([ast]);\n    } else if (Node.check(ast)) {\n      return Collection.fromNodes([ast]);\n    }\n  }\n  throw new TypeError(\n    'Received an unexpected value ' + Object.prototype.toString.call(ast)\n  );\n}\n\nfunction fromSource(source, options) {\n  if (!options) {\n    options = {};\n  }\n  if (!options.parser) {\n    options.parser = getParser();\n  }\n  return fromAST(recast.parse(source, options));\n}\n\n/**\n * Utility function to match a node against a pattern.\n * @augments core\n * @static\n * @param {Node|NodePath|Object} path\n * @parma {Object} filter\n * @return boolean\n */\nfunction match(path, filter) {\n  if (!(path instanceof NodePath)) {\n    if (typeof path.get === 'function') {\n      path = path.get();\n    } else {\n      path = {value: path};\n    }\n  }\n  return matchNode(path.value, filter);\n}\n\nconst plugins = [];\n\n/**\n * Utility function for registering plugins.\n *\n * Plugins are simple functions that are passed the core jscodeshift instance.\n * They should extend jscodeshift by calling `registerMethods`, etc.\n * This method guards against repeated registrations (the plugin callback will only be called once).\n *\n * @augments core\n * @static\n * @param {Function} plugin\n */\nfunction use(plugin) {\n  if (plugins.indexOf(plugin) === -1) {\n    plugins.push(plugin);\n    plugin(core);\n  }\n}\n\n/**\n * Returns a version of the core jscodeshift function \"bound\" to a specific\n * parser.\n *\n * @augments core\n * @static\n */\nfunction withParser(parser) {\n  if (typeof parser === 'string') {\n    parser = getParser(parser);\n  }\n\n  const newCore = function(source, options) {\n    if (options && !options.parser) {\n      options.parser = parser;\n    } else {\n      options = {parser};\n    }\n    return core(source, options);\n  };\n\n  return enrichCore(newCore, parser);\n}\n\n/**\n* The ast-types library\n* @external astTypes\n* @see {@link https://github.com/benjamn/ast-types}\n*/\n\nfunction enrichCore(core, parser) {\n  // add builders and types to the function for simple access\n  Object.assign(core, recast.types.namedTypes);\n  Object.assign(core, recast.types.builders);\n  core.registerMethods = Collection.registerMethods;\n  /**\n  * @augments core\n  * @type external:astTypes\n  */\n  core.types = recast.types;\n  core.match = match;\n  core.template = template(parser);\n\n  // add mappings and filters to function\n  core.filters = {};\n  core.mappings = {};\n  for (const name in collections) {\n    if (collections[name].filters) {\n      core.filters[name] = collections[name].filters;\n    }\n    if (collections[name].mappings) {\n      core.mappings[name] = collections[name].mappings;\n    }\n  }\n  core.use = use;\n  core.withParser = withParser;\n  return core;\n}\n\nmodule.exports = enrichCore(core, getParser());\n"
  },
  {
    "path": "src/getParser.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nmodule.exports = function getParser(parserName, options) {\n  switch (parserName) {\n    case 'babylon':\n      return require('../parser/babylon')(options);\n    case 'flow':\n      return require('../parser/flow')(options);\n    case 'ts':\n      return require('../parser/ts')(options);\n    case 'tsx':\n      return require('../parser/tsx')(options);\n    case 'babel':\n    default:\n      return require('../parser/babel5Compat')(options);\n  }\n};\n"
  },
  {
    "path": "src/ignoreFiles.js",
    "content": "'use strict';\n\nconst fs = require('fs');\nconst mm = require('micromatch');\n\nconst matchers = [];\n\n/**\n * Add glob patterns to ignore matched files and folders.\n * Creates glob patterns to approximate gitignore patterns.\n * @param {String} val - the glob or gitignore-style pattern to ignore\n * @see {@linkplain https://git-scm.com/docs/gitignore#_pattern_format}\n */\nfunction addIgnorePattern(val) {\n  if (val && typeof val === 'string' && val[0] !== '#') {\n    let pattern = val;\n    if (pattern.indexOf('/') === -1) {\n      matchers.push('**/' + pattern);\n    } else if (pattern[pattern.length-1] === '/') {\n      matchers.push('**/' + pattern + '**');\n      matchers.push(pattern + '**');\n    }\n    matchers.push(pattern);\n  }\n}\n\n/**\n * Adds ignore patterns directly from function input\n * @param {String|Array<String>} input - the ignore patterns\n */\nfunction addIgnoreFromInput(input) {\n  let patterns = [];\n  if (input) {\n    patterns = patterns.concat(input);\n  }\n  patterns.forEach(addIgnorePattern);\n}\n\n/**\n * Adds ignore patterns by reading files\n * @param {String|Array<String>} input - the paths to the ignore config files\n */\nfunction addIgnoreFromFile(input) {\n  let lines = [];\n  let files = [];\n  if (input) {\n    files = files.concat(input);\n  }\n\n  files.forEach(function(config) {\n    const stats = fs.statSync(config);\n    if (stats.isFile()) {\n      const content = fs.readFileSync(config, 'utf8');\n      lines = lines.concat(content.split(/\\r?\\n/));\n    }\n  });\n\n  lines.forEach(addIgnorePattern);\n}\n\nfunction shouldIgnore(path) {\n  const matched = matchers.length ? mm.isMatch(path, matchers, { dot:true }) : false;\n  return matched;\n}\n\nexports.add = addIgnoreFromInput;\nexports.addFromFile = addIgnoreFromFile;\nexports.shouldIgnore = shouldIgnore;\n"
  },
  {
    "path": "src/matchNode.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst hasOwn =\n  Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);\n\n/**\n * Checks whether needle is a strict subset of haystack.\n *\n * @param {*} haystack Value to test.\n * @param {*} needle Test function or value to look for in `haystack`.\n * @return {bool}\n */\nfunction matchNode(haystack, needle) {\n  if (typeof needle === 'function') {\n    return needle(haystack);\n  }\n  if (isNode(needle) && isNode(haystack)) {\n    return Object.keys(needle).every(function(property) {\n      return (\n        hasOwn(haystack, property) &&\n        matchNode(haystack[property], needle[property])\n      );\n    });\n  }\n  return haystack === needle;\n}\n\nfunction isNode(value) {\n  return typeof value === 'object' && value;\n}\n\nmodule.exports = matchNode;\n"
  },
  {
    "path": "src/template.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst recast = require('recast');\n\nconst builders = recast.types.builders;\nconst types = recast.types.namedTypes;\n\nfunction splice(arr, element, replacement) {\n  arr.splice.apply(arr, [arr.indexOf(element), 1].concat(replacement));\n}\n\nfunction cleanLocation(node) {\n  delete node.start;\n  delete node.end;\n  delete node.loc;\n  return node;\n}\n\nfunction ensureStatement(node) {\n  return types.Statement.check(node) ?\n    // Removing the location information seems to ensure that the node is\n    // correctly reprinted with a trailing semicolon\n    cleanLocation(node) :\n    builders.expressionStatement(node);\n}\n\nfunction getVistor(varNames, nodes) {\n  return {\n    visitIdentifier: function(path) {\n      this.traverse(path);\n      const node = path.node;\n      const parent = path.parent.node;\n\n      // If this identifier is not one of our generated ones, do nothing\n      const varIndex = varNames.indexOf(node.name);\n      if (varIndex === -1) {\n        return;\n      }\n\n      let replacement = nodes[varIndex];\n      nodes[varIndex] = null;\n\n      // If the replacement is an array, we need to explode the nodes in context\n      if (Array.isArray(replacement)) {\n\n        if (types.Function.check(parent) &&\n            parent.params.indexOf(node) > -1) {\n          // Function parameters: function foo(${bar}) {}\n          splice(parent.params, node, replacement);\n        } else if (types.VariableDeclarator.check(parent)) {\n          // Variable declarations: var foo = ${bar}, baz = 42;\n          splice(\n            path.parent.parent.node.declarations,\n            parent,\n            replacement\n          );\n        } else if (types.ArrayExpression.check(parent)) {\n          // Arrays: var foo = [${bar}, baz];\n          splice(parent.elements, node, replacement);\n        } else if (types.Property.check(parent) && parent.shorthand) {\n          // Objects: var foo = {${bar}, baz: 42};\n          splice(\n            path.parent.parent.node.properties,\n            parent,\n            replacement\n          );\n        } else if (types.CallExpression.check(parent) &&\n            parent.arguments.indexOf(node) > -1) {\n          // Function call arguments: foo(${bar}, baz)\n          splice(parent.arguments, node, replacement);\n        } else if (types.ExpressionStatement.check(parent)) {\n          // Generic sequence of statements: { ${foo}; bar; }\n          path.parent.replace.apply(\n            path.parent,\n            replacement.map(ensureStatement)\n          );\n        } else {\n          // Every else, let recast take care of it\n          path.replace.apply(path, replacement);\n        }\n      } else if (types.ExpressionStatement.check(parent)) {\n        path.parent.replace(ensureStatement(replacement));\n      } else {\n        path.replace(replacement);\n      }\n    }\n  };\n}\n\nfunction replaceNodes(src, varNames, nodes, parser) {\n  const ast = recast.parse(src, {parser});\n  recast.visit(ast, getVistor(varNames, nodes));\n  return ast;\n}\n\nlet varNameCounter = 0;\nfunction getUniqueVarName() {\n  return `$jscodeshift${varNameCounter++}$`;\n}\n\n\nmodule.exports = function withParser(parser) {\n  function statements(template/*, ...nodes*/) {\n    template = Array.from(template);\n    const nodes = Array.from(arguments).slice(1);\n    const varNames = nodes.map(() => getUniqueVarName());\n    const src = template.reduce(\n      (result, elem, i) => result + varNames[i - 1] + elem\n    );\n\n    return replaceNodes(\n      src,\n      varNames,\n      nodes,\n      parser\n    ).program.body;\n  }\n\n  function statement(/*template, ...nodes*/) {\n    return statements.apply(null, arguments)[0];\n  }\n\n  function expression(template/*, ...nodes*/) {\n    // wrap code in `(...)` to force evaluation as expression\n    template = Array.from(template);\n    if (template.length > 0) {\n      template[0] = '(' + template[0];\n      template[template.length - 1] += ')';\n    }\n\n    const expression = statement.apply(\n      null,\n      [template].concat(Array.from(arguments).slice(1))\n    ).expression;\n\n    // Remove added parens\n    if (expression.extra) {\n      expression.extra.parenthesized = false;\n    }\n\n    return expression;\n  }\n\n  function asyncExpression(template/*, ...nodes*/) {\n    template = Array.from(template);\n    if (template.length > 0) {\n      template[0] = 'async () => (' + template[0];\n      template[template.length - 1] += ')';\n    }\n\n    const expression = statement.apply(\n      null,\n      [template].concat(Array.from(arguments).slice(1))\n    ).expression.body;\n\n    // Remove added parens\n    if (expression.extra) {\n      expression.extra.parenthesized = false;\n    }\n\n    return expression;\n  }\n\n  return {statements, statement, expression, asyncExpression};\n}\n"
  },
  {
    "path": "src/testUtils.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/* global expect, describe, it */\n\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\n\nfunction applyTransform(module, options, input, testOptions = {}) {\n  // Handle ES6 modules using default export for the transform\n  const transform = module.default ? module.default : module;\n\n  // Jest resets the module registry after each test, so we need to always get\n  // a fresh copy of jscodeshift on every test run.\n  let jscodeshift = require('./core');\n  if (testOptions.parser || module.parser) {\n    jscodeshift = jscodeshift.withParser(testOptions.parser || module.parser);\n  }\n\n  const output = transform(\n    input,\n    {\n      jscodeshift,\n      j: jscodeshift,\n      stats: () => {},\n    },\n    options || {}\n  );\n\n  // Support async transforms\n  if (output instanceof Promise) {\n    return output.then(output => (output || '').trim());\n  }\n\n  return (output || '').trim();\n}\nexports.applyTransform = applyTransform;\n\nfunction runSnapshotTest(module, options, input) {\n  const output = applyTransform(module, options, input);\n  if (output instanceof Promise) {\n    return output.then(output => {\n      expect(output).toMatchSnapshot();\n      return output;\n    });\n  }\n  expect(output).toMatchSnapshot();\n  return output;\n}\nexports.runSnapshotTest = runSnapshotTest;\n\nfunction runInlineTest(module, options, input, expectedOutput, testOptions) {\n  const output = applyTransform(module, options, input, testOptions);\n  const expectation = (output => expect(output).toEqual(expectedOutput.trim()))\n  if (output instanceof Promise) {\n    return output.then(output => {\n      expectation(output);\n      return output;\n    });\n  }\n  expectation(output);\n  return output;\n}\nexports.runInlineTest = runInlineTest;\n\nfunction extensionForParser(parser) {\n  switch (parser) {\n    case 'ts':\n    case 'tsx':\n      return parser;\n    default:\n      return 'js'\n  }\n}\n\n/**\n * Utility function to run a jscodeshift script within a unit test. This makes\n * several assumptions about the environment:\n *\n * - `dirName` contains the name of the directory the test is located in. This\n *   should normally be passed via __dirname.\n * - The test should be located in a subdirectory next to the transform itself.\n *   Commonly tests are located in a directory called __tests__.\n * - `transformName` contains the filename of the transform being tested,\n *   excluding the .js extension.\n * - `testFilePrefix` optionally contains the name of the file with the test\n *   data. If not specified, it defaults to the same value as `transformName`.\n *   This will be suffixed with \".input.js\" for the input file and \".output.js\"\n *   for the expected output. For example, if set to \"foo\", we will read the\n *   \"foo.input.js\" file, pass this to the transform, and expect its output to\n *   be equal to the contents of \"foo.output.js\".\n * - Test data should be located in a directory called __testfixtures__\n *   alongside the transform and __tests__ directory.\n */\nfunction runTest(dirName, transformName, options, testFilePrefix, testOptions = {}) {\n  if (!testFilePrefix) {\n    testFilePrefix = transformName;\n  }\n\n  // Assumes transform is one level up from __tests__ directory\n  const module = require(path.join(dirName, '..', transformName));\n  const extension = extensionForParser(testOptions.parser || module.parser)\n  const fixtureDir = path.join(dirName, '..', '__testfixtures__');\n  const inputPath = path.join(fixtureDir, testFilePrefix + `.input.${extension}`);\n  const source = fs.readFileSync(inputPath, 'utf8');\n  const expectedOutput = fs.readFileSync(\n    path.join(fixtureDir, testFilePrefix + `.output.${extension}`),\n    'utf8'\n  );\n  const testResult = runInlineTest(module, options, {\n    path: inputPath,\n    source\n  }, expectedOutput, testOptions);\n\n  return testResult instanceof Promise ? testResult : undefined;\n}\nexports.runTest = runTest;\n\n/**\n * Handles some boilerplate around defining a simple jest/Jasmine test for a\n * jscodeshift transform.\n */\nfunction defineTest(dirName, transformName, options, testFilePrefix, testOptions) {\n  const testName = testFilePrefix\n    ? `transforms correctly using \"${testFilePrefix}\" data`\n    : 'transforms correctly';\n  describe(transformName, () => {\n    it(testName, () => {\n      const testResult = runTest(dirName, transformName, options, testFilePrefix, testOptions);\n      return testResult instanceof Promise ? testResult : undefined;\n    });\n  });\n}\nexports.defineTest = defineTest;\n\nfunction defineInlineTest(module, options, input, expectedOutput, testName) {\n  it(testName || 'transforms correctly', () => {\n    const testResult = runInlineTest(module, options, {\n      source: input\n    }, expectedOutput);\n    return testResult instanceof Promise ? testResult : undefined;\n  });\n}\nexports.defineInlineTest = defineInlineTest;\n\nfunction defineSnapshotTest(module, options, input, testName) {\n  it(testName || 'transforms correctly', () => {\n    const testResult = runSnapshotTest(module, options, {\n      source: input\n    });\n    return testResult instanceof Promise ? testResult : undefined;\n  });\n}\nexports.defineSnapshotTest = defineSnapshotTest;\n\n/**\n * Handles file-loading boilerplates, using same defaults as defineTest\n */\nfunction defineSnapshotTestFromFixture(dirName, module, options, testFilePrefix, testName, testOptions = {}) {\n  const extension = extensionForParser(testOptions.parser || module.parser)\n  const fixtureDir = path.join(dirName, '..', '__testfixtures__');\n  const inputPath = path.join(fixtureDir, testFilePrefix + `.input.${extension}`);\n  const source = fs.readFileSync(inputPath, 'utf8');\n  const testResult = defineSnapshotTest(module, options, source, testName)\n  return testResult instanceof Promise ? testResult : undefined;\n}\nexports.defineSnapshotTestFromFixture = defineSnapshotTestFromFixture;\n"
  },
  {
    "path": "src/utils/__tests__/intersection-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst intersection = require('../intersection');\n\nfunction test(testCases) {\n  for (const testName in testCases) {\n    const testCase = testCases[testName];\n    it(testName, function() {\n      expect(intersection(testCase.input)).toEqual(testCase.output);\n    });\n  }\n}\n\ndescribe('intersection', function() {\n  test({\n    'intersects string values': {\n      input: [['foo', 'bar', 'baz'], ['foo', 'bar'], ['bar', 'baz']],\n      output: ['bar'],\n    },\n\n    'returns empty list if no intersection': {\n      input: [['foo', 'bar', 'baz'], ['foo'], ['bar']],\n      output: [],\n    },\n  });\n});\n\n"
  },
  {
    "path": "src/utils/__tests__/once-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst once = require('../once');\n\ndescribe('once', function() {\n  it('executes the function only once', function() {\n    const mock = jest.fn().mockImplementation(foo => foo);\n    const wrapped = once(mock);\n\n    wrapped('foo');\n    const result = wrapped('bar');\n\n    expect(result).toEqual('foo');\n    expect(mock).toHaveBeenCalledTimes(1);\n  });\n});\n\n"
  },
  {
    "path": "src/utils/__tests__/union-test.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst union = require('../union');\n\nfunction test(testCases) {\n  for (const testName in testCases) {\n    const testCase = testCases[testName];\n    it(testName, function() {\n      expect(union(testCase.input)).toEqual(testCase.output);\n    });\n  }\n}\n\ndescribe('union', function() {\n  test({\n    'unions string values': {\n      input: [['foo', 'bar', 'baz'], ['foo', 'bar'], ['bar', 'baz']],\n      output: ['foo', 'bar', 'baz'],\n    },\n\n    'understands empty input arrays': {\n      input: [[], ['foo'], ['bar']],\n      output: ['foo', 'bar'],\n    },\n  });\n});\n\n"
  },
  {
    "path": "src/utils/intersection.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = function(arrays) {\n  const result = new Set(arrays[0]);\n  let resultSize = result.length;\n\n  let i, value, valuesToCheck;\n  for (i = 1; i < arrays.length; i++) {\n    valuesToCheck = new Set(arrays[i]);\n    for (value of result) {\n      if (!valuesToCheck.has(value)) {\n        result.delete(value);\n        resultSize -= 1;\n      }\n      if (resultSize === 0) {\n        return [];\n      }\n    }\n  }\n\n  return Array.from(result);\n};\n"
  },
  {
    "path": "src/utils/once.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/**\n * This replicates lodash's once functionality for our purposes.\n */\nmodule.exports = function(func) {\n  let called = false;\n  let result;\n  return function(...args) {\n    if (called) {\n      return result;\n    }\n    called = true;\n    return result = func.apply(this, args);\n  };\n};\n"
  },
  {
    "path": "src/utils/union.js",
    "content": "/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nmodule.exports = function(arrays) {\n  const result = new Set(arrays[0]);\n\n  let i,j, array;\n  for (i = 1; i < arrays.length; i++) {\n    array = arrays[i];\n    for (j = 0; j < array.length; j++) {\n      result.add(array[j]);\n    }\n  }\n\n  return Array.from(result);\n};\n"
  },
  {
    "path": "utils/requirePackage.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst path = require('path');\n\nmodule.exports = function requirePackage(name) {\n\tconst entry = require.resolve(name);\n  let dir = path.dirname(entry);\n  while (dir !== '/') {\n    try {\n      const pkg = require(path.join(dir, 'package.json'));\n      return pkg.name === name ? pkg : {};\n    } catch(error) {} // eslint-disable-line no-empty\n    dir = path.dirname(dir);\n  }\n  return {};\n}\n"
  },
  {
    "path": "utils/testUtils.js",
    "content": "\n/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nconst fs = require('fs');\nconst path = require('path');\nconst tmp = require('tmp');\n\nfunction renameFileTo(oldPath, newFilename, extension = '') {\n  const projectPath = path.dirname(oldPath);\n  const newPath = path.join(projectPath, newFilename + extension);\n  fs.mkdirSync(path.dirname(newPath), { recursive: true });\n  fs.renameSync(oldPath, newPath);\n  return newPath;\n}\n\nfunction createTempFileWith(content, filename, extension) {\n  const info = tmp.fileSync({ postfix: extension });\n  let filePath = info.name;\n  fs.writeSync(info.fd, content);\n  fs.closeSync(info.fd);\n  if (filename) {\n    filePath = renameFileTo(filePath, filename, extension);\n  }\n  return filePath;\n}\nexports.createTempFileWith = createTempFileWith;\n\n// Test transform files need a js extension to work with @babel/register\n// .ts or .tsx work as well\nfunction createTransformWith(content, ext='.js') {\n  return createTempFileWith(\n    'module.exports = function(fileInfo, api, options) { ' + content + ' }',\n    undefined,\n    ext\n  );\n}\nexports.createTransformWith = createTransformWith;\n\nfunction getFileContent(filePath) {\n  return fs.readFileSync(filePath).toString();\n}\nexports.getFileContent = getFileContent;\n"
  },
  {
    "path": "website/.astro/settings.json",
    "content": "{\n  \"_variables\": {\n    \"lastUpdateCheck\": 1719853949463\n  }\n}\n"
  },
  {
    "path": "website/.astro/types.d.ts",
    "content": "declare module 'astro:content' {\n  interface Render {\n    '.mdx': Promise<{\n      Content: import('astro').MarkdownInstance<{}>['Content'];\n      headings: import('astro').MarkdownHeading[];\n      remarkPluginFrontmatter: Record<string, any>;\n    }>;\n  }\n}\n\ndeclare module 'astro:content' {\n  interface Render {\n    '.md': Promise<{\n      Content: import('astro').MarkdownInstance<{}>['Content'];\n      headings: import('astro').MarkdownHeading[];\n      remarkPluginFrontmatter: Record<string, any>;\n    }>;\n  }\n}\n\ndeclare module 'astro:content' {\n  type Flatten<T> = T extends { [K: string]: infer U } ? U : never;\n\n  export type CollectionKey = keyof AnyEntryMap;\n  export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;\n\n  export type ContentCollectionKey = keyof ContentEntryMap;\n  export type DataCollectionKey = keyof DataEntryMap;\n\n  type AllValuesOf<T> = T extends any ? T[keyof T] : never;\n  type ValidContentEntrySlug<C extends keyof ContentEntryMap> = AllValuesOf<\n    ContentEntryMap[C]\n  >['slug'];\n\n  export function getEntryBySlug<\n    C extends keyof ContentEntryMap,\n    E extends ValidContentEntrySlug<C> | (string & {}),\n  >(\n    collection: C,\n    // Note that this has to accept a regular string too, for SSR\n    entrySlug: E\n  ): E extends ValidContentEntrySlug<C>\n    ? Promise<CollectionEntry<C>>\n    : Promise<CollectionEntry<C> | undefined>;\n\n  export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(\n    collection: C,\n    entryId: E\n  ): Promise<CollectionEntry<C>>;\n\n  export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(\n    collection: C,\n    filter?: (entry: CollectionEntry<C>) => entry is E\n  ): Promise<E[]>;\n  export function getCollection<C extends keyof AnyEntryMap>(\n    collection: C,\n    filter?: (entry: CollectionEntry<C>) => unknown\n  ): Promise<CollectionEntry<C>[]>;\n\n  export function getEntry<\n    C extends keyof ContentEntryMap,\n    E extends ValidContentEntrySlug<C> | (string & {}),\n  >(entry: {\n    collection: C;\n    slug: E;\n  }): E extends ValidContentEntrySlug<C>\n    ? Promise<CollectionEntry<C>>\n    : Promise<CollectionEntry<C> | undefined>;\n  export function getEntry<\n    C extends keyof DataEntryMap,\n    E extends keyof DataEntryMap[C] | (string & {}),\n  >(entry: {\n    collection: C;\n    id: E;\n  }): E extends keyof DataEntryMap[C]\n    ? Promise<DataEntryMap[C][E]>\n    : Promise<CollectionEntry<C> | undefined>;\n  export function getEntry<\n    C extends keyof ContentEntryMap,\n    E extends ValidContentEntrySlug<C> | (string & {}),\n  >(\n    collection: C,\n    slug: E\n  ): E extends ValidContentEntrySlug<C>\n    ? Promise<CollectionEntry<C>>\n    : Promise<CollectionEntry<C> | undefined>;\n  export function getEntry<\n    C extends keyof DataEntryMap,\n    E extends keyof DataEntryMap[C] | (string & {}),\n  >(\n    collection: C,\n    id: E\n  ): E extends keyof DataEntryMap[C]\n    ? Promise<DataEntryMap[C][E]>\n    : Promise<CollectionEntry<C> | undefined>;\n\n  /** Resolve an array of entry references from the same collection */\n  export function getEntries<C extends keyof ContentEntryMap>(\n    entries: {\n      collection: C;\n      slug: ValidContentEntrySlug<C>;\n    }[]\n  ): Promise<CollectionEntry<C>[]>;\n  export function getEntries<C extends keyof DataEntryMap>(\n    entries: {\n      collection: C;\n      id: keyof DataEntryMap[C];\n    }[]\n  ): Promise<CollectionEntry<C>[]>;\n\n  export function reference<C extends keyof AnyEntryMap>(\n    collection: C\n  ): import('astro/zod').ZodEffects<\n    import('astro/zod').ZodString,\n    C extends keyof ContentEntryMap\n      ? {\n        collection: C;\n        slug: ValidContentEntrySlug<C>;\n      }\n      : {\n        collection: C;\n        id: keyof DataEntryMap[C];\n      }\n  >;\n  // Allow generic `string` to avoid excessive type errors in the config\n  // if `dev` is not running to update as you edit.\n  // Invalid collection names will be caught at build time.\n  export function reference<C extends string>(\n    collection: C\n  ): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;\n\n  type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;\n  type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<\n    ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>\n  >;\n\n  type ContentEntryMap = {\n    \"docs\": {\n      \"build/api-reference.mdx\": {\n        id: \"build/api-reference.mdx\";\n        slug: \"build/api-reference\";\n        body: string;\n        collection: \"docs\";\n        data: InferEntrySchema<\"docs\">\n      } & { render(): Render[\".mdx\"] };\n      \"build/ast-grammar.mdx\": {\n        id: \"build/ast-grammar.mdx\";\n        slug: \"build/ast-grammar\";\n        body: string;\n        collection: \"docs\";\n        data: InferEntrySchema<\"docs\">\n      } & { render(): Render[\".mdx\"] };\n      \"index.mdx\": {\n        id: \"index.mdx\";\n        slug: \"index\";\n        body: string;\n        collection: \"docs\";\n        data: InferEntrySchema<\"docs\">\n      } & { render(): Render[\".mdx\"] };\n      \"overview/introduction.mdx\": {\n        id: \"overview/introduction.mdx\";\n        slug: \"overview/introduction\";\n        body: string;\n        collection: \"docs\";\n        data: InferEntrySchema<\"docs\">\n      } & { render(): Render[\".mdx\"] };\n      \"run/cli.mdx\": {\n        id: \"run/cli.mdx\";\n        slug: \"run/cli\";\n        body: string;\n        collection: \"docs\";\n        data: InferEntrySchema<\"docs\">\n      } & { render(): Render[\".mdx\"] };\n    };\n\n  };\n\n  type DataEntryMap = {};\n\n  type AnyEntryMap = ContentEntryMap & DataEntryMap;\n\n  export type ContentConfig = typeof import(\"../src/content/config.js\");\n}\n"
  },
  {
    "path": "website/README.md",
    "content": "# jscodeshift docs\n\n[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build)\n\n## 🚀 Project Structure\n\n```\n.\n├── public/\n├── src/\n│   ├── assets/\n│   ├── content/\n│   │   ├── docs/\n│   │   └── config.ts\n│   └── env.d.ts\n├── astro.config.mjs\n├── package.json\n└── tsconfig.json\n```\n\nStarlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on\nits file name.\n\nImages can be added to `src/assets/` and embedded in Markdown with a relative link.\n\nStatic assets, like favicons, can be placed in the `public/` directory.\n\n## 🧞 Commands\n\nAll commands are run from the root of the project, from a terminal:\n\n| Command                | Action                                           |\n|:-----------------------|:-------------------------------------------------|\n| `yarn install`         | Installs dependencies                            |\n| `yarn dev`             | Starts local dev server at `localhost:4321`      |\n| `yarn build`           | Build your production site to `./dist/`          |\n| `yarn preview`         | Preview your build locally, before deploying     |\n| `yarn astro ...`       | Run CLI commands like `astro add`, `astro check` |\n| `yarn astro -- --help` | Get help using the Astro CLI                     |\n\n## 👀 Want to learn more?\n\nCheck out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build),\nor jump into the [Astro Discord server](https://astro.build/chat).\n"
  },
  {
    "path": "website/astro.config.mjs",
    "content": "import {defineConfig} from 'astro/config';\nimport starlight from '@astrojs/starlight';\n\n// https://astro.build/config\nexport default defineConfig({\n  integrations: [\n    starlight({\n      title: 'jscodeshift',\n      social: {\n        github: 'https://github.com/facebook/jscodeshift',\n      },\n      sidebar: [\n        {\n          label: 'Overview',\n          items: [\n            // Each item here is one entry in the navigation menu.\n            {label: 'Introduction', link: '/overview/introduction/'},\n          ],\n        },\n        {\n          label: 'Building',\n          items: [\n            {label: 'API Reference', link: '/build/api-reference/'},\n            {label: 'AST Grammar', link: '/build/ast-grammar/'},\n          ],\n        },\n        {\n          label: 'Running',\n          items: [\n            {label: 'CLI', link: '/run/cli/'},\n          ],\n        },\n      ],\n    }),\n  ],\n});\n"
  },
  {
    "path": "website/package.json",
    "content": "{\n  \"name\": \"docs\",\n  \"type\": \"module\",\n  \"version\": \"0.0.1\",\n  \"scripts\": {\n    \"dev\": \"astro dev\",\n    \"start\": \"astro dev\",\n    \"build\": \"astro build\",\n    \"preview\": \"astro preview\",\n    \"astro\": \"astro\"\n  },\n  \"dependencies\": {\n    \"@astrojs/starlight\": \"^0.24.4\",\n    \"astro\": \"^4.16.18\",\n    \"sharp\": \"^0.32.5\"\n  }\n}"
  },
  {
    "path": "website/src/content/config.ts",
    "content": "import {defineCollection} from 'astro:content';\nimport {docsSchema} from '@astrojs/starlight/schema';\n\nexport const collections = {\n  docs: defineCollection({schema: docsSchema()}),\n};\n"
  },
  {
    "path": "website/src/content/docs/build/api-reference.mdx",
    "content": "---\ntitle: API Reference\n---\n\nimport {Steps, LinkCard, Card, CardGrid} from '@astrojs/starlight/components';\n\n`jscodeshift` has around 25 APIs to help developers easily detect and transform any JS/TS code.\n\nGenerally, creating a codemod involves two main tasks: **detection** and **transformation**.\n\n<Steps>\n  1. **Detection**\n\n      Detecting a specific pattern in a large codebase can be expensive, so this task is often divided into two passes.\n\n      <Steps>\n        1. **First pass**\n\n            In the first pass, we perform an initial scope reduction of the AST nodes to significantly reduce the search space and produce a collection of AST nodes to process.\n        2. **Second pass**\n\n            In the second pass, we process and filter the nodes collection to pinpoint the specific AST nodes that need transformation.\n      </Steps>\n\n  2. **Transformation**\n\n      Once we detect the desired nodes, we transform the AST and produce the modified code.\n</Steps>\n\nFor jscodeshift, we have a set of APIs for each part of the codemod process (initial traversal, filtering, transformation), as detailed below. jscodeshift accepts `—parser` as argument. We can select from the list of parser that are currently supported, all those parsers should be compatible with `estree` spec and have same AST grammar. It's important to know the AST grammar for describing the nodes in the codemod.\n\nRefer to the [`jscodeshift` node types](/build/ast-grammar/).\n\n## Building jscodeshift codemods\n\n<CardGrid>\n  <LinkCard title=\"Core API\" href=\"#core-api\"/>\n  <LinkCard title=\"Node Traversal APIs\" href=\"#node-traversal-apis\"/>\n  <LinkCard title=\"Node Transformation APIs\" href=\"#node-transformation-apis\"/>\n</CardGrid>\n\n## Core API\n\n### **`jscodeshift`**\n\nThe main function that returns the jscodeshift instance.\n\n**Parameters**: `source` (String): The source code to be transformed.\n\n**Example**:\n\n```jsx\nconst jscodeshift = require('jscodeshift');\nconst sourceCode = `const a = 1;`;\nconst j = jscodeshift(sourceCode);\n```\n\n## Node Traversal APIs\n\nBelow are APIs that often used in the **initial scope reduction** phase ([source](https://github.com/facebook/jscodeshift/blob/4851fc8a01036868efb4cf9676f3e97836097376/src/collections/Node.js#L139)). The input is usually the whole file, and the output is a collection of nodes.\n\n### **`find`**\n\nFinds nodes that match the provided type.\n\n**Parameters**: `type` (String or Function): The type of nodes to find.\n\n**Example**:\n\n```jsx\nconst variableDeclarations = j.find(j.VariableDeclaration);\n```\n\n### **`findImportDeclarations`**\n\nFinds all ImportDeclarations optionally filtered by name.\n\n**Parameters**: `sourcePath` (String).\n\n**Example**:\n\n```jsx\nconst routerImports = j.findImportDeclarations('react-router-dom');\n\n```\n\n### **`closestScope`**\n\nFinds the closest enclosing scope of a node. Useful for determining the scope context of variables and functions.\n\n**Example**:\n\n```jsx\nconst closestScopes = j.find(j.Identifier).closestScope();\n```\n\n### **`closest`**\n\nFinds the nearest parent node that matches the specified type. The child node must be obtained from a previous function call, such as find.\n\n**Parameters**:`type` (String or Function): The type of ancestor to find.\n\n```jsx\nconst closestFunction = j.find(j.Identifier).closest(j.FunctionDeclaration);\n```\n\n### **`getVariableDeclarators`**\n\nRetrieves variable declarators from the current collection. If the callback function returns a falsy value, the element is not included in the result.\n\n**Parameters**:`callback` (Function): A function that returns the name of the variable to find.\n\n**Example**:\n\n```jsx\nconst variableDeclarators = j.find(j.Identifier).getVariableDeclarators(path => path.value.name);\n```\n\n### **`findVariableDeclarators` ([source](https://github.com/facebook/jscodeshift/blob/main/src/collections/VariableDeclarator.js))**\n\nFinds variable declarators by name.\n\n**Parameters**: `name` (String): The name of the variable to find.\n\n**Example**:\n\n```jsx\nconst variableDeclarators = j.findVariableDeclarators('a');\n```\n\nBelow are the APIs that are often used in the second phase, which is the **detailed node filtering** ([source](https://github.com/facebook/jscodeshift/blob/4851fc8a01036868efb4cf9676f3e97836097376/src/Collection.js)). The input of this phase is usually a collection of nodes, and the output, is specific nodes to transform.\n\n### **`filter`**\n\nFilters nodes based on a predicate function.\n\n**Parameters**: `predicate` (Function): A function to test each element.\n\n**Example**:\n\n```jsx\nconst constDeclarations = j.find(j.VariableDeclaration)\n  .filter(path => path.node.kind === 'const');\n```\n\n### **`forEach`**\n\nIterates over each node in the collection.\n\n**Parameters**: `callback` (Function): A function to call for each node.\n\n**Example**:\n\n```jsx\nj.find(j.VariableDeclaration).forEach(path => {\n  console.log(path.node);\n});\n```\n\n### `some`\n\n`some` checks if at least one element in the collection passes the test implemented by the provided function.\n\n**Parameters:** `callback`: A function that tests each element. The callback function takes three arguments:\n\n- `path`: The current element being processed.\n- `index`: The index of the current element.\n- `array`: The array `some` was called upon.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1; const b = 2; const c = 3;`);\n\nconst hasVariableA = root.find(j.VariableDeclarator).some(path => path.node.id.name === 'a');\nconsole.log(hasVariableA); // true\n\n```\n\n### `every`\n\n`every` checks if all elements in the collection pass the test implemented by the provided function.\n\n**Parameters:** `callback`: A function that tests each element. The callback function takes three arguments:\n\n- `path`: The current element being processed.\n- `index`: The index of the current element.\n- `array`: The array `every` was called upon.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1; const b = 2; const c = 3;`);\n\nconst allAreConst = root.find(j.VariableDeclaration).every(path => path.node.kind === 'const');\nconsole.log(allAreConst); // true\n\n```\n\n### **`map`**\n\nMaps each node in the collection to a new value.\n\n**Parameters**:`callback` (Function): A function to call for each node.\n\n**Example**:\n\n```jsx\nconst variableNames = j.find(j.VariableDeclaration)\n  .map(path => path.node.declarations.map(decl => decl.id.name));\n```\n\n### **`size`**\n\nReturns the number of nodes in the collection.\n\n**Example**:\n\n```jsx\nconst numberOfNodes = j.find(j.VariableDeclaration).size();\n```\n\n### `length`\n\n`length` returns the number of elements in the collection.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1; const b = 2; const c = 3;`);\n\nconst varCount = root.find(j.VariableDeclarator).length;\nconsole.log(varCount); // 3\n\n```\n\n### **`nodes`**\n\nReturns the AST nodes in the collection.\n\n**Example**:\n\n```jsx\nconst nodes = j.find(j.VariableDeclaration).nodes();\n```\n\n### **`paths`**\n\nReturns the paths of the found nodes.\n\n**Example**:\n\n```jsx\nconst paths = j.find(j.VariableDeclaration).paths();\n```\n\n### `getAST`\n\n`getAST` returns the root AST node of the collection.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1;`);\n\nconst ast = root.getAST();\nconsole.log(ast.type); // File\n\n```\n\n### **`get`**\n\nGets the first node in the collection.\n\n**Example**:\n\n```jsx\nconst firstVariableDeclaration = j.find(j.VariableDeclaration).get();\n```\n\n### **`at`**\n\nNavigates to a specific path in the AST.\n\n**Parameters**: `index` (Number): The index of the path to navigate to.\n\n**Example**:\n\n```jsx\nconst secondVariableDeclaration = j.find(j.VariableDeclaration).at(1);\n```\n\n### `getTypes`\n\n`getTypes` returns the set of node types present in the collection.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1; const b = 2;`);\n\nconst types = root.find(j.VariableDeclarator).getTypes();\nconsole.log(types); // Set { 'VariableDeclarator' }\n\n```\n\n### `isOfType`\n\n`isOfType` checks if the node in the collection is of a specific type.\n\n**Parameters:** `type`: The type to check against.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1;`);\n\nconst isVariableDeclarator = root.find(j.VariableDeclarator).at(0).isOfType('VariableDeclarator');\nconsole.log(isVariableDeclarator); // true\n\n```\n\n## Node Transformation APIs\n\nBelow are the APIs used in node transformations. ([source](https://github.com/facebook/jscodeshift/blob/4851fc8a01036868efb4cf9676f3e97836097376/src/collections/Node.js#L139))\n\n### **`replaceWith`**\n\nReplaces the current node(s) with a new node.\n\n**Parameters**: `newNode` (Node or Function): The new node or a function that returns a new node.\n\n**Example**:\n\n```jsx\nj.find(j.Identifier)\n  .replaceWith(path => j.identifier(path.node.name.toUpperCase()));\n```\n\n### **`insertBefore`**\n\nInserts a node before the current node.\n\n**Parameters**: `newNode` (Node): The node to insert.\n\n**Example**:\n\n```jsx\nj.find(j.FunctionDeclaration)\n  .insertBefore(j.expressionStatement(j.stringLiteral('Inserted before')));\n```\n\n### **`insertAfter`**\n\nInserts a node after the current node.\n\n**Parameters**: `newNode` (Node): The node to insert.\n\n**Example**:\n\n```jsx\nj.find(j.FunctionDeclaration)\n  .insertAfter(j.expressionStatement(j.stringLiteral('Inserted after')));\n```\n\n### **`remove`**\n\nRemoves the current node(s).\n\n**Example**:\n\n```jsx\nj.find(j.VariableDeclaration).remove();\n```\n\n### `renameTo` ([source](https://github.com/facebook/jscodeshift/blob/main/src/collections/VariableDeclarator.js))\n\n`renameTo` renames the nodes in the collection to a new name.\n\n**Parameters:** `newName`: The new name to rename to.\n\n**Example:**\n\n```jsx\nconst j = require('jscodeshift');\n\nconst root = j(`const a = 1; const b = 2;`);\n\nroot.find(j.Identifier, { name: 'a' }).renameTo('x');\n\nconsole.log(root.toSource()); // const x = 1; const b = 2;\n\n```\n\nThese descriptions and examples should give you a clear understanding of how to use each of these jscodeshift APIs.\n\n### **`toSource`**\n\nConverts the transformed AST back to source code.\n\n**Parameters**: `options` (Object): Optional formatting options.\n\n**Example**:\n\n```jsx\nconst transformedSource = j.toSource({ quote: 'single' });\n```\n"
  },
  {
    "path": "website/src/content/docs/build/ast-grammar.mdx",
    "content": "---\ntitle: AST Grammar\n---\n\njscodeshift provides 278 node types which are mapped to their corresponding node type in `ast-types`. This is a comprehensive list of each node type used in `jscodeshift`.\n\nFor an easier approach to identifying the AST node type in a piece of code, please refer to [AST Explorer](https://astexplorer.net/).\n\n\n\n### AnyTypeAnnotation\nA type annotation representing any type.\n\n```typescript\nexport interface AnyTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"AnyTypeAnnotation\";\n}\n```\n\n### ArrayExpression\nRepresents an array literal.\n\n```typescript\nexport interface ArrayExpression extends Omit<Expression, \"type\"> {\n    type: \"ArrayExpression\";\n    elements: (K.ExpressionKind | K.SpreadElementKind | K.RestElementKind | null)[];\n}\n```\n\n### ArrayPattern\nA pattern that matches an array from a destructuring assignment.\n\n```typescript\nexport interface ArrayPattern extends Omit<Pattern, \"type\"> {\n    type: \"ArrayPattern\";\n    elements: (K.PatternKind | K.SpreadElementKind | null)[];\n}\n```\n\n### ArrayTypeAnnotation\nA type annotation for arrays.\n\n```typescript\nexport interface ArrayTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"ArrayTypeAnnotation\";\n    elementType: K.FlowTypeKind;\n}\n```\n\n### ArrowFunctionExpression\nAn arrow function expression.\n\n```typescript\nexport interface ArrowFunctionExpression extends Omit<Function, \"type\" | \"id\" | \"body\" | \"generator\">, Omit<Expression, \"type\"> {\n    type: \"ArrowFunctionExpression\";\n    id?: null;\n    body: K.BlockStatementKind | K.ExpressionKind;\n    generator?: false;\n}\n```\n\n### AssignmentExpression\nRepresents an assignment expression.\n\n```typescript\nexport interface AssignmentExpression extends Omit<Expression, \"type\"> {\n    type: \"AssignmentExpression\";\n    operator: \"=\" | \"+=\" | \"-=\" | \"*=\" | \"/=\" | \"%=\" | \"<<=\" | \">>=\" | \">>>=\" | \"|=\" | \"^=\" | \"&=\" | \"**=\" | \"||=\" | \"&&=\" | \"??=\";\n    left: K.PatternKind | K.MemberExpressionKind;\n    right: K.ExpressionKind;\n}\n```\n\n### AssignmentPattern\nA pattern that matches an assignment from a destructuring assignment.\n\n```typescript\nexport interface AssignmentPattern extends Omit<Pattern, \"type\"> {\n    type: \"AssignmentPattern\";\n    left: K.PatternKind;\n    right: K.ExpressionKind;\n}\n```\n\n### AwaitExpression\nRepresents an await expression.\n\n```typescript\nexport interface AwaitExpression extends Omit<Expression, \"type\"> {\n    type: \"AwaitExpression\";\n    argument: K.ExpressionKind | null;\n    all?: boolean;\n}\n```\n\n### BigIntLiteral\nA literal representing a big integer.\n\n```typescript\nexport interface BigIntLiteral extends Omit<Literal, \"type\" | \"value\"> {\n    type: \"BigIntLiteral\";\n    value: string | number;\n    extra?: {\n        rawValue: string;\n        raw: string;\n    };\n}\n```\n\n### BigIntLiteralTypeAnnotation\nA type annotation for big integer literals.\n\n```typescript\nexport interface BigIntLiteralTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"BigIntLiteralTypeAnnotation\";\n    value: null;\n    raw: string;\n}\n```\n\n### BigIntTypeAnnotation\nA type annotation for big integers.\n\n```typescript\nexport interface BigIntTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"BigIntTypeAnnotation\";\n}\n```\n\n### BinaryExpression\nRepresents a binary expression.\n\n```typescript\nexport interface BinaryExpression extends Omit<Expression, \"type\"> {\n    type: \"BinaryExpression\";\n    operator: \"==\" | \"!=\" | \"===\" | \"!==\" | \"<\" | \"<=\" | \">\" | \">=\" | \"<<\" | \">>\" | \">>>\" | \"+\" | \"-\" | \"*\" | \"/\" | \"%\" | \"&\" | \"|\" | \"^\" | \"in\" | \"instanceof\" | \"**\";\n    left: K.ExpressionKind;\n    right: K.ExpressionKind;\n}\n```\n\n### BindExpression\nRepresents a bind expression.\n\n```typescript\nexport interface BindExpression extends Omit<Expression, \"type\"> {\n    type: \"BindExpression\";\n    object: K.ExpressionKind | null;\n    callee: K.ExpressionKind;\n}\n```\n\n### Block\nA comment block.\n\n```typescript\nexport interface Block extends Comment {\n    type: \"Block\";\n}\n```\n\n### BlockStatement\nRepresents a block statement.\n\n```typescript\nexport interface BlockStatement extends Omit<Statement, \"type\"> {\n    type: \"BlockStatement\";\n    body: K.StatementKind[];\n    directives?: K.DirectiveKind[];\n}\n```\n\n### BooleanLiteral\nA literal representing a boolean value.\n\n```typescript\nexport interface BooleanLiteral extends Omit<Literal, \"type\" | \"value\"> {\n    type: \"BooleanLiteral\";\n    value: boolean;\n}\n```\n\n### BooleanLiteralTypeAnnotation\nA type annotation for boolean literals.\n\n```typescript\nexport interface BooleanLiteralTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"BooleanLiteralTypeAnnotation\";\n    value: boolean;\n    raw: string;\n}\n```\n\n### BooleanTypeAnnotation\nA type annotation for boolean values.\n\n```typescript\nexport interface BooleanTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"BooleanTypeAnnotation\";\n}\n```\n\n### BreakStatement\nRepresents a break statement.\n\n```typescript\nexport interface BreakStatement extends Omit<Statement, \"type\"> {\n    type: \"BreakStatement\";\n    label?: K.IdentifierKind | null;\n}\n```\n\n### CallExpression\nRepresents a call expression.\n\n```typescript\nexport interface CallExpression extends Omit<Expression, \"type\">, Omit<ChainElement, \"type\"> {\n    type: \"CallExpression\";\n    callee: K.ExpressionKind;\n    arguments: (K.ExpressionKind | K.SpreadElementKind)[];\n    typeArguments?: null | K.TypeParameterInstantiationKind;\n}\n```\n\n### CatchClause\nRepresents a catch clause in a try statement.\n\n```typescript\nexport interface CatchClause extends Omit<Node, \"type\"> {\n    type: \"CatchClause\";\n    param?: K.PatternKind | null;\n    guard?: K.ExpressionKind | null;\n    body: K.BlockStatementKind;\n}\n```\n\n### ChainElement\nAn element of a chain expression.\n\n```typescript\nexport interface ChainElement extends Node {\n    optional?: boolean;\n}\n```\n\n### ChainExpression\nRepresents a chain expression.\n\n```typescript\nexport interface ChainExpression extends Omit<Expression, \"type\"> {\n    type: \"ChainExpression\";\n    expression: K.ChainElementKind;\n}\n```\n\n### ClassBody\nRepresents the body of a class, which contains method definitions.\n\n```typescript\nexport interface ClassBody extends Omit<Declaration, \"type\"> {\n    type: \"ClassBody\";\n    body: (K.MethodDefinitionKind | K.VariableDeclaratorKind | K.ClassPropertyDefinitionKind | K.ClassPropertyKind | K.ClassPrivatePropertyKind | K.ClassAccessorPropertyKind | K.ClassMethodKind | K.ClassPrivateMethodKind | K.StaticBlockKind | K.TSDeclareMethodKind | K.TSCallSignatureDeclarationKind | K.TSConstructSignatureDeclarationKind | K.TSIndexSignatureKind | K.TSMethodSignatureKind | K.TSPropertySignatureKind)[];\n}\n```\n\n### ClassDeclaration\nRepresents a class declaration.\n\n```typescript\nexport interface ClassDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"ClassDeclaration\";\n    id: K.IdentifierKind | null;\n    body: K.ClassBodyKind;\n    superClass?: K.ExpressionKind | null;\n    typeParameters?: K.TypeParameterDeclarationKind | K.TSTypeParameterDeclarationKind | null;\n    superTypeParameters?: K.TypeParameterInstantiationKind | K.TSTypeParameterInstantiationKind | null;\n    implements?: K.ClassImplementsKind[] | K.TSExpressionWithTypeArgumentsKind[];\n}\n```\n\n### ClassExpression\nRepresents a class expression.\n\n```typescript\nexport interface ClassExpression extends Omit<Expression, \"type\"> {\n    type: \"ClassExpression\";\n    id?: K.IdentifierKind | null;\n    body: K.ClassBodyKind;\n    superClass?: K.ExpressionKind | null;\n    typeParameters?: K.TypeParameterDeclarationKind | K.TSTypeParameterDeclarationKind | null;\n    superTypeParameters?: K.TypeParameterInstantiationKind | K.TSTypeParameterInstantiationKind | null;\n    implements?: K.ClassImplementsKind[] | K.TSExpressionWithTypeArgumentsKind[];\n}\n```\n\n### ClassImplements\nRepresents an implementation of a class.\n\n```typescript\nexport interface ClassImplements extends Omit<Node, \"type\"> {\n    type: \"ClassImplements\";\n    id: K.IdentifierKind;\n    superClass?: K.ExpressionKind | null;\n    typeParameters?: K.TypeParameterInstantiationKind | null;\n}\n```\n\n### ClassMethod\nRepresents a method of a class.\n\n```typescript\nexport interface ClassMethod extends Omit<Declaration, \"type\">, Omit<Function, \"type\" | \"body\"> {\n    type: \"ClassMethod\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    kind?: \"get\" | \"set\" | \"method\" | \"constructor\";\n    body: K.BlockStatementKind;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    computed?: boolean;\n    static?: boolean;\n    abstract?: boolean;\n    accessibility?: \"public\" | \"private\" | \"protected\" | null;\n    decorators?: K.DecoratorKind[] | null;\n    definite?: boolean;\n    optional?: boolean;\n    override?: boolean;\n    readonly?: boolean;\n}\n```\n\n### ClassPrivateMethod\nRepresents a\n\n private method of a class.\n\n```typescript\nexport interface ClassPrivateMethod extends Omit<Declaration, \"type\">, Omit<Function, \"type\" | \"body\"> {\n    type: \"ClassPrivateMethod\";\n    key: K.PrivateNameKind;\n    body: K.BlockStatementKind;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    computed?: boolean;\n    static?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n}\n```\n\n### ClassPrivateProperty\nRepresents a private property of a class.\n\n```typescript\nexport interface ClassPrivateProperty extends Omit<Declaration, \"type\"> {\n    type: \"ClassPrivateProperty\";\n    key: K.PrivateNameKind;\n    value?: K.ExpressionKind | null;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    computed?: boolean;\n    static?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n    optional?: boolean;\n    override?: boolean;\n    readonly?: boolean;\n    variance?: K.VarianceKind | \"plus\" | \"minus\" | null;\n    definite?: boolean;\n}\n```\n\n### ClassProperty\nRepresents a property of a class.\n\n```typescript\nexport interface ClassProperty extends Omit<Declaration, \"type\"> {\n    type: \"ClassProperty\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    value?: K.ExpressionKind | null;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    computed?: boolean;\n    static?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n    optional?: boolean;\n    override?: boolean;\n    readonly?: boolean;\n    variance?: K.VarianceKind | \"plus\" | \"minus\" | null;\n    definite?: boolean;\n}\n```\n\n### ClassPropertyDefinition\nRepresents a property definition in a class.\n\n```typescript\nexport interface ClassPropertyDefinition extends Omit<Declaration, \"type\"> {\n    type: \"ClassPropertyDefinition\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    value?: K.ExpressionKind | null;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    computed?: boolean;\n    static?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n    optional?: boolean;\n    override?: boolean;\n    readonly?: boolean;\n    variance?: K.VarianceKind | \"plus\" | \"minus\" | null;\n    definite?: boolean;\n}\n```\n\n### Comment\nRepresents a comment in the code.\n\n```typescript\nexport interface Comment extends Printable {\n    type: \"Comment\";\n    value: string;\n}\n```\n\n### CommentBlock\nRepresents a block comment.\n\n```typescript\nexport interface CommentBlock extends Comment {\n    type: \"Block\";\n}\n```\n\n### CommentLine\nRepresents a line comment.\n\n```typescript\nexport interface CommentLine extends Comment {\n    type: \"Line\";\n}\n```\n\n### ComprehensionBlock\nRepresents a comprehension block.\n\n```typescript\nexport interface ComprehensionBlock extends Omit<Node, \"type\"> {\n    type: \"ComprehensionBlock\";\n    left: K.PatternKind;\n    right: K.ExpressionKind;\n    each: boolean;\n}\n```\n\n### ComprehensionExpression\nRepresents a comprehension expression.\n\n```typescript\nexport interface ComprehensionExpression extends Omit<Expression, \"type\"> {\n    type: \"ComprehensionExpression\";\n    body: K.ExpressionKind;\n    blocks: K.ComprehensionBlockKind[];\n    filter?: K.ExpressionKind | null;\n}\n```\n\n### ConditionalExpression\nRepresents a conditional expression (ternary).\n\n```typescript\nexport interface ConditionalExpression extends Omit<Expression, \"type\"> {\n    type: \"ConditionalExpression\";\n    test: K.ExpressionKind;\n    consequent: K.ExpressionKind;\n    alternate: K.ExpressionKind;\n}\n```\n\n### ContinueStatement\nRepresents a continue statement.\n\n```typescript\nexport interface ContinueStatement extends Omit<Statement, \"type\"> {\n    type: \"ContinueStatement\";\n    label?: K.IdentifierKind | null;\n}\n```\n\n### DebuggerStatement\nRepresents a debugger statement.\n\n```typescript\nexport interface DebuggerStatement extends Omit<Statement, \"type\"> {\n    type: \"DebuggerStatement\";\n}\n```\n\n### Declaration\nRepresents a declaration in the code.\n\n```typescript\nexport interface Declaration extends Statement {\n    type: \"Declaration\";\n}\n```\n\n### DeclareClass\nRepresents a Flow type declaration for a class.\n\n```typescript\nexport interface DeclareClass extends Omit<Declaration, \"type\"> {\n    type: \"DeclareClass\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    extends: K.InterfaceExtendsKind[];\n    body: K.ObjectTypeAnnotationKind;\n    mixins?: K.InterfaceExtendsKind[] | null;\n    implements?: K.ClassImplementsKind[] | K.TSExpressionWithTypeArgumentsKind[];\n}\n```\n\n### DeclaredPredicate\nRepresents a declared predicate in Flow.\n\n```typescript\nexport interface DeclaredPredicate extends Omit<FlowPredicate, \"type\"> {\n    type: \"DeclaredPredicate\";\n    value: K.ExpressionKind;\n}\n```\n\n### DeclareExportAllDeclaration\nRepresents a Flow type declaration for exporting everything.\n\n```typescript\nexport interface DeclareExportAllDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"DeclareExportAllDeclaration\";\n    source?: K.LiteralKind | null;\n}\n```\n\n### DeclareExportDeclaration\nRepresents a Flow type declaration for exporting.\n\n```typescript\nexport interface DeclareExportDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"DeclareExportDeclaration\";\n    default: boolean;\n    declaration?: K.DeclarationKind | K.ExpressionKind | null;\n    specifiers?: K.ExportSpecifierKind[] | null;\n    source?: K.LiteralKind | null;\n}\n```\n\n### DeclareFunction\nRepresents a Flow type declaration for a function.\n\n```typescript\nexport interface DeclareFunction extends Omit<Declaration, \"type\"> {\n    type: \"DeclareFunction\";\n    id: K.IdentifierKind;\n}\n```\n\n### DeclareInterface\nRepresents a Flow type declaration for an interface.\n\n```typescript\nexport interface DeclareInterface extends Omit<Declaration, \"type\"> {\n    type: \"DeclareInterface\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    extends: K.InterfaceExtendsKind[];\n    body: K.ObjectTypeAnnotationKind;\n}\n```\n\n### DeclareModule\nRepresents a Flow type declaration for a module.\n\n```typescript\nexport interface DeclareModule extends Omit<Declaration, \"type\"> {\n    type: \"DeclareModule\";\n    id: K.StringLiteralKind | K.IdentifierKind;\n    body: K.BlockStatementKind;\n    kind?: \"commonjs\" | \"es\" | null;\n}\n```\n\n### DeclareModuleExports\nRepresents a Flow type declaration for module exports.\n\n```typescript\nexport interface DeclareModuleExports extends Omit<Declaration, \"type\"> {\n    type: \"DeclareModuleExports\";\n    typeAnnotation: K.TypeAnnotationKind;\n}\n```\n\n### DeclareOpaqueType\nRepresents a Flow type declaration for an opaque type.\n\n```typescript\nexport interface DeclareOpaqueType extends Omit<Declaration, \"type\"> {\n    type: \"DeclareOpaqueType\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    impltype: K.FlowTypeKind;\n    supertype?: K.FlowTypeKind | null;\n}\n```\n\n### DeclareTypeAlias\nRepresents a Flow type declaration for a type alias.\n\n```typescript\nexport interface DeclareTypeAlias extends Omit<Declaration, \"type\"> {\n    type: \"DeclareTypeAlias\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    right: K.FlowTypeKind;\n}\n```\n\n### DeclareVariable\nRepresents a Flow type declaration for a variable.\n\n```typescript\nexport interface DeclareVariable extends Omit<Declaration, \"type\"> {\n    type: \"DeclareVariable\";\n    id: K.IdentifierKind;\n}\n```\n\n### Decorator\nRepresents a decorator.\n\n```typescript\nexport interface Decorator extends Omit<Node, \"type\"> {\n    type: \"Decorator\";\n    expression: K.ExpressionKind;\n}\n```\n\n### Directive\nRepresents a directive in a function or a script.\n\n```typescript\nexport interface Directive extends Node {\n    type: \"Directive\";\n    value: K.DirectiveLiteralKind;\n}\n```\n\n### DirectiveLiteral\nRepresents the value of a directive.\n\n```typescript\nexport interface DirectiveLiteral extends Omit<Literal, \"type\"> {\n    type: \"DirectiveLiteral\";\n    value: string;\n}\n```\n\n### DoExpression\nRepresents a do expression.\n\n```typescript\nexport interface DoExpression extends Omit<Expression, \"type\"> {\n    type: \"DoExpression\";\n    body: K.BlockStatementKind;\n}\n```\n\n### DoWhileStatement\nRepresents a do...while statement.\n\n```typescript\nexport interface DoWhileStatement extends Omit<Statement, \"type\"> {\n    type: \"DoWhileStatement\";\n    test: K.ExpressionKind;\n    body: K.StatementKind;\n}\n```\n\n### EmptyStatement\nRepresents an empty statement.\n\n```typescript\nexport interface EmptyStatement extends Omit<Statement, \"type\"> {\n    type: \"EmptyStatement\";\n}\n```\n\n### EmptyTypeAnnotation\nA type annotation for an empty type.\n\n```typescript\nexport interface EmptyTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"EmptyTypeAnnotation\";\n}\n```\n\n### EnumBooleanBody\nRepresents the body of a boolean enum.\n\n```typescript\nexport interface EnumBooleanBody extends Omit<Node, \"type\"> {\n    type: \"EnumBooleanBody\";\n    members: K.EnumBooleanMemberKind[];\n    explicitType?: boolean;\n    hasUnknownMembers?: boolean\n\n;\n}\n```\n\n### EnumBooleanMember\nRepresents a member of a boolean enum.\n\n```typescript\nexport interface EnumBooleanMember extends Omit<Node, \"type\"> {\n    type: \"EnumBooleanMember\";\n    id: K.IdentifierKind;\n    init: K.BooleanLiteralKind;\n}\n```\n\n### EnumDeclaration\nRepresents an enum declaration.\n\n```typescript\nexport interface EnumDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"EnumDeclaration\";\n    id: K.IdentifierKind;\n    body: K.EnumBooleanBodyKind | K.EnumNumberBodyKind | K.EnumStringBodyKind | K.EnumSymbolBodyKind;\n}\n```\n\n### EnumDefaultedMember\nRepresents a defaulted member of an enum.\n\n```typescript\nexport interface EnumDefaultedMember extends Omit<Node, \"type\"> {\n    type: \"EnumDefaultedMember\";\n    id: K.IdentifierKind;\n}\n```\n\n### EnumNumberBody\nRepresents the body of a number enum.\n\n```typescript\nexport interface EnumNumberBody extends Omit<Node, \"type\"> {\n    type: \"EnumNumberBody\";\n    members: K.EnumNumberMemberKind[];\n    explicitType?: boolean;\n    hasUnknownMembers?: boolean;\n}\n```\n\n### EnumNumberMember\nRepresents a member of a number enum.\n\n```typescript\nexport interface EnumNumberMember extends Omit<Node, \"type\"> {\n    type: \"EnumNumberMember\";\n    id: K.IdentifierKind;\n    init: K.NumericLiteralKind;\n}\n```\n\n### EnumStringBody\nRepresents the body of a string enum.\n\n```typescript\nexport interface EnumStringBody extends Omit<Node, \"type\"> {\n    type: \"EnumStringBody\";\n    members: K.EnumStringMemberKind[];\n    explicitType?: boolean;\n    hasUnknownMembers?: boolean;\n}\n```\n\n### EnumStringMember\nRepresents a member of a string enum.\n\n```typescript\nexport interface EnumStringMember extends Omit<Node, \"type\"> {\n    type: \"EnumStringMember\";\n    id: K.IdentifierKind;\n    init?: K.StringLiteralKind;\n}\n```\n\n### EnumSymbolBody\nRepresents the body of a symbol enum.\n\n```typescript\nexport interface EnumSymbolBody extends Omit<Node, \"type\"> {\n    type: \"EnumSymbolBody\";\n    members: K.EnumDefaultedMemberKind[];\n    hasUnknownMembers?: boolean;\n}\n```\n\n### ExistentialTypeParam\nRepresents an existential type parameter in Flow.\n\n```typescript\nexport interface ExistentialTypeParam extends Omit<FlowType, \"type\"> {\n    type: \"ExistentialTypeParam\";\n}\n```\n\n### ExistsTypeAnnotation\nA type annotation for an existential type.\n\n```typescript\nexport interface ExistsTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"ExistsTypeAnnotation\";\n}\n```\n\n### ExportAllDeclaration\nRepresents an export all declaration.\n\n```typescript\nexport interface ExportAllDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"ExportAllDeclaration\";\n    source: K.LiteralKind;\n    exportKind?: \"type\" | \"value\" | null;\n}\n```\n\n### ExportBatchSpecifier\nRepresents a batch export specifier.\n\n```typescript\nexport interface ExportBatchSpecifier extends Omit<Node, \"type\"> {\n    type: \"ExportBatchSpecifier\";\n}\n```\n\n### ExportDeclaration\nRepresents an export declaration.\n\n```typescript\nexport interface ExportDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"ExportDeclaration\";\n    default: boolean;\n    declaration?: K.DeclarationKind | K.ExpressionKind | null;\n    specifiers?: K.ExportSpecifierKind[] | null;\n    source?: K.LiteralKind | null;\n}\n```\n\n### ExportDefaultDeclaration\nRepresents an export default declaration.\n\n```typescript\nexport interface ExportDefaultDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"ExportDefaultDeclaration\";\n    declaration: K.DeclarationKind | K.ExpressionKind;\n}\n```\n\n### ExportDefaultSpecifier\nRepresents an export default specifier.\n\n```typescript\nexport interface ExportDefaultSpecifier extends Omit<Node, \"type\"> {\n    type: \"ExportDefaultSpecifier\";\n    exported: K.IdentifierKind;\n}\n```\n\n### ExportNamedDeclaration\nRepresents a named export declaration.\n\n```typescript\nexport interface ExportNamedDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"ExportNamedDeclaration\";\n    declaration?: K.DeclarationKind | null;\n    specifiers: K.ExportSpecifierKind[];\n    source?: K.LiteralKind | null;\n    exportKind?: \"type\" | \"value\" | null;\n}\n```\n\n### ExportNamespaceSpecifier\nRepresents an export namespace specifier.\n\n```typescript\nexport interface ExportNamespaceSpecifier extends Omit<Node, \"type\"> {\n    type: \"ExportNamespaceSpecifier\";\n    exported: K.IdentifierKind;\n}\n```\n\n### ExportSpecifier\nRepresents an export specifier.\n\n```typescript\nexport interface ExportSpecifier extends Omit<Node, \"type\"> {\n    type: \"ExportSpecifier\";\n    exported: K.IdentifierKind;\n    local: K.IdentifierKind;\n}\n```\n\n### Expression\nRepresents an expression in the code.\n\n```typescript\nexport interface Expression extends Node {\n    type: \"Expression\";\n}\n```\n\n### ExpressionStatement\nRepresents an expression statement.\n\n```typescript\nexport interface ExpressionStatement extends Omit<Statement, \"type\"> {\n    type: \"ExpressionStatement\";\n    expression: K.ExpressionKind;\n    directive?: string;\n}\n```\n\n### File\nRepresents a file in the AST.\n\n```typescript\nexport interface File extends Omit<Node, \"type\"> {\n    type: \"File\";\n    program: K.ProgramKind;\n    comments?: K.CommentKind[] | null;\n    tokens?: any[] | null;\n}\n```\n\n### Flow\nRepresents a Flow type.\n\n```typescript\nexport interface Flow extends Node {\n    type: \"Flow\";\n}\n```\n\n### FlowPredicate\nRepresents a Flow predicate.\n\n```typescript\nexport interface FlowPredicate extends Omit<Flow, \"type\"> {\n    type: \"FlowPredicate\";\n}\n```\n\n### FlowType\nRepresents a Flow type.\n\n```typescript\nexport interface FlowType extends Flow {\n    type: \"FlowType\";\n}\n```\n\n### ForAwaitStatement\nRepresents a for-await statement.\n\n```typescript\nexport interface ForAwaitStatement extends Omit<Statement, \"type\"> {\n    type: \"ForAwaitStatement\";\n    left: K.VariableDeclarationKind | K.ExpressionKind;\n    right: K.ExpressionKind;\n    body: K.StatementKind;\n}\n```\n\n### ForInStatement\nRepresents a for-in statement.\n\n```typescript\nexport interface ForInStatement extends Omit<Statement, \"type\"> {\n    type: \"ForInStatement\";\n    left: K.VariableDeclarationKind | K.ExpressionKind;\n    right: K.ExpressionKind;\n    body: K.StatementKind;\n}\n```\n\n### ForOfStatement\nRepresents a for-of statement.\n\n```typescript\nexport interface ForOfStatement extends Omit<Statement, \"type\"> {\n    type: \"ForOfStatement\";\n    left: K.VariableDeclarationKind | K.ExpressionKind;\n    right: K.ExpressionKind;\n    body: K.StatementKind;\n}\n```\n\n### ForStatement\nRepresents a for statement.\n\n```typescript\nexport interface ForStatement extends Omit<Statement, \"type\"> {\n    type: \"ForStatement\";\n    init?: K.VariableDeclarationKind | K.ExpressionKind | null;\n    test?: K.ExpressionKind | null;\n    update?: K.ExpressionKind | null;\n    body: K.StatementKind;\n}\n```\n\n### Function\nRepresents a function in the code.\n\n```typescript\nexport interface Function extends Node {\n    type: \"Function\";\n    id?: K.IdentifierKind | null;\n    params: (K.PatternKind | K.TSParameterPropertyKind)[];\n    body: K.BlockStatementKind;\n    generator?: boolean;\n    async?: boolean;\n    expression?: boolean;\n    returnType?: K.TypeAnnotationKind | K.TSTypeAnnotationKind | K.NoopKind | null;\n    typeParameters?: K.TypeParameterDeclarationKind | K.TSTypeParameterDeclarationKind | null;\n}\n```\n\n### FunctionDeclaration\nRepresents a function declaration.\n\n```typescript\nexport interface FunctionDeclaration extends Omit<Function, \"type\">, Omit<Declaration, \"type\"> {\n    type: \"FunctionDeclaration\";\n    body: K.BlockStatementKind;\n    declare?: boolean;\n}\n```\n\n### FunctionExpression\nRepresents a function expression.\n\n```typescript\nexport interface FunctionExpression extends Omit<Function, \"type\">, Omit<Expression, \"type\"> {\n    type: \"FunctionExpression\";\n}\n```\n\n### FunctionTypeAnnotation\nA type annotation for a function.\n\n```typescript\nexport interface FunctionTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"FunctionTypeAnnotation\";\n    params: K.FunctionTypeParamKind[];\n    returnType: K.FlowTypeKind;\n    rest?: K.FunctionTypeParamKind | null;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n}\n```\n\n### FunctionTypeParam\nRepresents a parameter in a function type annotation.\n\n```typescript\nexport interface FunctionTypeParam extends Omit<Node, \"type\"> {\n    type: \"FunctionTypeParam\";\n    name: K.IdentifierKind | null;\n    typeAnnotation: K.FlowTypeKind;\n    optional?: boolean;\n}\n```\n\n### GeneratorExpression\nRepresents a generator expression.\n\n```typescript\nexport interface GeneratorExpression extends Omit<Expression, \"type\"> {\n    type: \"GeneratorExpression\";\n}\n```\n\n### GenericTypeAnnotation\nA type annotation for a generic type.\n\n```typescript\nexport interface GenericTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"GenericTypeAnnotation\";\n    id: K.IdentifierKind | K.QualifiedTypeIdentifierKind;\n    typeParameters?: K.TypeParameterInstantiationKind | null;\n}\n```\n\n### Identifier\nRepresents an identifier.\n\n```typescript\nexport interface Identifier extends Omit<Expression\n\n, \"type\">, Omit<Pattern, \"type\"> {\n    type: \"Identifier\";\n    name: string;\n    optional?: boolean;\n    typeAnnotation?: K.TypeAnnotationKind | K.TSTypeAnnotationKind | null;\n    decorators?: K.DecoratorKind[] | null;\n}\n```\n\n### IfStatement\nRepresents an if statement.\n\n```typescript\nexport interface IfStatement extends Omit<Statement, \"type\"> {\n    type: \"IfStatement\";\n    test: K.ExpressionKind;\n    consequent: K.StatementKind;\n    alternate?: K.StatementKind | null;\n}\n```\n\n### Import\nRepresents an import expression.\n\n```typescript\nexport interface Import extends Omit<Expression, \"type\"> {\n    type: \"Import\";\n}\n```\n\n### ImportDeclaration\nRepresents an import declaration.\n\n```typescript\nexport interface ImportDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"ImportDeclaration\";\n    specifiers: (K.ImportSpecifierKind | K.ImportNamespaceSpecifierKind | K.ImportDefaultSpecifierKind)[];\n    source: K.LiteralKind;\n    importKind?: \"type\" | \"typeof\" | \"value\" | null;\n}\n```\n\n### ImportDefaultSpecifier\nRepresents a default import specifier.\n\n```typescript\nexport interface ImportDefaultSpecifier extends Omit<Node, \"type\"> {\n    type: \"ImportDefaultSpecifier\";\n    local: K.IdentifierKind;\n}\n```\n\n### ImportExpression\nRepresents an import expression.\n\n```typescript\nexport interface ImportExpression extends Omit<Expression, \"type\"> {\n    type: \"ImportExpression\";\n    source: K.LiteralKind;\n}\n```\n\n### ImportNamespaceSpecifier\nRepresents a namespace import specifier.\n\n```typescript\nexport interface ImportNamespaceSpecifier extends Omit<Node, \"type\"> {\n    type: \"ImportNamespaceSpecifier\";\n    local: K.IdentifierKind;\n}\n```\n\n### ImportSpecifier\nRepresents an import specifier.\n\n```typescript\nexport interface ImportSpecifier extends Omit<Node, \"type\"> {\n    type: \"ImportSpecifier\";\n    local: K.IdentifierKind;\n    imported: K.IdentifierKind;\n    importKind?: \"type\" | \"typeof\" | \"value\" | null;\n}\n```\n\n### InferredPredicate\nRepresents an inferred predicate in Flow.\n\n```typescript\nexport interface InferredPredicate extends Omit<FlowPredicate, \"type\"> {\n    type: \"InferredPredicate\";\n}\n```\n\n### InterfaceDeclaration\nRepresents an interface declaration.\n\n```typescript\nexport interface InterfaceDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"InterfaceDeclaration\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    extends: K.InterfaceExtendsKind[];\n    body: K.ObjectTypeAnnotationKind;\n}\n```\n\n### InterfaceExtends\nRepresents an extension of an interface.\n\n```typescript\nexport interface InterfaceExtends extends Omit<Node, \"type\"> {\n    type: \"InterfaceExtends\";\n    id: K.IdentifierKind | K.QualifiedTypeIdentifierKind;\n    typeParameters?: K.TypeParameterInstantiationKind | null;\n}\n```\n\n### InterfaceTypeAnnotation\nA type annotation for an interface.\n\n```typescript\nexport interface InterfaceTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"InterfaceTypeAnnotation\";\n    body: K.ObjectTypeAnnotationKind;\n    extends?: K.InterfaceExtendsKind[] | null;\n}\n```\n\n### InterpreterDirective\nRepresents an interpreter directive at the top of a script.\n\n```typescript\nexport interface InterpreterDirective extends Omit<Literal, \"type\"> {\n    type: \"InterpreterDirective\";\n    value: string;\n}\n```\n\n### IntersectionTypeAnnotation\nA type annotation for an intersection type.\n\n```typescript\nexport interface IntersectionTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"IntersectionTypeAnnotation\";\n    types: K.FlowTypeKind[];\n}\n```\n\n### JSXAttribute\nRepresents an attribute in a JSX element.\n\n```typescript\nexport interface JSXAttribute extends Omit<Node, \"type\"> {\n    type: \"JSXAttribute\";\n    name: K.JSXIdentifierKind | K.JSXNamespacedNameKind;\n    value?: K.LiteralKind | K.JSXExpressionContainerKind | null;\n}\n```\n\n### JSXClosingElement\nRepresents a closing element in JSX.\n\n```typescript\nexport interface JSXClosingElement extends Omit<Node, \"type\"> {\n    type: \"JSXClosingElement\";\n    name: K.JSXIdentifierKind | K.JSXMemberExpressionKind | K.JSXNamespacedNameKind;\n}\n```\n\n### JSXClosingFragment\nRepresents a closing fragment in JSX.\n\n```typescript\nexport interface JSXClosingFragment extends Omit<Node, \"type\"> {\n    type: \"JSXClosingFragment\";\n}\n```\n\n### JSXElement\nRepresents a JSX element.\n\n```typescript\nexport interface JSXElement extends Omit<Expression, \"type\"> {\n    type: \"JSXElement\";\n    openingElement: K.JSXOpeningElementKind;\n    closingElement?: K.JSXClosingElementKind | null;\n    children: K.JSXElementKind[];\n    selfClosing?: boolean;\n}\n```\n\n### JSXEmptyExpression\nRepresents an empty expression in JSX.\n\n```typescript\nexport interface JSXEmptyExpression extends Omit<Expression, \"type\"> {\n    type: \"JSXEmptyExpression\";\n}\n```\n\n### JSXExpressionContainer\nRepresents an expression container in JSX.\n\n```typescript\nexport interface JSXExpressionContainer extends Omit<Expression, \"type\"> {\n    type: \"JSXExpressionContainer\";\n    expression: K.ExpressionKind | K.JSXEmptyExpressionKind;\n}\n```\n\n### JSXFragment\nRepresents a JSX fragment.\n\n```typescript\nexport interface JSXFragment extends Omit<Expression, \"type\"> {\n    type: \"JSXFragment\";\n    openingFragment: K.JSXOpeningFragmentKind;\n    closingFragment: K.JSXClosingFragmentKind;\n    children: K.JSXElementKind[];\n}\n```\n\n### JSXIdentifier\nRepresents an identifier in JSX.\n\n```typescript\nexport interface JSXIdentifier extends Omit<Node, \"type\"> {\n    type: \"JSXIdentifier\";\n    name: string;\n}\n```\n\n### JSXMemberExpression\nRepresents a member expression in JSX.\n\n```typescript\nexport interface JSXMemberExpression extends Omit<Expression, \"type\"> {\n    type: \"JSXMemberExpression\";\n    object: K.JSXIdentifierKind | K.JSXMemberExpressionKind;\n    property: K.JSXIdentifierKind;\n}\n```\n\n### JSXNamespacedName\nRepresents a namespaced name in JSX.\n\n```typescript\nexport interface JSXNamespacedName extends Omit<Expression, \"type\"> {\n    type: \"JSXNamespacedName\";\n    namespace: K.JSXIdentifierKind;\n    name: K.JSXIdentifierKind;\n}\n```\n\n### JSXOpeningElement\nRepresents an opening element in JSX.\n\n```typescript\nexport interface JSXOpeningElement extends Omit<Node, \"type\"> {\n    type: \"JSXOpeningElement\";\n    name: K.JSXIdentifierKind | K.JSXMemberExpressionKind | K.JSXNamespacedNameKind;\n    attributes: (K.JSXAttributeKind | K.JSXSpreadAttributeKind)[];\n    selfClosing: boolean;\n}\n```\n\n### JSXOpeningFragment\nRepresents an opening fragment in JSX.\n\n```typescript\nexport interface JSXOpeningFragment extends Omit<Node, \"type\"> {\n    type: \"JSXOpeningFragment\";\n}\n```\n\n### JSXSpreadAttribute\nRepresents a spread attribute in JSX.\n\n```typescript\nexport interface JSXSpreadAttribute extends Omit<Node, \"type\"> {\n    type: \"JSXSpreadAttribute\";\n    argument: K.ExpressionKind;\n}\n```\n\n### JSXSpreadChild\nRepresents a spread child in JSX.\n\n```typescript\nexport interface JSXSpreadChild extends Omit<Expression, \"type\"> {\n    type: \"JSXSpreadChild\";\n    expression: K.ExpressionKind;\n}\n```\n\n### JSXText\nRepresents text in JSX.\n\n```typescript\nexport interface JSXText extends Omit<Literal, \"type\"> {\n    type: \"JSXText\";\n    value: string;\n    raw: string;\n}\n```\n\n### LabeledStatement\nRepresents a labeled statement.\n\n```typescript\nexport interface LabeledStatement extends Omit<Statement, \"type\"> {\n    type: \"LabeledStatement\";\n    label: K.IdentifierKind;\n    body: K.StatementKind;\n}\n```\n\n### Line\nRepresents a line comment.\n\n```typescript\nexport interface Line extends Comment {\n    type: \"Line\";\n}\n```\n\n### Literal\nRepresents a literal value.\n\n```typescript\nexport interface Literal extends Expression, Pattern {\n    type: \"Literal\";\n    value: boolean | number | string | RegExp | null;\n    regex?: { pattern: string; flags: string };\n    raw?: string;\n    bigint?: string;\n}\n```\n\n### LogicalExpression\nRepresents a logical expression.\n\n```typescript\nexport interface LogicalExpression extends Omit<Expression, \"type\"> {\n    type: \"LogicalExpression\";\n    operator: \"||\" | \"&&\" | \"??\";\n    left: K.ExpressionKind;\n    right: K.ExpressionKind;\n}\n```\n\n### MemberExpression\nRepresents a member expression.\n\n```typescript\nexport interface MemberExpression extends Omit<Expression, \"type\">, Omit<ChainElement, \"type\"> {\n    type: \"MemberExpression\";\n    object: K.ExpressionKind | K.SuperKind;\n    property: K.IdentifierKind | K.ExpressionKind;\n    computed: boolean;\n}\n```\n\n### MemberTypeAnnotation\nA type annotation for a member type.\n\n```typescript\nexport interface MemberTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"MemberTypeAnnotation\";\n    object: K.IdentifierKind;\n    property: K.IdentifierKind;\n}\n```\n\n### MetaProperty\nRepresents a meta property.\n\n```typescript\nexport interface MetaProperty extends Omit<Expression, \"type\n\n\"> {\n    type: \"MetaProperty\";\n    meta: K.IdentifierKind;\n    property: K.IdentifierKind;\n}\n```\n\n### MethodDefinition\nRepresents a method definition.\n\n```typescript\nexport interface MethodDefinition extends Omit<Declaration, \"type\"> {\n    type: \"MethodDefinition\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    value: K.FunctionExpressionKind;\n    kind?: \"get\" | \"set\" | \"method\" | \"constructor\";\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    computed?: boolean;\n    static?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n}\n```\n\n### MixedTypeAnnotation\nA type annotation for a mixed type.\n\n```typescript\nexport interface MixedTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"MixedTypeAnnotation\";\n}\n```\n\n### ModuleSpecifier\nRepresents a module specifier.\n\n```typescript\nexport interface ModuleSpecifier extends Node {\n    type: \"ModuleSpecifier\";\n}\n```\n\n### NewExpression\nRepresents a new expression.\n\n```typescript\nexport interface NewExpression extends Omit<Expression, \"type\"> {\n    type: \"NewExpression\";\n    callee: K.ExpressionKind;\n    arguments: (K.ExpressionKind | K.SpreadElementKind)[];\n    typeArguments?: null | K.TypeParameterInstantiationKind;\n}\n```\n\n### Node\nRepresents a generic AST node.\n\n```typescript\nexport interface Node {\n    type: string;\n    loc?: K.SourceLocationKind | null;\n    comments?: (K.CommentBlockKind | K.CommentLineKind)[] | null;\n}\n```\n\n### Noop\nRepresents a no-op (no operation) statement.\n\n```typescript\nexport interface Noop extends Omit<Statement, \"type\"> {\n    type: \"Noop\";\n}\n```\n\n### NullableTypeAnnotation\nA type annotation for a nullable type.\n\n```typescript\nexport interface NullableTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"NullableTypeAnnotation\";\n    typeAnnotation: K.FlowTypeKind;\n}\n```\n\n### NullLiteral\nRepresents a null literal.\n\n```typescript\nexport interface NullLiteral extends Omit<Literal, \"type\" | \"value\"> {\n    type: \"NullLiteral\";\n    value: null;\n}\n```\n\n### NullLiteralTypeAnnotation\nA type annotation for null literals.\n\n```typescript\nexport interface NullLiteralTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"NullLiteralTypeAnnotation\";\n    value: null;\n    raw: string;\n}\n```\n\n### NullTypeAnnotation\nA type annotation for null types.\n\n```typescript\nexport interface NullTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"NullTypeAnnotation\";\n}\n```\n\n### NumberLiteralTypeAnnotation\nA type annotation for number literals.\n\n```typescript\nexport interface NumberLiteralTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"NumberLiteralTypeAnnotation\";\n    value: number;\n    raw: string;\n}\n```\n\n### NumberTypeAnnotation\nA type annotation for number types.\n\n```typescript\nexport interface NumberTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"NumberTypeAnnotation\";\n}\n```\n\n### NumericLiteral\nRepresents a numeric literal.\n\n```typescript\nexport interface NumericLiteral extends Omit<Literal, \"type\" | \"value\"> {\n    type: \"NumericLiteral\";\n    value: number;\n    raw?: string;\n}\n```\n\n### NumericLiteralTypeAnnotation\nA type annotation for numeric literals.\n\n```typescript\nexport interface NumericLiteralTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"NumericLiteralTypeAnnotation\";\n    value: number;\n    raw: string;\n}\n```\n\n### ObjectExpression\nRepresents an object expression.\n\n```typescript\nexport interface ObjectExpression extends Omit<Expression, \"type\"> {\n    type: \"ObjectExpression\";\n    properties: (K.PropertyKind | K.ObjectMethodKind | K.SpreadElementKind | K.RestElementKind)[];\n}\n```\n\n### ObjectMethod\nRepresents a method in an object.\n\n```typescript\nexport interface ObjectMethod extends Omit<Declaration, \"type\">, Omit<Function, \"type\" | \"body\"> {\n    type: \"ObjectMethod\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    kind?: \"method\" | \"get\" | \"set\";\n    body: K.BlockStatementKind;\n    computed?: boolean;\n    static?: boolean;\n    shorthand?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    optional?: boolean;\n    readonly?: boolean;\n    definite?: boolean;\n}\n```\n\n### ObjectPattern\nRepresents an object pattern for destructuring.\n\n```typescript\nexport interface ObjectPattern extends Omit<Pattern, \"type\"> {\n    type: \"ObjectPattern\";\n    properties: (K.PropertyKind | K.RestElementKind)[];\n    decorators?: K.DecoratorKind[] | null;\n}\n```\n\n### ObjectProperty\nRepresents a property in an object.\n\n```typescript\nexport interface ObjectProperty extends Omit<Declaration, \"type\"> {\n    type: \"ObjectProperty\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    value: K.ExpressionKind;\n    computed?: boolean;\n    shorthand?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n    access?: \"public\" | \"private\" | \"protected\" | null;\n    optional?: boolean;\n    readonly?: boolean;\n    definite?: boolean;\n}\n```\n\n### ObjectTypeAnnotation\nA type annotation for object types.\n\n```typescript\nexport interface ObjectTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"ObjectTypeAnnotation\";\n    properties: K.ObjectTypePropertyKind[];\n    indexers?: K.ObjectTypeIndexerKind[] | null;\n    callProperties?: K.ObjectTypeCallPropertyKind[] | null;\n    internalSlots?: K.ObjectTypeInternalSlotKind[] | null;\n    exact?: boolean;\n    inexact?: boolean;\n}\n```\n\n### ObjectTypeCallProperty\nRepresents a call property in an object type annotation.\n\n```typescript\nexport interface ObjectTypeCallProperty extends Omit<Node, \"type\"> {\n    type: \"ObjectTypeCallProperty\";\n    value: K.FunctionTypeAnnotationKind;\n    static?: boolean;\n}\n```\n\n### ObjectTypeIndexer\nRepresents an indexer in an object type annotation.\n\n```typescript\nexport interface ObjectTypeIndexer extends Omit<Node, \"type\"> {\n    type: \"ObjectTypeIndexer\";\n    id?: K.IdentifierKind | null;\n    key: K.FlowTypeKind;\n    value: K.FlowTypeKind;\n    variance?: K.VarianceKind | \"plus\" | \"minus\" | null;\n    static?: boolean;\n}\n```\n\n### ObjectTypeInternalSlot\nRepresents an internal slot in an object type annotation.\n\n```typescript\nexport interface ObjectTypeInternalSlot extends Omit<Node, \"type\"> {\n    type: \"ObjectTypeInternalSlot\";\n    id: K.IdentifierKind;\n    value: K.FlowTypeKind;\n    optional?: boolean;\n    static?: boolean;\n    method?: boolean;\n}\n```\n\n### ObjectTypeProperty\nRepresents a property in an object type annotation.\n\n```typescript\nexport interface ObjectTypeProperty extends Omit<Node, \"type\"> {\n    type: \"ObjectTypeProperty\";\n    key: K.LiteralKind | K.IdentifierKind;\n    value: K.FlowTypeKind;\n    optional?: boolean;\n    variance?: K.VarianceKind | \"plus\" | \"minus\" | null;\n    static?: boolean;\n}\n```\n\n### ObjectTypeSpreadProperty\nRepresents a spread property in an object type annotation.\n\n```typescript\nexport interface ObjectTypeSpreadProperty extends Omit<Node, \"type\"> {\n    type: \"ObjectTypeSpreadProperty\";\n    argument: K.FlowTypeKind;\n}\n```\n\n### OpaqueType\nRepresents an opaque type.\n\n```typescript\nexport interface OpaqueType extends Omit<Declaration, \"type\"> {\n    type: \"OpaqueType\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    impltype: K.FlowTypeKind;\n    supertype?: K.FlowTypeKind | null;\n}\n```\n\n### OptionalCallExpression\nRepresents an optional call expression.\n\n```typescript\nexport interface OptionalCallExpression extends Omit<Expression, \"type\">, Omit<ChainElement, \"type\"> {\n    type: \"OptionalCallExpression\";\n    callee: K.ExpressionKind;\n    arguments: (K.ExpressionKind | K.SpreadElementKind)[];\n    optional?: boolean;\n    typeArguments?: null | K.TypeParameterInstantiationKind;\n}\n```\n\n### OptionalMemberExpression\nRepresents an optional member expression.\n\n```typescript\nexport interface OptionalMemberExpression extends Omit<Expression, \"type\">, Omit<ChainElement, \"type\"> {\n    type: \"OptionalMemberExpression\";\n    object: K.ExpressionKind | K.SuperKind;\n    property: K.IdentifierKind | K.ExpressionKind;\n    computed?: boolean;\n    optional?: boolean;\n}\n```\n\n### ParenthesizedExpression\nRepresents a parenthesized expression.\n\n```typescript\nexport interface ParenthesizedExpression extends Omit<Expression, \"type\"> {\n    type: \"ParenthesizedExpression\";\n    expression: K.ExpressionKind;\n}\n```\n\n### Pattern\nRepresents a pattern in the code.\n\n```typescript\nexport interface Pattern extends Node {\n    type: \"Pattern\";\n}\n```\n\n### Position\nRepresents a position in the source code.\n\n```typescript\nexport interface Position extends Omit<Node, \"type\"> {\n    type: \"Position\";\n    line: number;\n    column: number;\n}\n```\n\n### Printable\nRepresents a printable node.\n\n```typescript\nexport interface\n\n Printable extends Node {\n    type: \"Printable\";\n}\n```\n\n### PrivateName\nRepresents a private name.\n\n```typescript\nexport interface PrivateName extends Omit<Expression, \"type\"> {\n    type: \"PrivateName\";\n    id: K.IdentifierKind;\n}\n```\n\n### Program\nRepresents the entire program.\n\n```typescript\nexport interface Program extends Omit<Node, \"type\"> {\n    type: \"Program\";\n    body: (K.StatementKind | K.ModuleDeclarationKind)[];\n    sourceType: \"script\" | \"module\";\n    directives?: K.DirectiveKind[] | null;\n}\n```\n\n### Property\nRepresents a property in an object.\n\n```typescript\nexport interface Property extends Omit<Declaration, \"type\"> {\n    type: \"Property\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    value: K.ExpressionKind;\n    kind?: \"init\" | \"get\" | \"set\";\n    computed?: boolean;\n    method?: boolean;\n    shorthand?: boolean;\n    decorators?: K.DecoratorKind[] | null;\n}\n```\n\n### PropertyPattern\nRepresents a pattern property in an object.\n\n```typescript\nexport interface PropertyPattern extends Omit<Pattern, \"type\"> {\n    type: \"PropertyPattern\";\n    key: K.LiteralKind | K.IdentifierKind | K.ExpressionKind;\n    pattern: K.PatternKind;\n}\n```\n\n### QualifiedTypeIdentifier\nRepresents a qualified type identifier in Flow.\n\n```typescript\nexport interface QualifiedTypeIdentifier extends Omit<FlowType, \"type\"> {\n    type: \"QualifiedTypeIdentifier\";\n    qualification: K.IdentifierKind | K.QualifiedTypeIdentifierKind;\n    id: K.IdentifierKind;\n}\n```\n\n### RegExpLiteral\nRepresents a regular expression literal.\n\n```typescript\nexport interface RegExpLiteral extends Omit<Literal, \"type\" | \"value\"> {\n    type: \"RegExpLiteral\";\n    value: RegExp;\n    regex: { pattern: string; flags: string };\n}\n```\n\n### RestElement\nRepresents a rest element in a destructuring assignment.\n\n```typescript\nexport interface RestElement extends Omit<Pattern, \"type\"> {\n    type: \"RestElement\";\n    argument: K.PatternKind;\n    decorators?: K.DecoratorKind[] | null;\n}\n```\n\n### RestProperty\nRepresents a rest property in an object pattern.\n\n```typescript\nexport interface RestProperty extends Omit<Pattern, \"type\"> {\n    type: \"RestProperty\";\n    argument: K.PatternKind;\n}\n```\n\n### ReturnStatement\nRepresents a return statement.\n\n```typescript\nexport interface ReturnStatement extends Omit<Statement, \"type\"> {\n    type: \"ReturnStatement\";\n    argument?: K.ExpressionKind | null;\n}\n```\n\n### SequenceExpression\nRepresents a sequence expression.\n\n```typescript\nexport interface SequenceExpression extends Omit<Expression, \"type\"> {\n    type: \"SequenceExpression\";\n    expressions: K.ExpressionKind[];\n}\n```\n\n### SourceLocation\nRepresents the source location of a node.\n\n```typescript\nexport interface SourceLocation extends Omit<Node, \"type\"> {\n    type: \"SourceLocation\";\n    start: K.PositionKind;\n    end: K.PositionKind;\n}\n```\n\n### Specifier\nRepresents a specifier in an import or export declaration.\n\n```typescript\nexport interface Specifier extends Node {\n    type: \"Specifier\";\n}\n```\n\n### SpreadElement\nRepresents a spread element in an array or function call.\n\n```typescript\nexport interface SpreadElement extends Omit<Expression, \"type\"> {\n    type: \"SpreadElement\";\n    argument: K.ExpressionKind;\n}\n```\n\n### SpreadElementPattern\nRepresents a spread element pattern in an array.\n\n```typescript\nexport interface SpreadElementPattern extends Omit<Pattern, \"type\"> {\n    type: \"SpreadElementPattern\";\n    argument: K.PatternKind;\n}\n```\n\n### SpreadProperty\nRepresents a spread property in an object.\n\n```typescript\nexport interface SpreadProperty extends Omit<Pattern, \"type\"> {\n    type: \"SpreadProperty\";\n    argument: K.PatternKind;\n}\n```\n\n### SpreadPropertyPattern\nRepresents a spread property pattern in an object.\n\n```typescript\nexport interface SpreadPropertyPattern extends Omit<Pattern, \"type\"> {\n    type: \"SpreadPropertyPattern\";\n    argument: K.PatternKind;\n}\n```\n\n### Statement\nRepresents a statement in the code.\n\n```typescript\nexport interface Statement extends Node {\n    type: \"Statement\";\n}\n```\n\n### StringLiteral\nRepresents a string literal.\n\n```typescript\nexport interface StringLiteral extends Omit<Literal, \"type\" | \"value\"> {\n    type: \"StringLiteral\";\n    value: string;\n    raw?: string;\n}\n```\n\n### StringLiteralTypeAnnotation\nA type annotation for string literals.\n\n```typescript\nexport interface StringLiteralTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"StringLiteralTypeAnnotation\";\n    value: string;\n    raw: string;\n}\n```\n\n### StringTypeAnnotation\nA type annotation for string types.\n\n```typescript\nexport interface StringTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"StringTypeAnnotation\";\n}\n```\n\n### Super\nRepresents the `super` keyword.\n\n```typescript\nexport interface Super extends Omit<Node, \"type\"> {\n    type: \"Super\";\n}\n```\n\n### SwitchCase\nRepresents a case in a switch statement.\n\n```typescript\nexport interface SwitchCase extends Omit<Node, \"type\"> {\n    type: \"SwitchCase\";\n    test?: K.ExpressionKind | null;\n    consequent: K.StatementKind[];\n}\n```\n\n### SwitchStatement\nRepresents a switch statement.\n\n```typescript\nexport interface SwitchStatement extends Omit<Statement, \"type\"> {\n    type: \"SwitchStatement\";\n    discriminant: K.ExpressionKind;\n    cases: K.SwitchCaseKind[];\n}\n```\n\n### SymbolTypeAnnotation\nA type annotation for symbol types.\n\n```typescript\nexport interface SymbolTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"SymbolTypeAnnotation\";\n}\n```\n\n### TaggedTemplateExpression\nRepresents a tagged template expression.\n\n```typescript\nexport interface TaggedTemplateExpression extends Omit<Expression, \"type\"> {\n    type: \"TaggedTemplateExpression\";\n    tag: K.ExpressionKind;\n    quasi: K.TemplateLiteralKind;\n}\n```\n\n### TemplateElement\nRepresents an element in a template literal.\n\n```typescript\nexport interface TemplateElement extends Omit<Node, \"type\"> {\n    type: \"TemplateElement\";\n    tail: boolean;\n    value: { cooked: string; raw: string };\n}\n```\n\n### TemplateLiteral\nRepresents a template literal.\n\n```typescript\nexport interface TemplateLiteral extends Omit<Expression, \"type\"> {\n    type: \"TemplateLiteral\";\n    quasis: K.TemplateElementKind[];\n    expressions: K.ExpressionKind[];\n}\n```\n\n### ThisExpression\nRepresents the `this` expression.\n\n```typescript\nexport interface ThisExpression extends Omit<Expression, \"type\"> {\n    type: \"ThisExpression\";\n}\n```\n\n### ThisTypeAnnotation\nA type annotation for the `this` type.\n\n```typescript\nexport interface ThisTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"ThisTypeAnnotation\";\n}\n```\n\n### ThrowStatement\nRepresents a throw statement.\n\n```typescript\nexport interface ThrowStatement extends Omit<Statement, \"type\"> {\n    type: \"ThrowStatement\";\n    argument: K.ExpressionKind;\n}\n```\n\n### TryStatement\nRepresents a try statement.\n\n```typescript\nexport interface TryStatement extends Omit<Statement, \"type\"> {\n    type: \"TryStatement\";\n    block: K.BlockStatementKind;\n    handler?: K.CatchClauseKind | null;\n    finalizer?: K.BlockStatementKind | null;\n}\n```\n\n### TSAnyKeyword\nRepresents the TypeScript `any` keyword.\n\n```typescript\nexport interface TSAnyKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSAnyKeyword\";\n}\n```\n\n### TSArrayType\nRepresents a TypeScript array type.\n\n```typescript\nexport interface TSArrayType extends Omit<TSType, \"type\"> {\n    type: \"TSArrayType\";\n    elementType: K.TSTypeKind;\n}\n```\n\n### TSAsExpression\nRepresents a TypeScript as-expression.\n\n```typescript\nexport interface TSAsExpression extends Omit<Expression, \"type\"> {\n    type: \"TSAsExpression\";\n    expression: K.ExpressionKind;\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSBigIntKeyword\nRepresents the TypeScript `bigint` keyword.\n\n```typescript\nexport interface TSBigIntKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSBigIntKeyword\";\n}\n```\n\n### TSBooleanKeyword\nRepresents the TypeScript `boolean` keyword.\n\n```typescript\nexport interface TSBooleanKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSBooleanKeyword\";\n}\n```\n\n### TSCallSignatureDeclaration\nRepresents a TypeScript call signature declaration.\n\n```typescript\nexport interface TSCallSignatureDeclaration extends Omit<TSTypeElement, \"type\"> {\n    type: \"TSCallSignatureDeclaration\";\n    parameters: (K.IdentifierKind | K.RestElementKind)[];\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n}\n```\n\n### TSConditionalType\nRepresents a TypeScript conditional type.\n\n```typescript\nexport interface TSConditionalType extends Omit<TSType, \"type\"> {\n    type: \"TSConditionalType\";\n    checkType: K.TSTypeKind;\n    extendsType: K.TSTypeKind;\n    trueType: K.TSTypeKind;\n    falseType: K.TSTypeKind;\n}\n```\n\n### TSConstructorType\nRepresents a TypeScript constructor type.\n\n```\n\ntypescript\nexport interface TSConstructorType extends Omit<TSType, \"type\"> {\n    type: \"TSConstructorType\";\n    parameters: (K.IdentifierKind | K.RestElementKind)[];\n    typeAnnotation: K.TSTypeAnnotationKind;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n}\n```\n\n### TSConstructSignatureDeclaration\nRepresents a TypeScript construct signature declaration.\n\n```typescript\nexport interface TSConstructSignatureDeclaration extends Omit<TSTypeElement, \"type\"> {\n    type: \"TSConstructSignatureDeclaration\";\n    parameters: (K.IdentifierKind | K.RestElementKind)[];\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n}\n```\n\n### TSDeclareFunction\nRepresents a TypeScript function declaration.\n\n```typescript\nexport interface TSDeclareFunction extends Omit<FunctionDeclaration, \"type\"> {\n    type: \"TSDeclareFunction\";\n}\n```\n\n### TSDeclareMethod\nRepresents a TypeScript method declaration.\n\n```typescript\nexport interface TSDeclareMethod extends Omit<FunctionDeclaration, \"type\"> {\n    type: \"TSDeclareMethod\";\n}\n```\n\n### TSEnumDeclaration\nRepresents a TypeScript enum declaration.\n\n```typescript\nexport interface TSEnumDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"TSEnumDeclaration\";\n    id: K.IdentifierKind;\n    members: K.TSEnumMemberKind[];\n    const?: boolean;\n    declare?: boolean;\n    modifiers?: K.ModifierKind[] | null;\n}\n```\n\n### TSEnumMember\nRepresents a member of a TypeScript enum.\n\n```typescript\nexport interface TSEnumMember extends Omit<Node, \"type\"> {\n    type: \"TSEnumMember\";\n    id: K.IdentifierKind | K.StringLiteralKind;\n    initializer?: K.ExpressionKind | null;\n}\n```\n\n### TSExportAssignment\nRepresents a TypeScript export assignment.\n\n```typescript\nexport interface TSExportAssignment extends Omit<Declaration, \"type\"> {\n    type: \"TSExportAssignment\";\n    expression: K.ExpressionKind;\n}\n```\n\n### TSExpressionWithTypeArguments\nRepresents a TypeScript expression with type arguments.\n\n```typescript\nexport interface TSExpressionWithTypeArguments extends Omit<TSType, \"type\"> {\n    type: \"TSExpressionWithTypeArguments\";\n    expression: K.IdentifierKind | K.TSQualifiedNameKind;\n    typeParameters?: K.TSTypeParameterInstantiationKind | null;\n}\n```\n\n### TSExternalModuleReference\nRepresents a TypeScript external module reference.\n\n```typescript\nexport interface TSExternalModuleReference extends Omit<Declaration, \"type\"> {\n    type: \"TSExternalModuleReference\";\n    expression: K.StringLiteralKind;\n}\n```\n\n### TSFunctionType\nRepresents a TypeScript function type.\n\n```typescript\nexport interface TSFunctionType extends Omit<TSType, \"type\"> {\n    type: \"TSFunctionType\";\n    parameters: (K.IdentifierKind | K.RestElementKind)[];\n    typeAnnotation: K.TSTypeAnnotationKind;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n}\n```\n\n### TSHasOptionalTypeAnnotation\nRepresents an optional type annotation in TypeScript.\n\n```typescript\nexport interface TSHasOptionalTypeAnnotation extends Omit<TSType, \"type\"> {\n    type: \"TSHasOptionalTypeAnnotation\";\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n}\n```\n\n### TSHasOptionalTypeParameterInstantiation\nRepresents an optional type parameter instantiation in TypeScript.\n\n```typescript\nexport interface TSHasOptionalTypeParameterInstantiation extends Omit<TSType, \"type\"> {\n    type: \"TSHasOptionalTypeParameterInstantiation\";\n    typeParameters?: K.TSTypeParameterInstantiationKind | null;\n}\n```\n\n### TSHasOptionalTypeParameters\nRepresents optional type parameters in TypeScript.\n\n```typescript\nexport interface TSHasOptionalTypeParameters extends Omit<TSType, \"type\"> {\n    type: \"TSHasOptionalTypeParameters\";\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n}\n```\n\n### TSImportEqualsDeclaration\nRepresents a TypeScript import equals declaration.\n\n```typescript\nexport interface TSImportEqualsDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"TSImportEqualsDeclaration\";\n    id: K.IdentifierKind;\n    moduleReference: K.IdentifierKind | K.TSQualifiedNameKind | K.TSExternalModuleReferenceKind;\n    isExport?: boolean;\n}\n```\n\n### TSImportType\nRepresents a TypeScript import type.\n\n```typescript\nexport interface TSImportType extends Omit<TSType, \"type\"> {\n    type: \"TSImportType\";\n    argument: K.StringLiteralKind;\n    qualifier?: K.IdentifierKind | K.TSQualifiedNameKind | null;\n    typeParameters?: K.TSTypeParameterInstantiationKind | null;\n}\n```\n\n### TSIndexedAccessType\nRepresents a TypeScript indexed access type.\n\n```typescript\nexport interface TSIndexedAccessType extends Omit<TSType, \"type\"> {\n    type: \"TSIndexedAccessType\";\n    objectType: K.TSTypeKind;\n    indexType: K.TSTypeKind;\n}\n```\n\n### TSIndexSignature\nRepresents a TypeScript index signature.\n\n```typescript\nexport interface TSIndexSignature extends Omit<Declaration, \"type\"> {\n    type: \"TSIndexSignature\";\n    parameters: (K.IdentifierKind | K.RestElementKind)[];\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n    readonly?: boolean;\n    static?: boolean;\n    declare?: boolean;\n    optional?: boolean;\n    accessibility?: \"public\" | \"private\" | \"protected\" | null;\n}\n```\n\n### TSInferType\nRepresents a TypeScript infer type.\n\n```typescript\nexport interface TSInferType extends Omit<TSType, \"type\"> {\n    type: \"TSInferType\";\n    typeParameter: K.TSTypeParameterKind;\n}\n```\n\n### TSInterfaceBody\nRepresents the body of a TypeScript interface.\n\n```typescript\nexport interface TSInterfaceBody extends Omit<Node, \"type\"> {\n    type: \"TSInterfaceBody\";\n    body: K.TSTypeElementKind[];\n}\n```\n\n### TSInterfaceDeclaration\nRepresents a TypeScript interface declaration.\n\n```typescript\nexport interface TSInterfaceDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"TSInterfaceDeclaration\";\n    id: K.IdentifierKind;\n    body: K.TSInterfaceBodyKind;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n    extends?: K.TSExpressionWithTypeArgumentsKind[] | null;\n    declare?: boolean;\n}\n```\n\n### TSIntersectionType\nRepresents a TypeScript intersection type.\n\n```typescript\nexport interface TSIntersectionType extends Omit<TSType, \"type\"> {\n    type: \"TSIntersectionType\";\n    types: K.TSTypeKind[];\n}\n```\n\n### TSLiteralType\nRepresents a TypeScript literal type.\n\n```typescript\nexport interface TSLiteralType extends Omit<TSType, \"type\"> {\n    type: \"TSLiteralType\";\n    literal: K.NumericLiteralKind | K.StringLiteralKind | K.BooleanLiteralKind;\n}\n```\n\n### TSMappedType\nRepresents a TypeScript mapped type.\n\n```typescript\nexport interface TSMappedType extends Omit<TSType, \"type\"> {\n    type: \"TSMappedType\";\n    typeParameter: K.TSTypeParameterKind;\n    nameType?: K.TSTypeKind | null;\n    optional?: boolean | \"+\" | \"-\";\n    readonly?: boolean | \"+\" | \"-\";\n    typeAnnotation?: K.TSTypeKind | null;\n}\n```\n\n### TSMethodSignature\nRepresents a TypeScript method signature.\n\n```typescript\nexport interface TSMethodSignature extends Omit<TSTypeElement, \"type\"> {\n    type: \"TSMethodSignature\";\n    key: K.ExpressionKind;\n    parameters: (K.IdentifierKind | K.RestElementKind)[];\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n    computed?: boolean;\n    optional?: boolean;\n}\n```\n\n### TSModuleBlock\nRepresents a TypeScript module block.\n\n```typescript\nexport interface TSModuleBlock extends Omit<Node, \"type\"> {\n    type: \"TSModuleBlock\";\n    body: K.StatementKind[];\n}\n```\n\n### TSModuleDeclaration\nRepresents a TypeScript module declaration.\n\n```typescript\nexport interface TSModuleDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"TSModuleDeclaration\";\n    id: K.IdentifierKind | K.StringLiteralKind;\n    body: K.TSModuleBlockKind | K.TSModuleDeclarationKind;\n    declare?: boolean;\n    global?: boolean;\n    modifiers?: K.ModifierKind[] | null;\n}\n```\n\n### TSNamedTupleMember\nRepresents a named tuple member in TypeScript.\n\n```typescript\nexport interface TSNamedTupleMember extends Omit<TSType, \"type\"> {\n    type: \"TSNamedTupleMember\";\n    elementType: K.TSTypeKind;\n    label: K.IdentifierKind;\n    optional?: boolean;\n}\n```\n\n### TSNamespaceExportDeclaration\nRepresents a TypeScript namespace export declaration.\n\n```typescript\nexport interface TSNamespaceExportDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"TSNamespaceExportDeclaration\";\n    id: K.IdentifierKind;\n}\n```\n\n### TSNeverKeyword\nRepresents the TypeScript `never` keyword.\n\n```typescript\nexport interface TSNeverKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSNeverKeyword\";\n}\n```\n\n### TSNonNullExpression\nRepresents a non-null assertion in TypeScript.\n\n```typescript\nexport interface TSNonNullExpression extends Omit<Expression, \"type\"> {\n    type: \"TSNonNullExpression\";\n    expression: K.ExpressionKind;\n}\n```\n\n### TSNullKeyword\nRepresents the TypeScript `null` keyword.\n\n```typescript\nexport interface\n\n TSNullKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSNullKeyword\";\n}\n```\n\n### TSNumberKeyword\nRepresents the TypeScript `number` keyword.\n\n```typescript\nexport interface TSNumberKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSNumberKeyword\";\n}\n```\n\n### TSObjectKeyword\nRepresents the TypeScript `object` keyword.\n\n```typescript\nexport interface TSObjectKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSObjectKeyword\";\n}\n```\n\n### TSOptionalType\nRepresents an optional type in TypeScript.\n\n```typescript\nexport interface TSOptionalType extends Omit<TSType, \"type\"> {\n    type: \"TSOptionalType\";\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSParameterProperty\nRepresents a parameter property in TypeScript.\n\n```typescript\nexport interface TSParameterProperty extends Omit<Pattern, \"type\"> {\n    type: \"TSParameterProperty\";\n    parameter: K.IdentifierKind | K.AssignmentPatternKind;\n    accessibility?: \"public\" | \"private\" | \"protected\" | null;\n    readonly?: boolean;\n}\n```\n\n### TSParenthesizedType\nRepresents a parenthesized type in TypeScript.\n\n```typescript\nexport interface TSParenthesizedType extends Omit<TSType, \"type\"> {\n    type: \"TSParenthesizedType\";\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSPropertySignature\nRepresents a property signature in TypeScript.\n\n```typescript\nexport interface TSPropertySignature extends Omit<TSTypeElement, \"type\"> {\n    type: \"TSPropertySignature\";\n    key: K.ExpressionKind;\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n    initializer?: K.ExpressionKind | null;\n    computed?: boolean;\n    optional?: boolean;\n    readonly?: boolean;\n}\n```\n\n### TSQualifiedName\nRepresents a qualified name in TypeScript.\n\n```typescript\nexport interface TSQualifiedName extends Omit<TSType, \"type\"> {\n    type: \"TSQualifiedName\";\n    left: K.IdentifierKind | K.TSQualifiedNameKind;\n    right: K.IdentifierKind;\n}\n```\n\n### TSRestType\nRepresents a rest type in TypeScript.\n\n```typescript\nexport interface TSRestType extends Omit<TSType, \"type\"> {\n    type: \"TSRestType\";\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSStringKeyword\nRepresents the TypeScript `string` keyword.\n\n```typescript\nexport interface TSStringKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSStringKeyword\";\n}\n```\n\n### TSSymbolKeyword\nRepresents the TypeScript `symbol` keyword.\n\n```typescript\nexport interface TSSymbolKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSSymbolKeyword\";\n}\n```\n\n### TSThisType\nRepresents the TypeScript `this` type.\n\n```typescript\nexport interface TSThisType extends Omit<TSType, \"type\"> {\n    type: \"TSThisType\";\n}\n```\n\n### TSTupleType\nRepresents a tuple type in TypeScript.\n\n```typescript\nexport interface TSTupleType extends Omit<TSType, \"type\"> {\n    type: \"TSTupleType\";\n    elementTypes: K.TSTypeKind[];\n}\n```\n\n### TSType\nRepresents a TypeScript type.\n\n```typescript\nexport interface TSType extends Node {\n    type: \"TSType\";\n}\n```\n\n### TSTypeAliasDeclaration\nRepresents a TypeScript type alias declaration.\n\n```typescript\nexport interface TSTypeAliasDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"TSTypeAliasDeclaration\";\n    id: K.IdentifierKind;\n    typeAnnotation: K.TSTypeKind;\n    typeParameters?: K.TSTypeParameterDeclarationKind | null;\n    declare?: boolean;\n}\n```\n\n### TSTypeAnnotation\nRepresents a TypeScript type annotation.\n\n```typescript\nexport interface TSTypeAnnotation extends Omit<Declaration, \"type\"> {\n    type: \"TSTypeAnnotation\";\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSTypeAssertion\nRepresents a TypeScript type assertion.\n\n```typescript\nexport interface TSTypeAssertion extends Omit<Expression, \"type\"> {\n    type: \"TSTypeAssertion\";\n    expression: K.ExpressionKind;\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSTypeLiteral\nRepresents a TypeScript type literal.\n\n```typescript\nexport interface TSTypeLiteral extends Omit<TSType, \"type\"> {\n    type: \"TSTypeLiteral\";\n    members: K.TSTypeElementKind[];\n}\n```\n\n### TSTypeOperator\nRepresents a TypeScript type operator.\n\n```typescript\nexport interface TSTypeOperator extends Omit<TSType, \"type\"> {\n    type: \"TSTypeOperator\";\n    operator: \"keyof\" | \"unique\" | \"readonly\";\n    typeAnnotation: K.TSTypeKind;\n}\n```\n\n### TSTypeParameter\nRepresents a type parameter in TypeScript.\n\n```typescript\nexport interface TSTypeParameter extends Omit<TSType, \"type\"> {\n    type: \"TSTypeParameter\";\n    name: string;\n    constraint?: K.TSTypeKind | null;\n    default?: K.TSTypeKind | null;\n}\n```\n\n### TSTypeParameterDeclaration\nRepresents a type parameter declaration in TypeScript.\n\n```typescript\nexport interface TSTypeParameterDeclaration extends Omit<TSType, \"type\"> {\n    type: \"TSTypeParameterDeclaration\";\n    params: K.TSTypeParameterKind[];\n}\n```\n\n### TSTypeParameterInstantiation\nRepresents a type parameter instantiation in TypeScript.\n\n```typescript\nexport interface TSTypeParameterInstantiation extends Omit<TSType, \"type\"> {\n    type: \"TSTypeParameterInstantiation\";\n    params: K.TSTypeKind[];\n}\n```\n\n### TSTypePredicate\nRepresents a type predicate in TypeScript.\n\n```typescript\nexport interface TSTypePredicate extends Omit<TSType, \"type\"> {\n    type: \"TSTypePredicate\";\n    asserts: boolean;\n    parameterName: K.IdentifierKind | K.TSThisTypeKind;\n    typeAnnotation?: K.TSTypeAnnotationKind | null;\n}\n```\n\n### TSTypeQuery\nRepresents a type query in TypeScript.\n\n```typescript\nexport interface TSTypeQuery extends Omit<TSType, \"type\"> {\n    type: \"TSTypeQuery\";\n    exprName: K.IdentifierKind | K.TSQualifiedNameKind;\n}\n```\n\n### TSTypeReference\nRepresents a type reference in TypeScript.\n\n```typescript\nexport interface TSTypeReference extends Omit<TSType, \"type\"> {\n    type: \"TSTypeReference\";\n    typeName: K.IdentifierKind | K.TSQualifiedNameKind;\n    typeParameters?: K.TSTypeParameterInstantiationKind | null;\n}\n```\n\n### TSUndefinedKeyword\nRepresents the TypeScript `undefined` keyword.\n\n```typescript\nexport interface TSUndefinedKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSUndefinedKeyword\";\n}\n```\n\n### TSUnionType\nRepresents a union type in TypeScript.\n\n```typescript\nexport interface TSUnionType extends Omit<TSType, \"type\"> {\n    type: \"TSUnionType\";\n    types: K.TSTypeKind[];\n}\n```\n\n### TSUnknownKeyword\nRepresents the TypeScript `unknown` keyword.\n\n```typescript\nexport interface TSUnknownKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSUnknownKeyword\";\n}\n```\n\n### TSVoidKeyword\nRepresents the TypeScript `void` keyword.\n\n```typescript\nexport interface TSVoidKeyword extends Omit<TSType, \"type\"> {\n    type: \"TSVoidKeyword\";\n}\n```\n\n### TupleTypeAnnotation\nA type annotation for a tuple type.\n\n```typescript\nexport interface TupleTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"TupleTypeAnnotation\";\n    types: K.FlowTypeKind[];\n}\n```\n\n### TypeAlias\nRepresents a type alias in Flow.\n\n```typescript\nexport interface TypeAlias extends Omit<Declaration, \"type\"> {\n    type: \"TypeAlias\";\n    id: K.IdentifierKind;\n    typeParameters?: K.TypeParameterDeclarationKind | null;\n    right: K.FlowTypeKind;\n}\n```\n\n### TypeAnnotation\nRepresents a type annotation.\n\n```typescript\nexport interface TypeAnnotation extends Omit<Node, \"type\"> {\n    type: \"TypeAnnotation\";\n    typeAnnotation: K.FlowTypeKind;\n}\n```\n\n### TypeCastExpression\nRepresents a type cast expression.\n\n```typescript\nexport interface TypeCastExpression extends Omit<Expression, \"type\"> {\n    type: \"TypeCastExpression\";\n    expression: K.ExpressionKind;\n    typeAnnotation: K.TypeAnnotationKind;\n}\n```\n\n### TypeofTypeAnnotation\nA type annotation for a `typeof` type.\n\n```typescript\nexport interface TypeofTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"TypeofTypeAnnotation\";\n    argument: K.FlowTypeKind;\n}\n```\n\n### TypeParameter\nRepresents a type parameter.\n\n```typescript\nexport interface TypeParameter extends Omit<Node, \"type\"> {\n    type: \"TypeParameter\";\n    name: string;\n    variance?: K.VarianceKind | \"plus\" | \"minus\" | null;\n    bound?: K.TypeAnnotationKind | null;\n    default?: K.FlowTypeKind | null;\n}\n```\n\n### TypeParameterDeclaration\nRepresents a type parameter declaration.\n\n```typescript\nexport interface TypeParameterDeclaration extends Omit<Node, \"type\"> {\n    type: \"TypeParameterDeclaration\";\n    params: K.TypeParameterKind[];\n}\n```\n\n### TypeParameterInstantiation\nRepresents a type parameter instantiation.\n\n```typescript\nexport interface TypeParameterInstantiation extends Omit<Node, \"type\"> {\n    type: \"TypeParameterInstantiation\";\n    params: K.FlowType\n\nKind[];\n}\n```\n\n### UnaryExpression\nRepresents a unary expression.\n\n```typescript\nexport interface UnaryExpression extends Omit<Expression, \"type\"> {\n    type: \"UnaryExpression\";\n    operator: \"-\" | \"+\" | \"!\" | \"~\" | \"typeof\" | \"void\" | \"delete\";\n    argument: K.ExpressionKind;\n    prefix: boolean;\n}\n```\n\n### UnionTypeAnnotation\nA type annotation for a union type.\n\n```typescript\nexport interface UnionTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"UnionTypeAnnotation\";\n    types: K.FlowTypeKind[];\n}\n```\n\n### UpdateExpression\nRepresents an update expression.\n\n```typescript\nexport interface UpdateExpression extends Omit<Expression, \"type\"> {\n    type: \"UpdateExpression\";\n    operator: \"++\" | \"--\";\n    argument: K.ExpressionKind;\n    prefix: boolean;\n}\n```\n\n### VariableDeclaration\nRepresents a variable declaration.\n\n```typescript\nexport interface VariableDeclaration extends Omit<Declaration, \"type\"> {\n    type: \"VariableDeclaration\";\n    declarations: K.VariableDeclaratorKind[];\n    kind: \"var\" | \"let\" | \"const\";\n}\n```\n\n### VariableDeclarator\nRepresents a variable declarator.\n\n```typescript\nexport interface VariableDeclarator extends Omit<Node, \"type\"> {\n    type: \"VariableDeclarator\";\n    id: K.PatternKind;\n    init?: K.ExpressionKind | null;\n    definite?: boolean;\n}\n```\n\n### Variance\nRepresents a variance in Flow types.\n\n```typescript\nexport interface Variance extends Omit<Node, \"type\"> {\n    type: \"Variance\";\n    kind: \"plus\" | \"minus\";\n}\n```\n\n### VoidTypeAnnotation\nA type annotation for void types.\n\n```typescript\nexport interface VoidTypeAnnotation extends Omit<FlowType, \"type\"> {\n    type: \"VoidTypeAnnotation\";\n}\n```\n\n### WhileStatement\nRepresents a while statement.\n\n```typescript\nexport interface WhileStatement extends Omit<Statement, \"type\"> {\n    type: \"WhileStatement\";\n    test: K.ExpressionKind;\n    body: K.StatementKind;\n}\n```\n\n### WithStatement\nRepresents a with statement.\n\n```typescript\nexport interface WithStatement extends Omit<Statement, \"type\"> {\n    type: \"WithStatement\";\n    object: K.ExpressionKind;\n    body: K.StatementKind;\n}\n```\n\n### YieldExpression\nRepresents a yield expression.\n\n```typescript\nexport interface YieldExpression extends Omit<Expression, \"type\"> {\n    type: \"YieldExpression\";\n    argument?: K.ExpressionKind | null;\n    delegate: boolean;\n}\n```"
  },
  {
    "path": "website/src/content/docs/index.mdx",
    "content": "---\ntitle: Docs\ndescription: Get started with building and running jscodeshift codemods.\ntemplate: doc\nhero:\n  tagline: Get started with building and running jscodeshift codemods.\n  actions:\n    - text: Get started\n      link: /overview/introduction/\n      icon: right-arrow\n      variant: primary\n    - text: GitHub\n      link: https://github.com/facebook/jscodeshift\n      icon: external\n---\n"
  },
  {
    "path": "website/src/content/docs/overview/introduction.mdx",
    "content": "---\ntitle: Introduction\n---\n\nimport { Steps, LinkCard, Card, CardGrid } from '@astrojs/starlight/components';\n\n`jscodeshift` is a toolkit for building and running codemods over multiple JavaScript or TypeScript files. It provides:\n\n- A runner, which executes the provided transform for each file passed to it. It also outputs a summary of how many files have **not** been transformed.\n- A wrapper around [recast](https://github.com/benjamn/recast), providing a different API.  Recast is an AST-to-AST transform tool and also tries to preserve the style of original code\nas much as possible.\n\n## How does jscodeshift work?\n\n<Steps>\n  1. **Parsing Code into AST**\n\n      First, jscodeshift takes your JavaScript code and converts it into an Abstract Syntax Tree (AST). An AST is a tree representation of your code where each node represents a different part of the code, like variables, functions, and expressions.\n  \n  2. **Transforming the AST**\n      \n      Using jscodeshift, you can navigate through the AST and apply transformations. For example, you can find all instances of a certain function and rename it or change its parameters.\n  \n  3. **Generating Code from AST**\n      \n      After transforming the AST, jscodeshift converts it back into JavaScript code. The result is your original code with the specified changes applied.\n</Steps>\n\n## Installation\n\nGet jscodeshift from [npm](https://www.npmjs.com/package/jscodeshift):\n\n```\n$ npm install -g jscodeshift\n```\n\nThis will install the runner as `jscodeshift`.\n\n\n## Getting started\n\n<CardGrid>\n  <LinkCard title=\"Build jscodeshift codemods\" href=\"/build/api-reference/\" />\n  <LinkCard title=\"Run jscodeshift codemods\" href=\"/run/cli/\" />\n</CardGrid>\n"
  },
  {
    "path": "website/src/content/docs/run/cli.mdx",
    "content": "---\ntitle: CLI Reference\n---\n\nimport { Aside } from '@astrojs/starlight/components';\n\nThe `jscodeshift` command-line interface (CLI) allows you to run jscodeshift codemods using a terminal or through an automated system.\n\n## Usage\n\nYou can use the `jscodeshift` command to run codemods in 4 different ways\n\n**Option 1: Run from `transform.js` file in current working directory:**\n\n```bash\njscodeshift [OPTION]... PATH...\n```\n\nThis automatically looks for a `transform.js` file in the current working directory and attempts to run the transform over the specified `PATH`.\n\n**Option 2: Run from specific transform file:**\n\n```bash\njscodeshift [OPTION]... -t TRANSFORM_PATH PATH...\n```\n\nThis allows you to specify a path to a transform file and run the transform over the specified `PATH`.\n\n**Option 3: Run from specific transform URL:**\n\n```bash\njscodeshift [OPTION]... -t URL PATH...\n```\n\nThis allows you to specify a URL to a transform file and run the transform over the specified `PATH`.\n\n**Option 4: Apply transform to standard input:**\n\n```bash\njscodeshift [OPTION]... --stdin < file_list.txt\n```\n\nUsing `--stdin` allows you to run the transform over every line of standard input provided in `file_list.txt`.\n\n\n## Options\n\n### `--(no-)babel`\n\n`default: true`\n\nThis allows you to apply babeljs to the transform file.\n\n### `--cpus=N`\n\n`aliases: -c`\n\n`default: max(all - 1, 1)`\n\nThis allows you to start at most N child processes to process source files.\n\n### `--(no-)dry`\n\n`aliases: -d`\n\n`default: false`\n\nThis allows you to dry run the codemod. Dry running is useful when you need to see how a codemod will affect your project without making changes to your files.\n\n### `--extensions=[EXT]`\n\n`default: js`\n\nAllows you to specify the extension of the files to be transformed.\n\n\n### `--help`\n\n`aliases: -h`\n\nAllows you to print the help menu.\n\n### `--ignore-config=[FILE] ...`\n\nAllows you to ignore files if they match patterns sourced from a configuration file (e.g. a .gitignore).\n\n### `--ignore-pattern=[GLOB] ...`\n\nAllows you to ignore files that match a provided glob expression.\n\n### `--(no-)gitignore`\n\n`default: false`\n\nAllows you to add entries to the current directory's .gitignore file.\n\n### `--parser=[PARSER]`\n\n`default: babel`\n\n`available options: babel|babylon|flow|ts|tsx`\n\nAllows you to specify the parser to use for parsing the source files.\n\n### `--parser-config=[FILE]`\n\nAllows you to specify path to a JSON file containing a custom parser configuration for flow or babylon.\n\n### `--(no-)print`\n\n`aliases: -p`\n\n`default: false`\n\nAllows you to print transformed files to stdout, useful for development.\n\n### `--(no-)run-in-band`\n\n`default: false`\n\nAllows `jscodeshift` to run serially in the current process.\n\n### `--(no-)silent`\n\n`aliases: -s`\n\n`default: false`\n\nAllows you to run silently (prevent writing to stdout or stderr).\n\n### `--(no-)stdin`\n\n`default: false`\n\nAllows you to run the transform over every line of standard input.\n\n### `--transform=[FILE]`\n\n`aliases: -t`\n\n`default: ./transform.js`\n\nAllows you to specify a path to the transform file. Can be either a local path or url.\n\n### `--verbose=[MODE]`\n\n`aliases: -v`\n\n`available options: 0|1|2`\n\n`default: 0`\n\nAllows you to show more information about the transform process.\n\n### `--version`\n\nAllows you to print your `jscodeshift` version.\n\n### `--fail-on-error`\n\nAllows you to return a 1 exit code when errors were found during execution of codemods.\n"
  },
  {
    "path": "website/src/env.d.ts",
    "content": "/// <reference path=\"../.astro/types.d.ts\" />\n/// <reference types=\"astro/client\" />\n"
  },
  {
    "path": "website/tsconfig.json",
    "content": "{\n  \"extends\": \"astro/tsconfigs/strict\"\n}\n"
  }
]