no-boolean-default.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /**
  2. * @fileoverview Prevents boolean defaults from being set
  3. * @author Hiroki Osame
  4. */
  5. 'use strict'
  6. const utils = require('../utils')
  7. /**
  8. * @typedef {import('../utils').ComponentArrayProp} ComponentArrayProp
  9. * @typedef {import('../utils').ComponentObjectProp} ComponentObjectProp
  10. */
  11. // ------------------------------------------------------------------------------
  12. // Rule Definition
  13. // ------------------------------------------------------------------------------
  14. /**
  15. * @param {Property | SpreadElement} prop
  16. */
  17. function isBooleanProp(prop) {
  18. return (
  19. prop.type === 'Property' &&
  20. prop.key.type === 'Identifier' &&
  21. prop.key.name === 'type' &&
  22. prop.value.type === 'Identifier' &&
  23. prop.value.name === 'Boolean'
  24. )
  25. }
  26. /**
  27. * @typedef {ComponentObjectProp & { value : ObjectExpression }} ObjectExpressionProp
  28. */
  29. /**
  30. * @param {(ComponentArrayProp | ComponentObjectProp)[]} props
  31. * @returns {ObjectExpressionProp[]}
  32. */
  33. function getBooleanProps(props) {
  34. return props.filter(
  35. /**
  36. * @param {ComponentArrayProp | ComponentObjectProp} prop
  37. * @returns {prop is ObjectExpressionProp}
  38. */
  39. (prop) =>
  40. prop.value != null &&
  41. prop.value.type === 'ObjectExpression' &&
  42. prop.value.properties.some(isBooleanProp)
  43. )
  44. }
  45. /**
  46. * @param {ObjectExpressionProp} propDef
  47. */
  48. function getDefaultNode(propDef) {
  49. return utils.findProperty(propDef.value, 'default')
  50. }
  51. module.exports = {
  52. meta: {
  53. type: 'suggestion',
  54. docs: {
  55. description: 'disallow boolean defaults',
  56. categories: undefined,
  57. url: 'https://eslint.vuejs.org/rules/no-boolean-default.html'
  58. },
  59. fixable: 'code',
  60. schema: [
  61. {
  62. enum: ['default-false', 'no-default']
  63. }
  64. ]
  65. },
  66. /** @param {RuleContext} context */
  67. create(context) {
  68. return utils.executeOnVueComponent(context, (obj) => {
  69. const props = utils.getComponentProps(obj)
  70. const booleanProps = getBooleanProps(props)
  71. if (!booleanProps.length) return
  72. const booleanType = context.options[0] || 'no-default'
  73. booleanProps.forEach((propDef) => {
  74. const defaultNode = getDefaultNode(propDef)
  75. if (!defaultNode) {
  76. return
  77. }
  78. switch (booleanType) {
  79. case 'no-default':
  80. context.report({
  81. node: defaultNode,
  82. message:
  83. 'Boolean prop should not set a default (Vue defaults it to false).'
  84. })
  85. break
  86. case 'default-false':
  87. if (
  88. defaultNode.value.type !== 'Literal' ||
  89. defaultNode.value.value !== false
  90. ) {
  91. context.report({
  92. node: defaultNode,
  93. message: 'Boolean prop should only be defaulted to false.'
  94. })
  95. }
  96. break
  97. }
  98. })
  99. })
  100. }
  101. }