| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 | 
							- /**
 
-  * @fileoverview Rule to require or disallow line breaks inside braces.
 
-  * @author Toru Nagashima
 
-  */
 
- "use strict";
 
- //------------------------------------------------------------------------------
 
- // Requirements
 
- //------------------------------------------------------------------------------
 
- const astUtils = require("./utils/ast-utils");
 
- const lodash = require("lodash");
 
- //------------------------------------------------------------------------------
 
- // Helpers
 
- //------------------------------------------------------------------------------
 
- // Schema objects.
 
- const OPTION_VALUE = {
 
-     oneOf: [
 
-         {
 
-             enum: ["always", "never"]
 
-         },
 
-         {
 
-             type: "object",
 
-             properties: {
 
-                 multiline: {
 
-                     type: "boolean"
 
-                 },
 
-                 minProperties: {
 
-                     type: "integer",
 
-                     minimum: 0
 
-                 },
 
-                 consistent: {
 
-                     type: "boolean"
 
-                 }
 
-             },
 
-             additionalProperties: false,
 
-             minProperties: 1
 
-         }
 
-     ]
 
- };
 
- /**
 
-  * Normalizes a given option value.
 
-  * @param {string|Object|undefined} value An option value to parse.
 
-  * @returns {{multiline: boolean, minProperties: number, consistent: boolean}} Normalized option object.
 
-  */
 
- function normalizeOptionValue(value) {
 
-     let multiline = false;
 
-     let minProperties = Number.POSITIVE_INFINITY;
 
-     let consistent = false;
 
-     if (value) {
 
-         if (value === "always") {
 
-             minProperties = 0;
 
-         } else if (value === "never") {
 
-             minProperties = Number.POSITIVE_INFINITY;
 
-         } else {
 
-             multiline = Boolean(value.multiline);
 
-             minProperties = value.minProperties || Number.POSITIVE_INFINITY;
 
-             consistent = Boolean(value.consistent);
 
-         }
 
-     } else {
 
-         consistent = true;
 
-     }
 
-     return { multiline, minProperties, consistent };
 
- }
 
- /**
 
-  * Normalizes a given option value.
 
-  * @param {string|Object|undefined} options An option value to parse.
 
-  * @returns {{
 
-  *   ObjectExpression: {multiline: boolean, minProperties: number, consistent: boolean},
 
-  *   ObjectPattern: {multiline: boolean, minProperties: number, consistent: boolean},
 
-  *   ImportDeclaration: {multiline: boolean, minProperties: number, consistent: boolean},
 
-  *   ExportNamedDeclaration : {multiline: boolean, minProperties: number, consistent: boolean}
 
-  * }} Normalized option object.
 
-  */
 
- function normalizeOptions(options) {
 
-     const isNodeSpecificOption = lodash.overSome([lodash.isPlainObject, lodash.isString]);
 
-     if (lodash.isPlainObject(options) && lodash.some(options, isNodeSpecificOption)) {
 
-         return {
 
-             ObjectExpression: normalizeOptionValue(options.ObjectExpression),
 
-             ObjectPattern: normalizeOptionValue(options.ObjectPattern),
 
-             ImportDeclaration: normalizeOptionValue(options.ImportDeclaration),
 
-             ExportNamedDeclaration: normalizeOptionValue(options.ExportDeclaration)
 
-         };
 
-     }
 
-     const value = normalizeOptionValue(options);
 
-     return { ObjectExpression: value, ObjectPattern: value, ImportDeclaration: value, ExportNamedDeclaration: value };
 
- }
 
- /**
 
-  * Determines if ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration
 
-  * node needs to be checked for missing line breaks
 
-  * @param {ASTNode} node Node under inspection
 
-  * @param {Object} options option specific to node type
 
-  * @param {Token} first First object property
 
-  * @param {Token} last Last object property
 
-  * @returns {boolean} `true` if node needs to be checked for missing line breaks
 
-  */
 
- function areLineBreaksRequired(node, options, first, last) {
 
-     let objectProperties;
 
-     if (node.type === "ObjectExpression" || node.type === "ObjectPattern") {
 
-         objectProperties = node.properties;
 
-     } else {
 
-         // is ImportDeclaration or ExportNamedDeclaration
 
-         objectProperties = node.specifiers
 
-             .filter(s => s.type === "ImportSpecifier" || s.type === "ExportSpecifier");
 
-     }
 
-     return objectProperties.length >= options.minProperties ||
 
-         (
 
-             options.multiline &&
 
-             objectProperties.length > 0 &&
 
-             first.loc.start.line !== last.loc.end.line
 
-         );
 
- }
 
- //------------------------------------------------------------------------------
 
- // Rule Definition
 
- //------------------------------------------------------------------------------
 
