createInstanceFromFbtConstructCallsite(moduleName, node, this);
  }

  getOptions(): Options {
    const [value, rangeArg] = this.getCallNodeArguments() || [];
    let rangeNode = rangeArg;

    try {
      let range = {};
      // $FlowFixMe[incompatible-type]
      rangeNode = enforceBabelNode(rangeNode, '`range`');
      if (isArrayExpression(rangeNode)) {
        invariant(
          rangeNode.elements && rangeNode.elements.length,
          'List of enum entries must not be empty',
        );
        rangeNode.elements.forEach(item => {
          invariant(
            isStringLiteral(item),
            'Enum values must be string literals',
          );
          // $FlowFixMe[cannot-write] Force write here to assemble the range object
          // $FlowFixMe[prop-missing]
          range[item.value] = item.value;
        });
      } else if (isObjectExpression(rangeNode)) {
        rangeNode.properties.forEach(prop => {
          invariant(
            isObjectProperty(prop),
            'Enum entries must be standard object properties. ' +
              'Method or spread expressions are forbidden',
          );
          const valueNode = prop.value;
          const keyNode: mixed = prop.key;
          invariant(
            isStringLiteral(valueNode),
            'Enum values must be string literals',
          );
          if (isStringLiteral(keyNode) || isNumericLiteral(keyNode)) {
            // $FlowFixMe[cannot-write] Force write here to assemble the range object
            // $FlowFixMe[prop-missing]
            range[keyNode.value.toString()] = valueNode.value;
          } else {
            invariant(
              isIdentifier(keyNode) && prop.computed === false,
              'Enum keys must be string literals instead of `%s` ' +
                'when using an object with computed property names',
              // $FlowFixMe[incompatible-use] BabelNode child classes have a "type" property
              keyNode.type,
            );
            // $FlowFixMe[cannot-write] Force write here to assemble the range object
            range[keyNode.name] = valueNode.value;
          }
        });
        invariant(
          Object.keys(range).length,
          'Map of enum entries must not be empty',
        );
      } else {
        invariant(
          isIdentifier(rangeNode),
          'Expected enum range (second argument) to be an array, object or ' +
            'a variable referring to an fbt enum',
        );

        const manifest = nullthrows(
          FbtEnumRegistrar.getEnum(rangeNode.name),
          `Fbt Enum \`${rangeNode.name}\` not registered; ensure the enum ` +
            `was correctly imported and that it has the ${FBT_ENUM_MODULE_SUFFIX} suffix.`,
        );
        range = manifest;
      }

      return {
        range,
        value: enforceBabelNodeCallExpressionArg(value, '`value`'),
      };
    } catch (error) {
      throw errorAt(this.node, error);
    }
  }
Create a new class instance given a BabelNode root node.
If that node is incompatible, we'll just return `null`.