'use strict';

var utils = require('../utils.js');
var utils$1 = require('@typescript-eslint/utils');
var astUtils = require('@typescript-eslint/utils/ast-utils');
require('eslint-visitor-keys');
require('espree');
require('estraverse');

const listeningNodes = [
  "ObjectExpression",
  "ObjectPattern",
  "ImportDeclaration",
  "ExportNamedDeclaration",
  "ExportAllDeclaration",
  "TSTypeLiteral",
  "TSInterfaceBody",
  "ClassBody"
];
function containsLineTerminator(str) {
  return utils.LINEBREAK_MATCHER.test(str);
}
function last(arr) {
  return arr[arr.length - 1];
}
function isSingleLine(node) {
  return node.loc.end.line === node.loc.start.line;
}
function isSingleLineImportAttributes(node, sourceCode) {
  const openingBrace = sourceCode.getTokenBefore(node.attributes[0], utils.isOpeningBraceToken);
  const closingBrace = sourceCode.getTokenAfter(node.attributes[node.attributes.length - 1], utils.isClosingBraceToken);
  return closingBrace.loc.end.line === openingBrace.loc.start.line;
}
function isSingleLineProperties(properties) {
  const [firstProp] = properties;
  const lastProp = last(properties);
  return firstProp.loc.start.line === lastProp.loc.end.line;
}
function initOptionProperty(toOptions, fromOptions) {
  toOptions.mode = fromOptions.mode || "strict";
  if (typeof fromOptions.beforeColon !== "undefined")
    toOptions.beforeColon = +fromOptions.beforeColon;
  else
    toOptions.beforeColon = 0;
  if (typeof fromOptions.afterColon !== "undefined")
    toOptions.afterColon = +fromOptions.afterColon;
  else
    toOptions.afterColon = 1;
  if (typeof fromOptions.align !== "undefined") {
    if (typeof fromOptions.align === "object") {
      toOptions.align = fromOptions.align;
    } else {
      toOptions.align = {
        on: fromOptions.align,
        mode: toOptions.mode,
        beforeColon: toOptions.beforeColon,
        afterColon: toOptions.afterColon
      };
    }
  }
  return toOptions;
}
function initOptions(toOptions, fromOptions) {
  if (typeof fromOptions.align === "object") {
    toOptions.align = initOptionProperty({}, fromOptions.align);
    toOptions.align.on = fromOptions.align.on || "colon";
    toOptions.align.mode = fromOptions.align.mode || "strict";
    toOptions.multiLine = initOptionProperty({}, fromOptions.multiLine || fromOptions);
    toOptions.singleLine = initOptionProperty({}, fromOptions.singleLine || fromOptions);
  } else {
    toOptions.multiLine = initOptionProperty({}, fromOptions.multiLine || fromOptions);
    toOptions.singleLine = initOptionProperty({}, fromOptions.singleLine || fromOptions);
    if (toOptions.multiLine.align) {
      toOptions.align = {
        on: toOptions.multiLine.align.on,
        mode: toOptions.multiLine.align.mode || toOptions.multiLine.mode,
        beforeColon: toOptions.multiLine.align.beforeColon,
        afterColon: toOptions.multiLine.align.afterColon
      };
    }
  }
  toOptions.ignoredNodes = fromOptions.ignoredNodes || [];
  return toOptions;
}
var _baseRule = utils.createRule({
  name: "key-spacing",
  package: "js",
  meta: {
    type: "layout",
    docs: {
      description: "Enforce consistent spacing between keys and values in object literal properties"
    },
    fixable: "whitespace",
    schema: [{
      anyOf: [
        {
          type: "object",
          properties: {
            align: {
              anyOf: [
                {
                  type: "string",
                  enum: ["colon", "value"]
                },
                {
                  type: "object",
                  properties: {
                    mode: {
                      type: "string",
                      enum: ["strict", "minimum"]
                    },
                    on: {
                      type: "string",
                      enum: ["colon", "value"]
                    },
                    beforeColon: {
                      type: "boolean"
                    },
                    afterColon: {
                      type: "boolean"
                    }
                  },
                  additionalProperties: false
                }
              ]
            },
            mode: {
              type: "string",
              enum: ["strict", "minimum"]
            },
            beforeColon: {
              type: "boolean"
            },
            afterColon: {
              type: "boolean"
            },
            ignoredNodes: {
              type: "array",
              items: {
                type: "string",
                enum: listeningNodes
              }
            }
          },
          additionalProperties: false
        },
        {
          type: "object",
          properties: {
            singleLine: {
              type: "object",
              properties: {
                mode: {
                  type: "string",
                  enum: ["strict", "minimum"]
                },
                beforeColon: {
                  type: "boolean"
                },
                afterColon: {
                  type: "boolean"
                }
              },
              additionalProperties: false
            },
            multiLine: {
              type: "object",
              properties: {
                align: {
                  anyOf: [
                    {
                      type: "string",
                      enum: ["colon", "value"]
                    },
                    {
                      type: "object",
                      properties: {
                        mode: {
                          type: "string",
                          enum: ["strict", "minimum"]
                        },
                        on: {
                          type: "string",
                          enum: ["colon", "value"]
                        },
                        beforeColon: {
                          type: "boolean"
                        },
                        afterColon: {
                          type: "boolean"
                        }
                      },
                      additionalProperties: false
                    }
                  ]
                },
                mode: {
                  type: "string",
                  enum: ["strict", "minimum"]
                },
                beforeColon: {
                  type: "boolean"
                },
                afterColon: {
                  type: "boolean"
                }
              },
              additionalProperties: false
            }
          },
          additionalProperties: false
        },
        {
          type: "object",
          properties: {
            singleLine: {
              type: "object",
              properties: {
                mode: {
                  type: "string",
                  enum: ["strict", "minimum"]
                },
                beforeColon: {
                  type: "boolean"
                },
                afterColon: {
                  type: "boolean"
                }
              },
              additionalProperties: false
            },
            multiLine: {
              type: "object",
              properties: {
                mode: {
                  type: "string",
                  enum: ["strict", "minimum"]
                },
                beforeColon: {
                  type: "boolean"
                },
                afterColon: {
                  type: "boolean"
                }
              },
              additionalProperties: false
            },
            align: {
              type: "object",
              properties: {
                mode: {
                  type: "string",
                  enum: ["strict", "minimum"]
                },
                on: {
                  type: "string",
                  enum: ["colon", "value"]
                },
                beforeColon: {
                  type: "boolean"
                },
                afterColon: {
                  type: "boolean"
                }
              },
              additionalProperties: false
            }
          },
          additionalProperties: false
        }
      ]
    }],
    messages: {
      extraKey: "Extra space after {{computed}}key '{{key}}'.",
      extraValue: "Extra space before value for {{computed}}key '{{key}}'.",
      missingKey: "Missing space after {{computed}}key '{{key}}'.",
      missingValue: "Missing space before value for {{computed}}key '{{key}}'."
    }
  },
  create(context) {
    const options = context.options[0] || {};
    const ruleOptions = initOptions({}, options);
    const multiLineOptions = ruleOptions.multiLine;
    const singleLineOptions = ruleOptions.singleLine;
    const alignmentOptions = ruleOptions.align || null;
    const ignoredNodes = ruleOptions.ignoredNodes;
    const sourceCode = context.sourceCode;
    function isKeyValueProperty(property) {
      if (property.type === "ImportAttribute")
        return true;
      return !("method" in property && property.method || "shorthand" in property && property.shorthand || "kind" in property && property.kind !== "init" || property.type !== "Property");
    }
    function getNextColon(node) {
      return sourceCode.getTokenAfter(node, utils.isColonToken);
    }
    function getLastTokenBeforeColon(node) {
      const colonToken = getNextColon(node);
      return sourceCode.getTokenBefore(colonToken);
    }
    function getFirstTokenAfterColon(node) {
      const colonToken = getNextColon(node);
      return sourceCode.getTokenAfter(colonToken);
    }
    function continuesPropertyGroup(lastMember, candidate) {
      const groupEndLine = lastMember.loc.start.line;
      const candidateValueStartLine = (isKeyValueProperty(candidate) ? getFirstTokenAfterColon(candidate.key) : candidate).loc.start.line;
      if (candidateValueStartLine - groupEndLine <= 1)
        return true;
      const leadingComments = sourceCode.getCommentsBefore(candidate);
      if (leadingComments.length && leadingComments[0].loc.start.line - groupEndLine <= 1 && candidateValueStartLine - last(leadingComments).loc.end.line <= 1) {
        for (let i = 1; i < leadingComments.length; i++) {
          if (leadingComments[i].loc.start.line - leadingComments[i - 1].loc.end.line > 1)
            return false;
        }
        return true;
      }
      return false;
    }
    function getKey(property) {
      const key = property.key;
      if (property.type !== "ImportAttribute" && property.computed)
        return sourceCode.getText().slice(key.range[0], key.range[1]);
      return utils.getStaticPropertyName(property);
    }
    function report(property, side, whitespace, expected, mode) {
      const diff = whitespace.length - expected;
      if ((diff && mode === "strict" || diff < 0 && mode === "minimum" || diff > 0 && !expected && mode === "minimum") && !(expected && containsLineTerminator(whitespace))) {
        const nextColon = getNextColon(property.key);
        const tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true });
        const tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true });
        const isKeySide = side === "key";
        const isExtra = diff > 0;
        const diffAbs = Math.abs(diff);
        const spaces = new Array(diffAbs + 1).join(" ");
        const locStart = isKeySide ? tokenBeforeColon.loc.end : nextColon.loc.start;
        const locEnd = isKeySide ? nextColon.loc.start : tokenAfterColon.loc.start;
        const missingLoc = isKeySide ? tokenBeforeColon.loc : tokenAfterColon.loc;
        const loc = isExtra ? { start: locStart, end: locEnd } : missingLoc;
        let fix;
        if (isExtra) {
          let range;
          if (isKeySide)
            range = [tokenBeforeColon.range[1], tokenBeforeColon.range[1] + diffAbs];
          else
            range = [tokenAfterColon.range[0] - diffAbs, tokenAfterColon.range[0]];
          fix = function(fixer) {
            return fixer.removeRange(range);
          };
        } else {
          if (isKeySide) {
            fix = function(fixer) {
              return fixer.insertTextAfter(tokenBeforeColon, spaces);
            };
          } else {
            fix = function(fixer) {
              return fixer.insertTextBefore(tokenAfterColon, spaces);
            };
          }
        }
        let messageId;
        if (isExtra)
          messageId = side === "key" ? "extraKey" : "extraValue";
        else
          messageId = side === "key" ? "missingKey" : "missingValue";
        context.report({
          node: property[side],
          loc,
          messageId,
          data: {
            computed: property.type !== "ImportAttribute" && property.computed ? "computed " : "",
            key: getKey(property)
          },
          fix
        });
      }
    }
    function getKeyWidth(property) {
      const startToken = sourceCode.getFirstToken(property);
      const endToken = getLastTokenBeforeColon(property.key);
      return utils.getStringLength(sourceCode.getText().slice(startToken.range[0], endToken.range[1]));
    }
    function getPropertyWhitespace(property) {
      const whitespace = /(\s*):(\s*)/u.exec(sourceCode.getText().slice(
        property.key.range[1],
        property.value.range[0]
      ));
      if (whitespace) {
        return {
          beforeColon: whitespace[1],
          afterColon: whitespace[2]
        };
      }
      return null;
    }
    function createGroups(properties) {
      if (properties.length === 1)
        return [properties];
      return properties.reduce((groups, property) => {
        const currentGroup = last(groups);
        const prev = last(currentGroup);
        if (!prev || continuesPropertyGroup(prev, property))
          currentGroup.push(property);
        else
          groups.push([property]);
        return groups;
      }, [
        []
      ]);
    }
    function verifyGroupAlignment(properties) {
      const length = properties.length;
      const widths = properties.map(getKeyWidth);
      const align = alignmentOptions.on;
      let targetWidth = Math.max(...widths);
      let beforeColon;
      let afterColon;
      let mode;
      if (alignmentOptions && length > 1) {
        beforeColon = alignmentOptions.beforeColon;
        afterColon = alignmentOptions.afterColon;
        mode = alignmentOptions.mode;
      } else {
        beforeColon = multiLineOptions.beforeColon;
        afterColon = multiLineOptions.afterColon;
        mode = alignmentOptions.mode;
      }
      targetWidth += align === "colon" ? beforeColon : afterColon;
      for (let i = 0; i < length; i++) {
        const property = properties[i];
        const whitespace = getPropertyWhitespace(property);
        if (whitespace) {
          const width = widths[i];
          if (align === "value") {
            report(property, "key", whitespace.beforeColon, beforeColon, mode);
            report(property, "value", whitespace.afterColon, targetWidth - width, mode);
          } else {
            report(property, "key", whitespace.beforeColon, targetWidth - width, mode);
            report(property, "value", whitespace.afterColon, afterColon, mode);
          }
        }
      }
    }
    function verifySpacing(node, lineOptions) {
      if (ignoredNodes.includes(node.parent.type))
        return;
      const actual = getPropertyWhitespace(node);
      if (actual) {
        report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode);
        report(node, "value", actual.afterColon, lineOptions.afterColon, lineOptions.mode);
      }
    }
    function verifyListSpacing(properties, lineOptions) {
      const length = properties.length;
      for (let i = 0; i < length; i++)
        verifySpacing(properties[i], lineOptions);
    }
    function verifyAlignment(properties) {
      createGroups(properties).forEach((group) => {
        const properties2 = group.filter(isKeyValueProperty);
        if (properties2.length > 0 && isSingleLineProperties(properties2))
          verifyListSpacing(properties2, multiLineOptions);
        else
          verifyGroupAlignment(properties2);
      });
    }
    function verifyImportAttributes(node) {
      if (ignoredNodes.includes(node.type))
        return;
      if (!node.attributes)
        return;
      if (!node.attributes.length)
        return;
      if (isSingleLineImportAttributes(node, sourceCode))
        verifyListSpacing(node.attributes, singleLineOptions);
      else
        verifyAlignment(node.attributes);
    }
    if (alignmentOptions) {
      return {
        ObjectExpression(node) {
          if (ignoredNodes.includes(node.type))
            return;
          if (isSingleLine(node))
            verifyListSpacing(node.properties.filter(isKeyValueProperty), singleLineOptions);
          else
            verifyAlignment(node.properties);
        },
        ImportDeclaration(node) {
          verifyImportAttributes(node);
        },
        ExportNamedDeclaration(node) {
          verifyImportAttributes(node);
        },
        ExportAllDeclaration(node) {
          verifyImportAttributes(node);
        }
      };
    }
    return {
      Property(node) {
        verifySpacing(node, isSingleLine(node.parent) ? singleLineOptions : multiLineOptions);
      },
      ImportAttribute(node) {
        const parent = node.parent;
        verifySpacing(node, isSingleLineImportAttributes(parent, sourceCode) ? singleLineOptions : multiLineOptions);
      }
    };
  }
});

