tools: update ESLint to v6.5.1

PR-URL: https://github.com/nodejs/node/pull/29785
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
Reviewed-By: Beth Griggs <Bethany.Griggs@uk.ibm.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: David Carlier <devnexen@gmail.com>
This commit is contained in:
Rich Trott 2019-09-30 21:09:47 -07:00
parent a67b73b9ae
commit 88ef086e39
37 changed files with 603 additions and 156 deletions

16
tools/node_modules/eslint/README.md generated vendored
View File

@ -120,7 +120,7 @@ Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [confi
### What ECMAScript versions does ESLint support? ### What ECMAScript versions does ESLint support?
ESLint has full support for ECMAScript 3, 5 (default), 2015, 2016, 2017, and 2018. 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, and 2019. 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).
### What about experimental features? ### What about experimental features?
@ -210,11 +210,6 @@ Toru Nagashima
Gyandeep Singh Gyandeep Singh
</a> </a>
</td><td align="center" valign="top" width="11%"> </td><td align="center" valign="top" width="11%">
<a href="https://github.com/kaicataldo">
<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
Kai Cataldo
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/not-an-aardvark"> <a href="https://github.com/not-an-aardvark">
<img src="https://github.com/not-an-aardvark.png?s=75" width="75" height="75"><br /> <img src="https://github.com/not-an-aardvark.png?s=75" width="75" height="75"><br />
Teddy Katz Teddy Katz
@ -241,6 +236,11 @@ The people who review and implement new features.
The people who review and fix bugs and help triage issues. The people who review and fix bugs and help triage issues.
<table><tbody><tr><td align="center" valign="top" width="11%"> <table><tbody><tr><td align="center" valign="top" width="11%">
<a href="https://github.com/kaicataldo">
<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
Kai Cataldo
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/g-plane"> <a href="https://github.com/g-plane">
<img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br /> <img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br />
Pig Fang Pig Fang
@ -262,9 +262,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
<!-- NOTE: This section is autogenerated. Do not manually edit.--> <!-- NOTE: This section is autogenerated. Do not manually edit.-->
<!--sponsorsstart--> <!--sponsorsstart-->
<h3>Gold Sponsors</h3> <h3>Gold Sponsors</h3>
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/d1b37c4/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3> <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://opensource.facebook.com"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3> <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://moneypug.co.uk/"><img src="https://images.opencollective.com/moneypug/45f8d53/logo.png" alt="MONEYPUG" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p> <p><a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
<!--sponsorsend--> <!--sponsorsend-->
## <a name="technology-sponsors"></a>Technology Sponsors ## <a name="technology-sponsors"></a>Technology Sponsors

View File

