Comparing version 8.26.0 to 8.27.0
@@ -46,81 +46,106 @@ /** | ||
body { | ||
font-family:Arial, "Helvetica Neue", Helvetica, sans-serif; | ||
font-size:16px; | ||
font-weight:normal; | ||
margin:0; | ||
padding:0; | ||
color:#333 | ||
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; | ||
font-size: 16px; | ||
font-weight: normal; | ||
margin: 0; | ||
padding: 0; | ||
color: #333; | ||
} | ||
#overview { | ||
padding:20px 30px | ||
padding: 20px 30px; | ||
} | ||
td, th { | ||
padding:5px 10px | ||
td, | ||
th { | ||
padding: 5px 10px; | ||
} | ||
h1 { | ||
margin:0 | ||
margin: 0; | ||
} | ||
table { | ||
margin:30px; | ||
width:calc(100% - 60px); | ||
max-width:1000px; | ||
border-radius:5px; | ||
border:1px solid #ddd; | ||
border-spacing:0px; | ||
margin: 30px; | ||
width: calc(100% - 60px); | ||
max-width: 1000px; | ||
border-radius: 5px; | ||
border: 1px solid #ddd; | ||
border-spacing: 0; | ||
} | ||
th { | ||
font-weight:400; | ||
font-size:medium; | ||
text-align:left; | ||
cursor:pointer | ||
font-weight: 400; | ||
font-size: medium; | ||
text-align: left; | ||
cursor: pointer; | ||
} | ||
td.clr-1, td.clr-2, th span { | ||
font-weight:700 | ||
td.clr-1, | ||
td.clr-2, | ||
th span { | ||
font-weight: 700; | ||
} | ||
th span { | ||
float:right; | ||
margin-left:20px | ||
float: right; | ||
margin-left: 20px; | ||
} | ||
th span:after { | ||
content:""; | ||
clear:both; | ||
display:block | ||
th span::after { | ||
content: ""; | ||
clear: both; | ||
display: block; | ||
} | ||
tr:last-child td { | ||
border-bottom:none | ||
border-bottom: none; | ||
} | ||
tr td:first-child, tr td:last-child { | ||
color:#9da0a4 | ||
tr td:first-child, | ||
tr td:last-child { | ||
color: #9da0a4; | ||
} | ||
#overview.bg-0, tr.bg-0 th { | ||
color:#468847; | ||
background:#dff0d8; | ||
border-bottom:1px solid #d6e9c6 | ||
#overview.bg-0, | ||
tr.bg-0 th { | ||
color: #468847; | ||
background: #dff0d8; | ||
border-bottom: 1px solid #d6e9c6; | ||
} | ||
#overview.bg-1, tr.bg-1 th { | ||
color:#f0ad4e; | ||
background:#fcf8e3; | ||
border-bottom:1px solid #fbeed5 | ||
#overview.bg-1, | ||
tr.bg-1 th { | ||
color: #f0ad4e; | ||
background: #fcf8e3; | ||
border-bottom: 1px solid #fbeed5; | ||
} | ||
#overview.bg-2, tr.bg-2 th { | ||
color:#b94a48; | ||
background:#f2dede; | ||
border-bottom:1px solid #eed3d7 | ||
#overview.bg-2, | ||
tr.bg-2 th { | ||
color: #b94a48; | ||
background: #f2dede; | ||
border-bottom: 1px solid #eed3d7; | ||
} | ||
td { | ||
border-bottom:1px solid #ddd | ||
border-bottom: 1px solid #ddd; | ||
} | ||
td.clr-1 { | ||
color:#f0ad4e | ||
color: #f0ad4e; | ||
} | ||
td.clr-2 { | ||
color:#b94a48 | ||
color: #b94a48; | ||
} | ||
td a { | ||
color:#3a33d1; | ||
text-decoration:none | ||
color: #3a33d1; | ||
text-decoration: none; | ||
} | ||
td a:hover { | ||
color:#272296; | ||
text-decoration:underline | ||
color: #272296; | ||
text-decoration: underline; | ||
} | ||
@@ -218,3 +243,3 @@ </style> | ||
return ` | ||
<tr style="display:none" class="f-${parentIndex}"> | ||
<tr style="display: none;" class="f-${parentIndex}"> | ||
<td>${lineNumber}:${columnNumber}</td> | ||
@@ -221,0 +246,0 @@ <td class="clr-${severityNumber}">${severityName}</td> |
@@ -31,2 +31,13 @@ /** | ||
//----------------------------------------------------------------------------- | ||
// Types | ||
//----------------------------------------------------------------------------- | ||
/** | ||
* @typedef {Object} GlobSearch | ||
* @property {Array<string>} patterns The normalized patterns to use for a search. | ||
* @property {Array<string>} rawPatterns The patterns as entered by the user | ||
* before doing any normalization. | ||
*/ | ||
//----------------------------------------------------------------------------- | ||
// Errors | ||
@@ -52,2 +63,26 @@ //----------------------------------------------------------------------------- | ||
/** | ||
* The error type when a search fails to match multiple patterns. | ||
*/ | ||
class UnmatchedSearchPatternsError extends Error { | ||
/** | ||
* @param {Object} options The options for the error. | ||
* @param {string} options.basePath The directory that was searched. | ||
* @param {Array<string>} options.unmatchedPatterns The glob patterns | ||
* which were not found. | ||
* @param {Array<string>} options.patterns The glob patterns that were | ||
* searched. | ||
* @param {Array<string>} options.rawPatterns The raw glob patterns that | ||
* were searched. | ||
*/ | ||
constructor({ basePath, unmatchedPatterns, patterns, rawPatterns }) { | ||
super(`No files matching '${rawPatterns}' in '${basePath}' were found.`); | ||
this.basePath = basePath; | ||
this.patternsToCheck = unmatchedPatterns; | ||
this.patterns = patterns; | ||
this.rawPatterns = rawPatterns; | ||
} | ||
} | ||
/** | ||
* The error type when there are files matched by a glob, but all of them have been ignored. | ||
@@ -112,3 +147,66 @@ */ | ||
/** | ||
* Determines if a given glob pattern will return any results. | ||
* Used primarily to help with useful error messages. | ||
* @param {Object} options The options for the function. | ||
* @param {string} options.basePath The directory to search. | ||
* @param {string} options.pattern A glob pattern to match. | ||
* @returns {Promise<boolean>} True if there is a glob match, false if not. | ||
*/ | ||
function globMatch({ basePath, pattern }) { | ||
let found = false; | ||
const patternToUse = path.isAbsolute(pattern) | ||
? normalizeToPosix(path.relative(basePath, pattern)) | ||
: pattern; | ||
const matcher = new Minimatch(patternToUse); | ||
const fsWalkSettings = { | ||
deepFilter(entry) { | ||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||
return !found && matcher.match(relativePath, true); | ||
}, | ||
entryFilter(entry) { | ||
if (found || entry.dirent.isDirectory()) { | ||
return false; | ||
} | ||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||
if (matcher.match(relativePath)) { | ||
found = true; | ||
return true; | ||
} | ||
return false; | ||
} | ||
}; | ||
return new Promise(resolve => { | ||
// using a stream so we can exit early because we just need one match | ||
const globStream = fswalk.walkStream(basePath, fsWalkSettings); | ||
globStream.on("data", () => { | ||
globStream.destroy(); | ||
resolve(true); | ||
}); | ||
// swallow errors as they're not important here | ||
globStream.on("error", () => { }); | ||
globStream.on("end", () => { | ||
resolve(false); | ||
}); | ||
globStream.read(); | ||
}); | ||
} | ||
/** | ||
* Searches a directory looking for matching glob patterns. This uses | ||
@@ -122,8 +220,20 @@ * the config array's logic to determine if a directory or file should | ||
* to match. | ||
* @param {Array<string>} options.rawPatterns An array of glob patterns | ||
* as the user inputted them. Used for errors. | ||
* @param {FlatConfigArray} options.configs The config array to use for | ||
* determining what to ignore. | ||
* @param {boolean} options.errorOnUnmatchedPattern Determines if an error | ||
* should be thrown when a pattern is unmatched. | ||
* @returns {Promise<Array<string>>} An array of matching file paths | ||
* or an empty array if there are no matches. | ||
* @throws {UnmatchedSearchPatternsErrror} If there is a pattern that doesn't | ||
* match any files. | ||
*/ | ||
async function globSearch({ basePath, patterns, configs }) { | ||
async function globSearch({ | ||
basePath, | ||
patterns, | ||
rawPatterns, | ||
configs, | ||
errorOnUnmatchedPattern | ||
}) { | ||
@@ -134,3 +244,16 @@ if (patterns.length === 0) { | ||
const matchers = patterns.map(pattern => { | ||
/* | ||
* In this section we are converting the patterns into Minimatch | ||
* instances for performance reasons. Because we are doing the same | ||
* matches repeatedly, it's best to compile those patterns once and | ||
* reuse them multiple times. | ||
* | ||
* To do that, we convert any patterns with an absolute path into a | ||
* relative path and normalize it to Posix-style slashes. We also keep | ||
* track of the relative patterns to map them back to the original | ||
* patterns, which we need in order to throw an error if there are any | ||
* unmatched patterns. | ||
*/ | ||
const relativeToPatterns = new Map(); | ||
const matchers = patterns.map((pattern, i) => { | ||
const patternToUse = path.isAbsolute(pattern) | ||
@@ -140,7 +263,18 @@ ? normalizeToPosix(path.relative(basePath, pattern)) | ||
relativeToPatterns.set(patternToUse, patterns[i]); | ||
return new minimatch.Minimatch(patternToUse); | ||
}); | ||
return (await doFsWalk(basePath, { | ||
/* | ||
* We track unmatched patterns because we may want to throw an error when | ||
* they occur. To start, this set is initialized with all of the patterns. | ||
* Every time a match occurs, the pattern is removed from the set, making | ||
* it easy to tell if we have any unmatched patterns left at the end of | ||
* search. | ||
*/ | ||
const unmatchedPatterns = new Set([...relativeToPatterns.keys()]); | ||
const filePaths = (await doFsWalk(basePath, { | ||
deepFilter(entry) { | ||
@@ -160,90 +294,173 @@ const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||
const matchesPattern = matchers.some(matcher => matcher.match(relativePath)); | ||
/* | ||
* Optimization: We need to track when patterns are left unmatched | ||
* and so we use `unmatchedPatterns` to do that. There is a bit of | ||
* complexity here because the same file can be matched by more than | ||
* one pattern. So, when we start, we actually need to test every | ||
* pattern against every file. Once we know there are no remaining | ||
* unmatched patterns, then we can switch to just looking for the | ||
* first matching pattern for improved speed. | ||
*/ | ||
const matchesPattern = unmatchedPatterns.size > 0 | ||
? matchers.reduce((previousValue, matcher) => { | ||
const pathMatches = matcher.match(relativePath); | ||
/* | ||
* We updated the unmatched patterns set only if the path | ||
* matches and the file isn't ignored. If the file is | ||
* ignored, that means there wasn't a match for the | ||
* pattern so it should not be removed. | ||
* | ||
* Performance note: isFileIgnored() aggressively caches | ||
* results so there is no performance penalty for calling | ||
* it twice with the same argument. | ||
*/ | ||
if (pathMatches && !configs.isFileIgnored(entry.path)) { | ||
unmatchedPatterns.delete(matcher.pattern); | ||
} | ||
return pathMatches || previousValue; | ||
}, false) | ||
: matchers.some(matcher => matcher.match(relativePath)); | ||
return matchesPattern && !configs.isFileIgnored(entry.path); | ||
} | ||
})).map(entry => entry.path); | ||
// now check to see if we have any unmatched patterns | ||
if (errorOnUnmatchedPattern && unmatchedPatterns.size > 0) { | ||
throw new UnmatchedSearchPatternsError({ | ||
basePath, | ||
unmatchedPatterns: [...unmatchedPatterns].map( | ||
pattern => relativeToPatterns.get(pattern) | ||
), | ||
patterns, | ||
rawPatterns | ||
}); | ||
} | ||
return filePaths; | ||
} | ||
/** | ||
* Checks to see if there are any ignored results for a given search. This | ||
* happens either when there are unmatched patterns during a search or if | ||
* a search returns no results. | ||
* @param {Object} options The options for this function. | ||
* @param {string} options.basePath The directory to search. | ||
* @param {Array<string>} options.patterns An array of glob patterns | ||
* that were used in the original search. | ||
* @param {Array<string>} options.rawPatterns An array of glob patterns | ||
* as the user inputted them. Used for errors. | ||
* @param {Array<string>} options.patternsToCheck An array of glob patterns | ||
* to use for this check. | ||
* @returns {void} | ||
* @throws {NoFilesFoundError} If there is a pattern that doesn't match | ||
* any files and `errorOnUnmatchedPattern` is true. | ||
* @throws {AllFilesIgnoredError} If there is a pattern that matches files | ||
* when there are no ignores. | ||
*/ | ||
async function checkForIgnoredResults({ | ||
basePath, | ||
patterns, | ||
rawPatterns, | ||
patternsToCheck = patterns | ||
}) { | ||
for (const pattern of patternsToCheck) { | ||
const patternHasMatch = await globMatch({ | ||
basePath, | ||
pattern | ||
}); | ||
if (patternHasMatch) { | ||
throw new AllFilesIgnoredError( | ||
rawPatterns[patterns.indexOf(pattern)] | ||
); | ||
} | ||
} | ||
// if we get here there are truly no matches | ||
throw new NoFilesFoundError( | ||
rawPatterns[patterns.indexOf(patternsToCheck[0])], | ||
true | ||
); | ||
} | ||
/** | ||
* Performs multiple glob searches in parallel. | ||
* @param {Object} options The options for this function. | ||
* @param {Array<{patterns:Array<string>,rawPatterns:Array<string>}>} options.searches | ||
* @param {Map<string,GlobSearch>} options.searches | ||
* An array of glob patterns to match. | ||
* @param {FlatConfigArray} options.configs The config array to use for | ||
* determining what to ignore. | ||
* @param {boolean} options.errorOnUnmatchedPattern Determines if an | ||
* unmatched glob pattern should throw an error. | ||
* @returns {Promise<Array<string>>} An array of matching file paths | ||
* or an empty array if there are no matches. | ||
*/ | ||
async function globMultiSearch({ searches, configs }) { | ||
async function globMultiSearch({ searches, configs, errorOnUnmatchedPattern }) { | ||
const results = await Promise.all( | ||
[...searches].map( | ||
([basePath, { patterns }]) => globSearch({ basePath, patterns, configs }) | ||
/* | ||
* For convenience, we normalized the search map into an array of objects. | ||
* Next, we filter out all searches that have no patterns. This happens | ||
* primarily for the cwd, which is prepopulated in the searches map as an | ||
* optimization. However, if it has no patterns, it means all patterns | ||
* occur outside of the cwd and we can safely filter out that search. | ||
*/ | ||
const normalizedSearches = [...searches].map( | ||
([basePath, { patterns, rawPatterns }]) => ({ basePath, patterns, rawPatterns }) | ||
).filter(({ patterns }) => patterns.length > 0); | ||
const results = await Promise.allSettled( | ||
normalizedSearches.map( | ||
({ basePath, patterns, rawPatterns }) => globSearch({ | ||
basePath, | ||
patterns, | ||
rawPatterns, | ||
configs, | ||
errorOnUnmatchedPattern | ||
}) | ||
) | ||
); | ||
return [...new Set(results.flat())]; | ||
} | ||
const filePaths = []; | ||
/** | ||
* Determines if a given glob pattern will return any results. | ||
* Used primarily to help with useful error messages. | ||
* @param {Object} options The options for the function. | ||
* @param {string} options.basePath The directory to search. | ||
* @param {string} options.pattern A glob pattern to match. | ||
* @returns {Promise<boolean>} True if there is a glob match, false if not. | ||
*/ | ||
function globMatch({ basePath, pattern }) { | ||
for (let i = 0; i < results.length; i++) { | ||
let found = false; | ||
const patternToUse = path.isAbsolute(pattern) | ||
? normalizeToPosix(path.relative(basePath, pattern)) | ||
: pattern; | ||
const result = results[i]; | ||
const currentSearch = normalizedSearches[i]; | ||
const matcher = new Minimatch(patternToUse); | ||
if (result.status === "fulfilled") { | ||
const fsWalkSettings = { | ||
deepFilter(entry) { | ||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||
return !found && matcher.match(relativePath, true); | ||
}, | ||
entryFilter(entry) { | ||
if (found || entry.dirent.isDirectory()) { | ||
return false; | ||
// if the search was successful just add the results | ||
if (result.value.length > 0) { | ||
filePaths.push(...result.value); | ||
} | ||
const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||
continue; | ||
} | ||
if (matcher.match(relativePath)) { | ||
found = true; | ||
return true; | ||
} | ||
// if we make it here then there was an error | ||
const error = result.reason; | ||
return false; | ||
// unexpected errors should be re-thrown | ||
if (!error.basePath) { | ||
throw error; | ||
} | ||
}; | ||
return new Promise(resolve => { | ||
if (errorOnUnmatchedPattern) { | ||
// using a stream so we can exit early because we just need one match | ||
const globStream = fswalk.walkStream(basePath, fsWalkSettings); | ||
await checkForIgnoredResults({ | ||
...currentSearch, | ||
patternsToCheck: error.patternsToCheck | ||
}); | ||
globStream.on("data", () => { | ||
globStream.destroy(); | ||
resolve(true); | ||
}); | ||
} | ||
// swallow errors as they're not important here | ||
globStream.on("error", () => {}); | ||
} | ||
globStream.on("end", () => { | ||
resolve(false); | ||
}); | ||
globStream.read(); | ||
}); | ||
return [...new Set(filePaths)]; | ||
@@ -345,38 +562,2 @@ } | ||
const globbyResults = await globMultiSearch({ | ||
searches, | ||
configs | ||
}); | ||
// if there are no results, tell the user why | ||
if (!results.length && !globbyResults.length) { | ||
for (const [basePath, { patterns: patternsToCheck, rawPatterns: patternsToReport }] of searches) { | ||
let index = 0; | ||
// try globby without ignoring anything | ||
for (const patternToCheck of patternsToCheck) { | ||
// check if there are any matches at all | ||
const patternHasMatch = await globMatch({ | ||
basePath, | ||
pattern: patternToCheck | ||
}); | ||
if (patternHasMatch) { | ||
throw new AllFilesIgnoredError(patternsToReport[index]); | ||
} | ||
// otherwise no files were found | ||
if (errorOnUnmatchedPattern) { | ||
throw new NoFilesFoundError(patternsToReport[index], globInputPaths); | ||
} | ||
index++; | ||
} | ||
} | ||
} | ||
// there were patterns that didn't match anything, tell the user | ||
@@ -387,2 +568,8 @@ if (errorOnUnmatchedPattern && missingPatterns.length) { | ||
// now we are safe to do the search | ||
const globbyResults = await globMultiSearch({ | ||
searches, | ||
configs, | ||
errorOnUnmatchedPattern | ||
}); | ||
@@ -389,0 +576,0 @@ return [ |
@@ -164,2 +164,12 @@ /** | ||
/** | ||
* Return the absolute path of a file named `"__placeholder__.js"` in a given directory. | ||
* This is used as a replacement for a missing file path. | ||
* @param {string} cwd An absolute directory path. | ||
* @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory. | ||
*/ | ||
function getPlaceholderPath(cwd) { | ||
return path.join(cwd, "__placeholder__.js"); | ||
} | ||
/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */ | ||
@@ -181,3 +191,3 @@ const usedDeprecatedRulesCache = new WeakMap(); | ||
? maybeFilePath | ||
: path.join(cwd, "__placeholder__.js"); | ||
: getPlaceholderPath(cwd); | ||
const config = configs.getConfig(filePath); | ||
@@ -427,3 +437,3 @@ | ||
*/ | ||
const filePathToVerify = filePath === "<text>" ? path.join(cwd, "__placeholder__.js") : filePath; | ||
const filePathToVerify = filePath === "<text>" ? getPlaceholderPath(cwd) : filePath; | ||
const { fixed, messages, output } = linter.verifyAndFix( | ||
@@ -525,2 +535,10 @@ text, | ||
/** | ||
* Creates an error to be thrown when an array of results passed to `getRulesMetaForResults` was not created by the current engine. | ||
* @returns {TypeError} An error object. | ||
*/ | ||
function createExtraneousResultsError() { | ||
return new TypeError("Results object was not created from this ESLint instance."); | ||
} | ||
//----------------------------------------------------------------------------- | ||
@@ -662,3 +680,6 @@ // Main API | ||
const resultRules = new Map(); | ||
const { configs } = privateMembers.get(this); | ||
const { | ||
configs, | ||
options: { cwd } | ||
} = privateMembers.get(this); | ||
@@ -672,3 +693,3 @@ /* | ||
if (!configs) { | ||
throw new TypeError("Results object was not created from this ESLint instance."); | ||
throw createExtraneousResultsError(); | ||
} | ||
@@ -682,9 +703,3 @@ | ||
const filePath = result.filePath === "<text>" | ||
? "__placeholder__.js" : result.filePath; | ||
/* | ||
* All of the plugin and rule information is contained within the | ||
* calculated config for the given file. | ||
*/ | ||
const config = configs.getConfig(filePath); | ||
? getPlaceholderPath(cwd) : result.filePath; | ||
const allMessages = result.messages.concat(result.suppressedMessages); | ||
@@ -697,2 +712,11 @@ | ||
/* | ||
* All of the plugin and rule information is contained within the | ||
* calculated config for the given file. | ||
*/ | ||
const config = configs.getConfig(filePath); | ||
if (!config) { | ||
throw createExtraneousResultsError(); | ||
} | ||
const rule = getRuleFromConfig(ruleId, config); | ||
@@ -1035,3 +1059,3 @@ | ||
// TODO: This is pretty dirty...would be nice to clean up at some point. | ||
formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js")); | ||
formatterPath = ModuleResolver.resolve(npmFormat, getPlaceholderPath(cwd)); | ||
} catch { | ||
@@ -1038,0 +1062,0 @@ formatterPath = path.resolve(__dirname, "../", "cli-engine", "formatters", `${normalizedFormatName}.js`); |
@@ -53,3 +53,3 @@ /** | ||
exports: optionValue, | ||
functions: (!ecmaVersion || ecmaVersion < 8) ? "ignore" : optionValue | ||
functions: ecmaVersion < 2017 ? "ignore" : optionValue | ||
}; | ||
@@ -138,3 +138,3 @@ } | ||
create(context) { | ||
const options = normalizeOptions(context.options[0], context.parserOptions.ecmaVersion); | ||
const options = normalizeOptions(context.options[0], context.languageOptions.ecmaVersion); | ||
@@ -141,0 +141,0 @@ const sourceCode = context.getSourceCode(); |
@@ -47,3 +47,3 @@ /** | ||
function isIdentifier(name, ecmaVersion) { | ||
if (ecmaVersion >= 6) { | ||
if (ecmaVersion >= 2015) { | ||
return esutils.keyword.isIdentifierES6(name); | ||
@@ -108,3 +108,3 @@ } | ||
const includeModuleExports = options.includeCommonJSModuleExports; | ||
const ecmaVersion = context.parserOptions && context.parserOptions.ecmaVersion ? context.parserOptions.ecmaVersion : 5; | ||
const ecmaVersion = context.languageOptions.ecmaVersion; | ||
@@ -111,0 +111,0 @@ /** |
@@ -126,2 +126,3 @@ /** | ||
"no-empty-pattern": () => require("./no-empty-pattern"), | ||
"no-empty-static-block": () => require("./no-empty-static-block"), | ||
"no-eq-null": () => require("./no-eq-null"), | ||
@@ -171,2 +172,3 @@ "no-eval": () => require("./no-eval"), | ||
"no-new-func": () => require("./no-new-func"), | ||
"no-new-native-nonconstructor": () => require("./no-new-native-nonconstructor"), | ||
"no-new-object": () => require("./no-new-object"), | ||
@@ -173,0 +175,0 @@ "no-new-require": () => require("./no-new-require"), |
@@ -20,2 +20,3 @@ /** | ||
meta: { | ||
hasSuggestions: true, | ||
type: "suggestion", | ||
@@ -43,3 +44,4 @@ | ||
messages: { | ||
unexpected: "Empty {{type}} statement." | ||
unexpected: "Empty {{type}} statement.", | ||
suggestComment: "Add comment inside empty {{type}} statement." | ||
} | ||
@@ -76,3 +78,18 @@ }, | ||
context.report({ node, messageId: "unexpected", data: { type: "block" } }); | ||
context.report({ | ||
node, | ||
messageId: "unexpected", | ||
data: { type: "block" }, | ||
suggest: [ | ||
{ | ||
messageId: "suggestComment", | ||
data: { type: "block" }, | ||
fix(fixer) { | ||
const range = [node.range[0] + 1, node.range[1] - 1]; | ||
return fixer.replaceTextRange(range, " /* empty */ "); | ||
} | ||
} | ||
] | ||
}); | ||
}, | ||
@@ -79,0 +96,0 @@ |
@@ -196,6 +196,6 @@ /** | ||
function isValidWithUnicodeFlag(pattern) { | ||
const { ecmaVersion } = context.parserOptions; | ||
const { ecmaVersion } = context.languageOptions; | ||
// ecmaVersion is unknown or it doesn't support the 'u' flag | ||
if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) { | ||
// ecmaVersion <= 5 doesn't support the 'u' flag | ||
if (ecmaVersion <= 5) { | ||
return false; | ||
@@ -205,3 +205,3 @@ } | ||
const validator = new RegExpValidator({ | ||
ecmaVersion: Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION) | ||
ecmaVersion: Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION) | ||
}); | ||
@@ -208,0 +208,0 @@ |
@@ -251,10 +251,10 @@ /** | ||
* Returns a ecmaVersion compatible for regexpp. | ||
* @param {any} ecmaVersion The ecmaVersion to convert. | ||
* @param {number} ecmaVersion The ecmaVersion to convert. | ||
* @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp. | ||
*/ | ||
function getRegexppEcmaVersion(ecmaVersion) { | ||
if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) { | ||
if (ecmaVersion <= 5) { | ||
return 5; | ||
} | ||
return Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION); | ||
return Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION); | ||
} | ||
@@ -324,3 +324,3 @@ | ||
const regexppEcmaVersion = getRegexppEcmaVersion(context.parserOptions.ecmaVersion); | ||
const regexppEcmaVersion = getRegexppEcmaVersion(context.languageOptions.ecmaVersion); | ||
const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: regexppEcmaVersion }); | ||
@@ -327,0 +327,0 @@ |
{ | ||
"name": "eslint", | ||
"version": "8.26.0", | ||
"version": "8.27.0", | ||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>", | ||
@@ -5,0 +5,0 @@ "description": "An AST-based pattern checker for JavaScript.", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2843650
400
67509