const baseRule = /* @__PURE__ */ utils.castRuleModule(_baseRule);
const baseSchema = Array.isArray(baseRule.meta.schema) ? baseRule.meta.schema[0] : baseRule.meta.schema;
var keySpacing = utils.createRule({
  name: "key-spacing",
  package: "ts",
  meta: {
    type: "layout",
    docs: {
      description: "Enforce consistent spacing between property names and type annotations in types and interfaces"
    },
    fixable: "whitespace",
    hasSuggestions: baseRule.meta.hasSuggestions,
    schema: [baseSchema],
    messages: baseRule.meta.messages
  },
  defaultOptions: [{}],
  create(context, [_options]) {
    const options = _options || {};
    const ignoredNodes = options.ignoredNodes || [];
    const sourceCode = context.sourceCode;
    const baseRules = baseRule.create(context);
    function adjustedColumn(position) {
      const line = position.line - 1;
      return utils.getStringLength(
        sourceCode.lines.at(line).slice(0, position.column)
      );
    }
    function getLastTokenBeforeColon(node) {
      const colonToken = sourceCode.getTokenAfter(node, astUtils.isColonToken);
      return sourceCode.getTokenBefore(colonToken);
    }
    function isKeyTypeNode(node) {
      return (node.type === utils$1.AST_NODE_TYPES.TSPropertySignature || node.type === utils$1.AST_NODE_TYPES.TSIndexSignature || node.type === utils$1.AST_NODE_TYPES.PropertyDefinition) && !!node.typeAnnotation;
    }
    function isApplicable(node) {
      return isKeyTypeNode(node) && node.typeAnnotation.loc.start.line === node.loc.end.line;
    }
    function getKeyText(node) {
      if (node.type !== utils$1.AST_NODE_TYPES.TSIndexSignature)
        return sourceCode.getText(node.key);
      const code = sourceCode.getText(node);
      return code.slice(
        0,
        sourceCode.getTokenAfter(
          node.parameters.at(-1),
          astUtils.isClosingBracketToken
        ).range[1] - node.range[0]
      );
    }
    function getKeyLocEnd(node) {
      return getLastTokenBeforeColon(
        node.type !== utils$1.AST_NODE_TYPES.TSIndexSignature ? node.key : node.parameters.at(-1)
      ).loc.end;
    }
    function checkBeforeColon(node, expectedWhitespaceBeforeColon, mode) {
      const { typeAnnotation } = node;
      const colon = typeAnnotation.loc.start.column;
      const keyEnd = getKeyLocEnd(node);
      const difference = colon - keyEnd.column - expectedWhitespaceBeforeColon;
      if (mode === "strict" ? difference : difference < 0) {
        context.report({
          node,
          messageId: difference > 0 ? "extraKey" : "missingKey",
          fix: (fixer) => {
            if (difference > 0) {
              return fixer.removeRange([
                typeAnnotation.range[0] - difference,
                typeAnnotation.range[0]
              ]);
            }
            return fixer.insertTextBefore(
              typeAnnotation,
              " ".repeat(-difference)
            );
          },
          data: {
            computed: "",
            key: getKeyText(node)
          }
        });
      }
    }
    function checkAfterColon(node, expectedWhitespaceAfterColon, mode) {
      const { typeAnnotation } = node;
      const colonToken = sourceCode.getFirstToken(typeAnnotation);
      const typeStart = sourceCode.getTokenAfter(colonToken, {
        includeComments: true
      }).loc.start.column;
      const difference = typeStart - colonToken.loc.start.column - 1 - expectedWhitespaceAfterColon;
      if (mode === "strict" ? difference : difference < 0) {
        context.report({
          node,
          messageId: difference > 0 ? "extraValue" : "missingValue",
          fix: (fixer) => {
            if (difference > 0) {
              return fixer.removeRange([
                colonToken.range[1],
                colonToken.range[1] + difference
              ]);
            }
            return fixer.insertTextAfter(colonToken, " ".repeat(-difference));
          },
          data: {
            computed: "",
            key: getKeyText(node)
          }
        });
      }
    }
    function continuesAlignGroup(lastMember, candidate) {
      const groupEndLine = lastMember.loc.start.line;
      const candidateValueStartLine = (isKeyTypeNode(candidate) ? candidate.typeAnnotation : candidate).loc.start.line;
      if (candidateValueStartLine === groupEndLine)
        return false;
      if (candidateValueStartLine - groupEndLine === 1)
        return true;
      const leadingComments = sourceCode.getCommentsBefore(candidate);
      if (leadingComments.length && leadingComments[0].loc.start.line - groupEndLine <= 1 && candidateValueStartLine - leadingComments.at(-1).loc.end.line <= 1) {
        for (let i = 1; i < leadingComments.length; i++) {
          if (leadingComments[i].loc.start.line - leadingComments[i - 1].loc.end.line > 1) {
            return false;
          }
        }
        return true;
      }
      return false;
    }
    function checkAlignGroup(group) {
      let alignColumn = 0;
      const align = (typeof options.align === "object" ? options.align.on : typeof options.multiLine?.align === "object" ? options.multiLine.align.on : options.multiLine?.align ?? options.align) ?? "colon";
      const beforeColon = (typeof options.align === "object" ? options.align.beforeColon : options.multiLine ? typeof options.multiLine.align === "object" ? options.multiLine.align.beforeColon : options.multiLine.beforeColon : options.beforeColon) ?? false;
      const expectedWhitespaceBeforeColon = beforeColon ? 1 : 0;
      const afterColon = (typeof options.align === "object" ? options.align.afterColon : options.multiLine ? typeof options.multiLine.align === "object" ? options.multiLine.align.afterColon : options.multiLine.afterColon : options.afterColon) ?? true;
      const expectedWhitespaceAfterColon = afterColon ? 1 : 0;
      const mode = (typeof options.align === "object" ? options.align.mode : options.multiLine ? typeof options.multiLine.align === "object" ? options.multiLine.align.mode ?? options.multiLine.mode : options.multiLine.mode : options.mode) ?? "strict";
      for (const node of group) {
        if (isKeyTypeNode(node)) {
          const keyEnd = adjustedColumn(getKeyLocEnd(node));
          alignColumn = Math.max(
            alignColumn,
            align === "colon" ? keyEnd + expectedWhitespaceBeforeColon : keyEnd + ":".length + expectedWhitespaceAfterColon + expectedWhitespaceBeforeColon
          );
        }
      }
      for (const node of group) {
        if (!isApplicable(node))
          continue;
        const { typeAnnotation } = node;
        const toCheck = align === "colon" ? typeAnnotation : typeAnnotation.typeAnnotation;
        const difference = adjustedColumn(toCheck.loc.start) - alignColumn;
        if (difference) {
          context.report({
            node,
            messageId: difference > 0 ? align === "colon" ? "extraKey" : "extraValue" : align === "colon" ? "missingKey" : "missingValue",
            fix: (fixer) => {
              if (difference > 0) {
                return fixer.removeRange([
                  toCheck.range[0] - difference,
                  toCheck.range[0]
                ]);
              }
              return fixer.insertTextBefore(toCheck, " ".repeat(-difference));
            },
            data: {
              computed: "",
              key: getKeyText(node)
            }
          });
        }
        if (align === "colon")
          checkAfterColon(node, expectedWhitespaceAfterColon, mode);
        else
          checkBeforeColon(node, expectedWhitespaceBeforeColon, mode);
      }
    }
    function checkIndividualNode(node, { singleLine }) {
      const beforeColon = (singleLine ? options.singleLine ? options.singleLine.beforeColon : options.beforeColon : options.multiLine ? options.multiLine.beforeColon : options.beforeColon) ?? false;
      const expectedWhitespaceBeforeColon = beforeColon ? 1 : 0;
      const afterColon = (singleLine ? options.singleLine ? options.singleLine.afterColon : options.afterColon : options.multiLine ? options.multiLine.afterColon : options.afterColon) ?? true;
      const expectedWhitespaceAfterColon = afterColon ? 1 : 0;
      const mode = (singleLine ? options.singleLine ? options.singleLine.mode : options.mode : options.multiLine ? options.multiLine.mode : options.mode) ?? "strict";
      if (isApplicable(node)) {
        checkBeforeColon(node, expectedWhitespaceBeforeColon, mode);
        checkAfterColon(node, expectedWhitespaceAfterColon, mode);
      }
    }
    function validateBody(body) {
      if (ignoredNodes.includes(body.type))
        return;
      const isSingleLine = body.loc.start.line === body.loc.end.line;
      const members = body.type === utils$1.AST_NODE_TYPES.TSTypeLiteral ? body.members : body.body;
      let alignGroups = [];
      let unalignedElements = [];
      if (options.align || options.multiLine?.align) {
        let currentAlignGroup = [];
        alignGroups.push(currentAlignGroup);
        let prevNode;
        for (const node of members) {
          let prevAlignedNode = currentAlignGroup.at(-1);
          if (prevAlignedNode !== prevNode)
            prevAlignedNode = undefined;
          if (prevAlignedNode && continuesAlignGroup(prevAlignedNode, node)) {
            currentAlignGroup.push(node);
          } else if (prevNode?.loc.start.line === node.loc.start.line) {
            if (prevAlignedNode) {
              unalignedElements.push(prevAlignedNode);
              currentAlignGroup.pop();
            }
            unalignedElements.push(node);
          } else {
            currentAlignGroup = [node];
            alignGroups.push(currentAlignGroup);
          }
          prevNode = node;
        }
        unalignedElements = unalignedElements.concat(
          ...alignGroups.filter((group) => group.length === 1)
        );
        alignGroups = alignGroups.filter((group) => group.length >= 2);
      } else {
        unalignedElements = members;
      }
      for (const group of alignGroups)
        checkAlignGroup(group);
      for (const node of unalignedElements)
        checkIndividualNode(node, { singleLine: isSingleLine });
    }
    return {
      ...baseRules,
      TSTypeLiteral: validateBody,
      TSInterfaceBody: validateBody,
      ClassBody: validateBody
    };
  }
});

module.exports = keySpacing;