- module.exports = {
 
-     meta: {
 
-         type: "layout",
 
-         docs: {
 
-             description: "enforce consistent line breaks inside braces",
 
-             category: "Stylistic Issues",
 
-             recommended: false,
 
-             url: "https://eslint.org/docs/rules/object-curly-newline"
 
-         },
 
-         fixable: "whitespace",
 
-         schema: [
 
-             {
 
-                 oneOf: [
 
-                     OPTION_VALUE,
 
-                     {
 
-                         type: "object",
 
-                         properties: {
 
-                             ObjectExpression: OPTION_VALUE,
 
-                             ObjectPattern: OPTION_VALUE,
 
-                             ImportDeclaration: OPTION_VALUE,
 
-                             ExportDeclaration: OPTION_VALUE
 
-                         },
 
-                         additionalProperties: false,
 
-                         minProperties: 1
 
-                     }
 
-                 ]
 
-             }
 
-         ]
 
-     },
 
-     create(context) {
 
-         const sourceCode = context.getSourceCode();
 
-         const normalizedOptions = normalizeOptions(context.options[0]);
 
-         /**
 
-          * Reports a given node if it violated this rule.
 
-          * @param {ASTNode} node A node to check. This is an ObjectExpression, ObjectPattern, ImportDeclaration or ExportNamedDeclaration node.
 
-          * @returns {void}
 
-          */
 
-         function check(node) {
 
-             const options = normalizedOptions[node.type];
 
-             if (
 
-                 (node.type === "ImportDeclaration" &&
 
-                     !node.specifiers.some(specifier => specifier.type === "ImportSpecifier")) ||
 
-                 (node.type === "ExportNamedDeclaration" &&
 
-                     !node.specifiers.some(specifier => specifier.type === "ExportSpecifier"))
 
-             ) {
 
-                 return;
 
-             }
 
-             const openBrace = sourceCode.getFirstToken(node, token => token.value === "{");
 
-             let closeBrace;
 
-             if (node.typeAnnotation) {
 
-                 closeBrace = sourceCode.getTokenBefore(node.typeAnnotation);
 
-             } else {
 
-                 closeBrace = sourceCode.getLastToken(node, token => token.value === "}");
 
-             }
 
-             let first = sourceCode.getTokenAfter(openBrace, { includeComments: true });
 
-             let last = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
 
-             const needsLineBreaks = areLineBreaksRequired(node, options, first, last);
 
-             const hasCommentsFirstToken = astUtils.isCommentToken(first);
 
-             const hasCommentsLastToken = astUtils.isCommentToken(last);
 
-             /*
 
-              * Use tokens or comments to check multiline or not.
 
-              * But use only tokens to check whether line breaks are needed.
 
-              * This allows:
 
-              *     var obj = { // eslint-disable-line foo
 
-              *         a: 1
 
-              *     }
 
-              */
 
-             first = sourceCode.getTokenAfter(openBrace);
 
-             last = sourceCode.getTokenBefore(closeBrace);
 
-             if (needsLineBreaks) {
 
-                 if (astUtils.isTokenOnSameLine(openBrace, first)) {
 
-                     context.report({
 
-                         message: "Expected a line break after this opening brace.",
 
-                         node,
 
-                         loc: openBrace.loc.start,
 
-                         fix(fixer) {
 
-                             if (hasCommentsFirstToken) {
 
-                                 return null;
 
-                             }
 
-                             return fixer.insertTextAfter(openBrace, "\n");
 
-                         }
 
-                     });
 
-                 }
 
-                 if (astUtils.isTokenOnSameLine(last, closeBrace)) {
 
-                     context.report({
 
-                         message: "Expected a line break before this closing brace.",
 
-                         node,
 
-                         loc: closeBrace.loc.start,
 
-                         fix(fixer) {
 
-                             if (hasCommentsLastToken) {
 
-                                 return null;
 
-                             }
 
-                             return fixer.insertTextBefore(closeBrace, "\n");
 
-                         }
 
-                     });
 
-                 }
 
-             } else {
 
-                 const consistent = options.consistent;
 
-                 const hasLineBreakBetweenOpenBraceAndFirst = !astUtils.isTokenOnSameLine(openBrace, first);
 
-                 const hasLineBreakBetweenCloseBraceAndLast = !astUtils.isTokenOnSameLine(last, closeBrace);
 
-                 if (
 
-                     (!consistent && hasLineBreakBetweenOpenBraceAndFirst) ||
 
-                     (consistent && hasLineBreakBetweenOpenBraceAndFirst && !hasLineBreakBetweenCloseBraceAndLast)
 
-                 ) {
 
-                     context.report({
 
-                         message: "Unexpected line break after this opening brace.",
 
-                         node,
 
-                         loc: openBrace.loc.start,
 
-                         fix(fixer) {
 
-                             if (hasCommentsFirstToken) {
 
-                                 return null;
 
-                             }
 
-                             return fixer.removeRange([
 
-                                 openBrace.range[1],
 
-                                 first.range[0]
 
-                             ]);
 
-                         }
 
-                     });
 
-                 }
 
-                 if (
 
-                     (!consistent && hasLineBreakBetweenCloseBraceAndLast) ||
 
-                     (consistent && !hasLineBreakBetweenOpenBraceAndFirst && hasLineBreakBetweenCloseBraceAndLast)
 
-                 ) {
 
-                     context.report({
 
-                         message: "Unexpected line break before this closing brace.",
 
-                         node,
 
-                         loc: closeBrace.loc.start,
 
-                         fix(fixer) {
 
-                             if (hasCommentsLastToken) {
 
-                                 return null;
 
-                             }
 
-                             return fixer.removeRange([
 
-                                 last.range[1],
 
-                                 closeBrace.range[0]
 
-                             ]);
 
-                         }
 
-                     });
 
-                 }
 
-             }
 
-         }
 
-         return {
 
-             ObjectExpression: check,
 
-             ObjectPattern: check,
 
-             ImportDeclaration: check,
 
-             ExportNamedDeclaration: check
 
-         };
 
-     }
 
- };
 
 
  |