Skip to content

refactor: use regexp-groups to simplify ignores #2776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions lib/rules/attribute-hyphenation.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

const utils = require('../utils')
const casing = require('../utils/casing')
const { toRegExp } = require('../utils/regexp')
const { toRegExpGroupMatcher } = require('../utils/regexp')
const svgAttributes = require('../utils/svg-attributes-weird-case.json')

/**
Expand Down Expand Up @@ -79,11 +79,7 @@ module.exports = {
const option = context.options[0]
const optionsPayload = context.options[1]
const useHyphenated = option !== 'never'
/** @type {RegExp[]} */
const ignoredTagsRegexps = (
(optionsPayload && optionsPayload.ignoreTags) ||
[]
).map(toRegExp)
const ignoredTagsMatcher = toRegExpGroupMatcher(optionsPayload?.ignoreTags)
const ignoredAttributes = ['data-', 'aria-', 'slot-scope', ...svgAttributes]

if (optionsPayload && optionsPayload.ignore) {
Expand Down Expand Up @@ -142,17 +138,12 @@ module.exports = {
return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
}

/** @param {string} name */
function isIgnoredTagName(name) {
return ignoredTagsRegexps.some((re) => re.test(name))
}

return utils.defineTemplateBodyVisitor(context, {
VAttribute(node) {
const element = node.parent.parent
if (
(!utils.isCustomComponent(element) && element.name !== 'slot') ||
isIgnoredTagName(element.rawName)
ignoredTagsMatcher(element.rawName)
)
return

Expand Down
7 changes: 3 additions & 4 deletions lib/rules/component-name-in-template-casing.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

const utils = require('../utils')
const casing = require('../utils/casing')
const { toRegExp } = require('../utils/regexp')
const { toRegExpGroupMatcher } = require('../utils/regexp')

const allowedCaseOptions = ['PascalCase', 'kebab-case']
const defaultCase = 'PascalCase'
Expand Down Expand Up @@ -81,8 +81,7 @@ module.exports = {
const caseType = allowedCaseOptions.includes(caseOption)
? caseOption
: defaultCase
/** @type {RegExp[]} */
const ignores = (options.ignores || []).map(toRegExp)
const ignoreMatcher = toRegExpGroupMatcher(options.ignores)
/** @type {string[]} */
const globals = (options.globals || []).map(casing.pascalCase)
const registeredComponentsOnly = options.registeredComponentsOnly !== false
Expand Down Expand Up @@ -116,7 +115,7 @@ module.exports = {
* @returns {boolean} `true` if the given node is the verification target node.
*/
function isVerifyTarget(node) {
if (ignores.some((re) => re.test(node.rawName))) {
if (ignoreMatcher(node.rawName)) {
// ignore
return false
}
Expand Down
7 changes: 3 additions & 4 deletions lib/rules/custom-event-name-casing.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
const { findVariable } = require('@eslint-community/eslint-utils')
const utils = require('../utils')
const casing = require('../utils/casing')
const { toRegExp } = require('../utils/regexp')
const { toRegExpGroupMatcher } = require('../utils/regexp')

/**
* @typedef {import('../utils').VueObjectData} VueObjectData
Expand Down Expand Up @@ -92,8 +92,7 @@ module.exports = {
const caseType = context.options[0] || DEFAULT_CASE
const objectOption = context.options[1] || {}
const caseChecker = casing.getChecker(caseType)
/** @type {RegExp[]} */
const ignores = (objectOption.ignores || []).map(toRegExp)
const ignoreMatcher = toRegExpGroupMatcher(objectOption.ignores)

/**
* Check whether the given event name is valid.
Expand All @@ -109,7 +108,7 @@ module.exports = {
*/
function verify(nameWithLoc) {
const name = nameWithLoc.name
if (isValidEventName(name) || ignores.some((re) => re.test(name))) {
if (isValidEventName(name) || ignoreMatcher(name)) {
return
}
context.report({
Expand Down
18 changes: 2 additions & 16 deletions lib/rules/no-restricted-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,16 @@ const regexp = require('../utils/regexp')
* @property {string} [message]
*/

/**
* @param {string} str
* @returns {(str: string) => boolean}
*/
function buildMatcher(str) {
if (regexp.isRegExp(str)) {
const re = regexp.toRegExp(str)
return (s) => {
re.lastIndex = 0
return re.test(s)
}
}
return (s) => s === str
}
/**
* @param {any} option
* @returns {ParsedOption}
*/
function parseOption(option) {
if (typeof option === 'string') {
const matcher = buildMatcher(option)
const matcher = regexp.toRegExp(option, { remove: 'g' })
return {
test(block) {
return matcher(block.rawName)
return matcher.test(block.rawName)
}
}
}
Expand Down
28 changes: 7 additions & 21 deletions lib/rules/no-restricted-class.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,15 @@ const regexp = require('../utils/regexp')
* @param {string} className
* @param {*} node
* @param {RuleContext} context
* @param {Set<string>} forbiddenClasses
* @param {Array<RegExp>} forbiddenClassesRegexps
* @param {(name: string) => boolean} forbiddenGroupMatcher
*/
const reportForbiddenClass = (
className,
node,
context,
forbiddenClasses,
forbiddenClassesRegexps
forbiddenGroupMatcher
) => {
if (
forbiddenClasses.has(className) ||
forbiddenClassesRegexps.some((re) => re.test(className))
) {
if (forbiddenGroupMatcher(className)) {
const loc = node.value ? node.value.loc : node.loc
context.report({
node,
Expand Down Expand Up @@ -123,24 +118,16 @@ module.exports = {

/** @param {RuleContext} context */
create(context) {
const forbiddenClasses = new Set(context.options || [])
const forbiddenClassesRegexps = (context.options || [])
.filter((cl) => regexp.isRegExp(cl))
.map((cl) => regexp.toRegExp(cl))
const { options = [] } = context
const forbiddenGroupMatcher = regexp.toRegExpGroupMatcher(options)

return utils.defineTemplateBodyVisitor(context, {
/**
* @param {VAttribute & { value: VLiteral } } node
*/
'VAttribute[directive=false][key.name="class"][value!=null]'(node) {
for (const className of node.value.value.split(/\s+/)) {
reportForbiddenClass(
className,
node,
context,
forbiddenClasses,
forbiddenClassesRegexps
)
reportForbiddenClass(className, node, context, forbiddenGroupMatcher)
}
},

Expand All @@ -159,8 +146,7 @@ module.exports = {
className,
reportNode,
context,
forbiddenClasses,
forbiddenClassesRegexps
forbiddenGroupMatcher
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/no-restricted-component-names.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const { isRegExp, toRegExp } = require('../utils/regexp')
*/
function buildMatcher(str) {
if (isRegExp(str)) {
const regex = toRegExp(str)
const regex = toRegExp(str, { remove: 'g' })
return (s) => regex.test(s)
}
return (s) => s === casing.pascalCase(str) || s === casing.kebabCase(str)
Expand Down
18 changes: 2 additions & 16 deletions lib/rules/no-restricted-component-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,6 @@ const regexp = require('../utils/regexp')
* @typedef { (node: Property | SpreadElement) => (MatchResult | null) } Tester
*/

/**
* @param {string} str
* @returns {Matcher}
*/
function buildMatcher(str) {
if (regexp.isRegExp(str)) {
const re = regexp.toRegExp(str)
return (s) => {
re.lastIndex = 0
return re.test(s)
}
}
return (s) => s === str
}

/**
* @param {string | string[] | { name: string | string[], message?: string } } option
* @returns {ParsedOption}
Expand Down Expand Up @@ -65,7 +50,8 @@ function parseOption(option) {
if (name === '*') {
steps.push({ wildcard: true })
} else {
steps.push({ test: buildMatcher(name) })
const matcher = regexp.toRegExp(name, { remove: 'g' })
steps.push({ test: (value) => matcher.test(value) })
}
}
const message = option.message
Expand Down
18 changes: 2 additions & 16 deletions lib/rules/no-restricted-custom-event.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,16 @@ const regexp = require('../utils/regexp')
* @property {string|undefined} [suggest]
*/

/**
* @param {string} str
* @returns {(str: string) => boolean}
*/
function buildMatcher(str) {
if (regexp.isRegExp(str)) {
const re = regexp.toRegExp(str)
return (s) => {
re.lastIndex = 0
return re.test(s)
}
}
return (s) => s === str
}
/**
* @param {string|{event: string, message?: string, suggest?: string}} option
* @returns {ParsedOption}
*/
function parseOption(option) {
if (typeof option === 'string') {
const matcher = buildMatcher(option)
const matcher = regexp.toRegExp(option, { remove: 'g' })
return {
test(name) {
return matcher(name)
return matcher.test(name)
}
}
}
Expand Down
18 changes: 2 additions & 16 deletions lib/rules/no-restricted-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,16 @@ const regexp = require('../utils/regexp')
* @property {string|undefined} [suggest]
*/

/**
* @param {string} str
* @returns {(str: string) => boolean}
*/
function buildMatcher(str) {
if (regexp.isRegExp(str)) {
const re = regexp.toRegExp(str)
return (s) => {
re.lastIndex = 0
return re.test(s)
}
}
return (s) => s === str
}
/**
* @param {string|{name:string, message?: string, suggest?:string}} option
* @returns {ParsedOption}
*/
function parseOption(option) {
if (typeof option === 'string') {
const matcher = buildMatcher(option)
const matcher = regexp.toRegExp(option, { remove: 'g' })
return {
test(name) {
return matcher(name)
return matcher.test(name)
}
}
}
Expand Down
26 changes: 6 additions & 20 deletions lib/rules/no-restricted-static-attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,16 @@ const regexp = require('../utils/regexp')
* @property {string} [message]
*/

/**
* @param {string} str
* @returns {(str: string) => boolean}
*/
function buildMatcher(str) {
if (regexp.isRegExp(str)) {
const re = regexp.toRegExp(str)
return (s) => {
re.lastIndex = 0
return re.test(s)
}
}
return (s) => s === str
}
/**
* @param {any} option
* @returns {ParsedOption}
*/
function parseOption(option) {
if (typeof option === 'string') {
const matcher = buildMatcher(option)
const matcher = regexp.toRegExp(option, { remove: 'g' })
return {
test({ key }) {
return matcher(key.rawName)
return matcher.test(key.rawName)
}
}
}
Expand All @@ -53,25 +39,25 @@ function parseOption(option) {
return node.value == null || node.value.value === node.key.rawName
}
} else {
const valueMatcher = buildMatcher(option.value)
const valueMatcher = regexp.toRegExp(option.value, { remove: 'g' })
parsed.test = (node) => {
if (!keyTest(node)) {
return false
}
return node.value != null && valueMatcher(node.value.value)
return node.value != null && valueMatcher.test(node.value.value)
}
}
parsed.useValue = true
}
if (option.element) {
const argTest = parsed.test
const tagMatcher = buildMatcher(option.element)
const tagMatcher = regexp.toRegExp(option.element, { remove: 'g' })
parsed.test = (node) => {
if (!argTest(node)) {
return false
}
const element = node.parent.parent
return tagMatcher(element.rawName)
return tagMatcher.test(element.rawName)
}
parsed.useElement = true
}
Expand Down
Loading