computed-property-even-spacing.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. 'use strict'
  2. /**
  3. * @fileoverview Disallows or enforces spaces inside computed properties.
  4. * @author Jamund Ferguson
  5. * @copyright 2015 Jamund Ferguson. All rights reserved.
  6. */
  7. // ------------------------------------------------------------------------------
  8. // Rule Definition
  9. // ------------------------------------------------------------------------------
  10. module.exports = {
  11. meta: {
  12. type: 'layout',
  13. docs: {
  14. url: 'https://github.com/standard/eslint-plugin-standard#rules-explanations'
  15. }
  16. },
  17. create: function (context) {
  18. const propertyNameMustBeSpaced = context.options[0] === 'always' // default is "never"
  19. const propertyNameMustBeEven = context.options[0] === 'even' // default is "never"
  20. // --------------------------------------------------------------------------
  21. // Helpers
  22. // --------------------------------------------------------------------------
  23. /**
  24. * Determines whether two adjacent tokens are have whitespace between them.
  25. * @param {Object} left - The left token object.
  26. * @param {Object} right - The right token object.
  27. * @returns {boolean} Whether or not there is space between the tokens.
  28. */
  29. function isSpaced (left, right) {
  30. return left.range[1] < right.range[0]
  31. }
  32. /**
  33. * Determines whether two adjacent tokens are on the same line.
  34. * @param {Object} left - The left token object.
  35. * @param {Object} right - The right token object.
  36. * @returns {boolean} Whether or not the tokens are on the same line.
  37. */
  38. function isSameLine (left, right) {
  39. return left.loc.start.line === right.loc.start.line
  40. }
  41. /**
  42. * Reports that there shouldn't be a space after the first token
  43. * @param {ASTNode} node - The node to report in the event of an error.
  44. * @param {Token} token - The token to use for the report.
  45. * @returns {void}
  46. */
  47. function reportNoBeginningSpace (node, token) {
  48. context.report(node, token.loc.start,
  49. "There should be no space after '" + token.value + "'")
  50. }
  51. /**
  52. * Reports that there shouldn't be a space before the last token
  53. * @param {ASTNode} node - The node to report in the event of an error.
  54. * @param {Token} token - The token to use for the report.
  55. * @returns {void}
  56. */
  57. function reportNoEndingSpace (node, token) {
  58. context.report(node, token.loc.start,
  59. "There should be no space before '" + token.value + "'")
  60. }
  61. /**
  62. * Reports that there should be a space after the first token
  63. * @param {ASTNode} node - The node to report in the event of an error.
  64. * @param {Token} token - The token to use for the report.
  65. * @returns {void}
  66. */
  67. function reportRequiredBeginningSpace (node, token) {
  68. context.report(node, token.loc.start,
  69. "A space is required after '" + token.value + "'")
  70. }
  71. /**
  72. * Reports that there should be a space before the last token
  73. * @param {ASTNode} node - The node to report in the event of an error.
  74. * @param {Token} token - The token to use for the report.
  75. * @returns {void}
  76. */
  77. function reportRequiredEndingSpace (node, token) {
  78. context.report(node, token.loc.start,
  79. "A space is required before '" + token.value + "'")
  80. }
  81. /**
  82. * Returns a function that checks the spacing of a node on the property name
  83. * that was passed in.
  84. * @param {String} propertyName The property on the node to check for spacing
  85. * @returns {Function} A function that will check spacing on a node
  86. */
  87. function checkSpacing (propertyName) {
  88. return function (node) {
  89. if (!node.computed) {
  90. return
  91. }
  92. const property = node[propertyName]
  93. const before = context.getTokenBefore(property)
  94. const first = context.getFirstToken(property)
  95. const last = context.getLastToken(property)
  96. const after = context.getTokenAfter(property)
  97. let startSpace, endSpace
  98. if (propertyNameMustBeEven) {
  99. if (!isSameLine(before, after)) {
  100. context.report(node, 'Expected "[" and "]" to be on the same line')
  101. return
  102. }
  103. startSpace = first.loc.start.column - before.loc.end.column
  104. endSpace = after.loc.start.column - last.loc.end.column
  105. if (startSpace !== endSpace || startSpace > 1) {
  106. context.report(node, 'Expected 1 or 0 spaces around "[" and "]"')
  107. }
  108. return
  109. }
  110. if (isSameLine(before, first)) {
  111. if (propertyNameMustBeSpaced) {
  112. if (!isSpaced(before, first) && isSameLine(before, first)) {
  113. reportRequiredBeginningSpace(node, before)
  114. }
  115. } else {
  116. if (isSpaced(before, first)) {
  117. reportNoBeginningSpace(node, before)
  118. }
  119. }
  120. }
  121. if (isSameLine(last, after)) {
  122. if (propertyNameMustBeSpaced) {
  123. if (!isSpaced(last, after) && isSameLine(last, after)) {
  124. reportRequiredEndingSpace(node, after)
  125. }
  126. } else {
  127. if (isSpaced(last, after)) {
  128. reportNoEndingSpace(node, after)
  129. }
  130. }
  131. }
  132. }
  133. }
  134. // --------------------------------------------------------------------------
  135. // Public
  136. // --------------------------------------------------------------------------
  137. return {
  138. Property: checkSpacing('key'),
  139. MemberExpression: checkSpacing('property')
  140. }
  141. }
  142. }