Node.js API Reference - ESLint - Pluggable JavaScript Linter (original) (raw)

Table of Contents

  1. ESLint class
    1. ◆ new ESLint(options)
      1. Parameters
    2. ◆ eslint.lintFiles(patterns)
      1. Parameters
      2. Return Value
    3. ◆ eslint.lintText(code, options)
      1. Parameters
      2. Return Value
    4. ◆ eslint.getRulesMetaForResults(results)
      1. Parameters
      2. Return Value
    5. ◆ eslint.calculateConfigForFile(filePath)
      1. Parameters
      2. Return Value
    6. ◆ eslint.isPathIgnored(filePath)
      1. Parameters
      2. Return Value
    7. ◆ eslint.loadFormatter(nameOrPath)
      1. Parameters
      2. Return Value
    8. ◆ eslint.hasFlag(flagName)
      1. Parameters
      2. Return Value
    9. ◆ ESLint.version
    10. ◆ ESLint.defaultConfig
    11. ◆ ESLint.outputFixes(results)
      1. Parameters
      2. Return Value
    12. ◆ ESLint.getErrorResults(results)
      1. Parameters
      2. Return Value
    13. ◆ LintResult type
    14. ◆ LintMessage type
    15. ◆ SuppressedLintMessage type
    16. ◆ EditInfo type
    17. ◆ LoadedFormatter type
  2. loadESLint()
  3. SourceCode
    1. SourceCode#splitLines()
  4. Linter
    1. Linter#verify
    2. Linter#verifyAndFix()
    3. Linter#version/Linter.version
    4. Linter#getTimes()
    5. Linter#getFixPassCount()
    6. Linter#hasFlag()
  5. RuleTester
    1. Testing Errors with messageId
    2. Testing Fixes
    3. Testing Suggestions
    4. Customizing RuleTester

While ESLint is designed to be run on the command line, it’s possible to use ESLint programmatically through the Node.js API. The purpose of the Node.js API is to allow plugin and tool authors to use the ESLint functionality directly, without going through the command line interface.

Note: Use undocumented parts of the API at your own risk. Only those parts that are specifically mentioned in this document are approved for use and will remain stable and reliable. Anything left undocumented is unstable and may change or be removed at any point.

ESLint class

The ESLint class is the primary class to use in Node.js applications.

This class depends on the Node.js fs module and the file system, so you cannot use it in browsers. If you want to lint code on browsers, use the Linter class instead.

Here’s a simple example of using the ESLint class:

const { ESLint } = require("eslint");

(async function main() {
    // 1. Create an instance.
    const eslint = new ESLint();

    // 2. Lint files.
    const results = await eslint.lintFiles(["lib/**/*.js"]);

    // 3. Format the results.
    const formatter = await eslint.loadFormatter("stylish");
    const resultText = formatter.format(results);

    // 4. Output it.
    console.log(resultText);
})().catch(error => {
    process.exitCode = 1;
    console.error(error);
});

Here’s an example that autofixes lint problems:

const { ESLint } = require("eslint");

(async function main() {
    // 1. Create an instance with the `fix` option.
    const eslint = new ESLint({ fix: true });

    // 2. Lint files. This doesn't modify target files.
    const results = await eslint.lintFiles(["lib/**/*.js"]);

    // 3. Modify the files with the fixed code.
    await ESLint.outputFixes(results);

    // 4. Format the results.
    const formatter = await eslint.loadFormatter("stylish");
    const resultText = formatter.format(results);

    // 5. Output it.
    console.log(resultText);
})().catch(error => {
    process.exitCode = 1;
    console.error(error);
});

And here is an example of using the ESLint class with lintText API:

const { ESLint } = require("eslint");

const testCode = `
  const name = "eslint";
  if(true) {
    console.log("constant condition warning")
  };
`;

(async function main() {
    // 1. Create an instance
    const eslint = new ESLint({
        overrideConfigFile: true,
        overrideConfig: {
            languageOptions: {
                ecmaVersion: 2018,
                sourceType: "commonjs",
            },
        },
    });

    // 2. Lint text.
    const results = await eslint.lintText(testCode);

    // 3. Format the results.
    const formatter = await eslint.loadFormatter("stylish");
    const resultText = formatter.format(results);

    // 4. Output it.
    console.log(resultText);
})().catch(error => {
    process.exitCode = 1;
    console.error(error);
});

