eslint-plugin-import icon indicating copy to clipboard operation
eslint-plugin-import copied to clipboard

`import/order` ignores `pathGroups`

Open TheZoker opened this issue 2 years ago • 3 comments

Hi there,

I'm trying to use import/order with this setting:

"import/order": [
    "error",
    {
        "alphabetize": {
            "order": "asc",
            "caseInsensitive": false
        },
        "groups": [
            ["builtin", "external"],
            ["internal", "parent", "sibling", "index"]
        ],         
        "newlines-between": "always",
        "pathGroups": [
            {
                "pattern": "app/**",
                "group": "internal"
            }
        ],
        "distinctGroup": false
    }
],

When I run the code, the linter orders the imports like this:

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { ExternalUserPasswordResetModalComponent } from 'app/account/password-reset/external/external-user-password-reset-modal.component';
import { ArtemisSharedModule } from 'app/shared/shared.module';

import { accountState } from './account.route';
import { ActivateComponent } from './activate/activate.component';

When instead it should order it like this:

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

import { accountState } from './account.route';
import { ActivateComponent } from './activate/activate.component';
import { ArtemisSharedModule } from 'app/shared/shared.module';
import { ExternalUserPasswordResetModalComponent } from 'app/account/password-reset/external/external-user-password-reset-modal.component';

Can you tell me, why my pathGroups and my groups setting to not work?

Thanks!

TheZoker avatar Mar 15 '23 01:03 TheZoker

I had to go digging through old issues, but the reason is that builtin and external are excluded from pathGroups by default: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#pathgroupsexcludedimporttypes-array

You'll want to set pathGroupsExcludedImportTypes: []

Issue which helped: https://github.com/import-js/eslint-plugin-import/issues/2363

inglec-arista avatar Mar 31 '23 18:03 inglec-arista

I found another weirdness. Using internal with pathGroups will not work, but it will work with import/internal-regex setting.

Before:

import { X } from 'package/src/ui'
import { useCallback } from 'react'
import { Y } from 'package/src/utils'
import { something } from './something'

Expected:

import { useCallback } from 'react'
import { X } from 'package/src/ui'
import { Y } from 'package/src/utils'
import { something } from './something'

This will not work.

  rules: {
    "import/order": ["warn", {
      "groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
      "pathGroups": [
        {
          "pattern": "package/**",
          "group": "internal",
        },
      ],
    }],
  },

This will work.

  settings: {
    "import/internal-regex": "^package/",
  },
  rules: {
    "import/order": ["warn", {
      "groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
    }],
  },

Why?


/edit

Using it like this will also work, but why?

  settings: {
    // "import/internal-regex": "^package/",
  },
  rules: {
    "import/order": ["warn", {
      "groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
      "pathGroups": [
        {
          "pattern": "package/**",
          "group": "internal",
        },
      ],
      pathGroupsExcludedImportTypes: [],
    }],
  },

I don't understand the description for pathGroupsExcludedImportTypes at all either.

 pathGroups: [array of objects]  To be able to group by paths mostly needed with aliases pathGroups can be defined.

pattern - minimatch pattern for the paths to be in this group (will not be used for builtins or externals)

{
  "import/order": ["error", {
    "pathGroups": [
      {
        "pattern": "~/**",
        "group": "external"
      }
    ]
  }]
}

From the example and description, I get it that when a pattern is matched, the import will be regarded as belonging to the group.

But what the heck does this do??

pathGroupsExcludedImportTypes: [array] This defines import types that are not handled by configured pathGroups. This is mostly needed when you want to handle path groups that look like external imports.


/edit 2

Okay, after further experimenting I think that I understand what it does, but damn, that is hell confusing.

The point is

  1. Each import is assigned an implicit group - builtin, external, parent, sibling, index, etc.
  2. pathGroups is invoked and imports are then matched.
    • if a match is found, that import is reassigned to a different group as specified.
    • however, matching WILL NOT be done against imports from pathGroupsExcludedImportTypes array, which is by default ["builtin", "external", "object"].
  3. groups are then organized

Therefore if you have an import, such as import { X } from 'package/src/ui' that simply LOOKS as if it was an external import, even though it isn't, it will get implicitly ignored by pathGroups matching pattern and will not be tested.

This means that in order to get a pathGroups match, you first need to un-exclude that possible implicitly assigned group from pathGroupsExcludedImportTypes.... LIKE ... WHAT THE HECK 🙄

ackvf avatar Oct 13 '23 01:10 ackvf

@ackvf Thank you, you saved me a lot of time. I will document this as a quirk for future reference.

akay64 avatar Mar 17 '24 05:03 akay64