object-property-newline.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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. /** @type {import('../shared/types').Rule} */
  10. module.exports = {
  11. meta: {
  12. type: "layout",
  13. docs: {
  14. description: "Enforce placing object properties on separate lines",
  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. messages: {
  36. propertiesOnNewlineAll: "Object properties must go on a new line if they aren't all on the same line.",
  37. propertiesOnNewline: "Object properties must go on a new line."
  38. }
  39. },
  40. create(context) {
  41. const allowSameLine = context.options[0] && (
  42. (context.options[0].allowAllPropertiesOnSameLine || context.options[0].allowMultiplePropertiesPerLine /* Deprecated */)
  43. );
  44. const messageId = allowSameLine
  45. ? "propertiesOnNewlineAll"
  46. : "propertiesOnNewline";
  47. const sourceCode = context.getSourceCode();
  48. return {
  49. ObjectExpression(node) {
  50. if (allowSameLine) {
  51. if (node.properties.length > 1) {
  52. const firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]);
  53. const lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]);
  54. if (firstTokenOfFirstProperty.loc.end.line === lastTokenOfLastProperty.loc.start.line) {
  55. // All keys and values are on the same line
  56. return;
  57. }
  58. }
  59. }
  60. for (let i = 1; i < node.properties.length; i++) {
  61. const lastTokenOfPreviousProperty = sourceCode.getLastToken(node.properties[i - 1]);
  62. const firstTokenOfCurrentProperty = sourceCode.getFirstToken(node.properties[i]);
  63. if (lastTokenOfPreviousProperty.loc.end.line === firstTokenOfCurrentProperty.loc.start.line) {
  64. context.report({
  65. node,
  66. loc: firstTokenOfCurrentProperty.loc,
  67. messageId,
  68. fix(fixer) {
  69. const comma = sourceCode.getTokenBefore(firstTokenOfCurrentProperty);
  70. const rangeAfterComma = [comma.range[1], firstTokenOfCurrentProperty.range[0]];
  71. // Don't perform a fix if there are any comments between the comma and the next property.
  72. if (sourceCode.text.slice(rangeAfterComma[0], rangeAfterComma[1]).trim()) {
  73. return null;
  74. }
  75. return fixer.replaceTextRange(rangeAfterComma, "\n");
  76. }
  77. });
  78. }
  79. }
  80. }
  81. };
  82. }
  83. };