◆ new ESLint(options)

const eslint = new ESLint(options);

Create a new ESLint instance.

Parameters

The ESLint constructor takes an options object. If you omit the options object then it uses default values for all options. The options object has the following properties.

File Enumeration
Linting
Autofix
Other Options

◆ eslint.lintFiles(patterns)

const results = await eslint.lintFiles(patterns);

This method lints the files that match the glob patterns and then returns the results.

Parameters

Return Value

◆ eslint.lintText(code, options)

const results = await eslint.lintText(code, options);

This method lints the given source code text and then returns the results.

By default, this method uses the configuration that applies to files in the current working directory (the cwd constructor option). If you want to use a different configuration, pass options.filePath, and ESLint will load the same configuration that eslint.lintFiles() would use for a file at options.filePath.

If the options.filePath value is configured to be ignored, this method returns an empty array. If the options.warnIgnored option is set along with the options.filePath option, this method returns a LintResult object. In that case, the result may contain a warning that indicates the file was ignored.

Parameters

The second parameter options is omittable.

Return Value

◆ eslint.getRulesMetaForResults(results)

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

Return Value

◆ eslint.calculateConfigForFile(filePath)

const config = await eslint.calculateConfigForFile(filePath);

This method calculates the configuration for a given file, which can be useful for debugging purposes.

Parameters

Return Value

◆ eslint.isPathIgnored(filePath)

const isPathIgnored = await eslint.isPathIgnored(filePath);

This method checks if a given file is ignored by your configuration.

Parameters

Return Value

◆ eslint.loadFormatter(nameOrPath)

const formatter = await eslint.loadFormatter(nameOrPath);

This method loads a formatter. Formatters convert lint results to a human- or machine-readable string.

Parameters

Return Value

◆ eslint.hasFlag(flagName)

This method is used to determine if a given feature flag is set, as in this example:

if (eslint.hasFlag("x_feature")) {
    // handle flag
}

Parameters

Return Value

◆ ESLint.version

const version = ESLint.version;

The version string of ESLint. E.g. "7.0.0".

This is a static property.

◆ ESLint.defaultConfig

const defaultConfig = ESLint.defaultConfig;

The default configuration that ESLint uses internally. This is provided for tooling that wants to calculate configurations using the same defaults as ESLint. Keep in mind that the default configuration may change from version to version, so you shouldn’t rely on any particular keys or values to be present.

This is a static property.

◆ ESLint.outputFixes(results)

await ESLint.outputFixes(results);

This method writes code modified by ESLint’s autofix feature into its respective file. If any of the modified files don’t exist, this method does nothing.

This is a static method.

Parameters

Return Value

◆ ESLint.getErrorResults(results)

const filteredResults = ESLint.getErrorResults(results);

This method copies the given results and removes warnings. The returned value contains only errors.

This is a static method.

Parameters

Return Value

◆ LintResult type

The LintResult value is the information of the linting result of each file. The eslint.lintFiles() and eslint.lintText() methods return it. It has the following properties:

◆ LintMessage type

The LintMessage value is the information of each linting error. The messages property of the LintResult type contains it. It has the following properties:

◆ SuppressedLintMessage type

The SuppressedLintMessage value is the information of each suppressed linting error. The suppressedMessages property of the LintResult type contains it. It has the following properties:

◆ EditInfo type

The EditInfo value is information to edit text. The fix and suggestions properties of LintMessage type contain it. It has following properties:

This edit information means replacing the range of the range property by the text property value. It’s like sourceCodeText.slice(0, edit.range[0]) + edit.text + sourceCodeText.slice(edit.range[1]). Therefore, it’s an add if the range[0] and range[1] property values are the same value, and it’s removal if the text property value is empty string.

◆ LoadedFormatter type

The LoadedFormatter value is the object to convert the LintResult objects to text. The eslint.loadFormatter() method returns it. It has the following method:


loadESLint()

The loadESLint() function is used for integrations that wish to support both the current configuration system (flat config) and the old configuration system (eslintrc). This function returns the correct ESLint class implementation based on the arguments provided:

const { loadESLint } = require("eslint");

// loads the default ESLint that the CLI would use based on process.cwd()
const DefaultESLint = await loadESLint();

// loads the flat config version specifically
const FlatESLint = await loadESLint({ useFlatConfig: true });

// loads the legacy version specifically
const LegacyESLint = await loadESLint({ useFlatConfig: false });

You can then use the returned constructor to instantiate a new ESLint instance, like this:

// loads the default ESLint that the CLI would use based on process.cwd()
const DefaultESLint = await loadESLint();
const eslint = new DefaultESLint();

If you’re ever unsure which config system the returned constructor uses, check the configType property, which is either "flat" or "eslintrc":

// loads the default ESLint that the CLI would use based on process.cwd()
const DefaultESLint = await loadESLint();

if (DefaultESLint.configType === "flat") {
    // do something specific to flat config
}

If you don’t need to support both the old and new configuration systems, then it’s recommended to just use the ESLint constructor directly.


SourceCode

The SourceCode type represents the parsed source code that ESLint executes on. It’s used internally in ESLint and is also available so that already-parsed code can be used. You can create a new instance of SourceCode by passing in the text string representing the code and an abstract syntax tree (AST) in ESTree format (including location information, range information, comments, and tokens):

const SourceCode = require("eslint").SourceCode;

const code = new SourceCode("var foo = bar;", ast);

The SourceCode constructor throws an error if the AST is missing any of the required information.

The SourceCode constructor strips Unicode BOM. Please note the AST also should be parsed from stripped text.

const SourceCode = require("eslint").SourceCode;

const code = new SourceCode("\uFEFFvar foo = bar;", ast);

assert(code.hasBOM === true);
assert(code.text === "var foo = bar;");

SourceCode#splitLines()

This is a static function on SourceCode that is used to split the source code text into an array of lines.

const SourceCode = require("eslint").SourceCode;

const code = "var a = 1;\nvar b = 2;";

// split code into an array
const codeLines = SourceCode.splitLines(code);

/*
    Value of codeLines will be
    [
        "var a = 1;",
        "var b = 2;"
    ]
 */

Linter

The Linter object does the actual evaluation of the JavaScript code. It doesn’t do any filesystem operations, it simply parses and reports on the code. In particular, the Linter object does not process configuration files. Unless you are working in the browser, you probably want to use the ESLint class instead.

The Linter is a constructor, and you can create a new instance by passing in the options you want to use. The available options are:

For example:

const Linter = require("eslint").Linter;
const linter1 = new Linter({ cwd: "path/to/project" });
const linter2 = new Linter();