@ -16,9 +16,9 @@ require("v8-compile-cache");
// Helpers // Helpers
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const useStdIn = (process.argv.indexOf("--stdin") > -1), const useStdIn = process.argv.includes("--stdin"),
init = (process.argv.indexOf("--init") > -1), init = process.argv.includes("--init"),
debug = (process.argv.indexOf("--debug") > -1); debug = process.argv.includes("--debug");
// must do this initialization *before* other requires in order to work // must do this initialization *before* other requires in order to work
if (debug) { if (debug) {
@ -30,9 +30,9 @@ if (debug) {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// now we can safely include the other modules that use debug // now we can safely include the other modules that use debug
const cli = require("../lib/cli"), const path = require("path"),
path = require("path"), fs = require("fs"),
fs = require("fs"); cli = require("../lib/cli");
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Execution // Execution
@ -50,7 +50,6 @@ process.once("uncaughtException", err => {
console.error("\nOops! Something went wrong! :("); console.error("\nOops! Something went wrong! :(");
console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`); console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
} else { } else {
console.error(err.stack); console.error(err.stack);
} }
@ -60,13 +59,40 @@ process.once("uncaughtException", err => {
if (useStdIn) { if (useStdIn) {
/* /*
* Note: `process.stdin.fd` is not used here due to https://github.com/nodejs/node/issues/7439. * Note: See
* Accessing the `process.stdin` property seems to modify the behavior of file descriptor 0, resulting * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
* in an error when stdin is piped in asynchronously. * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
* - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
* - https://github.com/nodejs/node/issues/7439 (historical)
*
* On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
* to read 4096 bytes before blocking and never drains to read further data.
*
* The investigation on the Emacs thread indicates:
*
* > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
* > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
* > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
* > the subprocess to read its end of the pipe, at which time Emacs will
* > write the rest of the stuff.
*
* Using the nodejs code example for reading from stdin.
*/ */
const STDIN_FILE_DESCRIPTOR = 0; let contents = "",
chunk = "";
process.exitCode = cli.execute(process.argv, fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")); process.stdin.setEncoding("utf8");
process.stdin.on("readable", () => {
// Use a loop to make sure we read all available data.
while ((chunk = process.stdin.read()) !== null) {
contents += chunk;
}
});
process.stdin.on("end", () => {
process.exitCode = cli.execute(process.argv, contents, "utf8");
});
} else if (init) { } else if (init) {
const configInit = require("../lib/init/config-initializer"); const configInit = require("../lib/init/config-initializer");

View File

@ -85,8 +85,8 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
* @property {number} warningCount Number of warnings for the result. * @property {number} warningCount Number of warnings for the result.
* @property {number} fixableErrorCount Number of fixable errors for the result. * @property {number} fixableErrorCount Number of fixable errors for the result.
* @property {number} fixableWarningCount Number of fixable warnings for the result. * @property {number} fixableWarningCount Number of fixable warnings for the result.
* @property {string=} [source] The source code of the file that was linted. * @property {string} [source] The source code of the file that was linted.
* @property {string=} [output] The source code of the file that was linted, with as many fixes applied as possible. * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
*/ */
/** /**
@ -329,7 +329,6 @@ function getRule(ruleId, configArrays) {
/** /**
* Collect used deprecated rules. * Collect used deprecated rules.
* @param {ConfigArray[]} usedConfigArrays The config arrays which were used. * @param {ConfigArray[]} usedConfigArrays The config arrays which were used.
* @param {Map<string, Object>} ruleMap The rule definitions which were used (built-ins).
* @returns {IterableIterator<DeprecatedRuleInfo>} Used deprecated rules. * @returns {IterableIterator<DeprecatedRuleInfo>} Used deprecated rules.
*/ */
function *iterateRuleDeprecationWarnings(usedConfigArrays) { function *iterateRuleDeprecationWarnings(usedConfigArrays) {
@ -530,7 +529,6 @@ class CLIEngine {
/** /**
* Creates a new instance of the core CLI engine. * Creates a new instance of the core CLI engine.
* @param {CLIEngineOptions} providedOptions The options for this instance. * @param {CLIEngineOptions} providedOptions The options for this instance.
* @constructor
*/ */
constructor(providedOptions) { constructor(providedOptions) {
const options = Object.assign( const options = Object.assign(

View File

@ -78,7 +78,7 @@ function mergeDefaultOptions(options) {
return Object.assign({}, DEFAULT_OPTIONS, options); return Object.assign({}, DEFAULT_OPTIONS, options);
} }
/* eslint-disable valid-jsdoc */ /* eslint-disable jsdoc/check-param-names, jsdoc/require-param */
/** /**
* Normalize the path separators in a given string. * Normalize the path separators in a given string.
* On Windows environment, this replaces `\` by `/`. * On Windows environment, this replaces `\` by `/`.
@ -89,7 +89,7 @@ function mergeDefaultOptions(options) {
const normalizePathSeps = path.sep === "/" const normalizePathSeps = path.sep === "/"
? (str => str) ? (str => str)
: ((seps, str) => str.replace(seps, "/")).bind(null, new RegExp(`\\${path.sep}`, "gu")); : ((seps, str) => str.replace(seps, "/")).bind(null, new RegExp(`\\${path.sep}`, "gu"));
/* eslint-enable valid-jsdoc */ /* eslint-enable jsdoc/check-param-names, jsdoc/require-param */
/** /**
* Converts a glob pattern to a new glob pattern relative to a different directory * Converts a glob pattern to a new glob pattern relative to a different directory
@ -298,7 +298,7 @@ class IgnoredPaths {
/** /**
* read ignore filepath * read ignore filepath
* @param {string} filePath, file to add to ig * @param {string} filePath file to add to ig
* @returns {Array} raw ignore rules * @returns {Array} raw ignore rules
*/ */
readIgnoreFile(filePath) { readIgnoreFile(filePath) {

View File

@ -47,7 +47,6 @@ class LintResultCache {
/** /**
* Creates a new LintResultCache instance. * Creates a new LintResultCache instance.
* @constructor
* @param {string} cacheFileLocation The cache file location. * @param {string} cacheFileLocation The cache file location.
* configuration lookup by file path). * configuration lookup by file path).
*/ */

25
tools/node_modules/eslint/lib/cli.js generated vendored
View File

@ -20,7 +20,8 @@ const fs = require("fs"),
mkdirp = require("mkdirp"), mkdirp = require("mkdirp"),
{ CLIEngine } = require("./cli-engine"), { CLIEngine } = require("./cli-engine"),
options = require("./options"), options = require("./options"),
log = require("./shared/logging"); log = require("./shared/logging"),
RuntimeInfo = require("./shared/runtime-info");
const debug = require("debug")("eslint:cli"); const debug = require("debug")("eslint:cli");
@ -159,13 +160,18 @@ const cli = {
} }
const files = currentOptions._; const files = currentOptions._;
const useStdin = typeof text === "string"; const useStdin = typeof text === "string";
if (currentOptions.version) { // version from package.json if (currentOptions.version) {
log.info(RuntimeInfo.version());
log.info(`v${require("../package.json").version}`); } else if (currentOptions.envInfo) {
try {
log.info(RuntimeInfo.environment());
return 0;
} catch (err) {
log.error(err.message);
return 2;
}
} else if (currentOptions.printConfig) { } else if (currentOptions.printConfig) {
if (files.length) { if (files.length) {
log.error("The --print-config option must be used with exactly one file name."); log.error("The --print-config option must be used with exactly one file name.");
@ -177,17 +183,13 @@ const cli = {
} }
const engine = new CLIEngine(translateOptions(currentOptions)); const engine = new CLIEngine(translateOptions(currentOptions));
const fileConfig = engine.getConfigForFile(currentOptions.printConfig); const fileConfig = engine.getConfigForFile(currentOptions.printConfig);
log.info(JSON.stringify(fileConfig, null, " ")); log.info(JSON.stringify(fileConfig, null, " "));
return 0; return 0;
} else if (currentOptions.help || (!files.length && !useStdin)) { } else if (currentOptions.help || (!files.length && !useStdin)) {
log.info(options.generateHelp()); log.info(options.generateHelp());
} else { } else {
debug(`Running on ${useStdin ? "text" : "files"}`); debug(`Running on ${useStdin ? "text" : "files"}`);
if (currentOptions.fix && currentOptions.fixDryRun) { if (currentOptions.fix && currentOptions.fixDryRun) {
@ -227,9 +229,8 @@ const cli = {
return (report.errorCount || tooManyWarnings) ? 1 : 0; return (report.errorCount || tooManyWarnings) ? 1 : 0;
} }
return 2; return 2;
} }
return 0; return 0;

View File

@ -99,7 +99,7 @@ function groupByProperty(objects) {
* Configs may also have one or more additional elements to specify rule * Configs may also have one or more additional elements to specify rule
* configuration or options. * configuration or options.
* *
* @typedef {array|number} ruleConfig * @typedef {Array|number} ruleConfig
* @param {number} 0 The rule's severity (0, 1, 2). * @param {number} 0 The rule's severity (0, 1, 2).
*/ */
@ -185,7 +185,7 @@ class RuleConfigSet {
/** /**
* Stored valid rule configurations for this instance * Stored valid rule configurations for this instance
* @type {array} * @type {Array}
*/ */
this.ruleConfigs = configs || []; this.ruleConfigs = configs || [];
} }

View File

@ -163,7 +163,7 @@ function checkDevDeps(packages) {
/** /**
* Check whether package.json is found in current path. * Check whether package.json is found in current path.
* *
* @param {string=} startDir Starting directory * @param {string} [startDir] Starting directory
* @returns {boolean} Whether a package.json is found in current path. * @returns {boolean} Whether a package.json is found in current path.
*/ */
function checkPackageJson(startDir) { function checkPackageJson(startDir) {

View File

@ -21,7 +21,7 @@ const debug = require("debug")("eslint:code-path");
* @returns {string} Id of the segment. * @returns {string} Id of the segment.
*/ */
/* istanbul ignore next */ /* istanbul ignore next */
function getId(segment) { // eslint-disable-line require-jsdoc function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc
return segment.id + (segment.reachable ? "" : "!"); return segment.id + (segment.reachable ? "" : "!");
} }

View File

@ -472,7 +472,6 @@ function normalizeFilename(filename) {
return index === -1 ? filename : parts.slice(index).join(path.sep); return index === -1 ? filename : parts.slice(index).join(path.sep);
} }
// eslint-disable-next-line valid-jsdoc
/** /**
* Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
* consistent shape. * consistent shape.

View File

@ -224,6 +224,12 @@ module.exports = optionator({
default: "false", default: "false",
description: "Run config initialization wizard" description: "Run config initialization wizard"
}, },
{
option: "env-info",
type: "Boolean",
default: "false",
description: "Output execution environment information"
},
{ {
option: "debug", option: "debug",
type: "Boolean", type: "Boolean",

View File

@ -130,7 +130,7 @@ function freezeDeeply(x) {
*/ */
function sanitize(text) { function sanitize(text) {
return text.replace( return text.replace(
/[\u0000-\u001f]/gu, // eslint-disable-line no-control-regex /[\u0000-\u0009|\u000b-\u001a]/gu, // eslint-disable-line no-control-regex
c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}` c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
); );
} }
@ -177,7 +177,6 @@ class RuleTester {
/** /**
* Creates a new instance of RuleTester. * Creates a new instance of RuleTester.
* @param {Object} [testerConfig] Optional, extra configuration for the tester * @param {Object} [testerConfig] Optional, extra configuration for the tester
* @constructor
*/ */
constructor(testerConfig) { constructor(testerConfig) {

View File

@ -59,7 +59,7 @@ const DEFAULTS = {
* @param {string} which Either "line" or "block". * @param {string} which Either "line" or "block".
* @returns {Object} The normalized options. * @returns {Object} The normalized options.
*/ */
function getNormalizedOptions(rawOptions = {}, which) { function getNormalizedOptions(rawOptions, which) {
return Object.assign({}, DEFAULTS, rawOptions[which] || rawOptions); return Object.assign({}, DEFAULTS, rawOptions[which] || rawOptions);
} }
@ -70,7 +70,7 @@ function getNormalizedOptions(rawOptions = {}, which) {
* @returns {Object} An object with "Line" and "Block" keys and corresponding * @returns {Object} An object with "Line" and "Block" keys and corresponding
* normalized options objects. * normalized options objects.
*/ */
function getAllNormalizedOptions(rawOptions) { function getAllNormalizedOptions(rawOptions = {}) {
return { return {
Line: getNormalizedOptions(rawOptions, "line"), Line: getNormalizedOptions(rawOptions, "line"),
Block: getNormalizedOptions(rawOptions, "block") Block: getNormalizedOptions(rawOptions, "block")

View File

@ -303,7 +303,7 @@ module.exports = {
* @param {int} needed Expected indentation character count * @param {int} needed Expected indentation character count
* @param {int} gottenSpaces Indentation space count in the actual node/code * @param {int} gottenSpaces Indentation space count in the actual node/code
* @param {int} gottenTabs Indentation tab count in the actual node/code * @param {int} gottenTabs Indentation tab count in the actual node/code
* @param {Object=} loc Error line and column location * @param {Object} [loc] Error line and column location
* @param {boolean} isLastNodeCheck Is the error for last node check * @param {boolean} isLastNodeCheck Is the error for last node check
* @returns {void} * @returns {void}
*/ */

View File

@ -81,6 +81,9 @@ const KNOWN_NODES = new Set([
"WhileStatement", "WhileStatement",
"WithStatement", "WithStatement",
"YieldExpression", "YieldExpression",
"JSXFragment",
"JSXOpeningFragment",
"JSXClosingFragment",
"JSXIdentifier", "JSXIdentifier",
"JSXNamespacedName", "JSXNamespacedName",
"JSXMemberExpression", "JSXMemberExpression",
@ -1453,6 +1456,31 @@ module.exports = {
offsets.setDesiredOffsets(node.name.range, firstToken, 1); offsets.setDesiredOffsets(node.name.range, firstToken, 1);
}, },
JSXFragment(node) {
const firstOpeningToken = sourceCode.getFirstToken(node.openingFragment);
const firstClosingToken = sourceCode.getFirstToken(node.closingFragment);
addElementListIndent(node.children, firstOpeningToken, firstClosingToken, 1);
},
JSXOpeningFragment(node) {
const firstToken = sourceCode.getFirstToken(node);
const closingToken = sourceCode.getLastToken(node);
offsets.setDesiredOffsets(node.range, firstToken, 1);
offsets.matchOffsetOf(firstToken, closingToken);
},
JSXClosingFragment(node) {
const firstToken = sourceCode.getFirstToken(node);
const slashToken = sourceCode.getLastToken(node, { skip: 1 });
const closingToken = sourceCode.getLastToken(node);
const tokenToMatch = astUtils.isTokenOnSameLine(slashToken, closingToken) ? slashToken : closingToken;
offsets.setDesiredOffsets(node.range, firstToken, 1);
offsets.matchOffsetOf(firstToken, tokenToMatch);
},
JSXExpressionContainer(node) { JSXExpressionContainer(node) {
const openingCurly = sourceCode.getFirstToken(node); const openingCurly = sourceCode.getFirstToken(node);
const closingCurly = sourceCode.getLastToken(node); const closingCurly = sourceCode.getLastToken(node);

View File

@ -65,7 +65,11 @@ module.exports = {
const lastToken = sourceCode.getLastToken(node); const lastToken = sourceCode.getLastToken(node);
const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken); const hasLastParen = lastToken && astUtils.isClosingParenToken(lastToken);
const hasParens = hasLastParen && astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken));
// `hasParens` is true only if the new expression ends with its own parens, e.g., new new foo() does not end with its own parens
const hasParens = hasLastParen &&
astUtils.isOpeningParenToken(sourceCode.getTokenBefore(lastToken)) &&
node.callee.range[1] < node.range[1];
if (always) { if (always) {
if (!hasParens) { if (!hasParens) {

View File

@ -40,6 +40,7 @@ module.exports = {
}, },
create(context) { create(context) {
const sourceCode = context.getSourceCode();
let scopeInfo = null; let scopeInfo = null;
/** /**
@ -71,8 +72,13 @@ module.exports = {
return null; return null;
} }
const firstTokenToRemove = context.getSourceCode() const firstTokenToRemove = sourceCode
.getFirstTokenBetween(node.parent.object, node.parent.property, astUtils.isNotClosingParenToken); .getFirstTokenBetween(node.parent.object, node.parent.property, astUtils.isNotClosingParenToken);
const lastTokenToRemove = sourceCode.getLastToken(node.parent.parent);
if (sourceCode.commentsExistBetween(firstTokenToRemove, lastTokenToRemove)) {
return null;
}
return fixer.removeRange([firstTokenToRemove.range[0], node.parent.parent.range[1]]); return fixer.removeRange([firstTokenToRemove.range[0], node.parent.parent.range[1]]);
} }

View File

@ -116,7 +116,15 @@ module.exports = {
node: labelNode, node: labelNode,
messageId: "unexpected", messageId: "unexpected",
data: labelNode, data: labelNode,
fix: fixer => fixer.removeRange([sourceCode.getFirstToken(node).range[1], labelNode.range[1]]) fix(fixer) {
const breakOrContinueToken = sourceCode.getFirstToken(node);
if (sourceCode.commentsExistBetween(breakOrContinueToken, labelNode)) {
return null;
}
return fixer.removeRange([breakOrContinueToken.range[1], labelNode.range[1]]);
}
}); });
} }
return; return;

View File

@ -205,7 +205,14 @@ module.exports = {
const lastToken = sourceCode.getLastToken(newExpression); const lastToken = sourceCode.getLastToken(newExpression);
const penultimateToken = sourceCode.getTokenBefore(lastToken); const penultimateToken = sourceCode.getTokenBefore(lastToken);
return newExpression.arguments.length > 0 || astUtils.isOpeningParenToken(penultimateToken) && astUtils.isClosingParenToken(lastToken); return newExpression.arguments.length > 0 ||
(
// The expression should end with its own parens, e.g., new new foo() is not a new expression with parens
astUtils.isOpeningParenToken(penultimateToken) &&
astUtils.isClosingParenToken(lastToken) &&
newExpression.callee.range[1] < newExpression.range[1]
);
} }
/** /**
@ -338,7 +345,7 @@ module.exports = {
function finishReport() { function finishReport() {
context.report({ context.report({
node, node,
loc: leftParenToken.loc.start, loc: leftParenToken.loc,
messageId: "unexpected", messageId: "unexpected",
fix(fixer) { fix(fixer) {
const parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]); const parenthesizedSource = sourceCode.text.slice(leftParenToken.range[1], rightParenToken.range[0]);
@ -887,6 +894,12 @@ module.exports = {
report(node.object); report(node.object);
} }
if (nodeObjHasExcessParens &&
node.object.type === "NewExpression" &&
isNewExpressionWithParens(node.object)) {
report(node.object);
}
if (node.computed && hasExcessParens(node.property)) { if (node.computed && hasExcessParens(node.property)) {
report(node.property); report(node.property);
} }

View File

@ -5,7 +5,29 @@
"use strict"; "use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils"); const astUtils = require("./utils/ast-utils");
const regexpp = require("regexpp");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const regExpParser = new regexpp.RegExpParser();
const DOUBLE_SPACE = / {2}/u;
/**
* Check if node is a string
* @param {ASTNode} node node to evaluate
* @returns {boolean} True if its a string
* @private
*/
function isString(node) {
return node && node.type === "Literal" && typeof node.value === "string";
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Rule Definition // Rule Definition
@ -27,40 +49,70 @@ module.exports = {
}, },
create(context) { create(context) {
const sourceCode = context.getSourceCode();
/** /**
* Validate regular expressions * Validate regular expression
* @param {ASTNode} node node to validate *
* @param {string} value regular expression to validate * @param {ASTNode} nodeToReport Node to report.
* @param {number} valueStart The start location of the regex/string literal. It will always be the case that * @param {string} pattern Regular expression pattern to validate.
* `sourceCode.getText().slice(valueStart, valueStart + value.length) === value` * @param {string} rawPattern Raw representation of the pattern in the source code.
* @param {number} rawPatternStartRange Start range of the pattern in the source code.
* @param {string} flags Regular expression flags.
* @returns {void} * @returns {void}
* @private * @private
*/ */
function checkRegex(node, value, valueStart) { function checkRegex(nodeToReport, pattern, rawPattern, rawPatternStartRange, flags) {
const multipleSpacesRegex = /( {2,})( [+*{?]|[^+*{?]|$)/u,
regexResults = multipleSpacesRegex.exec(value);
if (regexResults !== null) { // Skip if there are no consecutive spaces in the source code, to avoid reporting e.g., RegExp(' \ ').
const count = regexResults[1].length; if (!DOUBLE_SPACE.test(rawPattern)) {
return;
}
const characterClassNodes = [];
let regExpAST;
try {
regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
} catch (e) {
// Ignore regular expressions with syntax errors
return;
}
regexpp.visitRegExpAST(regExpAST, {
onCharacterClassEnter(ccNode) {
characterClassNodes.push(ccNode);
}
});
const spacesPattern = /( {2,})(?: [+*{?]|[^+*{?]|$)/gu;
let match;
while ((match = spacesPattern.exec(pattern))) {
const { 1: { length }, index } = match;
// Report only consecutive spaces that are not in character classes.
if (
characterClassNodes.every(({ start, end }) => index < start || end <= index)
) {
context.report({ context.report({
node, node: nodeToReport,
message: "Spaces are hard to count. Use {{{count}}}.", message: "Spaces are hard to count. Use {{{length}}}.",
data: { count }, data: { length },
fix(fixer) { fix(fixer) {
if (pattern !== rawPattern) {
return null;
}
return fixer.replaceTextRange( return fixer.replaceTextRange(
[valueStart + regexResults.index, valueStart + regexResults.index + count], [rawPatternStartRange + index, rawPatternStartRange + index + length],
` {${count}}` ` {${length}}`
); );
} }
}); });
/* // Report only the first occurence of consecutive spaces
* TODO: (platinumazure) Fix message to use rule message return;
* substitution when api.report is fixed in lib/eslint.js. }
*/
} }
} }
@ -71,25 +123,22 @@ module.exports = {
* @private * @private
*/ */
function checkLiteral(node) { function checkLiteral(node) {
const token = sourceCode.getFirstToken(node), if (node.regex) {
nodeType = token.type, const pattern = node.regex.pattern;
nodeValue = token.value; const rawPattern = node.raw.slice(1, node.raw.lastIndexOf("/"));
const rawPatternStartRange = node.range[0] + 1;
const flags = node.regex.flags;
if (nodeType === "RegularExpression") { checkRegex(
checkRegex(node, nodeValue, token.range[0]); node,
pattern,
rawPattern,
rawPatternStartRange,
flags
);
} }
} }
/**
* Check if node is a string
* @param {ASTNode} node node to evaluate
* @returns {boolean} True if its a string
* @private
*/
function isString(node) {
return node && node.type === "Literal" && typeof node.value === "string";
}
/** /**
* Validate strings passed to the RegExp constructor * Validate strings passed to the RegExp constructor
* @param {ASTNode} node node to validate * @param {ASTNode} node node to validate
@ -100,9 +149,22 @@ module.exports = {
const scope = context.getScope(); const scope = context.getScope();
const regExpVar = astUtils.getVariableByName(scope, "RegExp"); const regExpVar = astUtils.getVariableByName(scope, "RegExp");
const shadowed = regExpVar && regExpVar.defs.length > 0; const shadowed = regExpVar && regExpVar.defs.length > 0;
const patternNode = node.arguments[0];
const flagsNode = node.arguments[1];
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0]) && !shadowed) { if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(patternNode) && !shadowed) {
checkRegex(node, node.arguments[0].value, node.arguments[0].range[0] + 1); const pattern = patternNode.value;
const rawPattern = patternNode.raw.slice(1, -1);
const rawPatternStartRange = patternNode.range[0] + 1;
const flags = isString(flagsNode) ? flagsNode.value : "";
checkRegex(
node,
pattern,
rawPattern,
rawPatternStartRange,
flags
);
} }
} }
@ -111,6 +173,5 @@ module.exports = {
CallExpression: checkFunction, CallExpression: checkFunction,
NewExpression: checkFunction NewExpression: checkFunction
}; };
} }
}; };

View File

@ -37,7 +37,8 @@ module.exports = {
init = node.init && node.init.name, init = node.init && node.init.name,
scope = context.getScope(), scope = context.getScope(),
undefinedVar = astUtils.getVariableByName(scope, "undefined"), undefinedVar = astUtils.getVariableByName(scope, "undefined"),
shadowed = undefinedVar && undefinedVar.defs.length > 0; shadowed = undefinedVar && undefinedVar.defs.length > 0,
lastToken = sourceCode.getLastToken(node);
if (init === "undefined" && node.parent.kind !== "const" && !shadowed) { if (init === "undefined" && node.parent.kind !== "const" && !shadowed) {
context.report({ context.report({
@ -54,6 +55,11 @@ module.exports = {
// Don't fix destructuring assignment to `undefined`. // Don't fix destructuring assignment to `undefined`.
return null; return null;
} }
if (sourceCode.commentsExistBetween(node.id, lastToken)) {
return null;
}
return fixer.removeRange([node.id.range[1], node.range[1]]); return fixer.removeRange([node.id.range[1], node.range[1]]);
} }
}); });

View File

@ -36,7 +36,8 @@ module.exports = {
}, },
create(context) { create(context) {
const options = context.options[0] || {}, const sourceCode = context.getSourceCode(),
options = context.options[0] || {},
ignoreDestructuring = options.ignoreDestructuring === true, ignoreDestructuring = options.ignoreDestructuring === true,
ignoreImport = options.ignoreImport === true, ignoreImport = options.ignoreImport === true,
ignoreExport = options.ignoreExport === true; ignoreExport = options.ignoreExport === true;
@ -64,10 +65,18 @@ module.exports = {
type type
}, },
fix(fixer) { fix(fixer) {
if (sourceCode.commentsExistBetween(initial, result)) {
return null;
}
const replacementText = result.type === "AssignmentPattern"
? sourceCode.getText(result)
: name;
return fixer.replaceTextRange([ return fixer.replaceTextRange([
initial.range[0], initial.range[0],
result.range[1] result.range[1]
], name); ], replacementText);
} }
}); });
} }
@ -82,26 +91,29 @@ module.exports = {
return; return;
} }
const properties = node.properties; for (const property of node.properties) {
for (let i = 0; i < properties.length; i++) { /*
if (properties[i].shorthand) { * TODO: Remove after babel-eslint removes ExperimentalRestProperty
* https://github.com/eslint/eslint/issues/12335
*/
if (property.type === "ExperimentalRestProperty") {
continue; continue;
} }
/** /**
* If an ObjectPattern property is computed, we have no idea * Properties using shorthand syntax and rest elements can not be renamed.
* if a rename is useless or not. If an ObjectPattern property * If the property is computed, we have no idea if a rename is useless or not.
* lacks a key, it is likely an ExperimentalRestProperty and
* so there is no "renaming" occurring here.
*/ */
if (properties[i].computed || !properties[i].key) { if (property.shorthand || property.type === "RestElement" || property.computed) {
continue; continue;
} }
if (properties[i].key.type === "Identifier" && properties[i].key.name === properties[i].value.name || const key = (property.key.type === "Identifier" && property.key.name) || (property.key.type === "Literal" && property.key.value);
properties[i].key.type === "Literal" && properties[i].key.value === properties[i].value.name) { const renamedKey = property.value.type === "AssignmentPattern" ? property.value.left.name : property.value.name;
reportError(properties[i], properties[i].key, properties[i].value, "Destructuring assignment");
if (key === renamedKey) {
reportError(property, property.key, property.value, "Destructuring assignment");
} }
} }
} }

View File

@ -82,6 +82,7 @@ module.exports = {
create(context) { create(context) {
const segmentInfoMap = new WeakMap(); const segmentInfoMap = new WeakMap();
const usedUnreachableSegments = new WeakSet(); const usedUnreachableSegments = new WeakSet();
const sourceCode = context.getSourceCode();
let scopeInfo = null; let scopeInfo = null;
/** /**
@ -216,7 +217,7 @@ module.exports = {
loc: node.loc, loc: node.loc,
message: "Unnecessary return statement.", message: "Unnecessary return statement.",
fix(fixer) { fix(fixer) {
if (isRemovable(node)) { if (isRemovable(node) && !sourceCode.getCommentsInside(node).length) {
/* /*
* Extend the replacement range to include the * Extend the replacement range to include the
@ -224,7 +225,7 @@ module.exports = {
* no-else-return. * no-else-return.
* https://github.com/eslint/eslint/issues/8026 * https://github.com/eslint/eslint/issues/8026
*/ */
return new FixTracker(fixer, context.getSourceCode()) return new FixTracker(fixer, sourceCode)
.retainEnclosingFunction(node) .retainEnclosingFunction(node)
.remove(node); .remove(node);
} }

View File

@ -50,16 +50,16 @@ module.exports = {
/** /**
* Function to check regular expression. * Function to check regular expression.
* *
* @param {string} regex The regular expression to be check. * @param {string} pattern The regular expression pattern to be check.
* @param {ASTNode} node AST node which contains regular expression. * @param {ASTNode} node AST node which contains regular expression.
* @param {boolean} uFlag Flag indicates whether unicode mode is enabled or not. * @param {boolean} uFlag Flag indicates whether unicode mode is enabled or not.
* @returns {void} * @returns {void}
*/ */
function checkRegex(regex, node, uFlag) { function checkRegex(pattern, node, uFlag) {
let ast; let ast;
try { try {
ast = parser.parsePattern(regex, 0, regex.length, uFlag); ast = parser.parsePattern(pattern, 0, pattern.length, uFlag);
} catch (_) { } catch (_) {
// ignore regex syntax errors // ignore regex syntax errors
@ -69,21 +69,9 @@ module.exports = {
regexpp.visitRegExpAST(ast, { regexpp.visitRegExpAST(ast, {
onCapturingGroupEnter(group) { onCapturingGroupEnter(group) {
if (!group.name) { if (!group.name) {
const locNode = node.type === "Literal" ? node : node.arguments[0];
context.report({ context.report({
node, node,
messageId: "required", messageId: "required",
loc: {
start: {
line: locNode.loc.start.line,
column: locNode.loc.start.column + group.start + 1
},
end: {
line: locNode.loc.start.line,
column: locNode.loc.start.column + group.end + 1
}
},
data: { data: {
group: group.raw group: group.raw
} }

View File

@ -96,6 +96,10 @@ module.exports = {
fix(fixer) { fix(fixer) {
const newPrefix = prefixMap[node.arguments[1].value]; const newPrefix = prefixMap[node.arguments[1].value];
if (sourceCode.getCommentsInside(node).length) {
return null;
}
if (+(newPrefix + node.arguments[0].value) !== parseInt(node.arguments[0].value, node.arguments[1].value)) { if (+(newPrefix + node.arguments[0].value) !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
/* /*

View File

@ -5,6 +5,19 @@
"use strict"; "use strict";
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Determines if the given node is a NaN `Identifier` node.
* @param {ASTNode|null} node The node to check.
* @returns {boolean} `true` if the node is 'NaN' identifier.
*/
function isNaNIdentifier(node) {
return Boolean(node) && node.type === "Identifier" && node.name === "NaN";
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Rule Definition // Rule Definition
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -20,21 +33,69 @@ module.exports = {
url: "https://eslint.org/docs/rules/use-isnan" url: "https://eslint.org/docs/rules/use-isnan"
}, },
schema: [], schema: [
{
type: "object",
properties: {
enforceForSwitchCase: {
type: "boolean",
default: false
}
},
additionalProperties: false
}
],
messages: { messages: {
useIsNaN: "Use the isNaN function to compare with NaN." comparisonWithNaN: "Use the isNaN function to compare with NaN.",
switchNaN: "'switch(NaN)' can never match a case clause. Use Number.isNaN instead of the switch.",
caseNaN: "'case NaN' can never match. Use Number.isNaN before the switch."
} }
}, },
create(context) { create(context) {
return { const enforceForSwitchCase = context.options[0] && context.options[0].enforceForSwitchCase;
BinaryExpression(node) {
if (/^(?:[<>]|[!=]=)=?$/u.test(node.operator) && (node.left.name === "NaN" || node.right.name === "NaN")) { /**
context.report({ node, messageId: "useIsNaN" }); * Checks the given `BinaryExpression` node.
* @param {ASTNode} node The node to check.
* @returns {void}
*/
function checkBinaryExpression(node) {
if (
/^(?:[<>]|[!=]=)=?$/u.test(node.operator) &&
(isNaNIdentifier(node.left) || isNaNIdentifier(node.right))
) {
context.report({ node, messageId: "comparisonWithNaN" });
} }
} }
/**
* Checks the discriminant and all case clauses of the given `SwitchStatement` node.
* @param {ASTNode} node The node to check.
* @returns {void}
*/
function checkSwitchStatement(node) {
if (isNaNIdentifier(node.discriminant)) {
context.report({ node, messageId: "switchNaN" });
}
for (const switchCase of node.cases) {
if (isNaNIdentifier(switchCase.test)) {
context.report({ node: switchCase, messageId: "caseNaN" });
}
}
}
const listeners = {
BinaryExpression: checkBinaryExpression
}; };
if (enforceForSwitchCase) {
listeners.SwitchStatement = checkSwitchStatement;
}
return listeners;
} }
}; };

View File

@ -12,6 +12,7 @@ module.exports = {
/** /**
* Cover for console.log * Cover for console.log
* @param {...any} args The elements to log.
* @returns {void} * @returns {void}
*/ */
info(...args) { info(...args) {
@ -20,6 +21,7 @@ module.exports = {
/** /**
* Cover for console.error * Cover for console.error
* @param {...any} args The elements to log.
* @returns {void} * @returns {void}
*/ */
error(...args) { error(...args) {

163
tools/node_modules/eslint/lib/shared/runtime-info.js generated vendored Normal file
View File

@ -0,0 +1,163 @@
/**
* @fileoverview Utility to get information about the execution environment.
* @author Kai Cataldo
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const path = require("path");
const spawn = require("cross-spawn");
const { isEmpty } = require("lodash");
const log = require("../shared/logging");
const packageJson = require("../../package.json");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Generates and returns execution environment information.
* @returns {string} A string that contains execution environment information.
*/
function environment() {
const cache = new Map();
/**
* Checks if a path is a child of a directory.
* @param {string} parentPath - The parent path to check.
* @param {string} childPath - The path to check.
* @returns {boolean} Whether or not the given path is a child of a directory.
*/
function isChildOfDirectory(parentPath, childPath) {
return !path.relative(parentPath, childPath).startsWith("..");
}
/**
* Synchronously executes a shell command and formats the result.
* @param {string} cmd - The command to execute.
* @param {Array} args - The arguments to be executed with the command.
* @returns {string} The version returned by the command.
*/
function execCommand(cmd, args) {
const key = [cmd, ...args].join(" ");
if (cache.has(key)) {
return cache.get(key);
}
const process = spawn.sync(cmd, args, { encoding: "utf8" });
if (process.error) {
throw process.error;
}
const result = process.stdout.trim();
cache.set(key, result);
return result;
}
/**
* Normalizes a version number.
* @param {string} versionStr - The string to normalize.
* @returns {string} The normalized version number.
*/
function normalizeVersionStr(versionStr) {
return versionStr.startsWith("v") ? versionStr : `v${versionStr}`;
}
/**
* Gets bin version.
* @param {string} bin - The bin to check.
* @returns {string} The normalized version returned by the command.
*/
function getBinVersion(bin) {
const binArgs = ["--version"];
try {
return normalizeVersionStr(execCommand(bin, binArgs));
} catch (e) {
log.error(`Error finding ${bin} version running the command \`${bin} ${binArgs.join(" ")}\``);
throw e;
}
}
/**
* Gets installed npm package version.
* @param {string} pkg - The package to check.
* @param {boolean} global - Whether to check globally or not.
* @returns {string} The normalized version returned by the command.
*/
function getNpmPackageVersion(pkg, { global = false } = {}) {
const npmBinArgs = ["bin", "-g"];
const npmLsArgs = ["ls", "--depth=0", "--json", "eslint"];
if (global) {
npmLsArgs.push("-g");
}
try {
const parsedStdout = JSON.parse(execCommand("npm", npmLsArgs));
/*
* Checking globally returns an empty JSON object, while local checks
* include the name and version of the local project.
*/
if (isEmpty(parsedStdout) || !(parsedStdout.dependencies && parsedStdout.dependencies.eslint)) {
return "Not found";
}
const [, processBinPath] = process.argv;
let npmBinPath;
try {
npmBinPath = execCommand("npm", npmBinArgs);
} catch (e) {
log.error(`Error finding npm binary path when running command \`npm ${npmBinArgs.join(" ")}\``);
throw e;
}
const isGlobal = isChildOfDirectory(npmBinPath, processBinPath);
let pkgVersion = parsedStdout.dependencies.eslint.version;
if ((global && isGlobal) || (!global && !isGlobal)) {
pkgVersion += " (Currently used)";
}
return normalizeVersionStr(pkgVersion);
} catch (e) {
log.error(`Error finding ${pkg} version running the command \`npm ${npmLsArgs.join(" ")}\``);
throw e;
}
}
return [
"Environment Info:",
"",
`Node version: ${getBinVersion("node")}`,
`npm version: ${getBinVersion("npm")}`,
`Local ESLint version: ${getNpmPackageVersion("eslint", { global: false })}`,
`Global ESLint version: ${getNpmPackageVersion("eslint", { global: true })}`
].join("\n");
}
/**
* Returns version of currently executing ESLint.
* @returns {string} The version from the currently executing ESLint's package.json.
*/
function version() {
return `v${packageJson.version}`;
}
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
module.exports = {
environment,
version
};

View File

@ -93,7 +93,6 @@ class SourceCode extends TokenStore {
* @param {ScopeManager|null} textOrConfig.scopeManager - The scope of this source code. * @param {ScopeManager|null} textOrConfig.scopeManager - The scope of this source code.
* @param {Object|null} textOrConfig.visitorKeys - The visitor keys to traverse AST. * @param {Object|null} textOrConfig.visitorKeys - The visitor keys to traverse AST.
* @param {ASTNode} [astIfNoConfig] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped. * @param {ASTNode} [astIfNoConfig] - The Program node of the AST representing the code. This AST should be created from the text that BOM was stripped.
* @constructor
*/ */
constructor(textOrConfig, astIfNoConfig) { constructor(textOrConfig, astIfNoConfig) {
let text, ast, parserServices, scopeManager, visitorKeys; let text, ast, parserServices, scopeManager, visitorKeys;
@ -206,9 +205,9 @@ class SourceCode extends TokenStore {
/** /**
* Gets the source code for the given node. * Gets the source code for the given node.
* @param {ASTNode=} node The AST node to get the text for. * @param {ASTNode} [node] The AST node to get the text for.
* @param {int=} beforeCount The number of characters before the node to retrieve. * @param {int} [beforeCount] The number of characters before the node to retrieve.
* @param {int=} afterCount The number of characters after the node to retrieve. * @param {int} [afterCount] The number of characters after the node to retrieve.
* @returns {string} The text representing the AST node. * @returns {string} The text representing the AST node.
* @public * @public
*/ */

View File

@ -52,9 +52,10 @@ Options can be provided by passing a second argument, which should be
an object containing any of these fields: an object containing any of these fields:
- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be - **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018) or 10 (2019, partial either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), 10 (2019) or 11
support). This influences support for strict mode, the set of (2020, partial support). This influences support for strict mode,
reserved words, and support for new syntax features. Default is 10. the set of reserved words, and support for new syntax features.
Default is 10.
**NOTE**: Only 'stage 4' (finalized) ECMAScript features are being **NOTE**: Only 'stage 4' (finalized) ECMAScript features are being
implemented by Acorn. Other proposed new features can be implemented implemented by Acorn. Other proposed new features can be implemented

View File

@ -2173,7 +2173,7 @@
// super [ Expression ] // super [ Expression ]
// super . IdentifierName // super . IdentifierName
// SuperCall: // SuperCall:
// super Arguments // super ( Arguments )
if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
{ this.unexpected(); } { this.unexpected(); }
return this.finishNode(node, "Super") return this.finishNode(node, "Super")
@ -2468,7 +2468,7 @@
while (!this.eat(types.braceR)) { while (!this.eat(types.braceR)) {
if (!first) { if (!first) {
this.expect(types.comma); this.expect(types.comma);
if (this.afterTrailingComma(types.braceR)) { break } if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
} else { first = false; } } else { first = false; }
var prop = this.parseProperty(isPattern, refDestructuringErrors); var prop = this.parseProperty(isPattern, refDestructuringErrors);
@ -4923,7 +4923,29 @@
// Acorn is a tiny, fast JavaScript parser written in JavaScript. // Acorn is a tiny, fast JavaScript parser written in JavaScript.
var version = "7.0.0"; var version = "7.1.0";
Parser.acorn = {
Parser: Parser,
version: version,
defaultOptions: defaultOptions,
Position: Position,
SourceLocation: SourceLocation,
getLineInfo: getLineInfo,
Node: Node,
TokenType: TokenType,
tokTypes: types,
keywordTypes: keywords$1,
TokContext: TokContext,
tokContexts: types$1,
isIdentifierChar: isIdentifierChar,
isIdentifierStart: isIdentifierStart,
Token: Token,
isNewLine: isNewLine,
lineBreak: lineBreak,
lineBreakG: lineBreakG,
nonASCIIwhitespace: nonASCIIwhitespace
};
// The main exported interface (under `self.acorn` when in the // The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and // browser) is a `parse` function that takes a code string and

View File

@ -2167,7 +2167,7 @@ pp$3.parseExprAtom = function(refDestructuringErrors) {
// super [ Expression ] // super [ Expression ]
// super . IdentifierName // super . IdentifierName
// SuperCall: // SuperCall:
// super Arguments // super ( Arguments )
if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL)
{ this.unexpected(); } { this.unexpected(); }
return this.finishNode(node, "Super") return this.finishNode(node, "Super")
@ -2462,7 +2462,7 @@ pp$3.parseObj = function(isPattern, refDestructuringErrors) {
while (!this.eat(types.braceR)) { while (!this.eat(types.braceR)) {
if (!first) { if (!first) {
this.expect(types.comma); this.expect(types.comma);
if (this.afterTrailingComma(types.braceR)) { break } if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break }
} else { first = false; } } else { first = false; }
var prop = this.parseProperty(isPattern, refDestructuringErrors); var prop = this.parseProperty(isPattern, refDestructuringErrors);
@ -4917,7 +4917,29 @@ pp$9.readWord = function() {
// Acorn is a tiny, fast JavaScript parser written in JavaScript. // Acorn is a tiny, fast JavaScript parser written in JavaScript.
var version = "7.0.0"; var version = "7.1.0";
Parser.acorn = {
Parser: Parser,
version: version,
defaultOptions: defaultOptions,
Position: Position,
SourceLocation: SourceLocation,
getLineInfo: getLineInfo,
Node: Node,
TokenType: TokenType,
tokTypes: types,
keywordTypes: keywords$1,
TokContext: TokContext,
tokContexts: types$1,
isIdentifierChar: isIdentifierChar,
isIdentifierStart: isIdentifierStart,
Token: Token,
isNewLine: isNewLine,
lineBreak: lineBreak,
lineBreakG: lineBreakG,
nonASCIIwhitespace: nonASCIIwhitespace
};
// The main exported interface (under `self.acorn` when in the // The main exported interface (under `self.acorn` when in the
// browser) is a `parse` function that takes a code string and // browser) is a `parse` function that takes a code string and

View File

@ -39,5 +39,5 @@
"scripts": { "scripts": {
"prepare": "cd ..; npm run build:main && npm run build:bin" "prepare": "cd ..; npm run build:main && npm run build:bin"
}, },
"version": "7.0.0" "version": "7.1.0"
} }

View File

@ -36,10 +36,19 @@ globParent('path/foo'); // 'path' (see issue #3 for details)
## API ## API
### `globParent(maybeGlobString)` ### `globParent(maybeGlobString, [options])`
Takes a string and returns the part of the path before the glob begins. Be aware of Escaping rules and Limitations below. Takes a string and returns the part of the path before the glob begins. Be aware of Escaping rules and Limitations below.
#### options
```js
{
// Disables the automatic conversion of slashes for Windows
flipBackslashes: true
}
```
## Escaping ## Escaping
The following characters have special significance in glob patterns and must be escaped if you want them to be treated as regular path characters: The following characters have special significance in glob patterns and must be escaped if you want them to be treated as regular path characters:

View File

@ -10,9 +10,16 @@ var enclosure = /[\{\[].*[\/]*.*[\}\]]$/;
var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/;
var escaped = /\\([\*\?\|\[\]\(\)\{\}])/g; var escaped = /\\([\*\?\|\[\]\(\)\{\}])/g;
module.exports = function globParent(str) { /**
* @param {string} str
* @param {Object} opts
* @param {boolean} [opts.flipBackslashes=true]
*/
module.exports = function globParent(str, opts) {
var options = Object.assign({ flipBackslashes: true }, opts);
// flip windows path separators // flip windows path separators
if (isWin32 && str.indexOf(slash) < 0) { if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
str = str.replace(backslash, slash); str = str.replace(backslash, slash);
} }

View File

@ -63,5 +63,5 @@
"pretest": "npm run lint", "pretest": "npm run lint",
"test": "nyc mocha --async-only" "test": "nyc mocha --async-only"
}, },
"version": "5.0.0" "version": "5.1.0"
} }

View File

@ -17,7 +17,7 @@
"cross-spawn": "^6.0.5", "cross-spawn": "^6.0.5",
"debug": "^4.0.1", "debug": "^4.0.1",
"doctrine": "^3.0.0", "doctrine": "^3.0.0",
"eslint-plugin-markdown": "1.0.0", "eslint-plugin-markdown": "^1.0.0",
"eslint-scope": "^5.0.0", "eslint-scope": "^5.0.0",
"eslint-utils": "^1.4.2", "eslint-utils": "^1.4.2",
"eslint-visitor-keys": "^1.1.0", "eslint-visitor-keys": "^1.1.0",
@ -67,6 +67,7 @@
"eslint-config-eslint": "file:packages/eslint-config-eslint", "eslint-config-eslint": "file:packages/eslint-config-eslint",
"eslint-plugin-eslint-plugin": "^2.0.1", "eslint-plugin-eslint-plugin": "^2.0.1",
"eslint-plugin-internal-rules": "file:tools/internal-rules", "eslint-plugin-internal-rules": "file:tools/internal-rules",
"eslint-plugin-jsdoc": "^15.9.5",
"eslint-plugin-node": "^9.0.0", "eslint-plugin-node": "^9.0.0",
"eslint-release": "^1.2.0", "eslint-release": "^1.2.0",
"eslump": "^2.0.0", "eslump": "^2.0.0",
@ -137,6 +138,7 @@
}, },
"scripts": { "scripts": {
"docs": "node Makefile.js docs", "docs": "node Makefile.js docs",
"fix": "node Makefile.js lint -- fix",
"fuzz": "node Makefile.js fuzz", "fuzz": "node Makefile.js fuzz",
"generate-alpharelease": "node Makefile.js generatePrerelease -- alpha", "generate-alpharelease": "node Makefile.js generatePrerelease -- alpha",
"generate-betarelease": "node Makefile.js generatePrerelease -- beta", "generate-betarelease": "node Makefile.js generatePrerelease -- beta",
@ -149,5 +151,5 @@
"test": "node Makefile.js test", "test": "node Makefile.js test",
"webpack": "node Makefile.js webpack" "webpack": "node Makefile.js webpack"
}, },
"version": "6.4.0" "version": "6.5.1"
} }