function isLegacyEnum()

in packages/eslint-plugin-fb-flow/rules/use-flow-enums.js [20:80]


function isLegacyEnum(node) {
  const {callee, arguments: args} = node;
  // Legacy enums: `keyMirror({...})` and `Object.freeze({...})`
  const literalTypes = new Set(['TemplateLiteral', 'Literal']);
  const uniqueValues = new Set();
  const uniqueKeys = new Set();
  const uniqueTypes = new Set();
  if (
    // `keyMirror(...)` or `Object.freeze(...)`
    (isIdentifier(callee, 'keyMirror') ||
      (callee.type === 'MemberExpression' &&
        isIdentifier(callee.object, 'Object') &&
        isIdentifier(callee.property, 'freeze'))) &&
    // A single argument that's an object literal.
    args.length === 1 &&
    args[0].type === 'ObjectExpression' &&
    args[0].properties.length > 0 &&
    args[0].properties.every(prop => {
      const isLiteral =
        !prop.computed &&
        !prop.shorthand &&
        !prop.method &&
        prop.key != null &&
        prop.value != null &&
        isIdentifier(prop.key) &&
        // Valid enum patterns names must start with an uppercase [A-Z]
        /^[A-Z]/.test(prop.key.name) &&
        literalTypes.has(prop.value.type) &&
        // String literals that don't follow this regex pattern are probably
        // just part of a bag of constants rather than an enum-like pattern.
        (prop.value.type !== 'Literal' ||
          /^[-a-zA-Z_0-9]*$/.test(prop.value.value));

      if (prop.value != null && prop.value.value != null) {
        uniqueValues.add(prop.value.value);
      } else if (prop.key) {
        // if the value is null, assume a keyMirror and increment the Set()
        uniqueValues.add(prop.key.name);
      }

      if (prop.key != null) {
        uniqueKeys.add(prop.key.name);
      }

      if (prop.value != null) {
        uniqueTypes.add(typeof prop.value.value);
      }

      return isLiteral;
    }) &&
    // Check all keys are unique
    uniqueKeys.size === args[0].properties.length &&
    // Check all values are unique
    uniqueValues.size === args[0].properties.length &&
    // The `type` of each property value is the same.
    uniqueTypes.size === 1
  ) {
    return true;
  }
  return false;
}