import-js / eslint-plugin-import

ESLint plugin with rules that help validate proper imports.
MIT License
5.45k stars 1.56k forks source link

[Feature Request] Support new ESLint flat config #2556

Closed TomerAberbach closed 6 days ago

TomerAberbach commented 1 year ago

ESLint has a new experimental config file format and this plugin doesn't work with it. The plugin fails at this line because the new config format doesn't pass parsers via paths. Instead the [parser object itself is passed](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#:~:text=parser%20%2D%20Either%20an%20object%20containing%20a%20parse()%20method%20or%20a%20string%20indicating%20the%20name%20of%20a%20parser%20inside%20of%20a%20plugin%20(i.e.%2C%20%22pluginName/parserName%22).%20(default%3A%20%22%40/espree%22)).

I was able to mostly fix this in my fork, but because the parserPath doesn't exist anymore for this config format some of the keysFromParser logic won't work anymore.

Anyway, figured I'd open this issue to start discussion on the new config file format!

vinicius-sabadim commented 1 month ago

I was able to make it work on my setup following this official guide.

A summary of the fix:

import { fixupPluginRules } from '@eslint/compat'
import eslintPluginImport from 'eslint-plugin-import'

export default [
  {
      // code omit
     plugins: { import: fixupPluginRules(eslintPluginImport) }
  }
]
glitch452 commented 1 month ago

I was able to make it work on my setup following this official guide.

A summary of the fix:

import { fixupPluginRules } from '@eslint/compat'
import eslintPluginImport from 'eslint-plugin-import'

export default [
  {
      // code omit
     plugins: { import: fixupPluginRules(eslintPluginImport) }
  }
]

I gave this a try. It doesn't seem to work with rules like import/namespace and import/export.

I'm getting the error parserPath or languageOptions.parser is required. I do have the @typescript-eslint parser setup.

vinicius-sabadim commented 1 month ago

@glitch452 I tested the import/export: 'error' here and it's working without problems. I'll share my whole eslint.config.mjs for you to compare:

import path from 'node:path'
import { fileURLToPath } from 'node:url'

import { fixupConfigRules, fixupPluginRules } from '@eslint/compat'
import { FlatCompat } from '@eslint/eslintrc'
import js from '@eslint/js'
import tsParser from '@typescript-eslint/parser'
import eslintPluginImport from 'eslint-plugin-import'
import prettier from 'eslint-plugin-prettier'
import simpleImportSort from 'eslint-plugin-simple-import-sort'
import globals from 'globals'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({
  baseDirectory: __dirname,
  recommendedConfig: js.configs.recommended,
  allConfig: js.configs.all,
})

export default [
  ...fixupConfigRules(
    compat.extends(
      'eslint:recommended',
      'plugin:@typescript-eslint/recommended',
      'plugin:react/recommended',
      'plugin:jsx-a11y/recommended',
      'plugin:prettier/recommended',
      'plugin:storybook/recommended',
      'plugin:jsonc/recommended-with-jsonc',
    ),
  ),
  {
    plugins: {
      import: fixupPluginRules(eslintPluginImport),
      'simple-import-sort': simpleImportSort,
      prettier: fixupPluginRules(prettier),
    },

    languageOptions: {
      globals: {
        ...globals.browser,
        ...globals.amd,
        ...globals.node,
      },

      parser: tsParser,
      ecmaVersion: 'latest',
      sourceType: 'module',

      parserOptions: {
        ecmaFeatures: {
          jsx: true,
        },
      },
    },

    settings: {
      react: {
        version: 'detect',
      },

      'import/resolver': {
        typescript: true,

        node: {
          paths: ['src'],
          extensions: ['.js', '.jsx', '.ts', '.tsx'],
        },
      },
    },

    rules: {
      // omit other rules
      'import/export': 'error',
      'import/newline-after-import': ['error', { count: 1, considerComments: true }],
    },
  },
]

if I run the ESLint in this code:

export const foo = function () {
  /*...*/
} // Multiple exports of name 'foo'.

function bar() {
  /*...*/
}
export { bar as foo } // Multiple exports of name 'foo'.

I get error Multiple exports of name 'foo' import/export

kubosho commented 1 month ago

By using fixupConfigRules() and fixupPluginRules() provided by @eslint/compat, and FlatCompat provided by @eslint/eslintrc, I able to narrow down the scope of using ESLint compatibility utilities and migrate to Flat config.

Sample code is as follows:

import { fixupConfigRules, fixupPluginRules } from "@eslint/compat";
import { FlatCompat } from "@eslint/eslintrc";
import eslintPluginImport from "eslint-plugin-import";
import importRecommendedConfig from "eslint-plugin-import/config/recommended.js";

const flatCompat = new FlatCompat();

export default [
  ...fixupConfigRules(flatCompat.config(importRecommendedConfig)),
  {
    plugins: {
      import: fixupPluginRules(eslintPluginImport),
    },
    rules: {
      // some rewrite rules
    },
    settings: {
      // some rewrite settings
    },
  },
];

By writing as above, can migrate import-related configurations to flat config without waiting for eslint-plugin-import to support flat config.

That code related to imports including other configurations is in my repository.

mshima commented 4 weeks ago

One more example:


import importPlugin from 'eslint-plugin-import';
import importRecommented from 'eslint-plugin-import/config/recommended.js';
import { fixupPluginRules } from '@eslint/compat';

export default [
  {
    languageOptions: {
      // import plugin does not use ecmaVersion and sourceType from languageOptions object
      parserOptions: {
        ecmaVersion: 2022,
        sourceType: 'module',
      },
    },
    plugins: {
      import: fixupPluginRules(importPlugin),
    },
    settings: {
      'import/parsers': {
        espree: ['.js', '.cjs', '.mjs'],
        '@typescript-eslint/parser': ['.ts'],
      },
      'import/resolver': {
        node: true,
        typescript: true,
      },
    },
    rules: {
      ...importRecommented.rules,
      'import/no-named-as-default-member': 'off',
      // Custom rules
    },
  },
];
marikaner commented 3 days ago

A release for this would be wonderful!