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

Refactor Linter to reduce API surface #9161

Closed
2 of 3 tasks
not-an-aardvark opened this issue Aug 26, 2017 · 3 comments
Closed
2 of 3 tasks

Refactor Linter to reduce API surface #9161

not-an-aardvark opened this issue Aug 26, 2017 · 3 comments
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion chore This change is not user-facing

Comments

@not-an-aardvark
Copy link
Member

not-an-aardvark commented Aug 26, 2017

I think it would be a good idea to refactor Linter in the near future. The goal is to reduce the amount of undocumented API surface area, and simplify the interactions between core modules to make them easier to maintain. Node.js API users frequently handle Linter instances, and having too much API surface area makes it more likely that users will rely on undocumented behavior, and then have their integrations break when we change the implementation details in the future.

Specific action items:

  • Don't make Linter a subclass of EventEmitter.

    Linter happens to use the EventEmitter API internally, but there's no reason it has to expose the entire EventEmitter API by being a subclass. We don't want users to use Linter instances in the same way that they would use generic EventEmitters (for example, we don't want API users to do something like linter.emit("foo", node) or linter.on("foo", listener) directly). Instead, one option would be to store an instance of EventEmitter as a private property. Another (possibly better) option would be to use a new EventEmitter for each verify call.

  • Don't give RuleContext objects access to the underlying Linter instance.

    Currently, rules can call methods on the Linter instance by accessing context.eslint. This allows them to interfere with other rules, or report problems as other rules (e.g. with context.eslint.report("some-other-rule", ...).

    I think it would be better to have the RuleContext constructor accept a report function as an argument. That way, it wouldn't need a reference to Linter at all -- it would just be able to emit reports.

  • Make Linter#verify be side-effect-free.

    Instances of Linter are mutable, and it's probably too late to change that. However, I think it would be good to prevent Linter#verify from having side-effects. To do this, we would get rid of properties like linter.messages, linter.currentConfig, linter.sourceCode, etc. and pass the values around internally instead. We would also remove methods like getAncestors from Linter (and provide an equivalent replacement elsewhere to avoid changing the rule API), since getAncestors necessarily involves some hidden state about the current traversal point, and it doesn't make sense for users of ESLint's Node API to call getAncestors directly.

@not-an-aardvark not-an-aardvark added the chore This change is not user-facing label Aug 26, 2017
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates `RuleTester` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates the tests for `ast-utils` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates the tests for `SourceCode` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates the tests for `Linter` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates `RuleTester` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates the tests for `ast-utils` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates the tests for `SourceCode` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
This updates the tests for `Linter` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
…9172)

This updates `RuleTester` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
… (#9174)

This updates the tests for `SourceCode` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 28, 2017
…9175)

This updates the tests for `Linter` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 30, 2017
…#9173)

This updates the tests for `ast-utils` to use the public `Linter#defineRule` API rather than the private `Linter#on` API.
not-an-aardvark added a commit that referenced this issue Aug 30, 2017
The `currentScopes` property is undocumented, and is redundant with the `scopeManager` property. This commit removes it.
not-an-aardvark added a commit that referenced this issue Sep 8, 2017
This updates `Linter` to remove the `Linter#getDeclaredVariables` method. The `context.getDeclaredVariables` method is still available to rules -- this just removes the version of the method on `Linter`.
not-an-aardvark added a commit that referenced this issue Sep 8, 2017
This updates `Linter` to remove the `Linter#getDeclaredVariables` method. The `context.getDeclaredVariables` method is still available to rules -- this just removes the version of the method on `Linter`.
not-an-aardvark added a commit that referenced this issue Sep 9, 2017
This updates `Linter` to remove the `Linter#getDeclaredVariables` method. The `context.getDeclaredVariables` method is still available to rules -- this just removes the version of the method on `Linter`.
not-an-aardvark added a commit that referenced this issue Sep 9, 2017
#9264)

This updates `Linter` to remove the `Linter#getDeclaredVariables` method. The `context.getDeclaredVariables` method is still available to rules -- this just removes the version of the method on `Linter`.
not-an-aardvark added a commit that referenced this issue Sep 9, 2017
This removes the undocumented `traverser`, `scopeManager`, and `currentConfig` properties from `Linter` instances.
not-an-aardvark added a commit that referenced this issue Sep 9, 2017
This removes the undocumented `traverser`, `scopeManager`, and `currentConfig` properties from `Linter` instances.
@not-an-aardvark
Copy link
Member Author

Status of this issue:

  • Most undocumented properties have been removed from Linter.
  • There are still a few undocumented properties (rules and environments) that I'd like to remove. However, these properties are used in other parts of the codebase, so removing them will require some more refactoring.
  • Linter#verify is mostly side-effect-free, except for the fact that it changes the value of Linter#getSourceCode. We can't remove Linter#getSourceCode right now because it's documented here. We could remove it in a major release, but we would probably need to create a usable replacement for it first. (For example, the ESLint demo currently uses Linter#getSourceCode because it's the only good way to get a SourceCode instance for the text being linted.)

@nzakas
Copy link
Member

nzakas commented Oct 22, 2018

@not-an-aardvark are you still working on this?

@not-an-aardvark
Copy link
Member Author

Not really, I'll close it.

not-an-aardvark added a commit that referenced this issue Jan 30, 2019
This removes the undocumented `rules` property from `Linter` instances, as part of the effort to remove undocumented API surface from `Linter` (also see #9161). Config processing now exclusively uses `Linter`'s public API when defining rules. As a side-effect, the rule map utility in `lib/rules.js` no longer needs to access the filesystem, so we can remove the odd code generation logic from the browserify build.
not-an-aardvark added a commit that referenced this issue Jan 30, 2019
This removes the undocumented `rules` property from `Linter` instances, as part of the effort to remove undocumented API surface from `Linter` (also see #9161). Config processing now exclusively uses `Linter`'s public API when defining rules. As a side-effect, the rule map utility in `lib/rules.js` no longer needs to access the filesystem, so we can remove the odd code generation logic from the browserify build.
@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Apr 21, 2019
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Apr 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
archived due to age This issue has been archived; please open a new issue for any further discussion chore This change is not user-facing
Projects
None yet
Development

No branches or pull requests

2 participants