text: "use strict";
  
  var t = require("../../");
  var stringifyValidator = require("../utils/stringifyValidator");
  var toFunctionName = require("../utils/toFunctionName");
  
  var code = "// NOTE: This file is autogenerated. Do not modify.\n// See packages/babel-types/scripts/generators/typescript.js for script used.\n\ninterface BaseComment {\n  value: string;\n  start: number;\n  end: number;\n  loc: SourceLocation;\n  type: \"CommentBlock\" | \"CommentLine\";\n}\n\nexport interface CommentBlock extends BaseComment {\n  type: \"CommentBlock\";\n}\n\nexport interface CommentLine extends BaseComment {\n  type: \"CommentLine\";\n}\n\nexport type Comment = CommentBlock | CommentLine;\n\nexport interface SourceLocation {\n  start: {\n    line: number;\n    column: number;\n  };\n\n  end: {\n    line: number;\n    column: number;\n  };\n}\n\ninterface BaseNode {\n  leadingComments: ReadonlyArray<Comment> | null;\n  innerComments: ReadonlyArray<Comment> | null;\n  trailingComments: ReadonlyArray<Comment> | null;\n  start: number | null;\n  end: number | null;\n  loc: SourceLocation | null;\n  type: Node[\"type\"];\n}\n\nexport type Node = " + t.TYPES.sort().join(" | ") + ";\n\n";
  
  //
  
  var lines = [];
  
  var _loop = function _loop(type) {
    var fields = t.NODE_FIELDS[type];
    var fieldNames = sortFieldNames(Object.keys(t.NODE_FIELDS[type]), type);
  
    var struct = ['type: "' + type + '";'];
    var args = [];
  
    fieldNames.forEach(function (fieldName) {
      var field = fields[fieldName];
      var typeAnnotation = stringifyValidator(field.validate, "");
  
      if (isNullable(field) && !hasDefault(field)) {
        typeAnnotation += " | null";
      }
  
      if (areAllRemainingFieldsNullable(fieldName, fieldNames, fields)) {
        args.push("" + t.toBindingIdentifierName(fieldName) + (isNullable(field) ? "?:" : ":") + " " + typeAnnotation);
      } else {
        args.push(t.toBindingIdentifierName(fieldName) + ": " + typeAnnotation + (isNullable(field) ? " | undefined" : ""));
      }
  
      var alphaNumeric = /^\w+$/;
  
      if (t.isValidIdentifier(fieldName) || alphaNumeric.test(fieldName)) {
        struct.push(fieldName + ": " + typeAnnotation + ";");
      } else {
        struct.push("\"" + fieldName + "\": " + typeAnnotation + ";");
      }
    });
  
    code += "export interface " + type + " extends BaseNode {\n  " + struct.join("\n  ").trim() + "\n}\n\n";
  
    // super and import are reserved words in JavaScript
    if (type !== "Super" && type !== "Import") {
      lines.push("export function " + toFunctionName(type) + "(" + args.join(", ") + "): " + type + ";");
    }
  };
  
  for (var type in t.NODE_FIELDS) {
    _loop(type);
  }
  
  for (var i = 0; i < t.TYPES.length; i++) {
    var decl = "export function is" + t.TYPES[i] + "(node: object | null | undefined, opts?: object | null): ";
  
    if (t.NODE_FIELDS[t.TYPES[i]]) {
      decl += "node is " + t.TYPES[i] + ";";
    } else if (t.FLIPPED_ALIAS_KEYS[t.TYPES[i]]) {
      decl += "node is " + t.TYPES[i] + ";";
    } else {
      decl += "boolean;";
    }
  
    lines.push(decl);
  }
  
  lines.push("export function validate(n: Node, key: string, value: any): void;", "export function clone<T extends Node>(n: T): T;", "export function cloneDeep<T extends Node>(n: T): T;", "export function removeProperties(\n  n: Node,\n  opts?: { preserveComments: boolean } | null\n): void;", "export function removePropertiesDeep<T extends Node>(\n  n: T,\n  opts?: { preserveComments: boolean } | null\n): T;", "export type TraversalAncestors = ReadonlyArray<{\n    node: Node,\n    key: string,\n    index?: number,\n  }>;\n  export type TraversalHandler<T> = (node: Node, parent: TraversalAncestors, type: T) => void;\n  export type TraversalHandlers<T> = {\n    enter?: TraversalHandler<T>,\n    exit?: TraversalHandler<T>,\n  };".replace(/(^|\n) {2}/g, "$1"),
  // eslint-disable-next-line
  "export function traverse<T>(n: Node, h: TraversalHandler<T> | TraversalHandlers<T>, state?: T): void;");
  
  for (var type in t.DEPRECATED_KEYS) {
    code += "/**\n * @deprecated Use `" + t.DEPRECATED_KEYS[type] + "`\n */\nexport type " + type + " = " + t.DEPRECATED_KEYS[type] + ";\n\n";
  }
  
  for (var _type in t.FLIPPED_ALIAS_KEYS) {
    var types = t.FLIPPED_ALIAS_KEYS[_type];
    code += "export type " + _type + " = " + types.map(function (type) {
      return "" + type;
    }).join(" | ") + ";\n";
  }
  code += "\n";
  
  code += "export interface Aliases {\n";
  for (var _type2 in t.FLIPPED_ALIAS_KEYS) {
    code += "  " + _type2 + ": " + _type2 + ";\n";
  }
  code += "}\n\n";
  
  code += lines.join("\n") + "\n";
  
  //
  
  process.stdout.write(code);
  
  //
  
  function areAllRemainingFieldsNullable(fieldName, fieldNames, fields) {
    var index = fieldNames.indexOf(fieldName);
    return fieldNames.slice(index).every(function (_) {
      return isNullable(fields[_]);
    });
  }
  
  function hasDefault(field) {
    return field.default != null;
  }
  
  function isNullable(field) {
    return field.optional || hasDefault(field);
  }
  
  function sortFieldNames(fields, type) {
    return fields.sort(function (fieldA, fieldB) {
      var indexA = t.BUILDER_KEYS[type].indexOf(fieldA);
      var indexB = t.BUILDER_KEYS[type].indexOf(fieldB);
      if (indexA === indexB) return fieldA < fieldB ? -1 : 1;
      if (indexA === -1) return 1;
      if (indexB === -1) return -1;
      return indexA - indexB;
    });
  }