Skip to content

Commit

Permalink
Merge branch 'main' into rfc-100-part1
Browse files Browse the repository at this point in the history
* main:
  fix: `TypeError: fs.exists is not a function` on read-only file system (eslint#17846)
  chore: add GitHub issue template for docs issues (eslint#17845)
  chore: Convert rule tests to FlatRuleTester (eslint#17819)
  docs: update link in ways-to-extend.md (eslint#17839)
  chore: upgrade eslint-plugin-unicorn to v49.0.0 (eslint#17837)
  chore: upgrade eslint-plugin-eslint-plugin v5.2.1 (eslint#17838)
  chore: update eslint-plugin-n v16.4.0 (eslint#17836)
  docs: Update README
  docs: fix migration-guide example (eslint#17829)
  docs: check config comments in rule examples (eslint#17815)
  docs: remove mention about ESLint stylistic rules in readme (eslint#17810)
  ci: unpin Node.js 21.2.0 (eslint#17821)
  docs: Update README
  fix: suggestion with invalid syntax in no-promise-executor-return rule (eslint#17812)
  • Loading branch information
bmish committed Dec 13, 2023
2 parents cd36dd7 + 7d5e5f6 commit ddf9aa2
Show file tree
Hide file tree
Showing 316 changed files with 8,665 additions and 7,955 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/change.yml
@@ -1,4 +1,4 @@
name: "\U0001F4DD Request a change (not rule-related)"
name: "\U0001F680 Request a change (not rule-related)"
description: "Request a change that is not a bug fix, rule change, or new rule"
title: "Change Request: (fill in)"
labels:
Expand Down
46 changes: 46 additions & 0 deletions .github/ISSUE_TEMPLATE/docs.yml
@@ -0,0 +1,46 @@
name: "\U0001F4DD Docs"
description: "Request an improvement to documentation"
title: "Docs: (fill in)"
labels:
- documentation
body:
- type: markdown
attributes:
value: By opening an issue, you agree to abide by the [Open JS Foundation Code of Conduct](https://eslint.org/conduct).
- type: textarea
attributes:
label: Docs page(s)
description: |
What page(s) are you suggesting be changed or created?
placeholder: |
e.g. https://eslint.org/docs/latest/use/getting-started
validations:
required: true
- type: textarea
attributes:
label: What documentation issue do you want to solve?
description: |
Please explain your issue in as much detail as possible.
placeholder: |
The ESLint docs currently...
validations:
required: true
- type: textarea
attributes:
label: What do you think is the correct solution?
description: |
Please explain how you'd like to change the ESLint docs to address the problem.
placeholder: |
I'd like the ESLint docs to...
validations:
required: true
- type: checkboxes
attributes:
label: Participation
options:
- label: I am willing to submit a pull request for this change.
required: false
- type: textarea
attributes:
label: Additional comments
description: Is there anything else that's important for the team to know?
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Expand Up @@ -47,7 +47,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
node: ["21.2.0", 20.x, 19.x, 18.x, 17.x, 16.x, 14.x, 12.x, "12.22.0"]
node: [21.x, 20.x, 19.x, 18.x, 17.x, 16.x, 14.x, 12.x, "12.22.0"]
include:
- os: windows-latest
node: "lts/*"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -103,7 +103,7 @@ We are now at or near 100% compatibility with JSCS. If you try ESLint and believ

### Does Prettier replace ESLint?

No, ESLint does both traditional linting (looking for problematic patterns) and style checking (enforcement of conventions). You can use ESLint for everything, or you can combine both using Prettier to format your code and ESLint to catch possible errors.
No, ESLint and Prettier have diffent jobs: ESLint is a linter (looking for problematic patterns) and Prettier is a code formatter. Using both tools is common, refer to [Prettier's documentation](https://prettier.io/docs/en/install#eslint-and-other-linters) to learn how to configure them to work well with each other.

### Why can't ESLint find my plugins?

Expand Down Expand Up @@ -293,8 +293,8 @@ The following companies, organizations, and individuals support ESLint's ongoing
<h3>Platinum Sponsors</h3>
<p><a href="#"><img src="https://images.opencollective.com/2021-frameworks-fund/logo.png" alt="Chrome Frameworks Fund" height="undefined"></a> <a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
<p><a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a></p>
<p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a></p>
<!--sponsorsend-->

## Technology Sponsors
Expand Down
2 changes: 1 addition & 1 deletion docs/src/extend/ways-to-extend.md
Expand Up @@ -53,7 +53,7 @@ ESLint custom parsers are a way to extend ESLint to support the linting of new l

ESLint ships with a built-in JavaScript parser (Espree), but custom parsers allow you to lint other languages or to extend the linting capabilities of the built-in parser.

For example, the custom parser [@typescript-eslint/parser](https://typescript-eslint.io/architecture/parser/) extends ESLint to lint TypeScript code.
For example, the custom parser [@typescript-eslint/parser](https://typescript-eslint.io/packages/parser) extends ESLint to lint TypeScript code.

Custom parsers **cannot** be included in a plugin, unlike the other extension types.

Expand Down
1 change: 1 addition & 0 deletions docs/src/rules/capitalized-comments.md
Expand Up @@ -33,6 +33,7 @@ Examples of **correct** code for this rule:
:::correct

```js
/* eslint capitalized-comments: error */

// Capitalized comment

Expand Down
4 changes: 4 additions & 0 deletions docs/src/rules/no-buffer-constructor.md
Expand Up @@ -21,6 +21,8 @@ Examples of **incorrect** code for this rule:
::: incorrect

```js
/* eslint no-buffer-constructor: error */

new Buffer(5);
new Buffer([1, 2, 3]);

Expand All @@ -38,6 +40,8 @@ Examples of **correct** code for this rule:
::: correct

```js
/* eslint no-buffer-constructor: error */

Buffer.alloc(5);
Buffer.allocUnsafe(5);
Buffer.from([1, 2, 3]);
Expand Down
1 change: 1 addition & 0 deletions docs/src/rules/no-implicit-globals.md
Expand Up @@ -264,6 +264,7 @@ Examples of **correct** code for `/* exported variableName */` operation:
::: correct { "sourceType": "script" }

```js
/* eslint no-implicit-globals: error */
/* exported global_var */

var global_var = 42;
Expand Down
20 changes: 0 additions & 20 deletions docs/src/rules/strict.md
Expand Up @@ -271,19 +271,13 @@ This option ensures that all functions are executed in strict mode. A strict mod

Examples of **incorrect** code for this rule with the earlier default option which has been removed:

::: incorrect { "sourceType": "script" }

```js
// "strict": "error"

function foo() {
}
```

:::

::: incorrect { "sourceType": "script" }

```js
// "strict": "error"

Expand All @@ -294,12 +288,8 @@ function foo() {
}());
```

:::

Examples of **correct** code for this rule with the earlier default option which has been removed:

::: correct { "sourceType": "script" }

```js
// "strict": "error"

Expand All @@ -309,10 +299,6 @@ function foo() {
}
```

:::

::: correct { "sourceType": "script" }

```js
// "strict": "error"

Expand All @@ -321,10 +307,6 @@ function foo() {
}
```

:::

::: correct { "sourceType": "script" }

```js
// "strict": "error"

Expand All @@ -336,8 +318,6 @@ function foo() {
}());
```

:::

## When Not To Use It

In a codebase that has both strict and non-strict code, either turn this rule off, or [selectively disable it](../use/configure/rules#disabling-rules) where necessary. For example, functions referencing `arguments.callee` are invalid in strict mode. A [full list of strict mode differences](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode#Differences_from_non-strict_to_strict) is available on MDN.
6 changes: 2 additions & 4 deletions docs/src/use/configure/migration-guide.md
Expand Up @@ -318,13 +318,11 @@ import globals from "globals";
export default [
{
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
globals: {
...globals.browser,
myCustomGlobal: "readonly"
},
parserOptions: {
ecmaVersion: 2022,
sourceType: "module"
}
}
// ...other config
Expand Down
13 changes: 12 additions & 1 deletion eslint.config.js
Expand Up @@ -135,7 +135,18 @@ module.exports = [
files: ["tests/lib/rules/*", "tests/tools/internal-rules/*"],
...merge({}, eslintPluginTestsRecommendedConfig, {
rules: {
"eslint-plugin/test-case-property-ordering": "error",
"eslint-plugin/test-case-property-ordering": [
"error",
[
"name",
"filename",
"code",
"output",
"options",
"languageOptions",
"errors"
]
],
"eslint-plugin/test-case-shorthand-strings": "error"
}
})
Expand Down
3 changes: 2 additions & 1 deletion lib/eslint/flat-eslint.js
Expand Up @@ -11,6 +11,7 @@

// Note: Node.js 12 does not support fs/promises.
const fs = require("fs").promises;
const { existsSync } = require("fs");
const path = require("path");
const findUp = require("find-up");
const { version } = require("../../package.json");
Expand Down Expand Up @@ -761,7 +762,7 @@ class FlatESLint {
const errorCode = error && error.code;

// Ignore errors when no such file exists or file system is read only (and cache file does not exist)
if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !(await fs.exists(cacheFilePath)))) {
if (errorCode !== "ENOENT" && !(errorCode === "EROFS" && !existsSync(cacheFilePath))) {
throw error;
}
}
Expand Down
36 changes: 35 additions & 1 deletion lib/linter/config-comment-parser.js
Expand Up @@ -15,7 +15,10 @@ const levn = require("levn"),
Legacy: {
ConfigOps
}
} = require("@eslint/eslintrc/universal");
} = require("@eslint/eslintrc/universal"),
{
directivesPattern
} = require("../shared/directives");

const debug = require("debug")("eslint:config-comment-parser");

Expand Down Expand Up @@ -148,4 +151,35 @@ module.exports = class ConfigCommentParser {
return items;
}

/**
* Extract the directive and the justification from a given directive comment and trim them.
* @param {string} value The comment text to extract.
* @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification.
*/
extractDirectiveComment(value) {
const match = /\s-{2,}\s/u.exec(value);

if (!match) {
return { directivePart: value.trim(), justificationPart: "" };
}

const directive = value.slice(0, match.index).trim();
const justification = value.slice(match.index + match[0].length).trim();

return { directivePart: directive, justificationPart: justification };
}

/**
* Parses a directive comment into directive text and value.
* @param {Comment} comment The comment node with the directive to be parsed.
* @returns {{directiveText: string, directiveValue: string}} The directive text and value.
*/
parseDirective(comment) {
const { directivePart } = this.extractDirectiveComment(comment.value);
const match = directivesPattern.exec(directivePart);
const directiveText = match[1];
const directiveValue = directivePart.slice(match.index + directiveText.length);

return { directiveText, directiveValue };
}
};
24 changes: 3 additions & 21 deletions lib/linter/linter.js
Expand Up @@ -317,24 +317,6 @@ function createDisableDirectives(options) {
return result;
}

/**
* Extract the directive and the justification from a given directive comment and trim them.
* @param {string} value The comment text to extract.
* @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification.
*/
function extractDirectiveComment(value) {
const match = /\s-{2,}\s/u.exec(value);

if (!match) {
return { directivePart: value.trim(), justificationPart: "" };
}

const directive = value.slice(0, match.index).trim();
const justification = value.slice(match.index + match[0].length).trim();

return { directivePart: directive, justificationPart: justification };
}

/**
* Parses comments in file to extract file-specific config of rules, globals
* and environments and merges them with global config; also code blocks
Expand All @@ -356,7 +338,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
});

sourceCode.getInlineConfigNodes().filter(token => token.type !== "Shebang").forEach(comment => {
const { directivePart, justificationPart } = extractDirectiveComment(comment.value);
const { directivePart, justificationPart } = commentParser.extractDirectiveComment(comment.value);

const match = directivesPattern.exec(directivePart);

Expand Down Expand Up @@ -501,7 +483,7 @@ function getDirectiveCommentsForFlatConfig(sourceCode, ruleMapper) {
const disableDirectives = [];

sourceCode.getInlineConfigNodes().filter(token => token.type !== "Shebang").forEach(comment => {
const { directivePart, justificationPart } = extractDirectiveComment(comment.value);
const { directivePart, justificationPart } = commentParser.extractDirectiveComment(comment.value);

const match = directivesPattern.exec(directivePart);

Expand Down Expand Up @@ -621,7 +603,7 @@ function findEslintEnv(text) {
if (match[0].endsWith("*/")) {
retv = Object.assign(
retv || {},
commentParser.parseListConfig(extractDirectiveComment(match[1]).directivePart)
commentParser.parseListConfig(commentParser.extractDirectiveComment(match[1]).directivePart)
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/rules/no-invalid-this.js
Expand Up @@ -96,7 +96,7 @@ module.exports = {

if (codePath.origin === "program") {
const scope = sourceCode.getScope(node);
const features = context.parserOptions.ecmaFeatures || {};
const features = context.languageOptions.parserOptions.ecmaFeatures || {};

// `this` at the top level of scripts always refers to the global object
stack.push({
Expand Down
15 changes: 9 additions & 6 deletions lib/rules/no-promise-executor-return.js
Expand Up @@ -209,12 +209,15 @@ module.exports = {
});
}

suggest.push({
messageId: "wrapBraces",
fix(fixer) {
return curlyWrapFixer(sourceCode, node, fixer);
}
});
// Do not suggest wrapping an unnamed FunctionExpression in braces as that would be invalid syntax.
if (!(node.body.type === "FunctionExpression" && !node.body.id)) {
suggest.push({
messageId: "wrapBraces",
fix(fixer) {
return curlyWrapFixer(sourceCode, node, fixer);
}
});
}

context.report({
node: node.body,
Expand Down

0 comments on commit ddf9aa2

Please sign in to comment.