Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Add ESLint#getRulesMetaForResults() (refs #13654) #14716

Merged
merged 3 commits into from Jun 18, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/developer-guide/nodejs-api.md
Expand Up @@ -10,6 +10,7 @@ While ESLint is designed to be run on the command line, it's possible to use ESL
* [constructor()][eslint-constructor]
* [lintFiles()][eslint-lintfiles]
* [lintText()][eslint-linttext]
* [getRulesMetaForResults()](eslint-getrulesmetaforresults)
* [calculateConfigForFile()][eslint-calculateconfigforfile]
* [isPathIgnored()][eslint-ispathignored]
* [loadFormatter()][eslint-loadformatter]
Expand Down Expand Up @@ -205,6 +206,25 @@ The second parameter `options` is omittable.
* (`Promise<LintResult[]>`)<br>
The promise that will be fulfilled with an array of [LintResult] objects. This is an array (despite there being only one lint result) in order to keep the interfaces between this and the [`eslint.lintFiles()`][eslint-lintfiles] method similar.

### ◆ eslint.getRulesMetaForResults(results)
nzakas marked this conversation as resolved.
Show resolved Hide resolved

```js
const results = await eslint.lintFiles(patterns);
const rulesMeta = eslint.getRulesMetaForResults(results);
```

This method returns an object containing meta information for each rule that triggered a lint error in the given `results`.

#### Parameters

* `results` (`LintResult[]`)<br>
An array of [LintResult] objects returned from a call to `ESLint#lintFiles()` or `ESLint#lintText()`.

#### Return Value

* (`Object`)<br>
An object whose property names are the rule IDs from the `results` and whose property values are the rule's meta information (if available).

### ◆ eslint.calculateConfigForFile(filePath)

```js
Expand Down Expand Up @@ -1389,6 +1409,7 @@ ruleTester.run("my-rule", myRule, {
[eslint-constructor]: #-new-eslintoptions
[eslint-lintfiles]: #-eslintlintfilespatterns
[eslint-linttext]: #-eslintlinttextcode-options
[eslint-getrulesmetaforresults]: #-eslintgetrulesmetaforresults
nzakas marked this conversation as resolved.
Show resolved Hide resolved
[eslint-calculateconfigforfile]: #-eslintcalculateconfigforfilefilepath
[eslint-ispathignored]: #-eslintispathignoredfilepath
[eslint-loadformatter]: #-eslintloadformatternameorpath
Expand Down
33 changes: 33 additions & 0 deletions lib/eslint/eslint.js
Expand Up @@ -514,6 +514,39 @@ class ESLint {
return CLIEngine.getErrorResults(results);
}

/**
* Returns meta objects for each rule represented in the lint results.
* @param {LintResult[]} results The results to fetch rules meta for.
* @returns {Object} A mapping of ruleIds to rule meta objects.
*/
getRulesMetaForResults(results) {

const resultRuleIds = new Set();

// first gather all ruleIds from all results

for (const result of results) {
for (const { ruleId } of result.messages) {
resultRuleIds.add(ruleId);
}
}

// create a map of all rules in the results

const { cliEngine } = privateMembersMap.get(this);
const rules = cliEngine.getRules();
const resultRules = new Map();

for (const [ruleId, rule] of rules) {
if (resultRuleIds.has(ruleId)) {
resultRules.set(ruleId, rule);
}
}

return createRulesMeta(resultRules);

}

/**
* Executes the current configuration on an array of file and directory names.
* @param {string[]} patterns An array of file and directory names.
Expand Down
75 changes: 75 additions & 0 deletions tests/lib/eslint/eslint.js
Expand Up @@ -22,6 +22,7 @@ const shell = require("shelljs");
const { CascadingConfigArrayFactory } = require("@eslint/eslintrc/lib/cascading-config-array-factory");
const hash = require("../../../lib/cli-engine/hash");
const { unIndent, createCustomTeardown } = require("../../_utils");
const coreRules = require("../../../lib/rules");

//------------------------------------------------------------------------------
// Tests
Expand Down Expand Up @@ -4790,6 +4791,80 @@ describe("ESLint", () => {
});
});

describe("getRulesMetaForResults()", () => {
it("should return empty object when there are no linting errors", async () => {
const engine = new ESLint({
useEslintrc: false
});

const rulesMeta = engine.getRulesMetaForResults([]);

assert.strictEqual(Object.keys(rulesMeta).length, 0);
});

it("should return one rule meta when there is a linting error", async () => {
const engine = new ESLint({
useEslintrc: false,
overrideConfig: {
rules: {
semi: 2
}
}
});

const results = await engine.lintText("a");
const rulesMeta = engine.getRulesMetaForResults(results);

assert.strictEqual(rulesMeta.semi, coreRules.get("semi").meta);
});

it("should return multiple rule meta when there are multiple linting errors", async () => {
const engine = new ESLint({
useEslintrc: false,
overrideConfig: {
rules: {
semi: 2,
quotes: [2, "double"]
}
}
});

const results = await engine.lintText("'a'");
const rulesMeta = engine.getRulesMetaForResults(results);

assert.strictEqual(rulesMeta.semi, coreRules.get("semi").meta);
assert.strictEqual(rulesMeta.quotes, coreRules.get("quotes").meta);
});

it("should return multiple rule meta when there are multiple linting errors from a plugin", async () => {
const nodePlugin = require("eslint-plugin-node");
const engine = new ESLint({
useEslintrc: false,
plugins: {
node: nodePlugin
},
overrideConfig: {
plugins: ["node"],
rules: {
"node/no-new-require": 2,
semi: 2,
quotes: [2, "double"]
}
}
});

const results = await engine.lintText("new require('hi')");
const rulesMeta = engine.getRulesMetaForResults(results);

assert.strictEqual(rulesMeta.semi, coreRules.get("semi").meta);
assert.strictEqual(rulesMeta.quotes, coreRules.get("quotes").meta);
assert.strictEqual(
rulesMeta["node/no-new-require"],
nodePlugin.rules["no-new-require"].meta
);
});
});

describe("outputFixes()", () => {
afterEach(() => {
sinon.verifyAndRestore();
Expand Down