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

docs: Update Linter API for v9 #17937

Merged
merged 2 commits into from Jan 1, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
113 changes: 18 additions & 95 deletions docs/src/integrate/nodejs-api.md
Expand Up @@ -491,7 +491,7 @@ const codeLines = SourceCode.splitLines(code);

## 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 objects or files. Unless you are working in the browser, you probably want to use the [ESLint class](#eslint-class) instead.
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](#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:

Expand All @@ -513,8 +513,8 @@ Those run on `linter2` will get `process.cwd()` if the global `process` object i
The most important method on `Linter` is `verify()`, which initiates linting of the given text. This method accepts three arguments:

* `code` - the source code to lint (a string or instance of `SourceCode`).
* `config` - a configuration object that has been processed and normalized by `ESLint` using eslintrc files and/or other configuration arguments.
* **Note**: If you want to lint text and have your configuration be read and processed, use [`ESLint#lintFiles()`][eslint-lintfiles] or [`ESLint#lintText()`][eslint-linttext] instead.
* `config` - a [Configuration object] or an array of configuration objects.
* **Note**: If you want to lint text and have your configuration be read from the file system, use [`ESLint#lintFiles()`][eslint-lintfiles] or [`ESLint#lintText()`][eslint-linttext] instead.
* `options` - (optional) Additional options for this run.
* `filename` - (optional) the filename to associate with the source code.
* `preprocess` - (optional) A function that [Processors in Plugins](../extend/plugins#processors-in-plugins) documentation describes as the `preprocess` method.
Expand Down Expand Up @@ -557,18 +557,20 @@ const messages = linter.verify(code, {
The `verify()` method returns an array of objects containing information about the linting warnings and errors. Here's an example:

```js
{
fatal: false,
ruleId: "semi",
severity: 2,
line: 1,
column: 23,
message: "Expected a semicolon.",
fix: {
range: [1, 15],
text: ";"
[
{
fatal: false,
ruleId: "semi",
severity: 2,
line: 1,
column: 23,
message: "Expected a semicolon.",
fix: {
range: [1, 15],
text: ";"
}
}
}
]
```
Comment on lines 557 to 574
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a change in v9, I just wrapped the lint message example in [] because verify() always returns arrays.


The information available for each linting message is:
Expand Down Expand Up @@ -601,8 +603,6 @@ const suppressedMessages = linter.getSuppressedMessages();
console.log(suppressedMessages[0].suppressions); // [{ "kind": "directive", "justification": "Need to suppress" }]
```

Linting message objects have a deprecated `source` property. This property **will be removed** from linting messages in an upcoming breaking release. If you depend on this property, you should now use the `SourceCode` instance provided by the linter.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This property was removed in ESLint v5 (27e3f24)


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

```js
Expand Down Expand Up @@ -653,83 +653,6 @@ The information available is:
* `output` - Fixed code text (might be the same as input if no fixes were applied).
* `messages` - Collection of all messages for the given code (It has the same information as explained above under `verify` block).

### Linter#defineRule

Each `Linter` instance holds a map of rule names to loaded rule objects. By default, all ESLint core rules are loaded. If you want to use `Linter` with custom rules, you should use the `defineRule` method to register your rules by ID.

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

linter.defineRule("my-custom-rule", {
// (an ESLint rule)

create(context) {
// ...
}
});

const results = linter.verify("// some source text", { rules: { "my-custom-rule": "error" } });
```

### Linter#defineRules

This is a convenience method similar to `Linter#defineRule`, except that it allows you to define many rules at once using an object.

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

linter.defineRules({
"my-custom-rule": { /* an ESLint rule */ create() {} },
"another-custom-rule": { /* an ESLint rule */ create() {} }
});

const results = linter.verify("// some source text", {
rules: {
"my-custom-rule": "error",
"another-custom-rule": "warn"
}
});
```

### Linter#getRules

This method returns a map of all loaded rules.

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

linter.getRules();

/*
Map {
'accessor-pairs' => { meta: { docs: [Object], schema: [Array] }, create: [Function: create] },
'array-bracket-newline' => { meta: { docs: [Object], schema: [Array] }, create: [Function: create] },
...
}
*/
```

### Linter#defineParser

Each instance of `Linter` holds a map of custom parsers. If you want to define a parser programmatically, you can add this function
with the name of the parser as first argument and the [parser object](../extend/custom-parsers) as second argument. The default `"espree"` parser will already be loaded for every `Linter` instance.

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

linter.defineParser("my-custom-parser", {
parse(code, options) {
// ...
}
});

const results = linter.verify("// some source text", { parser: "my-custom-parser" });
```

### 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.
Expand All @@ -738,15 +661,15 @@ Each instance of `Linter` has a `version` property containing the semantic versi
const Linter = require("eslint").Linter;
const linter = new Linter();

linter.version; // => '4.5.0'
linter.version; // => '9.0.0'
```

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

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

Linter.version; // => '4.5.0'
Linter.version; // => '9.0.0'
```

---
Expand Down
90 changes: 90 additions & 0 deletions docs/src/use/migrate-to-9.0.0.md
Expand Up @@ -43,6 +43,7 @@ The lists below are ordered roughly by the number of users each change is expect

* [Node.js < v18.18, v19 are no longer supported](#drop-old-node)
* [`FlatESLint` is now `ESLint`](#flat-eslint)
* [`Linter` now expects flat config format](#flat-linter)

---

Expand Down Expand Up @@ -374,3 +375,92 @@ const { LegacyESLint } = require("eslint/use-at-your-own-risk");
```

**Related Issues(s):** [#13481](https://github.com/eslint/eslint/issues/13481)

## <a name="flat-linter"></a> `Linter` now expects flat config format

In ESLint v9.0.0, the `config` argument passed to `Linter#verify()` and `Linter#verifyAndFix()` methods should be in the flat config format.

Additionally, methods `Linter#defineRule()`, `Linter#defineRules()`, `Linter#defineParser()`, and `Linter#getRules()` are no longer available.

**To address:** If you are using the `Linter` class, verify that your tests pass.

If you're passing configuration objects that are incompatible with the flat config format, you'll need to update the code.

```js
// eslintrc config format
linter.verify(code, {
parserOptions: {
ecmaVersion: 6
}
});

// flat config format
linter.verify(code, {
languageOptions: {
ecmaVersion: 6
}
});
```

Please refer to the [Configuration Migration Guide](configure/migration-guide) for details on translating other keys you may be using.

Rules and parsers can be defined directly in the configuration.

```js
// eslintrc mode
linter.defineRule("my-rule1", myRule1);
linter.defineRules({
"my-rule2": myRule2,
"my-rule3": myRule3
});
linter.defineParser("my-parser", myParser);
linter.verify(code, {
rules: {
"my-rule1": "error",
"my-rule2": "error",
"my-rule3": "error"
},
parser: "my-parser"
});

// flat config mode
linter.verify(code, {
plugins: {
"my-plugin-foo": {
rules: {
"my-rule1": myRule1
}
},
"my-plugin-bar": {
rules: {
"my-rule2": myRule2,
"my-rule3": myRule3
}
}
},
rules: {
"my-plugin-foo/my-rule1": "error",
"my-plugin-bar/my-rule2": "error",
"my-plugin-bar/my-rule3": "error"
},
languageOptions: {
parser: myParser
}
});
```

If you still need the v8.x `Linter` functionality, pass `configType: "eslintrc"` to the constructor like this:

```js
const linter = new Linter({ configType: "eslintrc" });

linter.verify(code, {
parserOptions: {
ecmaVersion: 6
}
});

linter.getRules();
```

**Related Issues(s):** [#13481](https://github.com/eslint/eslint/issues/13481)