no-regexp-lookbehind-assertions.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  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. onLookaroundAssertionEnter(_start, kind) {
  21. if (kind === "lookbehind") {
  22. found = true
  23. }
  24. },
  25. }).validatePattern(pattern, 0, pattern.length, flags.includes("u"))
  26. if (found) {
  27. context.report({ node, messageId: "forbidden" })
  28. }
  29. } catch (error) {
  30. //istanbul ignore else
  31. if (error.message.startsWith("Invalid regular expression:")) {
  32. return
  33. }
  34. //istanbul ignore next
  35. throw error
  36. }
  37. }
  38. module.exports = {
  39. meta: {
  40. docs: {
  41. description: "disallow RegExp lookbehind assertions.",
  42. category: "ES2018",
  43. recommended: false,
  44. url:
  45. "http://mysticatea.github.io/eslint-plugin-es/rules/no-regexp-lookbehind-assertions.html",
  46. },
  47. fixable: null,
  48. messages: {
  49. forbidden: "ES2018 RegExp lookbehind assertions are forbidden.",
  50. },
  51. schema: [],
  52. type: "problem",
  53. },
  54. create(context) {
  55. return {
  56. "Literal[regex]"(node) {
  57. const { pattern, flags } = node.regex
  58. verify(context, node, pattern || "", flags || "")
  59. },
  60. "Program:exit"() {
  61. const scope = context.getScope()
  62. for (const { node, pattern, flags } of getRegExpCalls(scope)) {
  63. verify(context, node, pattern || "", flags || "")
  64. }
  65. },
  66. }
  67. },
  68. }