In this example, rules run on linter1 will get path/to/project from context.cwd or when calling context.getCwd(). Those run on linter2 will get process.cwd() if the global process object is defined or undefined otherwise (e.g. on the browser https://eslint.org/demo).

Linter#verify

The most important method on Linter is verify(), which initiates linting of the given text. This method accepts three arguments:

If the third argument is a string, it is interpreted as the filename.

You can call verify() like this:

const Linter = require("eslint").Linter;
const linter = new Linter();

const messages = linter.verify(
    "var foo;",
    {
        rules: {
            semi: 2,
        },
    },
    { filename: "foo.js" },
);

// or using SourceCode

const Linter = require("eslint").Linter,
    linter = new Linter(),
    SourceCode = require("eslint").SourceCode;

const code = new SourceCode("var foo = bar;", ast);

const messages = linter.verify(
    code,
    {
        rules: {
            semi: 2,
        },
    },
    { filename: "foo.js" },
);

The verify() method returns an array of objects containing information about the linting warnings and errors. Here’s an example:

[
    {
        fatal: false,
        ruleId: "semi",
        severity: 2,
        line: 1,
        column: 23,
        message: "Expected a semicolon.",
        fix: {
            range: [1, 15],
            text: ";",
        },
    },
];

The information available for each linting message is:

You can get the suppressed messages from the previous run by getSuppressedMessages() method. If there is not a previous run, getSuppressedMessage() will return an empty list.

const Linter = require("eslint").Linter;
const linter = new Linter();

const messages = linter.verify(
    "var foo = bar; // eslint-disable-line -- Need to suppress",
    {
        rules: {
            semi: ["error", "never"],
        },
    },
    { filename: "foo.js" },
);
const suppressedMessages = linter.getSuppressedMessages();

console.log(suppressedMessages[0].suppressions); // [{ "kind": "directive", "justification": "Need to suppress" }]

You can also get an instance of the SourceCode object used inside of linter by using the getSourceCode() method:

const Linter = require("eslint").Linter;
const linter = new Linter();

const messages = linter.verify(
    "var foo = bar;",
    {
        rules: {
            semi: 2,
        },
    },
    { filename: "foo.js" },
);

const code = linter.getSourceCode();

console.log(code.text); // "var foo = bar;"

In this way, you can retrieve the text and AST used for the last run of linter.verify().

Linter#verifyAndFix()

This method is similar to verify except that it also runs autofixing logic, similar to the --fix flag on the command line. The result object will contain the autofixed code, along with any remaining linting messages for the code that were not autofixed.

const Linter = require("eslint").Linter;
const linter = new Linter();

const messages = linter.verifyAndFix("var foo", {
    rules: {
        semi: 2,
    },
});

Output object from this method:

{
    fixed: true,
    output: "var foo;",
    messages: []
}

The information available is:

Linter#version/Linter.version

Each instance of Linter has a version property containing the semantic version number of ESLint that the Linter instance is from.

const Linter = require("eslint").Linter;
const linter = new Linter();

linter.version; // => '9.0.0'

There is also a Linter.version property that you can read without instantiating Linter:

const Linter = require("eslint").Linter;

Linter.version; // => '9.0.0'

Linter#getTimes()

This method is used to get the times spent on (parsing, fixing, linting) a file. See times property of the Stats object.

Linter#getFixPassCount()

This method is used to get the number of autofix passes made. See fixPasses property of the Stats object.

Linter#hasFlag()

This method is used to determine if a given feature flag is set, as in this example:

const Linter = require("eslint").Linter;
const linter = new Linter({ flags: ["x_feature"] });

console.log(linter.hasFlag("x_feature")); // true

RuleTester

eslint.RuleTester is a utility to write tests for ESLint rules. It is used internally for the bundled rules that come with ESLint, and it can also be used by plugins.

Example usage:

"use strict";

const rule = require("../../../lib/rules/my-rule"),
    RuleTester = require("eslint").RuleTester;

const ruleTester = new RuleTester();

ruleTester.run("my-rule", rule, {
    valid: [
        {
            code: "var foo = true",
            options: [{ allowFoo: true }],
        },
    ],

    invalid: [
        {
            code: "var invalidVariable = true",
            errors: [{ message: "Unexpected invalid variable." }],
        },
        {
            code: "var invalidVariable = true",
            errors: [{ message: /^Unexpected.+variable/ }],
        },
    ],
});

The RuleTester constructor accepts an optional object argument, which can be used to specify defaults for your test cases. For example, if all of your test cases use ES2015, you can set it as a default:

const ruleTester = new RuleTester({ languageOptions: { ecmaVersion: 2015 } });

The RuleTester#run() method is used to run the tests. It should be passed the following arguments:

A test case is an object with the following properties:

In addition to the properties above, invalid test cases can also have the following properties:

Any additional properties of a test case will be passed directly to the linter as config options. For example, a test case can have a languageOptions property to configure parser behavior:

{
    code: "let foo;",
    languageOptions: { ecmaVersion: 2015 }
}

If a valid test case only uses the code property, it can optionally be provided as a string containing the code, rather than an object with a code key.

Testing Errors with messageId

If the rule under test uses messageIds, you can use messageId property in a test case to assert reported error’s messageId instead of its message.

{
    code: "let foo;",
    errors: [{ messageId: "unexpected" }]
}

For messages with placeholders, a test case can also use data property to additionally assert reported error’s message.

{
    code: "let foo;",
    errors: [{ messageId: "unexpected", data: { name: "foo" } }]
}

Please note that data in a test case does not assert data passed to context.report. Instead, it is used to form the expected message text which is then compared with the received message.

Testing Fixes

The result of applying fixes can be tested by using the output property of an invalid test case. The output property should be used only when you expect a fix to be applied to the specified code; you can safely omit output if no changes are expected to the code. Here’s an example:

ruleTester.run("my-rule-for-no-foo", rule, {
    valid: [],
    invalid: [
        {
            code: "var foo;",
            output: "var bar;",
            errors: [
                {
                    messageId: "shouldBeBar",
                    line: 1,
                    column: 5,
                },
            ],
        },
    ],
});

A the end of this invalid test case, RuleTester expects a fix to be applied that results in the code changing from var foo; to var bar;. If the output after applying the fix doesn’t match, then the test fails.

Testing Suggestions

Suggestions can be tested by defining a suggestions key on an errors object. If this is a number, it asserts the number of suggestions provided for the error. Otherwise, this should be an array of objects, each containing information about a single provided suggestion. The following properties can be used:

Example:

ruleTester.run("my-rule-for-no-foo", rule, {
    valid: [],
    invalid: [
        {
            code: "var foo;",
            errors: [
                {
                    suggestions: [
                        {
                            desc: "Rename identifier 'foo' to 'bar'",
                            output: "var bar;",
                        },
                    ],
                },
            ],
        },
    ],
});

messageId and data properties in suggestion test objects work the same way as in error test objects. See testing errors with messageId for details.

ruleTester.run("my-rule-for-no-foo", rule, {
    valid: [],
    invalid: [
        {
            code: "var foo;",
            errors: [
                {
                    suggestions: [
                        {
                            messageId: "renameFoo",
                            data: { newName: "bar" },
                            output: "var bar;",
                        },
                    ],
                },
            ],
        },
    ],
});

Customizing RuleTester

RuleTester depends on two functions to run tests: describe and it. These functions can come from various places:

  1. If RuleTester.describe and RuleTester.it have been set to function values, RuleTester will use RuleTester.describe and RuleTester.it to run tests. You can use this to customize the behavior of RuleTester to match a test framework that you’re using.
    If RuleTester.itOnly has been set to a function value, RuleTester will call RuleTester.itOnly instead of RuleTester.it to run cases with only: true. If RuleTester.itOnly is not set but RuleTester.it has an only function property, RuleTester will fall back to RuleTester.it.only.
  2. Otherwise, if describe and it are present as globals, RuleTester will use globalThis.describe and globalThis.it to run tests and globalThis.it.only to run cases with only: true. This allows RuleTester to work when using frameworks like Mocha without any additional configuration.
  3. Otherwise, RuleTester#run will simply execute all of the tests in sequence, and will throw an error if one of them fails. This means you can simply execute a test file that calls RuleTester.run using Node.js, without needing a testing framework.

RuleTester#run calls the describe function with two arguments: a string describing the rule, and a callback function. The callback calls the it function with a string describing the test case, and a test function. The test function will return successfully if the test passes, and throw an error if the test fails. The signature for only is the same as it. RuleTester calls either it or only for every case even when some cases have only: true, and the test framework is responsible for implementing test case exclusivity. (Note that this is the standard behavior for test suites when using frameworks like Mocha; this information is only relevant if you plan to customize RuleTester.describe, RuleTester.it, or RuleTester.itOnly.)

Example of customizing RuleTester:

"use strict";

const RuleTester = require("eslint").RuleTester,
    test = require("my-test-runner"),
    myRule = require("../../../lib/rules/my-rule");

RuleTester.describe = function (text, method) {
    RuleTester.it.title = text;
    return method.call(this);
};

RuleTester.it = function (text, method) {
    test(RuleTester.it.title + ": " + text, method);
};

// then use RuleTester as documented

const ruleTester = new RuleTester();

ruleTester.run("my-rule", myRule, {
    valid: [
        // valid test cases
    ],
    invalid: [
        // invalid test cases
    ],
});