Skip to content

Latest commit

 

History

History
219 lines (154 loc) · 12.4 KB

File metadata and controls

219 lines (154 loc) · 12.4 KB
  • Repo: eslint/eslint
  • Start Date: 2022-12-08
  • RFC PR: #100
  • Authors: bmish

Flexible configuration and stricter default behavior for reporting unused disable directives

Summary

Provide users with more flexible, intuitive control over how unused disable directives are reported by switching the CLI and config file options from using a boolean value to a severity level. Change the default behavior to warn on unused disable directives.

Motivation

Outdated/unused ESLint disable directive comments (e.g. notConsole(); // eslint-disable-line no-console) are currently a blind spot for most apps/repositories. These leftover comments cause clutter and confusion.

Existing Solutions

Detecting unused disable directive comments requires going out of one's way by using one of the following existing solutions:

  1. Running linting with eslint --report-unused-disable-directives (errors, but requires providing the CLI option whenever running ESLint)
  2. Adding reportUnusedDisableDirectives: true to the .eslintrc.js config file (warns, and thus easily ignored)
  3. Enabling the third-party rule eslint-comments/no-unused-disable (errors, but requires a third-party plugin)

These existing solutions have various downsides:

  1. Lack of discoverability.
  2. Requires manual configuration to enable and thus not commonly used.
  3. Inability to treat unused disable directives as errors in shareable configs using the first-party options.
  4. Inconsistency in behavior between the CLI option and config file option of the same name which is unintuitive and causes confusion.

New Design

We propose a new "explicit severity" design where the user can set the severity level of unused disable directive reporting using either the CLI option or the config file option. As a result, the user should always be able to achieve the desired effect (off / warn / error), regardless of where they set the option from (CLI option, config file option, or even from a shareable config).

We will also change the default behavior to warn on unused disable directives so that all users (unless they opt-out) will benefit from the detection (and automatic removal with --fix) of unused disable directives.

Detailed Design

How the new "explicit severity" design works:

  • The config and CLI options are both changed to also accept standard severity level string values: off, warn, error (or a the corresponding number for each level)
  • If both options are present, the CLI option takes precedence over (overrides) the config option
  • If only one of the options is present, the value of the present option is used
  • If neither option is present, the default value (warn) is used
  • Note: There's only one underlying setting, and the config and CLI options are just two different ways of controlling it

Boolean values will continue to be allowed with no change in behavior, as summarized below.

Allowed values for the config file option:

  • reportUnusedDisableDirectives: true - same behavior as today (warn)
  • reportUnusedDisableDirectives: false - same behavior as today (off)
  • reportUnusedDisableDirectives: "error" - new value
  • reportUnusedDisableDirectives: "warn" - new value
  • reportUnusedDisableDirectives: "off" - new value

Allowed values for the CLI option:

  • --report-unused-disable-directives - same behavior as today (error) (common CLI shorthand to omit the value)
  • --report-unused-disable-directives=true - same behavior as today (error)
  • --report-unused-disable-directives=false - same behavior as today (off)
  • --report-unused-disable-directives=error - new value
  • --report-unused-disable-directives=warn - new value
  • --report-unused-disable-directives=off - new value

Code Changes

  • conf/config-schema.js - also support string / number type
  • conf/default-cli-options.js - use new default
  • lib/options.js - also support string / number type and use new default for the option
    • Something like type: "Boolean|String|Number" and enum: ["true", "false", "error", "warn", "off", "0", "1", "2"]
  • When processing the config or CLI options, convert any boolean value provided to a severity level
  • Anywhere reportUnusedDisableDirectives is passed around as a boolean needs to change to using a severity level
  • In addition to testing reportUnusedDisableDirectives as a boolean, we'll also need to test it as a severity level

Luckily, reportUnusedDisableDirectives is already stored as a severity level in much of the underlying code.

Documentation

These documentation pages will be updated to reflect the new option values and defaults:

  • Configuration Files
  • Configuring Rules
  • Command Line Interface
  • Node.js API
  • eslint --help

Documentation will focus on the new severity level values as opposed to the boolean values. We may choose to leave the boolean values undocumented in some places, or add a note that they are deprecated and remain in place only for backwards compatibility, similar to the note in the globals configuration section that says:

For historical reasons, the boolean value false and the string value "readable" are equivalent to "readonly". Similarly, the boolean value true and the string value "writeable" are equivalent to "writable". However, the use of these older values is deprecated.

Drawbacks

  • While we attempted to limit the breaking changes involved, any amount of breaking changes can still be disruptive.
  • Some users may not like the new default behavior of warning on unused disable directives and will be burdened by having to opt-out.
  • The new warnings can be easily ignored and some may prefer to only use warnings temporarily.
  • Keeping around the boolean values for backwards compatibility means increased complexity in supporting both boolean and severity level values. It also means we still have the inconsistency where reportUnusedDisableDirectives: true means warn but --report-unused-disable-directives=true means error.

Backwards Compatibility Analysis

Users that already specify reportUnusedDisableDirectives or --report-unused-disable-directives will not experience any breaking changes, as the current behavior will be maintained.

Users that do not specify any of these options but do specify --max-warnings will experience a breaking change, as the additional warnings could cause ESLint to exit with a non-zero exit code.

Users that do not specify any of these options are less likely to experience a breaking change, as additional warnings will simply show up as output text. Note that this could still be a breaking change if the user cares about ESLint's exact output text to stdout, or that running with --fix will now fix the new warnings.

We don't need tweak our semantic versioning policy (discussed more in Alternatives), as the policy will only be violated (i.e. patch releases can break CI) if the user opts-in by setting one of the options to error.

Alternatives

  1. Leave as-is. But this means continued lack of configuration flexibility and discoverability of unused disable directives.

  2. Remove boolean values for configuration options. We decided against this because it's a breaking change that could be too disruptive for users, and the overhead of supporting both booleans and severity levels is limited.

  3. Adopt new option design but use error as the default behavior. We decided against this because causing CI to fail due to unused disable directives could be too disruptive to users and violates the current semantic versioning policy:

    Patch release (intended to not break your lint build)

    A bug fix in a rule that results in ESLint reporting fewer linting errors. ...

    Minor release (might break your lint build)

    A bug fix in a rule that results in ESLint reporting more linting errors. ...

    • eslint/eslint#12703 (comment)

      If we allowed for errors to be reported with reportUnusedDisableDirectives, we would limit what kind of changes we could publish in a semver-patch release (since fixing a bug that would result in fewer errors could create additional unused disable directives).

    • eslint/eslint#14699 (comment)

      ...because of our semver policy, which says that bug fixes that produce fewer errors should not break builds.

  4. Adopt new option design but use off as the default behavior. This would maintain the existing behavior for the majority of users who aren't reporting unused violations. But most users would continue to miss out on the benefit of this feature then.

  5. Turn reportUnusedDisableDirectives into a regular ESLint rule as suggested in #13104. While this could enable us to reduce complexity by eliminating a config option, a new rule implementing this feature may require special case handling, and it's not clear it's possible to implement within the current architecture. It's also a larger breaking change.

Open Questions

  1. Should we allow severity levels to be provided as numbers? If we allow these numbers everywhere else and have no plans to scrap them, then we likely want to allow them here as well for consistency.

Help Needed

I am open to implementing this.

Frequently Asked Questions

Related Discussions

  • eslint/eslint#15466 - the issue triggering this RFC
  • eslint/eslint#9382 - very similar earlier proposal with reportUnusedDisableDirectives accepting a severity level
  • #22 - previous RFC to allow reportUnusedDisableDirectives in config files