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

import/order not respecting builtin #2687

Closed
thernstig opened this issue Jan 20, 2023 · 16 comments · Fixed by #2854
Closed

import/order not respecting builtin #2687

thernstig opened this issue Jan 20, 2023 · 16 comments · Fixed by #2854

Comments

@thernstig
Copy link

thernstig commented Jan 20, 2023

Using "eslint-plugin-import": "2.27.5"

// .eslintrc.json
{
  "root": true,
  "reportUnusedDisableDirectives": true,
  "parserOptions": {
    "ecmaVersion": 2023,
    "sourceType": "module"
  },
  "env": {
    "node": true,
    "es2022": true
  },
  "plugins": ["import"],
  "rules": {
    "import/order": [
      "error",
      {
        "groups": [
          [
            "builtin",
            "external",
            "internal",
            "parent",
            "sibling",
            "index",
            "object",
            "type"
          ]
        ]
      }
    ]
  }
}
// test.js
import chpro from 'child_process';
import log4js from 'log4js';
import util from 'util';

const execFile = util.promisify(chpro.execFile);
const logger = log4js.getLogger('server');

I would expect util to be sorted before log4js but this is not the case. Neither is node:util.

@shawnmcknight
Copy link

I ran into this with a different built-in import (path). If I changed the import to use the new node protocol semantics (i.e. 'node:path') then the import order was correct. This made me believe that this detection might be due to a conflicting node core module and a module installed in node_modules. Sure enough, if I look at my node_modules there is a path dependency in there (also a util dependency, which might match @thernstig 's scenario).

If I use a core module like fs where I don't have a conflicting dependency in node_modules then the import order is correct (actually wanted to precede node:path which is what I would have expected).

Taking a guess here that import/order might be getting confused because of the duplicate names in core and node_modules, but that's just a shot in the dark guess.

@thernstig
Copy link
Author

@shawnmcknight that is not my experience. The above config does not complain about this ordering:

import express from 'express';
import log4js from 'log4js';
import chpro from 'node:child_process';
import fsp from 'node:fs/promises';

I would expect all node: to end up first.

@ljharb
Copy link
Member

ljharb commented Apr 14, 2023

@thernstig why do you have the nested array in groups?

ljharb added a commit to ljharb/eslint-plugin-import that referenced this issue Apr 14, 2023
@ljharb
Copy link
Member

ljharb commented Apr 14, 2023

I was able to partially fix this in 1fa2971 - now the same error shows up with a nested group or a flat one - but the ordering still isn't fully correct.

@thernstig
Copy link
Author

thernstig commented Apr 15, 2023

@ljharb I got that from eslint-config-airbnb-base which I used as a base for creating this issue, so maybe you can answer that. I saw though that https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md does not have the nested array.

But I am using eslint-config-airbnb-base so in the end I get my config from there.

@ljharb
Copy link
Member

ljharb commented Apr 15, 2023

@thernstig the base config has { groups: [['builtin', 'external', 'internal']] } in it, so something else must be providing that list.

@thernstig
Copy link
Author

thernstig commented Apr 16, 2023

@ljharb I took it from eslint-config-airbnb-base, but then just added all items from here to test them all:

```ts
"import/order": [
"error",
{
"groups": [
"index",
"sibling",
"parent",
"internal",
"external",
"builtin",
"object",
"type"
]
}
]
```

Is eslint-config-airbnb-base wrong?

@ljharb
Copy link
Member

ljharb commented Apr 16, 2023

No, it’s not wrong, i was just curious where the config comes from.

@yndajas
Copy link
Contributor

yndajas commented Aug 9, 2023

👋🏻 is the (partial) fix for this correct, particularly this conditional?

After updating to 2.28.0 we're seeing "groups": [["builtin", "external"]] (one group) lead to builtin and external being separated, when I believe these should be grouped together with everything else in a second group. This was the behaviour before 2.28.0 and seemingly what the docs suggest: ['sibling', 'parent'], // Then sibling and parent types. They can be mingled together ("They can be mingled together"). We've had to amend the config to keep the previous behaviour

I might not be fully understanding the original issue in this thread, but I would've thought it would be solved by de-nesting? It looks like the Airbnb config example is: groups: [['builtin', 'external', 'internal']], which would group builtin, external, and internal and then follow with everything else in a second group, so if you wanted builtin then external then internal then parent then sibling then index then object then type it would be groups: ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"] (de-nested)

I note that there's a TODO in the conditional and this is a described as a partial fix, so maybe the new behaviour is intended to be reverted eventually?

@ljharb
Copy link
Member

ljharb commented Aug 9, 2023

@yndajas that sounds right to me. If the behavior has changed in v2.28.0 then that's a bug that needs fixing.

@yndajas
Copy link
Contributor

yndajas commented Aug 9, 2023

@ljharb glad I'm not confused! Shall I open a new issue or leave it with you?

@ljharb
Copy link
Member

ljharb commented Aug 9, 2023

@yndajas I think this issue probably covers it; a PR would be most helpful :-)

