1/** 2 * @fileoverview Rule to enforce placing object properties on separate lines. 3 * @author Vitor Balocco 4 */ 5 6"use strict"; 7 8//------------------------------------------------------------------------------ 9// Rule Definition 10//------------------------------------------------------------------------------ 11 12module.exports = { 13 meta: { 14 type: "layout", 15 16 docs: { 17 description: "enforce placing object properties on separate lines", 18 category: "Stylistic Issues", 19 recommended: false, 20 url: "https://eslint.org/docs/rules/object-property-newline" 21 }, 22 23 schema: [ 24 { 25 type: "object", 26 properties: { 27 allowAllPropertiesOnSameLine: { 28 type: "boolean", 29 default: false 30 }, 31 allowMultiplePropertiesPerLine: { // Deprecated 32 type: "boolean", 33 default: false 34 } 35 }, 36 additionalProperties: false 37 } 38 ], 39 40 fixable: "whitespace", 41 42 messages: { 43 propertiesOnNewlineAll: "Object properties must go on a new line if they aren't all on the same line.", 44 propertiesOnNewline: "Object properties must go on a new line." 45 } 46 }, 47 48 create(context) { 49 const allowSameLine = context.options[0] && ( 50 (context.options[0].allowAllPropertiesOnSameLine || context.options[0].allowMultiplePropertiesPerLine /* Deprecated */) 51 ); 52 const messageId = allowSameLine 53 ? "propertiesOnNewlineAll" 54 : "propertiesOnNewline"; 55 56 const sourceCode = context.getSourceCode(); 57 58 return { 59 ObjectExpression(node) { 60 if (allowSameLine) { 61 if (node.properties.length > 1) { 62 const firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]); 63 const lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]); 64 65 if (firstTokenOfFirstProperty.loc.end.line === lastTokenOfLastProperty.loc.start.line) { 66 67 // All keys and values are on the same line 68 return; 69 } 70 } 71 } 72 73 for (let i = 1; i < node.properties.length; i++) { 74 const lastTokenOfPreviousProperty = sourceCode.getLastToken(node.properties[i - 1]); 75 const firstTokenOfCurrentProperty = sourceCode.getFirstToken(node.properties[i]); 76 77 if (lastTokenOfPreviousProperty.loc.end.line === firstTokenOfCurrentProperty.loc.start.line) { 78 context.report({ 79 node, 80 loc: firstTokenOfCurrentProperty.loc.start, 81 messageId, 82 fix(fixer) { 83 const comma = sourceCode.getTokenBefore(firstTokenOfCurrentProperty); 84 const rangeAfterComma = [comma.range[1], firstTokenOfCurrentProperty.range[0]]; 85 86 // Don't perform a fix if there are any comments between the comma and the next property. 87 if (sourceCode.text.slice(rangeAfterComma[0], rangeAfterComma[1]).trim()) { 88 return null; 89 } 90 91 return fixer.replaceTextRange(rangeAfterComma, "\n"); 92 } 93 }); 94 } 95 } 96 } 97 }; 98 } 99}; 100