Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
New: Add ESLint#getRulesMetaForResults() (refs #13654) (#14716)
* New: Add ESLint#getRulesMetaForResults() (refs #13654)

* Update docs

* Update docs/developer-guide/nodejs-api.md

Co-authored-by: Brandon Mills <btmills@users.noreply.github.com>

Co-authored-by: Brandon Mills <btmills@users.noreply.github.com>
  • Loading branch information
nzakas and btmills committed Jun 18, 2021
1 parent eea7e0d commit c2cd7b4
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 0 deletions.
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)

```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]: #-eslintgetrulesmetaforresultsresults
[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

0 comments on commit c2cd7b4

Please sign in to comment.