yndajas added a commit to yndajas/eslint-plugin-import that referenced this issue Aug 9, 2023
1fa2971 changed the way groups work when there is only one, leading
to single nested groups being treated as though they were unnested.
Prior to this, if you wanted to group e.g. builtin and external
imports together at the top and everything else together as a second
group, a single nested group was the way to do it

[It appears that this change was unintentional][1], and was made to
try to fix what seems to be a misunderstanding around nested groups
([import-js#2687]). [The docs][2] continue to suggest that nested groups
should be "mingled together" and makes no reference to a single nested
group with no other groups being an invalid option

This therefore reverts the change to how groups work when there is
only one. No documentation change should be necessary given this is
already the described behaviour

[1]: import-js#2687 (comment)
[2]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array
yndajas added a commit to yndajas/eslint-plugin-import that referenced this issue Aug 9, 2023
1fa2971 changed the way groups work when there is only one, leading
to single nested groups being treated as though they were unnested.
Prior to this, if you wanted to group e.g. builtin and external
imports together at the top and everything else together as a second
group, a single nested group was the way to do it

[It appears that this change was unintentional][1], and was made to
try to fix what seems to be a misunderstanding around nested groups
([import-js#2687]). [The docs][2] continue to suggest that nested groups
should be "mingled together" and makes no reference to a single nested
group with no other groups being an invalid option

This therefore reverts the change to how groups work when there is
only one. No documentation change should be necessary given this is
already the described behaviour

[1]: import-js#2687 (comment)
[2]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array
@thernstig
Copy link
Author

@yndajas @ljharb I am not sure how the problem reported there solves this issue? This is about it not respecting builtin at all.

ljharb pushed a commit to yndajas/eslint-plugin-import that referenced this issue Aug 17, 2023
1fa2971 changed the way groups work when there is only one, leading
to single nested groups being treated as though they were unnested.
Prior to this, if you wanted to group e.g. builtin and external
imports together at the top and everything else together as a second
group, a single nested group was the way to do it

[It appears that this change was unintentional][1], and was made to
try to fix what seems to be a misunderstanding around nested groups
([import-js#2687]). [The docs][2] continue to suggest that nested groups
should be "mingled together" and makes no reference to a single nested
group with no other groups being an invalid option

This therefore reverts the change to how groups work when there is
only one. No documentation change should be necessary given this is
already the described behaviour

[1]: import-js#2687 (comment)
[2]: https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/order.md#groups-array
@ljharb
Copy link
Member

ljharb commented Aug 17, 2023

@thernstig when it's nested like that, all of those groups can be intermingled. The config needs to de-nest the groups in order for their order to be enforced.

@yndajas
Copy link
Contributor

yndajas commented Aug 17, 2023

@thernstig per @ljharb, I believe the original issue in this thread would be solved by denesting the groups:

// .eslintrc.json
{
  "root": true,
  "reportUnusedDisableDirectives": true,
  "parserOptions": {
    "ecmaVersion": 2023,
    "sourceType": "module"
  },
  "env": {
    "node": true,
    "es2022": true
  },
  "plugins": ["import"],
  "rules": {
    "import/order": [
      "error",
      {
        "groups": [
          "builtin",
          "external",
          "internal",
          "parent",
          "sibling",
          "index",
          "object",
          "type"
        ]
      }
    ]
  }
}

More detailed explanation in my earlier comment

Hope that clarifies!

@ljharb
Copy link
Member

ljharb commented Aug 17, 2023

Per that comment, I'll close this, but can reopen if it doesn't work out.

@ljharb ljharb closed this as completed Aug 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging a pull request may close this issue.

4 participants