ronantakizawa/codereview-bench huggingface dataset:
Repository: babel/babel
File: packages/babel-traverse/src/scope/index.ts (TypeScript)

Code before:
      path.node.id &&
      (process.env.BABEL_8_BREAKING ||
        // @ts-expect-error Fixme: document symbol ast properties
        !path.node.id[NOT_LOCAL_BINDING])
    ) {
      path.scope.registerBinding("local", path.get("id"), path);
    }
  },

  TSTypeAnnotation(path) {
    path.skip();
  },
};

let scopeVisitor: ExplodedVisitor<CollectVisitorState>;

let uid = 0;

export type { Binding };

export { Scope as default };
class Scope {
  uid;

  declare path: NodePath;
  declare block: t.Pattern | t.Scopable;

  declare inited;

  declare labels: Map<string, NodePath<t.LabeledStatement>>;
  declare bindings: { [name: string]: Binding };
  /** Only defined in the program scope */
  declare referencesSet?: Set<string>;
  declare globals: { [name: string]: t.Identifier | t.JSXIdentifier };
  /** Only defined in the program scope */
  declare uidsSet?: Set<string>;
  declare data: { [key: string | symbol]: unknown };
  declare crawling: boolean;

  /**
   * This searches the current "scope" and collects all references/bindings
   * within.
   */
  constructor(path: NodePath<t.Pattern | t.Scopable>) {
    const { node } = path;
    const cached = scopeCache.get(node);
    // Sometimes, a scopable path is placed higher in the AST tree.
    // In these cases, have to create a new Scope.
    if (cached?.path === path) {
      return cached;
    }

Review comment (suggestion):
```suggestion
  path!: NodePath;
  block!: t.Pattern | t.Scopable;
```

Confer https://github.com/babel/babel/pull/17498#discussion_r2324708604

Code after:
    if (
      path.node.id &&
      (process.env.BABEL_8_BREAKING ||
        // @ts-expect-error Fixme: document symbol ast properties
        !path.node.id[NOT_LOCAL_BINDING])
    ) {
      path.scope.registerBinding("local", path.get("id"), path);
    }
  },

  TSTypeAnnotation(path) {
    path.skip();
  },
};

let scopeVisitor: ExplodedVisitor<CollectVisitorState>;

let uid = 0;

export type { Binding };

export { Scope as default };
class Scope {
  uid;

  path!: NodePath;
  block!: t.Pattern | t.Scopable;

  inited!: boolean;

  labels!: Map<string, NodePath<t.LabeledStatement>>;
  bindings!: { [name: string]: Binding };
  /** Only defined in the program scope */
  referencesSet?: Set<string>;
  globals!: { [name: string]: t.Identifier | t.JSXIdentifier };
  /** Only defined in the program scope */
  uidsSet?: Set<string>;
  data!: { [key: string | symbol]: unknown };
  crawling!: boolean;

