eslint-plugin-regexp
Advanced tools
Comparing version
@@ -76,3 +76,3 @@ "use strict"; | ||
const newText = convertText(CONVERTER[letterCase]); | ||
return fixer.replaceTextRange(range, newText); | ||
return fixer.replaceTextRange(range, utils_1.fixerApplyEscape(newText, node)); | ||
}, | ||
@@ -79,0 +79,0 @@ }); |
@@ -99,6 +99,6 @@ "use strict"; | ||
(flags.includes("u") && text === "}")) { | ||
text = utils_1.fixerApplyEscape("\\", node) + text; | ||
text = `\\${text}`; | ||
} | ||
} | ||
return fixer.replaceTextRange(range, text); | ||
return fixer.replaceTextRange(range, utils_1.fixerApplyEscape(text, node)); | ||
}, | ||
@@ -105,0 +105,0 @@ }); |
@@ -65,3 +65,3 @@ "use strict"; | ||
} | ||
newText += text; | ||
newText += utils_1.fixerApplyEscape(text, node); | ||
} | ||
@@ -68,0 +68,0 @@ return fixer.replaceTextRange(replaceRange, `[${newText}]`); |
@@ -199,3 +199,4 @@ "use strict"; | ||
} | ||
return fixer.replaceTextRange(range, buffer.target.raw + buffer.getQuantifier()); | ||
return fixer.replaceTextRange(range, utils_1.fixerApplyEscape(buffer.target.raw, node) + | ||
buffer.getQuantifier()); | ||
}, | ||
@@ -202,0 +203,0 @@ }); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("../utils"); | ||
const reOptionRange = /^([\ud800-\udbff][\udc00-\udfff]|[^\ud800-\udfff])-([\ud800-\udbff][\udc00-\udfff]|[^\ud800-\udfff])$/; | ||
function parseOption(option) { | ||
var _a; | ||
const target = (_a = option === null || option === void 0 ? void 0 : option.target) !== null && _a !== void 0 ? _a : ["alphanumeric"]; | ||
if (typeof target === "string") { | ||
return parseOption({ target: [target] }); | ||
} | ||
const predicates = []; | ||
for (const t of target) { | ||
if (t === "all") { | ||
return () => true; | ||
} | ||
if (t === "alphanumeric") { | ||
predicates.push((cp) => utils_1.isDigit(cp) || utils_1.isLetter(cp)); | ||
} | ||
const res = reOptionRange.exec(t); | ||
if (!res) { | ||
continue; | ||
} | ||
const from = res[1].codePointAt(0); | ||
const to = res[2].codePointAt(0); | ||
predicates.push((cp) => from <= cp && cp <= to); | ||
} | ||
return (cp) => predicates.some((p) => p(cp)); | ||
} | ||
exports.default = utils_1.createRule("prefer-range", { | ||
@@ -11,3 +36,36 @@ meta: { | ||
fixable: "code", | ||
schema: [], | ||
schema: [ | ||
{ | ||
type: "object", | ||
properties: { | ||
target: { | ||
anyOf: [ | ||
{ enum: ["all", "alphanumeric"] }, | ||
{ | ||
type: "array", | ||
items: [{ enum: ["all", "alphanumeric"] }], | ||
minItems: 1, | ||
additionalItems: false, | ||
}, | ||
{ | ||
type: "array", | ||
items: { | ||
anyOf: [ | ||
{ const: "alphanumeric" }, | ||
{ | ||
type: "string", | ||
pattern: reOptionRange.source, | ||
}, | ||
], | ||
}, | ||
uniqueItems: true, | ||
minItems: 1, | ||
additionalItems: false, | ||
}, | ||
], | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
messages: { | ||
@@ -19,2 +77,3 @@ unexpected: 'Unexpected multiple adjacent characters. Use "{{range}}" instead.', | ||
create(context) { | ||
const isTarget = parseOption(context.options[0]); | ||
const sourceCode = context.getSourceCode(); | ||
@@ -46,5 +105,12 @@ function createVisitor(node) { | ||
if (element.type === "Character") { | ||
if (!isTarget(element.value)) { | ||
continue; | ||
} | ||
data = { min: element, max: element }; | ||
} | ||
else if (element.type === "CharacterClassRange") { | ||
if (!isTarget(element.min.value) && | ||
!isTarget(element.max.value)) { | ||
continue; | ||
} | ||
data = { | ||
@@ -51,0 +117,0 @@ min: element.min, |
@@ -37,3 +37,3 @@ "use strict"; | ||
} | ||
return fixer.replaceTextRange(range, "\\t"); | ||
return fixer.replaceTextRange(range, utils_1.fixerApplyEscape("\\t", node)); | ||
}, | ||
@@ -40,0 +40,0 @@ }); |
@@ -42,3 +42,3 @@ "use strict"; | ||
} | ||
return fixer.replaceTextRange(range, `\\u{${text}}`); | ||
return fixer.replaceTextRange(range, utils_1.fixerApplyEscape(`\\u{${text}}`, node)); | ||
}, | ||
@@ -45,0 +45,0 @@ }); |
@@ -13,5 +13,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.canUnwrapped = exports.getQuantifierOffsets = exports.fixerApplyEscape = exports.availableRegexpLocation = exports.getRegexpLocation = exports.getRegexpRange = exports.defineRegexpVisitor = exports.createRule = exports.FLAG_UNICODE = exports.FLAG_STICKY = exports.FLAG_MULTILINE = exports.FLAG_IGNORECASE = exports.FLAG_DOTALL = exports.FLAG_GLOBAL = void 0; | ||
exports.canUnwrapped = exports.getQuantifierOffsets = exports.fixerApplyEscape = exports.getRegexpLocation = exports.getRegexpRange = exports.defineRegexpVisitor = exports.createRule = exports.FLAG_UNICODE = exports.FLAG_STICKY = exports.FLAG_MULTILINE = exports.FLAG_IGNORECASE = exports.FLAG_DOTALL = exports.FLAG_GLOBAL = void 0; | ||
const regexpp_1 = require("regexpp"); | ||
const eslint_utils_1 = require("eslint-utils"); | ||
const string_literal_parser_1 = require("./string-literal-parser"); | ||
__exportStar(require("./unicode"), exports); | ||
@@ -104,2 +105,3 @@ const regexpRules = new WeakMap(); | ||
const tracker = new eslint_utils_1.ReferenceTracker(scope); | ||
const regexpDataList = []; | ||
for (const { node } of tracker.iterateGlobalReferences({ | ||
@@ -114,3 +116,14 @@ RegExp: { [eslint_utils_1.CALL]: true, [eslint_utils_1.CONSTRUCT]: true }, | ||
const pattern = eslint_utils_1.getStringIfConstant(patternNode, scope); | ||
const flags = eslint_utils_1.getStringIfConstant(flagsNode, scope); | ||
const flags = flagsNode | ||
? eslint_utils_1.getStringIfConstant(flagsNode, scope) | ||
: null; | ||
regexpDataList.push({ | ||
newOrCall, | ||
patternNode, | ||
pattern, | ||
flagsNode, | ||
flags, | ||
}); | ||
} | ||
for (const { patternNode, pattern, flags } of regexpDataList) { | ||
if (typeof pattern === "string") { | ||
@@ -126,3 +139,21 @@ let verifyPatternNode = patternNode; | ||
def.node.init.type === "Literal") { | ||
verifyPatternNode = def.node.init; | ||
let useInit = false; | ||
if (variable.references.length > 2) { | ||
if (variable.references.every((ref) => { | ||
if (ref.isWriteOnly()) { | ||
return true; | ||
} | ||
return regexpDataList.some((r) => r.patternNode === | ||
ref.identifier && | ||
r.flags === flags); | ||
})) { | ||
useInit = true; | ||
} | ||
} | ||
else { | ||
useInit = true; | ||
} | ||
if (useInit) { | ||
verifyPatternNode = def.node.init; | ||
} | ||
} | ||
@@ -143,8 +174,41 @@ } | ||
} | ||
function getRegexpRange(sourceCode, node, regexpNode) { | ||
if (!availableRegexpLocation(sourceCode, node)) { | ||
return null; | ||
function getRegexpRange(sourceCode, node, regexpNode, offsets) { | ||
var _a, _b; | ||
const startOffset = regexpNode.start + ((_a = offsets === null || offsets === void 0 ? void 0 : offsets[0]) !== null && _a !== void 0 ? _a : 0); | ||
const endOffset = regexpNode.end + ((_b = offsets === null || offsets === void 0 ? void 0 : offsets[1]) !== null && _b !== void 0 ? _b : 0); | ||
if (isRegexpLiteral(node)) { | ||
const nodeStart = node.range[0] + 1; | ||
return [nodeStart + startOffset, nodeStart + endOffset]; | ||
} | ||
const nodeStart = node.range[0] + 1; | ||
return [nodeStart + regexpNode.start, nodeStart + regexpNode.end]; | ||
if (isStringLiteral(node)) { | ||
let start = null; | ||
let end = null; | ||
try { | ||
const sourceText = sourceCode.text.slice(node.range[0] + 1, node.range[1] - 1); | ||
let startIndex = 0; | ||
for (const t of string_literal_parser_1.parseStringTokens(sourceText)) { | ||
const endIndex = startIndex + t.value.length; | ||
if (start == null && | ||
startIndex <= startOffset && | ||
startOffset < endIndex) { | ||
start = t.range[0]; | ||
} | ||
if (start != null && | ||
end == null && | ||
startIndex < endOffset && | ||
endOffset <= endIndex) { | ||
end = t.range[1]; | ||
break; | ||
} | ||
startIndex = endIndex; | ||
} | ||
if (start != null && end != null) { | ||
const nodeStart = node.range[0] + 1; | ||
return [nodeStart + start, nodeStart + end]; | ||
} | ||
} | ||
catch (_c) { | ||
} | ||
} | ||
return null; | ||
} | ||
@@ -169,3 +233,3 @@ exports.getRegexpRange = getRegexpRange; | ||
exports.getRegexpLocation = getRegexpLocation; | ||
function availableRegexpLocation(sourceCode, node) { | ||
function isRegexpLiteral(node) { | ||
if (node.type !== "Literal") { | ||
@@ -175,13 +239,15 @@ return false; | ||
if (!node.regex) { | ||
if (typeof node.value !== "string") { | ||
return false; | ||
} | ||
if (sourceCode.text.slice(node.range[0] + 1, node.range[1] - 1) !== | ||
node.value) { | ||
return false; | ||
} | ||
return false; | ||
} | ||
return true; | ||
} | ||
exports.availableRegexpLocation = availableRegexpLocation; | ||
function isStringLiteral(node) { | ||
if (node.type !== "Literal") { | ||
return false; | ||
} | ||
if (typeof node.value !== "string") { | ||
return false; | ||
} | ||
return true; | ||
} | ||
function fixerApplyEscape(text, node) { | ||
@@ -188,0 +254,0 @@ if (node.type !== "Literal") { |
{ | ||
"name": "eslint-plugin-regexp", | ||
"version": "0.4.3", | ||
"version": "0.5.0", | ||
"description": "ESLint plugin for finding RegExp mistakes and RegExp style guide violations.", | ||
@@ -69,3 +69,3 @@ "main": "dist/index.js", | ||
"eslint-plugin-vue": "^7.5.0", | ||
"eslint-plugin-yml": "^0.7.0", | ||
"eslint-plugin-yml": "^0.8.0", | ||
"eslint4b": "^7.3.1", | ||
@@ -72,0 +72,0 @@ "mocha": "^8.0.0", |
247506
6.49%65
6.56%6087
6.75%