/**
 * @fileoverview Enforce boolean attributes notation in JSX
 * @author Yannick Croissant
 */
'use strict';

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

const exceptionsSchema = {
  type: 'array',
  items: {type: 'string', minLength: 1},
  uniqueItems: true
};

const ALWAYS = 'always';
const NEVER = 'never';

const errorData = new WeakMap();
function getErrorData(exceptions) {
  if (!errorData.has(exceptions)) {
    const exceptionProps = Array.from(exceptions, (name) => `\`${name}\``).join(', ');
    const exceptionsMessage = exceptions.size > 0 ? ` for the following props: ${exceptionProps}` : '';
    errorData.set(exceptions, {exceptionsMessage: exceptionsMessage});
  }
  return errorData.get(exceptions);
}

module.exports = {
  meta: {
    docs: {
      description: 'Enforce boolean attributes notation in JSX',
      category: 'Stylistic Issues',
      recommended: false
    },
    fixable: 'code',

    schema: {
      anyOf: [{
        type: 'array',
        items: [{enum: [ALWAYS, NEVER]}],
        additionalItems: false
      }, {
        type: 'array',
        items: [{
          enum: [ALWAYS]
        }, {
          type: 'object',
          additionalProperties: false,
          properties: {
            [NEVER]: exceptionsSchema
          }
        }],
        additionalItems: false
      }, {
        type: 'array',
        items: [{
          enum: [NEVER]
        }, {
          type: 'object',
          additionalProperties: false,
          properties: {
            [ALWAYS]: exceptionsSchema
          }
        }],
        additionalItems: false
      }]
    }
  },

  create: function(context) {
    const configuration = context.options[0] || NEVER;
    const configObject = context.options[1] || {};
    const exceptions = new Set((configuration === ALWAYS ? configObject[NEVER] : configObject[ALWAYS]) || []);

    const NEVER_MESSAGE = 'Value must be omitted for boolean attributes{{exceptionsMessage}}';
    const ALWAYS_MESSAGE = 'Value must be set for boolean attributes{{exceptionsMessage}}';

    return {
      JSXAttribute(node) {
        const propName = node.name && node.name.name;
        const value = node.value;
        const isException = exceptions.has(propName);

        const isAlways = configuration === ALWAYS ? !isException : isException;
        const isNever = configuration === NEVER ? !isException : isException;

        if (isAlways && value === null) {
          const data = getErrorData(exceptions);
          context.report({
            node: node,
            message: ALWAYS_MESSAGE,
            data: data,
            fix(fixer) {
              return fixer.insertTextAfter(node, '={true}');
            }
          });
        }
        if (isNever && value && value.type === 'JSXExpressionContainer' && value.expression.value === true) {
          const data = getErrorData(exceptions);
          context.report({
            node: node,
            message: NEVER_MESSAGE,
            data: data,
            fix(fixer) {
              return fixer.removeRange([node.name.range[1], value.range[1]]);
            }
          });
        }
      }
    };
  }
};

@@ -857,16 +857,400 @@
 ns);%0A%7D%0A%0A
+function isAlways(configuration, exceptions, propName) %7B%0A  const isException = exceptions.has(propName);%0A  if (configuration === ALWAYS) %7B%0A    return !isException;%0A  %7D%0A  return isException;%0A%7D%0A%0Afunction isNever(configuration, exceptions, propName) %7B%0A  const isException = exceptions.has(propName);%0A  if (configuration === NEVER) %7B%0A    return !isException;%0A  %7D%0A  return isException;%0A%7D%0A%0A
 module.e
@@ -2140,18 +2140,8 @@
 eate
-: function
 (con
@@ -2686,85 +2686,29 @@
 ue;%0A
- 
+%0A
        
-const isException = exceptions.has(propName);%0A%0A        const 
+ if (
 isAlways
  = c
@@ -2703,19 +2703,17 @@
 isAlways
- = 
+(
 configur
@@ -2721,149 +2721,31 @@
 tion
- === ALWAYS ? !isException : isException;%0A        const isNever = configuration === NEVER ? !isException : isException;%0A%0A        if (isAlways
+, exceptions, propName)
  && 
@@ -3066,16 +3066,53 @@
 (isNever
+(configuration, exceptions, propName)
  && valu

Refactor isAlways/isNever logic