  /**
   * This searches the current "scope" and collects all references/bindings
   * within.
   */
  constructor(path: NodePath<t.Pattern | t.Scopable>) {
    const { node } = path;
    const cached = scopeCache.get(node);
    // Sometimes, a scopable path is placed higher in the AST tree.
    // In these cases, have to create a new Scope.
    if (cached?.path === path) {
      return cached;
Repository: babel/babel
File: packages/babel-types/src/definitions/index.ts (TypeScript)

Code before:
  for (const type of types) {
    const aliases = FLIPPED_ALIAS_KEYS[type];
    if (aliases) {
      aliases.forEach(set.add, set);
    } else {
      set.add(type);
    }
  }
}

const TYPES: Array<string> = [].concat(
  Object.keys(VISITOR_KEYS),
  Object.keys(FLIPPED_ALIAS_KEYS),
  Object.keys(DEPRECATED_KEYS),
);

export {
  VISITOR_KEYS,
  ALIAS_KEYS,
  FLIPPED_ALIAS_KEYS,
  NODE_FIELDS,
  BUILDER_KEYS,
  DEPRECATED_ALIASES,
  DEPRECATED_KEYS,
  NODE_PARENT_VALIDATIONS,
  NODE_UNION_SHAPES__PRIVATE,
  PLACEHOLDERS,
  PLACEHOLDERS_ALIAS,
  PLACEHOLDERS_FLIPPED_ALIAS,
  TYPES,
};

export type { FieldOptions } from "./utils.ts";


Review comment (suggestion):
```suggestion
  NODE_UNION_SHAPES__PRIVATE as "\u{10FFFF} PRIVATE!!! NODE_UNION_SHAPES",
```
:)

(if it's meant to be private, lets make it not a valid identifier, and `\u{10FFFF}` ensures autocompletion always shows it at the end)

Code after:
  for (const type of types) {
    const aliases = FLIPPED_ALIAS_KEYS[type];
    if (aliases) {
      aliases.forEach(set.add, set);
    } else {
      set.add(type);
    }
  }
}

const TYPES: Array<string> = [].concat(
  Object.keys(VISITOR_KEYS),
  Object.keys(FLIPPED_ALIAS_KEYS),
  Object.keys(DEPRECATED_KEYS),
);

/**
 * @internal
 */
export { NODE_UNION_SHAPES__PRIVATE };

export {
  VISITOR_KEYS,
  ALIAS_KEYS,
  FLIPPED_ALIAS_KEYS,
  NODE_FIELDS,
  BUILDER_KEYS,
  DEPRECATED_ALIASES,
  DEPRECATED_KEYS,
  NODE_PARENT_VALIDATIONS,
  PLACEHOLDERS,
  PLACEHOLDERS_ALIAS,
  PLACEHOLDERS_FLIPPED_ALIAS,
  TYPES,
};

export type { FieldOptions } from "./utils.ts";
Repository: babel/babel
File: packages/babel-traverse/src/scope/index.ts (TypeScript)

Code before:

    case "JSXNamespacedName":
      gatherNodeParts(node.namespace, parts);
      gatherNodeParts(node.name, parts);
      break;
  }
}

function resetScope(scope: Scope) {
  if (!process.env.BABEL_8_BREAKING) {
    // @ts-expect-error(Babel 7 vs Babel 8)
    scope.references = Object.create(null);
    // @ts-expect-error(Babel 7 vs Babel 8)
    scope.uids = Object.create(null);
  } else if (scope.path.type === "Program") {
    scope.referencesSet = new Set();
    scope.uidsSet = new Set();
  }

  scope.bindings = Object.create(null);
  scope.globals = Object.create(null);
}

interface CollectVisitorState {
  assignments: NodePath<t.AssignmentExpression>[];
  references: NodePath<t.Identifier | t.JSXIdentifier>[];
  constantViolations: NodePath[];
}

if (!process.env.BABEL_8_BREAKING) {
  // eslint-disable-next-line no-var
  var NOT_LOCAL_BINDING = Symbol.for(
    "should not be considered a local binding",
  );
}

const collectorVisitor: Visitor<CollectVisitorState> = {
  ForStatement(path) {
    const declar = path.get("init");
    // delegate block scope handling to the `BlockScoped` method
    if (declar.isVar()) {
      const { scope } = path;
      const parentScope = scope.getFunctionParent() || scope.getProgramParent();
      parentScope.registerBinding("var", declar);
    }
  },

  Declaration(path) {
    // delegate block scope handling to the `BlockScoped` method
    if (path.isBlockScoped()) return;


Review comment (suggestion):
The predicate here also converts `NodePath<A> | NodePath<B>` to `NodePath<A | B>` such that `path.pushContainer` can work. This is a bit unfortunate as we have already made it distributive.

Code after:

    case "JSXNamespacedName":
      gatherNodeParts(node.namespace, parts);
      gatherNodeParts(node.name, parts);
      break;
  }
}

function resetScope(scope: Scope) {
  if (!process.env.BABEL_8_BREAKING) {
    // @ts-expect-error(Babel 7 vs Babel 8)
    scope.references = Object.create(null);
    // @ts-expect-error(Babel 7 vs Babel 8)
    scope.uids = Object.create(null);
  } else if (scope.path.type === "Program") {
    scope.referencesSet = new Set();
    scope.uidsSet = new Set();
  }

  scope.bindings = Object.create(null);
  scope.globals = Object.create(null);
}

function isAnonymousFunctionExpression(
  path: NodePath,
): path is NodePath<t.FunctionExpression | t.ArrowFunctionExpression> {
  return (
    (path.isFunctionExpression() && !path.node.id) ||
    path.isArrowFunctionExpression()
  );
}

interface CollectVisitorState {
  assignments: NodePath<t.AssignmentExpression>[];
  references: NodePath<t.Identifier | t.JSXIdentifier>[];
  constantViolations: NodePath[];
}

