Skip to content

Commit

Permalink
feat: Move parserServices to SourceCode (#17311)
Browse files Browse the repository at this point in the history
Deprecates `context.parserServices` in favor of `SourceCode#parserServices`

Refs #16999
  • Loading branch information
mdjermanovic committed Jun 28, 2023
1 parent cf88439 commit c8b1f4d
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 9 deletions.
4 changes: 2 additions & 2 deletions docs/src/extend/custom-parsers.md
Expand Up @@ -42,7 +42,7 @@ The `parse` method should simply return the [AST](#ast-specification) object.
The `parseForESLint` method should return an object that contains the required property `ast` and optional properties `services`, `scopeManager`, and `visitorKeys`.

* `ast` should contain the [AST](#ast-specification) object.
* `services` can contain any parser-dependent services (such as type checkers for nodes). The value of the `services` property is available to rules as `context.parserServices`. Default is an empty object.
* `services` can contain any parser-dependent services (such as type checkers for nodes). The value of the `services` property is available to rules as `context.sourceCode.parserServices`. Default is an empty object.
* `scopeManager` can be a [ScopeManager](./scope-manager-interface) object. Custom parsers can use customized scope analysis for experimental/enhancement syntaxes. The default is the `ScopeManager` object which is created by [eslint-scope](https://github.com/eslint/eslint-scope).
* Support for `scopeManager` was added in ESLint v4.14.0. ESLint versions that support `scopeManager` will provide an `eslintScopeManager: true` property in `parserOptions`, which can be used for feature detection.
* `visitorKeys` can be an object to customize AST traversal. The keys of the object are the type of AST nodes. Each value is an array of the property names which should be traversed. The default is [KEYS of `eslint-visitor-keys`](https://github.com/eslint/eslint-visitor-keys#evkkeys).
Expand Down Expand Up @@ -120,7 +120,7 @@ To learn more about using ESLint parsers in your project, refer to [Configure a

For a complex example of a custom parser, refer to the [`@typescript-eslint/parser`](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/parser) source code.

A simple custom parser that provides a `context.parserServices.foo()` method to rules.
A simple custom parser that provides a `context.sourceCode.parserServices.foo()` method to rules.

```javascript
// awesome-custom-parser.js
Expand Down
3 changes: 2 additions & 1 deletion docs/src/extend/custom-rules.md
Expand Up @@ -131,7 +131,7 @@ The `context` object has the following properties:
* `sourceCode`: (`object`) A `SourceCode` object that you can use to work with the source that was passed to ESLint (see [Accessing the Source Code](#accessing-the-source-code)).
* `settings`: (`object`) The [shared settings](../use/configure/configuration-files#adding-shared-settings) from the configuration.
* `parserPath`: (`string`) The name of the `parser` from the configuration.
* `parserServices`: (`object`) Contains parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.)
* `parserServices`: (**Deprecated:** Use `SourceCode#parserServices` instead.) Contains parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.)
* `parserOptions`: The parser options configured for this run (more details [here](../use/configure/language-options#specifying-parser-options)).

Additionally, the `context` object has the following methods:
Expand Down Expand Up @@ -575,6 +575,7 @@ There are also some properties you can access:
* `ast`: (`object`) `Program` node of the AST for the code being linted.
* `scopeManager`: [ScopeManager](./scope-manager-interface#scopemanager-interface) object of the code.
* `visitorKeys`: (`object`) Visitor keys to traverse this AST.
* `parserServices`: (`object`) Contains parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.)
* `lines`: (`array`) Array of lines, split according to the specification's definition of line breaks.

You should use a `SourceCode` object whenever you need to get more information about the code being linted.
Expand Down
12 changes: 8 additions & 4 deletions tests/lib/linter/linter.js
Expand Up @@ -1197,9 +1197,10 @@ describe("Linter", () => {
linter.defineRule("test-service-rule", {
create: context => ({
Literal(node) {
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);
context.report({
node,
message: context.parserServices.test.getMessage()
message: context.sourceCode.parserServices.test.getMessage()
});
}
})
Expand All @@ -1219,9 +1220,10 @@ describe("Linter", () => {
linter.defineRule("test-service-rule", {
create: context => ({
Literal(node) {
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);
context.report({
node,
message: context.parserServices.test.getMessage()
message: context.sourceCode.parserServices.test.getMessage()
});
}
})
Expand Down Expand Up @@ -7956,9 +7958,10 @@ describe("Linter with FlatConfigArray", () => {
"test-service-rule": {
create: context => ({
Literal(node) {
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);
context.report({
node,
message: context.parserServices.test.getMessage()
message: context.sourceCode.parserServices.test.getMessage()
});
}
})
Expand Down Expand Up @@ -7992,9 +7995,10 @@ describe("Linter with FlatConfigArray", () => {
"test-service-rule": {
create: context => ({
Literal(node) {
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);
context.report({
node,
message: context.parserServices.test.getMessage()
message: context.sourceCode.parserServices.test.getMessage()
});
}
})
Expand Down
4 changes: 3 additions & 1 deletion tests/lib/rule-tester/flat-rule-tester.js
Expand Up @@ -1199,7 +1199,9 @@ describe("FlatRuleTester", () => {
const disallowHiRule = {
create: context => ({
Literal(node) {
const disallowed = context.parserServices.test.getMessage(); // returns "Hi!"
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);

const disallowed = context.sourceCode.parserServices.test.getMessage(); // returns "Hi!"

if (node.value === disallowed) {
context.report({ node, message: `Don't use '${disallowed}'` });
Expand Down
4 changes: 3 additions & 1 deletion tests/lib/rule-tester/rule-tester.js
Expand Up @@ -1248,7 +1248,9 @@ describe("RuleTester", () => {
const disallowHiRule = {
create: context => ({
Literal(node) {
const disallowed = context.parserServices.test.getMessage(); // returns "Hi!"
assert.strictEqual(context.parserServices, context.sourceCode.parserServices);

const disallowed = context.sourceCode.parserServices.test.getMessage(); // returns "Hi!"

if (node.value === disallowed) {
context.report({ node, message: `Don't use '${disallowed}'` });
Expand Down

0 comments on commit c8b1f4d

Please sign in to comment.