ember-template-lint / ember-template-lint

Linter for Ember or Handlebars templates
MIT License
267 stars 235 forks source link

Can a plugin specify overrides? #2752

Open ijlee2 opened 1 year ago

ijlee2 commented 1 year ago

Background

When the latest versions of ember-template-lint (v5.3.0) and ember-template-lint-plugin-prettier (v4.1.0) are installed, template code in test files will be checked for formatting. Running yarn lint:hbs:fix will auto-format the code.

However, the indentations are currently suboptimal. In addition, reformatting increases the lines of code (LOC) changed in the pull request that updates ember-template-lint to v5. Thus, an end-developer may want to turn off auto-formatting in test files.

How to turn off auto-formatting

Suppose an end-developer has a shared configuration file (e.g. to maintain a monorepo). There are two approaches: one, where the developer uses require to read the file, and another, where they write a plugin and extend it.

Approach 1: Use require to read the file ```js /* Shared */ 'use strict'; module.exports = { plugins: ['ember-template-lint-plugin-prettier'], extends: ['recommended', 'ember-template-lint-plugin-prettier:recommended'], overrides: [ { files: ['tests/**/*-test.{js,ts}'], rules: { prettier: 'off', }, }, ], }; /* Consuming project */ module.exports = require('some-namespace/ember-template-lint'); ```
Approach 2: Use extends to extend a plugin ```js /* Shared */ 'use strict'; module.exports = { name: 'my-shared-plugin', rules: {}, configurations: { recommended: { plugins: ['ember-template-lint-plugin-prettier'], extends: ['recommended', 'ember-template-lint-plugin-prettier:recommended'], overrides: [ { files: ['tests/**/*-test.{js,ts}'], rules: { prettier: 'off', }, }, ], }, }, }; /* Consuming project */ module.exports = { plugins: ['some-namespace/ember-template-lint'], extends: 'my-shared-plugin:recommended' }; ```

Problem

In Approach 1, the overrides key correctly prevents auto-formatting the template code in test files. In Approach 2, however, the plugin's overrides is not respected.

Preliminary investigation

Depending on the approach, we get a different config from getProjectConfig(). (See the GitHub Gist for a diff view.)

Approach 1: Returned config ```json5 { "rules": { /* ... */ }, "overrides": [ { "files": [ "tests/**/*-test.{js,ts}" ], "rules": { "prettier": { "config": false, "severity": 0 } } } ], "ignore": [], "format": {}, "plugins": { "ember-template-lint-plugin-prettier": { /* ... */ } }, "loadedRules": {}, "loadedConfigurations": { "4-x-recommended": { /* ... */ }, "a11y": { /* ... */ }, "recommended": { /* ... */ }, "stylistic": { /* ... */ }, "ember-template-lint-plugin-prettier:recommended": { /* ... */ } }, "_processed": true } ```
Approach 2: Returned config ```json5 { "rules": { /* ... */ }, "overrides": [], "ignore": [], "format": {}, "plugins": { "my-shared-plugin": { /* ... */ }, "ember-template-lint-plugin-prettier": { /* ... */ } }, "loadedRules": {}, "loadedConfigurations": { "4-x-recommended": { /* ... */ }, "a11y": { /* ... */ }, "recommended": { /* ... */ }, "stylistic": { /* ... */ }, "my-shared-plugin:recommended": { /* ... */ }, "ember-template-lint-plugin-prettier:recommended": { /* ... */ } }, "_processed": true } ```

Notice that, in Approach 2, config.overrides is equal to the empty array. In other words, validateOverrides() must have determined that there are no rules to override. This is possibly because, when we enter the function validateOverrides(), config.overrides was [] to begin with; if so, the map function (line 347) would be a no-op.

I didn't find unit tests that cover these questions:

Possible solutions?

I'd expect that:

Regardless of whether we allow a plugin to specify overrides, I'd like to suggest that we:

Related links

I wrote this issue based on a couple of Discord chats. Here are the links to the main messages:

gossi commented 1 year ago

Turns out this happens everywhere where there is hbs used, as for example in this story:

export const Default = (args: { hello: string; to: string }) => ({
  template: hbs`
    <Greeting @hello={{this.hello}} @to={{this.to}} />
  `,
  context: args
});

As this is a .ts file and I configured vscode to use eslint as default formatter - my IDE shows this as totally fine, but CLI will complain about it. Meaning: no immediate feedback during development - needs a CI roundtrip for that.

andreyfel commented 1 year ago

In my case, I have a plugin that defines custom rules and is used in several apps in the yarn workspace. After upgrading to template lint v5 I want to disable a few rules in test files. Using overrides works in each app's config but adding overrides to a shared plugin doesn't work. So, I have to duplicate the overrides in all the apps.