if (!process.env.BABEL_8_BREAKING) {
  // eslint-disable-next-line no-var
  var NOT_LOCAL_BINDING = Symbol.for(
    "should not be considered a local binding",
  );
}

const collectorVisitor: Visitor<CollectVisitorState> = {
  ForStatement(path) {
    const declar = path.get("init");
    // delegate block scope handling to the `BlockScoped` method
    if (declar.isVar()) {
      const { scope } = path;
Repository: babel/babel
File: packages/babel-parser/src/index.ts (TypeScript)

Code before:

      return ast;
    } catch (moduleError) {
      try {
        options.sourceType = "script";
        return getParser(options, input).parse();
      } catch {}

      throw moduleError;
    }
  } else {
    return getParser(options, input).parse();
  }
}

export function parseExpression(
  input: string,
  options?: ParserOptions,
): ParseResult<Expression> {
  const parser = getParser(options, input);
  if (parser.options.strictMode) {
    parser.state.strict = true;
  }
  return parser.getExpression() as ParseResult<Expression>;
}

function generateExportedTokenTypes(
  internalTokenTypes: InternalTokenTypes,
): Record<string, ExportedTokenType> {
  const tokenTypes: Record<string, ExportedTokenType> = {};
  for (const typeName of Object.keys(
    internalTokenTypes,
  ) as (keyof InternalTokenTypes)[]) {
    tokenTypes[typeName] = getExportedToken(internalTokenTypes[typeName]);
  }
  return tokenTypes;
}

export const tokTypes = generateExportedTokenTypes(internalTokenTypes);

function getParser(options: Options | undefined | null, input: string): Parser {
  let cls = Parser;
  const pluginsMap: PluginsMap = new Map();
  if (options?.plugins) {
    for (const plugin of options.plugins) {
      let name, opts;
      if (typeof plugin === "string") {
        name = plugin;
      } else {
        [name, opts] = plugin;
      }

Review comment (suggestion):
`ParseResult<Expression>` doesn't declare properties like `.comments` correctly, could you improve it by the way? :)

Code after:
        ast.program.sourceType = "script";
      }

      return ast;
    } catch (moduleError) {
      try {
        options.sourceType = "script";
        return getParser(options, input).parse();
      } catch {}

      throw moduleError;
    }
  } else {
    return getParser(options, input).parse();
  }
}

export function parseExpression(
  input: string,
  options?: ParserOptions,
): ParseResult<Expression> {
  const parser = getParser(options, input);
  if (parser.options.strictMode) {
    parser.state.strict = true;
  }
  return parser.getExpression() as ParseResult<Expression>;
}

function generateExportedTokenTypes(
  internalTokenTypes: InternalTokenTypes,
): Record<string, ExportedTokenType> {
  const tokenTypes: Record<string, ExportedTokenType> = {};
  for (const typeName of Object.keys(
    internalTokenTypes,
  ) as (keyof InternalTokenTypes)[]) {
    tokenTypes[typeName] = getExportedToken(internalTokenTypes[typeName]);
  }
  return tokenTypes;
}

export const tokTypes = generateExportedTokenTypes(internalTokenTypes);

