eslint
Advanced tools
Comparing version 8.31.0 to 8.32.0
@@ -9,3 +9,3 @@ { | ||
"name": "Deprecated", | ||
"description": "These rules have been deprecated in accordance with the <a href=\"/docs/user-guide/rule-deprecation\">deprecation policy</a>, and replaced by newer rules:", | ||
"description": "These rules have been deprecated in accordance with the <a href=\"/docs/use/rule-deprecation\">deprecation policy</a>, and replaced by newer rules:", | ||
"rules": [] | ||
@@ -15,3 +15,3 @@ }, | ||
"name": "Removed", | ||
"description": "These rules from older versions of ESLint (before the <a href=\"/docs/user-guide/rule-deprecation\">deprecation policy</a> existed) have been replaced by newer rules:", | ||
"description": "These rules from older versions of ESLint (before the <a href=\"/docs/use/rule-deprecation\">deprecation policy</a> existed) have been replaced by newer rules:", | ||
"rules": [ | ||
@@ -18,0 +18,0 @@ { "removed": "generator-star", "replacedBy": ["generator-star-spacing"] }, |
@@ -20,7 +20,7 @@ [ | ||
"name": "json-with-metadata", | ||
"description": "Outputs JSON-serialized results. The `json-with-metadata` provides the same linting results as the [`json`](#json) formatter with additional metadata about the rules applied. The linting results are included in the `results` property and the rules metadata is included in the `metadata` property.\n\nAlternatively, you can use the [ESLint Node.js API](../../developer-guide/nodejs-api) to programmatically use ESLint." | ||
"description": "Outputs JSON-serialized results. The `json-with-metadata` provides the same linting results as the [`json`](#json) formatter with additional metadata about the rules applied. The linting results are included in the `results` property and the rules metadata is included in the `metadata` property.\n\nAlternatively, you can use the [ESLint Node.js API](../../integrate/nodejs-api) to programmatically use ESLint." | ||
}, | ||
{ | ||
"name": "json", | ||
"description": "Outputs JSON-serialized results. The `json` formatter is useful when you want to programmatically work with the CLI's linting results.\n\nAlternatively, you can use the [ESLint Node.js API](../../developer-guide/nodejs-api) to programmatically use ESLint." | ||
"description": "Outputs JSON-serialized results. The `json` formatter is useful when you want to programmatically work with the CLI's linting results.\n\nAlternatively, you can use the [ESLint Node.js API](../../integrate/nodejs-api) to programmatically use ESLint." | ||
}, | ||
@@ -27,0 +27,0 @@ { |
@@ -433,3 +433,3 @@ /** | ||
"Set `RuleTester.itOnly` to use `only` with a custom test framework.\n" + | ||
"See https://eslint.org/docs/developer-guide/nodejs-api#customizing-ruletester for more." | ||
"See https://eslint.org/docs/latest/integrate/nodejs-api#customizing-ruletester for more." | ||
); | ||
@@ -436,0 +436,0 @@ } |
@@ -317,3 +317,3 @@ /** | ||
process.emitWarning( | ||
`"${ruleName}" rule is using the deprecated function-style format and will stop working in ESLint v9. Please use object-style format: https://eslint.org/docs/developer-guide/working-with-rules`, | ||
`"${ruleName}" rule is using the deprecated function-style format and will stop working in ESLint v9. Please use object-style format: https://eslint.org/docs/latest/extend/custom-rules`, | ||
"DeprecationWarning" | ||
@@ -333,3 +333,3 @@ ); | ||
process.emitWarning( | ||
`"${ruleName}" rule has options but is missing the "meta.schema" property and will stop working in ESLint v9. Please add a schema: https://eslint.org/docs/developer-guide/working-with-rules#options-schemas`, | ||
`"${ruleName}" rule has options but is missing the "meta.schema" property and will stop working in ESLint v9. Please add a schema: https://eslint.org/docs/latest/extend/custom-rules#options-schemas`, | ||
"DeprecationWarning" | ||
@@ -498,3 +498,3 @@ ); | ||
"Set `RuleTester.itOnly` to use `only` with a custom test framework.\n" + | ||
"See https://eslint.org/docs/developer-guide/nodejs-api#customizing-ruletester for more." | ||
"See https://eslint.org/docs/latest/integrate/nodejs-api#customizing-ruletester for more." | ||
); | ||
@@ -501,0 +501,0 @@ } |
@@ -8,2 +8,8 @@ /** | ||
//------------------------------------------------------------------------------ | ||
// Requirements | ||
//------------------------------------------------------------------------------ | ||
const { directivesPattern } = require("../shared/directives"); | ||
//------------------------------------------------------------------------------ | ||
// Helpers | ||
@@ -15,2 +21,12 @@ //------------------------------------------------------------------------------ | ||
/** | ||
* Checks whether or not a given comment string is really a fallthrough comment and not an ESLint directive. | ||
* @param {string} comment The comment string to check. | ||
* @param {RegExp} fallthroughCommentPattern The regular expression used for checking for fallthrough comments. | ||
* @returns {boolean} `true` if the comment string is truly a fallthrough comment. | ||
*/ | ||
function isFallThroughComment(comment, fallthroughCommentPattern) { | ||
return fallthroughCommentPattern.test(comment) && !directivesPattern.test(comment.trim()); | ||
} | ||
/** | ||
* Checks whether or not a given case has a fallthrough comment. | ||
@@ -30,3 +46,3 @@ * @param {ASTNode} caseWhichFallsThrough SwitchCase node which falls through. | ||
if (commentInBlock && fallthroughCommentPattern.test(commentInBlock.value)) { | ||
if (commentInBlock && isFallThroughComment(commentInBlock.value, fallthroughCommentPattern)) { | ||
return true; | ||
@@ -38,3 +54,3 @@ } | ||
return Boolean(comment && fallthroughCommentPattern.test(comment.value)); | ||
return Boolean(comment && isFallThroughComment(comment.value, fallthroughCommentPattern)); | ||
} | ||
@@ -41,0 +57,0 @@ |
@@ -149,2 +149,4 @@ /** | ||
replaceWithLiteral: "Replace with an equivalent regular expression literal.", | ||
replaceWithLiteralAndFlags: "Replace with an equivalent regular expression literal with flags '{{ flags }}'.", | ||
replaceWithIntendedLiteralAndFlags: "Replace with a regular expression literal with flags '{{ flags }}'.", | ||
unexpectedRedundantRegExp: "Regular expression literal is unnecessarily wrapped within a 'RegExp' constructor.", | ||
@@ -262,2 +264,4 @@ unexpectedRedundantRegExpWithFlags: "Use regular expression literal with flags instead of the 'RegExp' constructor." | ||
const regexppEcmaVersion = getRegexppEcmaVersion(context.languageOptions.ecmaVersion); | ||
/** | ||
@@ -298,2 +302,79 @@ * Makes a character escaped or else returns null. | ||
/** | ||
* Checks whether the given regex and flags are valid for the ecma version or not. | ||
* @param {string} pattern The regex pattern to check. | ||
* @param {string | undefined} flags The regex flags to check. | ||
* @returns {boolean} True if the given regex pattern and flags are valid for the ecma version. | ||
*/ | ||
function isValidRegexForEcmaVersion(pattern, flags) { | ||
const validator = new RegExpValidator({ ecmaVersion: regexppEcmaVersion }); | ||
try { | ||
validator.validatePattern(pattern, 0, pattern.length, flags ? flags.includes("u") : false); | ||
if (flags) { | ||
validator.validateFlags(flags); | ||
} | ||
return true; | ||
} catch { | ||
return false; | ||
} | ||
} | ||
/** | ||
* Checks whether two given regex flags contain the same flags or not. | ||
* @param {string} flagsA The regex flags. | ||
* @param {string} flagsB The regex flags. | ||
* @returns {boolean} True if two regex flags contain same flags. | ||
*/ | ||
function areFlagsEqual(flagsA, flagsB) { | ||
return [...flagsA].sort().join("") === [...flagsB].sort().join(""); | ||
} | ||
/** | ||
* Merges two regex flags. | ||
* @param {string} flagsA The regex flags. | ||
* @param {string} flagsB The regex flags. | ||
* @returns {string} The merged regex flags. | ||
*/ | ||
function mergeRegexFlags(flagsA, flagsB) { | ||
const flagsSet = new Set([ | ||
...flagsA, | ||
...flagsB | ||
]); | ||
return [...flagsSet].join(""); | ||
} | ||
/** | ||
* Checks whether a give node can be fixed to the given regex pattern and flags. | ||
* @param {ASTNode} node The node to check. | ||
* @param {string} pattern The regex pattern to check. | ||
* @param {string} flags The regex flags | ||
* @returns {boolean} True if a node can be fixed to the given regex pattern and flags. | ||
*/ | ||
function canFixTo(node, pattern, flags) { | ||
const tokenBefore = sourceCode.getTokenBefore(node); | ||
return sourceCode.getCommentsInside(node).length === 0 && | ||
(!tokenBefore || validPrecedingTokens.has(tokenBefore.value)) && | ||
isValidRegexForEcmaVersion(pattern, flags); | ||
} | ||
/** | ||
* Returns a safe output code considering the before and after tokens. | ||
* @param {ASTNode} node The regex node. | ||
* @param {string} newRegExpValue The new regex expression value. | ||
* @returns {string} The output code. | ||
*/ | ||
function getSafeOutput(node, newRegExpValue) { | ||
const tokenBefore = sourceCode.getTokenBefore(node); | ||
const tokenAfter = sourceCode.getTokenAfter(node); | ||
return (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && tokenBefore.range[1] === node.range[0] ? " " : "") + | ||
newRegExpValue + | ||
(tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && node.range[1] === tokenAfter.range[0] ? " " : ""); | ||
} | ||
return { | ||
@@ -312,6 +393,65 @@ Program() { | ||
if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node)) { | ||
const regexNode = node.arguments[0]; | ||
if (node.arguments.length === 2) { | ||
context.report({ node, messageId: "unexpectedRedundantRegExpWithFlags" }); | ||
const suggests = []; | ||
const argFlags = getStringValue(node.arguments[1]) || ""; | ||
if (canFixTo(node, regexNode.regex.pattern, argFlags)) { | ||
suggests.push({ | ||
messageId: "replaceWithLiteralAndFlags", | ||
pattern: regexNode.regex.pattern, | ||
flags: argFlags | ||
}); | ||
} | ||
const literalFlags = regexNode.regex.flags || ""; | ||
const mergedFlags = mergeRegexFlags(literalFlags, argFlags); | ||
if ( | ||
!areFlagsEqual(mergedFlags, argFlags) && | ||
canFixTo(node, regexNode.regex.pattern, mergedFlags) | ||
) { | ||
suggests.push({ | ||
messageId: "replaceWithIntendedLiteralAndFlags", | ||
pattern: regexNode.regex.pattern, | ||
flags: mergedFlags | ||
}); | ||
} | ||
context.report({ | ||
node, | ||
messageId: "unexpectedRedundantRegExpWithFlags", | ||
suggest: suggests.map(({ flags, pattern, messageId }) => ({ | ||
messageId, | ||
data: { | ||
flags | ||
}, | ||
fix(fixer) { | ||
return fixer.replaceText(node, getSafeOutput(node, `/${pattern}/${flags}`)); | ||
} | ||
})) | ||
}); | ||
} else { | ||
context.report({ node, messageId: "unexpectedRedundantRegExp" }); | ||
const outputs = []; | ||
if (canFixTo(node, regexNode.regex.pattern, regexNode.regex.flags)) { | ||
outputs.push(sourceCode.getText(regexNode)); | ||
} | ||
context.report({ | ||
node, | ||
messageId: "unexpectedRedundantRegExp", | ||
suggest: outputs.map(output => ({ | ||
messageId: "replaceWithLiteral", | ||
fix(fixer) { | ||
return fixer.replaceText( | ||
node, | ||
getSafeOutput(node, output) | ||
); | ||
} | ||
})) | ||
}); | ||
} | ||
@@ -327,20 +467,6 @@ } else if (hasOnlyStaticStringArguments(node)) { | ||
const regexppEcmaVersion = getRegexppEcmaVersion(context.languageOptions.ecmaVersion); | ||
const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: regexppEcmaVersion }); | ||
try { | ||
RegExpValidatorInstance.validatePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false); | ||
if (flags) { | ||
RegExpValidatorInstance.validateFlags(flags); | ||
} | ||
} catch { | ||
if (!canFixTo(node, regexContent, flags)) { | ||
noFix = true; | ||
} | ||
const tokenBefore = sourceCode.getTokenBefore(node); | ||
if (tokenBefore && !validPrecedingTokens.has(tokenBefore.value)) { | ||
noFix = true; | ||
} | ||
if (!/^[-a-zA-Z0-9\\[\](){} \t\r\n\v\f!@#$%^&*+^_=/~`.><?,'"|:;]*$/u.test(regexContent)) { | ||
@@ -350,6 +476,2 @@ noFix = true; | ||
if (sourceCode.getCommentsInside(node).length > 0) { | ||
noFix = true; | ||
} | ||
if (regexContent && !noFix) { | ||
@@ -386,10 +508,3 @@ let charIncrease = 0; | ||
fix(fixer) { | ||
const tokenAfter = sourceCode.getTokenAfter(node); | ||
return fixer.replaceText( | ||
node, | ||
(tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && tokenBefore.range[1] === node.range[0] ? " " : "") + | ||
newRegExpValue + | ||
(tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && node.range[1] === tokenAfter.range[0] ? " " : "") | ||
); | ||
return fixer.replaceText(node, getSafeOutput(node, newRegExpValue)); | ||
} | ||
@@ -396,0 +511,0 @@ }] |
@@ -6,4 +6,4 @@ "use strict"; | ||
The '--print-config' CLI option requires a path to a source code file rather than a directory. | ||
See also: https://eslint.org/docs/user-guide/command-line-interface#--print-config | ||
See also: https://eslint.org/docs/latest/use/command-line-interface#--print-config | ||
`.trimStart(); | ||
}; |
{ | ||
"name": "eslint", | ||
"version": "8.31.0", | ||
"version": "8.32.0", | ||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>", | ||
@@ -5,0 +5,0 @@ "description": "An AST-based pattern checker for JavaScript.", |
@@ -13,6 +13,6 @@ [![npm version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint) | ||
[Website](https://eslint.org) | | ||
[Configuring](https://eslint.org/docs/user-guide/configuring) | | ||
[Configuring](https://eslint.org/docs/latest/use/configure) | | ||
[Rules](https://eslint.org/docs/rules/) | | ||
[Contributing](https://eslint.org/docs/developer-guide/contributing) | | ||
[Reporting Bugs](https://eslint.org/docs/developer-guide/contributing/reporting-bugs) | | ||
[Contributing](https://eslint.org/docs/latest/contribute) | | ||
[Reporting Bugs](https://eslint.org/docs/latest/contribute/report-bugs) | | ||
[Code of Conduct](https://eslint.org/conduct) | | ||
@@ -80,3 +80,3 @@ [Twitter](https://twitter.com/geteslint) | | ||
The three error levels allow you fine-grained control over how ESLint applies rules (for more configuration options and details, see the [configuration docs](https://eslint.org/docs/user-guide/configuring)). | ||
The three error levels allow you fine-grained control over how ESLint applies rules (for more configuration options and details, see the [configuration docs](https://eslint.org/docs/latest/use/configure)). | ||
@@ -91,6 +91,6 @@ ## Code of Conduct | ||
* [Bug Report](https://eslint.org/docs/developer-guide/contributing/reporting-bugs) | ||
* [Propose a New Rule](https://eslint.org/docs/developer-guide/contributing/new-rules) | ||
* [Proposing a Rule Change](https://eslint.org/docs/developer-guide/contributing/rule-changes) | ||
* [Request a Change](https://eslint.org/docs/developer-guide/contributing/changes) | ||
* [Bug Report](https://eslint.org/docs/latest/contribute/report-bugs) | ||
* [Propose a New Rule](https://eslint.org/docs/latest/contribute/propose-new-rule) | ||
* [Proposing a Rule Change](https://eslint.org/docs/latest/contribute/propose-rule-change) | ||
* [Request a Change](https://eslint.org/docs/latest/contribute/request-change) | ||
@@ -103,3 +103,3 @@ ## Frequently Asked Questions | ||
We have prepared a [migration guide](https://eslint.org/docs/user-guide/migrating-from-jscs) to help you convert your JSCS settings to an ESLint configuration. | ||
We have prepared a [migration guide](https://eslint.org/docs/latest/use/migrating-from-jscs) to help you convert your JSCS settings to an ESLint configuration. | ||
@@ -120,7 +120,7 @@ We are now at or near 100% compatibility with JSCS. If you try ESLint and believe we are not yet compatible with a JSCS rule/configuration, please create an issue (mentioning that it is a JSCS compatibility issue) and we will evaluate it as per our normal process. | ||
Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring)). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics. | ||
Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/latest/use/configure)). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics. | ||
### What ECMAScript versions does ESLint support? | ||
ESLint has full support for ECMAScript 3, 5 (default), 2015, 2016, 2017, 2018, 2019, 2020, 2021 and 2022. You can set your desired ECMAScript syntax (and other settings, like global variables or your target environments) through [configuration](https://eslint.org/docs/user-guide/configuring). | ||
ESLint has full support for ECMAScript 3, 5 (default), 2015, 2016, 2017, 2018, 2019, 2020, 2021 and 2022. You can set your desired ECMAScript syntax (and other settings, like global variables or your target environments) through [configuration](https://eslint.org/docs/latest/use/configure). | ||
@@ -133,3 +133,3 @@ ### What about experimental features? | ||
Once a language feature has been adopted into the ECMAScript standard (stage 4 according to the [TC39 process](https://tc39.github.io/process-document/)), we will accept issues and pull requests related to the new feature, subject to our [contributing guidelines](https://eslint.org/docs/developer-guide/contributing). Until then, please use the appropriate parser and plugin(s) for your experimental feature. | ||
Once a language feature has been adopted into the ECMAScript standard (stage 4 according to the [TC39 process](https://tc39.github.io/process-document/)), we will accept issues and pull requests related to the new feature, subject to our [contributing guidelines](https://eslint.org/docs/latest/contribute). Until then, please use the appropriate parser and plugin(s) for your experimental feature. | ||
@@ -136,0 +136,0 @@ ### Where to ask for help? |
Sorry, the diff of this file is too big to display
2862957
402
67891