no-regexp-named-capture-groups.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /**
  2. * @author Toru Nagashima <https://github.com/mysticatea>
  3. * See LICENSE file in root directory for full license.
  4. */
  5. "use strict"
  6. const { RegExpValidator } = require("regexpp")
  7. const { getRegExpCalls } = require("../utils")
  8. /**
  9. * Verify a given regular expression.
  10. * @param {RuleContext} context The rule context to report.
  11. * @param {Node} node The AST node to report.
  12. * @param {string} pattern The pattern part of a RegExp.
  13. * @param {string} flags The flags part of a RegExp.
  14. * @returns {void}
  15. */
  16. function verify(context, node, pattern, flags) {
  17. try {
  18. let found = false
  19. new RegExpValidator({
  20. onCapturingGroupEnter(_start, name) {
  21. if (name) {
  22. found = true
  23. }
  24. },
  25. onBackreference(_start, _end, ref) {
  26. if (typeof ref === "string") {
  27. found = true
  28. }
  29. },
  30. }).validatePattern(pattern, 0, pattern.length, flags.includes("u"))
  31. if (found) {
  32. context.report({ node, messageId: "forbidden" })
  33. }
  34. } catch (error) {
  35. //istanbul ignore else
  36. if (error.message.startsWith("Invalid regular expression:")) {
  37. return
  38. }
  39. //istanbul ignore next
  40. throw error
  41. }
  42. }
  43. module.exports = {
  44. meta: {
  45. docs: {
  46. description: "disallow RegExp named capture groups.",
  47. category: "ES2018",
  48. recommended: false,
  49. url:
  50. "http://mysticatea.github.io/eslint-plugin-es/rules/no-regexp-named-capture-groups.html",
  51. },
  52. fixable: null,
  53. schema: [],
  54. messages: {
  55. forbidden: "ES2018 RegExp named capture groups are forbidden.",
  56. },
  57. },
  58. create(context) {
  59. return {
  60. "Literal[regex]"(node) {
  61. const { pattern, flags } = node.regex
  62. verify(context, node, pattern || "", flags || "")
  63. },
  64. "Program:exit"() {
  65. const scope = context.getScope()
  66. for (const { node, pattern, flags } of getRegExpCalls(scope)) {
  67. verify(context, node, pattern || "", flags || "")
  68. }
  69. },
  70. }
  71. },
  72. }