function getParser(
  options: ParserOptions | undefined | null,
  input: string,
): Parser {
  let cls = Parser;
  const pluginsMap: PluginsMap = new Map();
  if (options?.plugins) {
    for (const plugin of options.plugins) {
      let name, opts;
Repository: babel/babel
File: packages/babel-traverse/src/path/context.ts (TypeScript)

Code before:

export function skip(this: NodePath) {
  this.shouldSkip = true;
}

export function skipKey(this: NodePath, key: string) {
  if (this.skipKeys == null) {
    this.skipKeys = {};
  }
  this.skipKeys[key] = true;
}

export function stop(this: NodePath) {
  // this.shouldSkip = true; this.shouldStop = true;
  this._traverseFlags |= SHOULD_SKIP | SHOULD_STOP;
}

export function setScope(this: NodePath) {
  if (!process.env.BABEL_8_BREAKING && this.opts?.noScope) return;

  let path = this.parentPath;

  if (
    // Skip method scope if is computed method key or decorator expression
    (path &&
      (this.key === "key" || this.listKey === "decorators") &&
      path.isMethod()) ||
    // Skip switch scope if for discriminant (`x` in `switch (x) {}`).
    (this.key === "discriminant" && path.isSwitchStatement())
  ) {
    path = path.parentPath;
  }

  let target;
  while (path && !target) {
    if (!process.env.BABEL_8_BREAKING && path.opts?.noScope) return;

    target = path.scope;
    path = path.parentPath;
  }

  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
  this.scope = this.getScope(target!);
  this.scope?.init();
}

export function setContext<S = unknown>(
  this: NodePath,
  context?: TraversalContext<S>,
) {
  if (this.skipKeys != null) {

Review comment (suggestion):
Could we instead do this?
```js
if (!path) {
  if (!this.isScope()) return;
} else if ( /* ... the existing if */ ) {
  path = path.parentPath;
}
```

Since if the current node is not a scope node and there is no parent, there is no way to actually define a scope.

Code after:

export function skip(this: NodePath) {
  this.shouldSkip = true;
}

export function skipKey(this: NodePath, key: string) {
  if (this.skipKeys == null) {
    this.skipKeys = {};
  }
  this.skipKeys[key] = true;
}

export function stop(this: NodePath) {
  // this.shouldSkip = true; this.shouldStop = true;
  this._traverseFlags |= SHOULD_SKIP | SHOULD_STOP;
}

export function _forceSetScope(this: NodePath) {
  let path = this.parentPath;

  if (
    // Skip method scope if is computed method key or decorator expression
    ((this.key === "key" || this.listKey === "decorators") &&
      path.isMethod()) ||
    // Skip switch scope if for discriminant (`x` in `switch (x) {}`).
    (this.key === "discriminant" && path.isSwitchStatement())
  ) {
    path = path.parentPath;
  }

  let target;
  while (path && !target) {
    target = path.scope;
    path = path.parentPath;
  }

  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
  this.scope = this.getScope(target!);
  this.scope?.init();
}

export function setScope(this: NodePath) {
  if (this.opts?.noScope) return;

  let path = this.parentPath;

  if (
    // Skip method scope if is computed method key or decorator expression
    ((this.key === "key" || this.listKey === "decorators") &&
      path.isMethod()) ||
    // Skip switch scope if for discriminant (`x` in `switch (x) {}`).
Repository: babel/babel
File: packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/object-ref-computed/output.js (JavaScript)

Code before:
expect(key).toBe(2);
expect(y).toBe(1);

// takes care of the order

key = 1;
var _$ = {
    2: {
      y: 2,
      z: 3
    },
    3: {
      y: 2,
      z: 3
    }
  },
  _key2 = ++key,
  _key3 = ++key,
  {
    [_key2]: {
      y
    },
    [_key3]: {
      z
    }
  } = _$,
  rest_y = babelHelpers.objectWithoutProperties(_$[_key2], ["y"]),
  rest_z = babelHelpers.objectWithoutProperties(_$[_key3], ["z"]);
expect(y).toBe(2);
expect(rest_y).toEqual({
  z: 3
});
expect(z).toBe(3);
expect(rest_z).toEqual({
  y: 2
});
expect(key).toBe(3);


Review comment (bug):
This change looks good to me. Could you update the `packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/object-ref-computed-exec/exec.js` such that the previous test failed on main but passed in this PR?

This test can be also merged with the `object-ref-computed` test: Just move `exec.js` within the `object-ref-computed` folder.

In general we will also sync the content of `input.js` and `exec.js`.

Code after:
expect(key).toBe(2);
expect(y).toBe(1);

// takes care of the order

key = 1;
var _$ = {
    2: {
      y: 2,
      z: 3
    },
    3: {
      y: 4,
      z: 6
    }
  },
  {
    [_key2 = ++key]: {
      y
    },
    [_key3 = ++key]: {
      z
    }
  } = _$,
  rest_y = babelHelpers.objectWithoutProperties(_$[_key2], ["y"]),
  rest_z = babelHelpers.objectWithoutProperties(_$[_key3], ["z"]);
expect(y).toBe(2);
expect(rest_y).toEqual({
  z: 3
});
expect(z).toBe(6);
expect(rest_z).toEqual({
  y: 4
});
expect(key).toBe(3);
Repository: babel/babel
File: packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/object-ref-computed/output.js (JavaScript)

Code before:
    [_key = key++]: {
      y
    }
  } = _,
  x = babelHelpers.objectWithoutProperties(_[_key], ["y"]);
expect(x).toEqual({
  a: 1
});
expect(key).toBe(2);
expect(y).toBe(1);

// takes care of the order

key = 1;
var _$ = {
    2: {
      y: 2,
      z: 3
    },
    3: {
      y: 2,
      z: 3
    }
  },
  {
    [_key2 = ++key]: {
      y
    },
    [_key3 = ++key]: {
      z
    }
  } = _$,
  rest_y = babelHelpers.objectWithoutProperties(_$[_key2], ["y"]),
  rest_z = babelHelpers.objectWithoutProperties(_$[_key3], ["z"]);
expect(y).toBe(2);
expect(rest_y).toEqual({
  z: 3
});
expect(z).toBe(3);
expect(rest_z).toEqual({
  y: 2
});
expect(key).toBe(3);


Review comment (bug):
This is a bugfix. Previously in the output, the `{ y, ...rest_y }` was actually destructured from the value of `3: { y: 2, z: 3 }` while it should have been destrctured from the value of `2: { y: 2, z: 3 }`. The `exec.js` test is merely passing because those two values happens to share the same shape and values. Could you update the `exec.js` (and `input.js` as well) such that they have different values? For example one can use `3: { y: 4, z: 6 }` so the assertions will pass only if they are destructured from the correct property.

Code after:
    [_key = key++]: {
      y
    }
  } = _,
  x = babelHelpers.objectWithoutProperties(_[_key], ["y"]);
expect(x).toEqual({
  a: 1
});
expect(key).toBe(2);
expect(y).toBe(1);

// takes care of the order

key = 1;
var _$ = {
    2: {
      y: 2,
      z: 3
    },
    3: {
      y: 4,
      z: 6
    }
  },
  {
    [_key2 = ++key]: {
      y
    },
    [_key3 = ++key]: {
      z
    }
  } = _$,
  rest_y = babelHelpers.objectWithoutProperties(_$[_key2], ["y"]),
  rest_z = babelHelpers.objectWithoutProperties(_$[_key3], ["z"]);
expect(y).toBe(2);
expect(rest_y).toEqual({
  z: 3
});
expect(z).toBe(6);
expect(rest_z).toEqual({
  y: 4
});
expect(key).toBe(3);
Repository: babel/babel
File: packages/babel-plugin-syntax-import-attributes/src/index.ts (TypeScript)

Code before:
import { declare } from "@babel/helper-plugin-utils";

export interface Options {
  deprecatedAssertSyntax?: boolean;
}

export default declare((api, { deprecatedAssertSyntax }: Options) => {
  api.assertVersion(REQUIRED_VERSION("^7.22.0"));

  if (
    deprecatedAssertSyntax != null &&
    typeof deprecatedAssertSyntax !== "boolean"
  ) {
    throw new Error(
      "'deprecatedAssertSyntax' must be a boolean, if specified.",
    );
  }

  return {
    name: "syntax-import-attributes",

    manipulateOptions({ parserOpts, generatorOpts }) {
      generatorOpts.importAttributesKeyword ??= "with";

      const importAssertionsPluginIndex =
        parserOpts.plugins.indexOf("importAssertions");
      if (importAssertionsPluginIndex !== -1) {
        parserOpts.plugins.splice(importAssertionsPluginIndex, 1);
        deprecatedAssertSyntax = true;
      }

      if (deprecatedAssertSyntax) {
        parserOpts.plugins.push("deprecatedImportAssert", [

Review comment (suggestion):
I think this plugin should be kept Babel 7 only. We should remove the `deprecatedImportAssert` parser plugin in Babel 8 and then archive this syntax plugin.

Code after:
import { declare } from "@babel/helper-plugin-utils";

export interface Options {
  deprecatedAssertSyntax?: boolean;
}

export default declare((api, { deprecatedAssertSyntax }: Options) => {
  api.assertVersion(REQUIRED_VERSION("^7.22.0 || ^8.0.0-0"));

  if (
    deprecatedAssertSyntax != null &&
    typeof deprecatedAssertSyntax !== "boolean"
  ) {
    throw new Error(
      "'deprecatedAssertSyntax' must be a boolean, if specified.",
    );
  }

  return {
    name: "syntax-import-attributes",

    manipulateOptions({ parserOpts, generatorOpts }) {
      generatorOpts.importAttributesKeyword ??= "with";

      const importAssertionsPluginIndex =
        parserOpts.plugins.indexOf("importAssertions");
      if (importAssertionsPluginIndex !== -1) {
        parserOpts.plugins.splice(importAssertionsPluginIndex, 1);
        deprecatedAssertSyntax = true;
      }

      if (deprecatedAssertSyntax) {
        parserOpts.plugins.push("deprecatedImportAssert", [
Repository: babel/babel
File: packages/babel-plugin-transform-block-scoping/test/fixtures/exec/switch-shadowing.js (JavaScript)

Code before:
            default:
                return false;
        }
    }
}
expect(test4({ f: () => "test" })).toBe(true);

// Test 5: switch(id(e))
function id(v) {
    return v;
}

function test5(e) {
    let i = e;
    {
        const e = i[0];
        switch (id(e)) {
            case "n":
                const e = 1;
                return true;
            default:
                return false;
        }
    }
}
console.log(test5("nn"));


Review comment (suggestion):
The test should use `expect` assertion instead of `console.log` to match the pattern of the other test cases. All previous test cases use `expect(...).toBe(true)` but this one just logs the result.
```suggestion
expect(test5("nn")).toBe(true);
```

Code after:
            default:
                return false;
        }
    }
}
expect(test4({ f: () => "test" })).toBe(true);

// Test 5: switch(id(e))
function id(v) {
    return v;
}

function test5(e) {
    let i = e;
    {
        const e = i[0];
        switch (id(e)) {
            case "n":
                const e = 1;
                return true;
            default:
                return false;
        }
    }
}
expect(test5("nn")).toBe(true);
Repository: babel/babel
File: packages/babel-cli/src/babel/options.ts (TypeScript)

Code before:
  "Exclude ignored files when copying non-compilable files.",
);

program.option(
  "--verbose",
  "Log everything. This option conflicts with --quiet",
);
program.option(
  "--quiet",
  "Don't log anything. This option conflicts with --verbose",
);
program.option(
  "--delete-dir-on-start",
  "Delete the out directory before compilation.",
);
program.option(
  "--out-file-extension [string]",
  "Use a specific extension for the output files",
);

program.version(PACKAGE_JSON.version + " (@babel/core " + version + ")");
program.usage("[options] <files ...>");
// register an empty action handler so that program.js can throw on
// unknown options _after_ args
// see https://github.com/tj/program.js/issues/561#issuecomment-522209408
program.action(() => {});

export type CmdOptions = {
  babelOptions: InputOptions;
  cliOptions: {
    filename: string;
    filenames: string[];
    extensions: string[];
    keepFileExtension: boolean;
    outFileExtension: string;
    watch: boolean;
    skipInitialBuild: boolean;
    outFile: string;
    outDir: string;
    relative: boolean;
    copyFiles: boolean;
    copyIgnored: boolean;
    includeDotfiles: boolean;
    verbose: boolean;
    quiet: boolean;
    deleteDirOnStart: boolean;
    sourceMapTarget: string;
  };
};

export default function parseArgv(args: string[]): CmdOptions | null {

Review comment (suggestion):
The empty action handler is also removed as the upstream issue was fixed.

Code after:
  "Exclude ignored files when copying non-compilable files.",
);

program.option(
  "--verbose",
  "Log everything. This option conflicts with --quiet",
);
program.option(
  "--quiet",
  "Don't log anything. This option conflicts with --verbose",
);
program.option(
  "--delete-dir-on-start",
  "Delete the out directory before compilation.",
);
program.option(
  "--out-file-extension [string]",
  "Use a specific extension for the output files",
);
program.argument("[files...]", "List of files to compile.");

program.version(PACKAGE_JSON.version + " (@babel/core " + version + ")");
program.usage("[options] [files...]");

export type CmdOptions = {
  babelOptions: InputOptions;
  cliOptions: {
    filename: string;
    filenames: string[];
    extensions: string[];
    keepFileExtension: boolean;
    outFileExtension: string;
    watch: boolean;
    skipInitialBuild: boolean;
    outFile: string;
    outDir: string;
    relative: boolean;
    copyFiles: boolean;
    copyIgnored: boolean;
    includeDotfiles: boolean;
    verbose: boolean;
    quiet: boolean;
    deleteDirOnStart: boolean;
    sourceMapTarget: string;
  };
};

export default function parseArgv(args: string[]): CmdOptions | null {
  //
  program.parse(args);