require-emit-validator.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * @fileoverview Emit definitions should be detailed
  3. * @author Pig Fang
  4. */
  5. 'use strict'
  6. const utils = require('../utils')
  7. /**
  8. * @typedef {import('../utils').ComponentEmit} ComponentEmit
  9. */
  10. // ------------------------------------------------------------------------------
  11. // Rule Definition
  12. // ------------------------------------------------------------------------------
  13. module.exports = {
  14. meta: {
  15. hasSuggestions: true,
  16. type: 'suggestion',
  17. docs: {
  18. description: 'require type definitions in emits',
  19. categories: undefined,
  20. url: 'https://eslint.vuejs.org/rules/require-emit-validator.html'
  21. },
  22. fixable: null,
  23. messages: {
  24. missing: 'Emit "{{name}}" should define at least its validator function.',
  25. skipped:
  26. 'Emit "{{name}}" should not skip validation, or you may define a validator function with no parameters.',
  27. emptyValidation: 'Replace with a validator function with no parameters.'
  28. },
  29. schema: []
  30. },
  31. /** @param {RuleContext} context */
  32. create(context) {
  33. // ----------------------------------------------------------------------
  34. // Helpers
  35. // ----------------------------------------------------------------------
  36. /**
  37. * @param {ComponentEmit} emit
  38. */
  39. function checker(emit) {
  40. if (emit.type !== 'object' && emit.type !== 'array') {
  41. return
  42. }
  43. const { value, node, emitName } = emit
  44. const hasType =
  45. !!value &&
  46. (value.type === 'ArrowFunctionExpression' ||
  47. value.type === 'FunctionExpression' ||
  48. // validator may from outer scope
  49. value.type === 'Identifier')
  50. if (!hasType) {
  51. const name =
  52. emitName ||
  53. (node.type === 'Identifier' && node.name) ||
  54. 'Unknown emit'
  55. if (value && value.type === 'Literal' && value.value === null) {
  56. context.report({
  57. node,
  58. messageId: 'skipped',
  59. data: { name },
  60. suggest: [
  61. {
  62. messageId: 'emptyValidation',
  63. fix: (fixer) => fixer.replaceText(value, '() => true')
  64. }
  65. ]
  66. })
  67. return
  68. }
  69. context.report({
  70. node,
  71. messageId: 'missing',
  72. data: { name }
  73. })
  74. }
  75. }
  76. // ----------------------------------------------------------------------
  77. // Public
  78. // ----------------------------------------------------------------------
  79. return utils.compositingVisitors(
  80. utils.executeOnVue(context, (obj) => {
  81. utils.getComponentEmitsFromOptions(obj).forEach(checker)
  82. }),
  83. utils.defineScriptSetupVisitor(context, {
  84. onDefineEmitsEnter(_node, emits) {
  85. emits.forEach(checker)
  86. }
  87. })
  88. )
  89. }
  90. }