object-property-newline.js 3.6 KB

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