eslint-plugin-regexp
Advanced tools
@@ -5,9 +5,17 @@ "use strict"; | ||
const CASE_SCHEMA = ["lowercase", "uppercase", "ignore"]; | ||
const DEFAULTS = { | ||
caseInsensitive: "lowercase", | ||
unicodeEscape: "lowercase", | ||
hexadecimalEscape: "ignore", | ||
controlEscape: "ignore", | ||
}; | ||
function parseOptions(option) { | ||
if (!option) { | ||
return { caseInsensitive: "lowercase", unicodeEscape: "lowercase" }; | ||
return DEFAULTS; | ||
} | ||
return { | ||
caseInsensitive: option.caseInsensitive || "lowercase", | ||
unicodeEscape: option.unicodeEscape || "lowercase", | ||
caseInsensitive: option.caseInsensitive || DEFAULTS.caseInsensitive, | ||
unicodeEscape: option.unicodeEscape || DEFAULTS.unicodeEscape, | ||
hexadecimalEscape: option.hexadecimalEscape || DEFAULTS.hexadecimalEscape, | ||
controlEscape: option.controlEscape || DEFAULTS.controlEscape, | ||
}; | ||
@@ -40,2 +48,4 @@ } | ||
unicodeEscape: { enum: CASE_SCHEMA }, | ||
hexadecimalEscape: { enum: CASE_SCHEMA }, | ||
controlEscape: { enum: CASE_SCHEMA }, | ||
}, | ||
@@ -99,3 +109,3 @@ additionalProperties: false, | ||
} | ||
const parts = /(\\u\{?)(.*)(\}?)/u.exec(cNode.raw); | ||
const parts = /^(\\u\{?)(.*)(\}?)$/u.exec(cNode.raw); | ||
if (STRING_CASE_CHECKER[options.unicodeEscape](parts[2])) { | ||
@@ -106,2 +116,22 @@ return; | ||
} | ||
function verifyCharacterInHexadecimalEscape(node, cNode) { | ||
if (options.hexadecimalEscape === "ignore") { | ||
return; | ||
} | ||
const parts = /^\\x(.*)$/u.exec(cNode.raw); | ||
if (STRING_CASE_CHECKER[options.hexadecimalEscape](parts[1])) { | ||
return; | ||
} | ||
report(node, cNode, options.hexadecimalEscape, (converter) => `\\x${converter(parts[1])}`); | ||
} | ||
function verifyCharacterInControl(node, cNode) { | ||
if (options.controlEscape === "ignore") { | ||
return; | ||
} | ||
const parts = /^\\c(.*)$/u.exec(cNode.raw); | ||
if (STRING_CASE_CHECKER[options.controlEscape](parts[1])) { | ||
return; | ||
} | ||
report(node, cNode, options.controlEscape, (converter) => `\\c${converter(parts[1])}`); | ||
} | ||
function createVisitor(node, _pattern, flags) { | ||
@@ -115,2 +145,8 @@ return Object.assign({ onCharacterEnter(cNode) { | ||
} | ||
if (/^\\x.+$/u.test(cNode.raw)) { | ||
verifyCharacterInHexadecimalEscape(node, cNode); | ||
} | ||
if (/^\\c[a-zA-Z]$/u.test(cNode.raw)) { | ||
verifyCharacterInControl(node, cNode); | ||
} | ||
} }, (flags.includes("i") | ||
@@ -117,0 +153,0 @@ ? { |
@@ -197,3 +197,16 @@ "use strict"; | ||
function canUnwrapped(node, text) { | ||
const { alternative, index } = getAlternativeAndIndex(); | ||
const parent = node.parent; | ||
let target, alternative; | ||
if (parent.type === "Quantifier") { | ||
alternative = parent.parent; | ||
target = parent; | ||
} | ||
else if (parent.type === "Alternative") { | ||
alternative = parent; | ||
target = node; | ||
} | ||
else { | ||
return true; | ||
} | ||
const index = alternative.elements.indexOf(target); | ||
if (index === 0) { | ||
@@ -250,19 +263,3 @@ return true; | ||
return true; | ||
function getAlternativeAndIndex() { | ||
const parent = node.parent; | ||
let target, alt; | ||
if (parent.type === "Quantifier") { | ||
alt = parent.parent; | ||
target = parent; | ||
} | ||
else { | ||
alt = parent; | ||
target = node; | ||
} | ||
return { | ||
alternative: alt, | ||
index: alt.elements.indexOf(target), | ||
}; | ||
} | ||
} | ||
exports.canUnwrapped = canUnwrapped; |
@@ -9,4 +9,6 @@ "use strict"; | ||
const match_any_1 = __importDefault(require("../rules/match-any")); | ||
const negation_1 = __importDefault(require("../rules/negation")); | ||
const no_assertion_capturing_group_1 = __importDefault(require("../rules/no-assertion-capturing-group")); | ||
const no_dupe_characters_character_class_1 = __importDefault(require("../rules/no-dupe-characters-character-class")); | ||
const no_dupe_disjunctions_1 = __importDefault(require("../rules/no-dupe-disjunctions")); | ||
const no_empty_group_1 = __importDefault(require("../rules/no-empty-group")); | ||
@@ -19,6 +21,10 @@ const no_empty_lookarounds_assertion_1 = __importDefault(require("../rules/no-empty-lookarounds-assertion")); | ||
const no_useless_character_class_1 = __importDefault(require("../rules/no-useless-character-class")); | ||
const no_useless_escape_1 = __importDefault(require("../rules/no-useless-escape")); | ||
const no_useless_exactly_quantifier_1 = __importDefault(require("../rules/no-useless-exactly-quantifier")); | ||
const no_useless_non_capturing_group_1 = __importDefault(require("../rules/no-useless-non-capturing-group")); | ||
const no_useless_non_greedy_1 = __importDefault(require("../rules/no-useless-non-greedy")); | ||
const no_useless_range_1 = __importDefault(require("../rules/no-useless-range")); | ||
const no_useless_two_nums_quantifier_1 = __importDefault(require("../rules/no-useless-two-nums-quantifier")); | ||
const order_in_character_class_1 = __importDefault(require("../rules/order-in-character-class")); | ||
const prefer_character_class_1 = __importDefault(require("../rules/prefer-character-class")); | ||
const prefer_d_1 = __importDefault(require("../rules/prefer-d")); | ||
@@ -28,2 +34,3 @@ const prefer_plus_quantifier_1 = __importDefault(require("../rules/prefer-plus-quantifier")); | ||
const prefer_question_quantifier_1 = __importDefault(require("../rules/prefer-question-quantifier")); | ||
const prefer_range_1 = __importDefault(require("../rules/prefer-range")); | ||
const prefer_regexp_exec_1 = __importDefault(require("../rules/prefer-regexp-exec")); | ||
@@ -38,4 +45,6 @@ const prefer_regexp_test_1 = __importDefault(require("../rules/prefer-regexp-test")); | ||
match_any_1.default, | ||
negation_1.default, | ||
no_assertion_capturing_group_1.default, | ||
no_dupe_characters_character_class_1.default, | ||
no_dupe_disjunctions_1.default, | ||
no_empty_group_1.default, | ||
@@ -48,6 +57,10 @@ no_empty_lookarounds_assertion_1.default, | ||
no_useless_character_class_1.default, | ||
no_useless_escape_1.default, | ||
no_useless_exactly_quantifier_1.default, | ||
no_useless_non_capturing_group_1.default, | ||
no_useless_non_greedy_1.default, | ||
no_useless_range_1.default, | ||
no_useless_two_nums_quantifier_1.default, | ||
order_in_character_class_1.default, | ||
prefer_character_class_1.default, | ||
prefer_d_1.default, | ||
@@ -57,2 +70,3 @@ prefer_plus_quantifier_1.default, | ||
prefer_question_quantifier_1.default, | ||
prefer_range_1.default, | ||
prefer_regexp_exec_1.default, | ||
@@ -59,0 +73,0 @@ prefer_regexp_test_1.default, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isLetter = exports.isUppercaseLetter = exports.isLowercaseLetter = exports.isDigit = exports.CP_RANGES_WORDS = exports.CP_RANGE_SPACES = exports.CP_RANGE_CAPITAL_LETTER = exports.CP_RANGE_SMALL_LETTER = exports.CP_RANGE_DIGIT = exports.CPS_SINGLE_SPACES = exports.CP_LOW_LINE = exports.CP_CAPITAL_Z = exports.CP_CAPITAL_A = exports.CP_SMALL_Z = exports.CP_SMALL_A = exports.CP_DIGIT_NINE = exports.CP_DIGIT_ZERO = exports.CP_BOM = exports.CP_IDEOGRAPHIC_SPACE = exports.CP_BRAILLE_PATTERN_BLANK = exports.CP_MMSP = exports.CP_NNBSP = exports.CP_PARAGRAPH_SEPARATOR = exports.CP_LINE_SEPARATOR = exports.CP_RLM = exports.CP_LRM = exports.CP_ZWJ = exports.CP_ZWNJ = exports.CP_ZWSP = exports.CP_HAIR_SPACE = exports.CP_EN_QUAD = exports.CP_MONGOLIAN_VOWEL_SEPARATOR = exports.CP_OGHAM_SPACE_MARK = exports.CP_NBSP = exports.CP_NEL = exports.CP_TILDE = exports.CP_OPENING_BRACE = exports.CP_BACKTICK = exports.CP_OPENING_BRACKET = exports.CP_AT = exports.CP_COLON = exports.CP_SLASH = exports.CP_BAN = exports.CP_SPACE = exports.CP_CR = exports.CP_FF = exports.CP_VT = exports.CP_LF = exports.CP_TAB = exports.CP_BACKSPACE = void 0; | ||
exports.invisibleEscape = exports.isInvisible = exports.isWord = exports.isSpace = exports.isSymbol = void 0; | ||
exports.CP_SMALL_Z = exports.CP_SMALL_A = exports.CP_DIGIT_NINE = exports.CP_DIGIT_ZERO = exports.CP_BOM = exports.CP_IDEOGRAPHIC_SPACE = exports.CP_BRAILLE_PATTERN_BLANK = exports.CP_MMSP = exports.CP_NNBSP = exports.CP_PARAGRAPH_SEPARATOR = exports.CP_LINE_SEPARATOR = exports.CP_RLM = exports.CP_LRM = exports.CP_ZWJ = exports.CP_ZWNJ = exports.CP_ZWSP = exports.CP_HAIR_SPACE = exports.CP_EN_QUAD = exports.CP_MONGOLIAN_VOWEL_SEPARATOR = exports.CP_OGHAM_SPACE_MARK = exports.CP_NBSP = exports.CP_NEL = exports.CP_TILDE = exports.CP_CLOSING_BRACE = exports.CP_PIPE = exports.CP_OPENING_BRACE = exports.CP_BACKTICK = exports.CP_CARET = exports.CP_CLOSING_BRACKET = exports.CP_BACK_SLASH = exports.CP_OPENING_BRACKET = exports.CP_AT = exports.CP_QUESTION = exports.CP_COLON = exports.CP_SLASH = exports.CP_DOT = exports.CP_MINUS = exports.CP_PLUS = exports.CP_STAR = exports.CP_CLOSING_PAREN = exports.CP_OPENING_PAREN = exports.CP_DOLLAR = exports.CP_BAN = exports.CP_SPACE = exports.CP_CR = exports.CP_FF = exports.CP_VT = exports.CP_LF = exports.CP_TAB = exports.CP_BACKSPACE = void 0; | ||
exports.invisibleEscape = exports.isInvisible = exports.isWord = exports.isSpace = exports.isSymbol = exports.isLetter = exports.isUppercaseLetter = exports.isLowercaseLetter = exports.isDigit = exports.CP_RANGES_WORDS = exports.CP_RANGE_SPACES = exports.CP_RANGE_CAPITAL_LETTER = exports.CP_RANGE_SMALL_LETTER = exports.CP_RANGE_DIGIT = exports.CPS_SINGLE_SPACES = exports.CP_LOW_LINE = exports.CP_CAPITAL_Z = exports.CP_CAPITAL_A = void 0; | ||
exports.CP_BACKSPACE = 8; | ||
@@ -13,8 +13,21 @@ exports.CP_TAB = 9; | ||
exports.CP_BAN = "!".codePointAt(0); | ||
exports.CP_DOLLAR = "$".codePointAt(0); | ||
exports.CP_OPENING_PAREN = "(".codePointAt(0); | ||
exports.CP_CLOSING_PAREN = ")".codePointAt(0); | ||
exports.CP_STAR = "*".codePointAt(0); | ||
exports.CP_PLUS = "+".codePointAt(0); | ||
exports.CP_MINUS = "-".codePointAt(0); | ||
exports.CP_DOT = ".".codePointAt(0); | ||
exports.CP_SLASH = "/".codePointAt(0); | ||
exports.CP_COLON = ":".codePointAt(0); | ||
exports.CP_QUESTION = "?".codePointAt(0); | ||
exports.CP_AT = "@".codePointAt(0); | ||
exports.CP_OPENING_BRACKET = "[".codePointAt(0); | ||
exports.CP_BACK_SLASH = "\\".codePointAt(0); | ||
exports.CP_CLOSING_BRACKET = "]".codePointAt(0); | ||
exports.CP_CARET = "^".codePointAt(0); | ||
exports.CP_BACKTICK = "`".codePointAt(0); | ||
exports.CP_OPENING_BRACE = "{".codePointAt(0); | ||
exports.CP_PIPE = "|".codePointAt(0); | ||
exports.CP_CLOSING_BRACE = "}".codePointAt(0); | ||
exports.CP_TILDE = "~".codePointAt(0); | ||
@@ -21,0 +34,0 @@ exports.CP_NEL = "\u0085".codePointAt(0); |
{ | ||
"name": "eslint-plugin-regexp", | ||
"version": "0.3.1", | ||
"version": "0.4.0", | ||
"description": "ESLint plugin for finding RegExp mistakes and RegExp style guide violations.", | ||
@@ -19,3 +19,3 @@ "main": "dist/index.js", | ||
"test:nyc": "nyc --reporter=lcov npm run test:base", | ||
"test:debug": "mocha --require ts-node/register/transpile-only \"tests/**/*.ts\" --reporter dot", | ||
"test:debug": "mocha --require ts-node/register/transpile-only \"tests/**/*.ts\" --reporter dot --timeout 60000", | ||
"test:watch": "npm run test:base -- --watch", | ||
@@ -22,0 +22,0 @@ "update": "ts-node --transpile-only ./tools/update.ts && npm run eslint-fix && npm run test:nyc", |
@@ -84,4 +84,6 @@ # Introduction | ||
| [regexp/match-any](https://ota-meshi.github.io/eslint-plugin-regexp/rules/match-any.html) | enforce match any character style | :star::wrench: | | ||
| [regexp/negation](https://ota-meshi.github.io/eslint-plugin-regexp/rules/negation.html) | enforce use of escapes on negation | :wrench: | | ||
| [regexp/no-assertion-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-assertion-capturing-group.html) | disallow capturing group that captures assertions. | :star: | | ||
| [regexp/no-dupe-characters-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-characters-character-class.html) | disallow duplicate characters in the RegExp character class | :star: | | ||
| [regexp/no-dupe-disjunctions](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-dupe-disjunctions.html) | disallow duplicate disjunctions | | | ||
| [regexp/no-empty-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-group.html) | disallow empty group | :star: | | ||
@@ -94,6 +96,10 @@ | [regexp/no-empty-lookarounds-assertion](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-empty-lookarounds-assertion.html) | disallow empty lookahead assertion or empty lookbehind assertion | :star: | | ||
| [regexp/no-useless-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-character-class.html) | disallow character class with one character | :wrench: | | ||
| [regexp/no-useless-escape](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-escape.html) | disallow unnecessary escape characters in RegExp | | | ||
| [regexp/no-useless-exactly-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-exactly-quantifier.html) | disallow unnecessary exactly quantifier | :star: | | ||
| [regexp/no-useless-non-capturing-group](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-non-capturing-group.html) | disallow unnecessary Non-capturing group | :wrench: | | ||
| [regexp/no-useless-non-greedy](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-non-greedy.html) | disallow unnecessary quantifier non-greedy (`?`) | :wrench: | | ||
| [regexp/no-useless-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-range.html) | disallow unnecessary range of characters by using a hyphen | :wrench: | | ||
| [regexp/no-useless-two-nums-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/no-useless-two-nums-quantifier.html) | disallow unnecessary `{n,m}` quantifier | :star: | | ||
| [regexp/order-in-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/order-in-character-class.html) | enforces elements order in character class | :wrench: | | ||
| [regexp/prefer-character-class](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-character-class.html) | enforce using character class | :wrench: | | ||
| [regexp/prefer-d](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-d.html) | enforce using `\d` | :star::wrench: | | ||
@@ -103,2 +109,3 @@ | [regexp/prefer-plus-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-plus-quantifier.html) | enforce using `+` quantifier | :star::wrench: | | ||
| [regexp/prefer-question-quantifier](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-question-quantifier.html) | enforce using `?` quantifier | :star::wrench: | | ||
| [regexp/prefer-range](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-range.html) | enforce using character class range | :wrench: | | ||
| [regexp/prefer-regexp-exec](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-exec.html) | enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | | | ||
@@ -105,0 +112,0 @@ | [regexp/prefer-regexp-test](https://ota-meshi.github.io/eslint-plugin-regexp/rules/prefer-regexp-test.html) | enforce that `RegExp#test` is used instead of `String#match` and `RegExp#exec` | :wrench: | |
231893
16.82%61
15.09%5686
17.53%136
5.43%