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
Rule proposal: detect and warn about circular imports #224
Comments
I've been using circular-dependency-plugin, but it's not compatible with |
@JoshuaKGoldberg To implement this feature, we need to preserve the state between linted files - it's needed to build the dependency graph between the modules. Is this an acceptable way of doing that? I wonder if there's some case where we would start linting with stale state (with some records from previous linting).
|
@krzysztof-grzybek Your comment is actually roughly how the Their lint uses the AST from the current file to determine its dependencies, then it does an out-of-band parse on each dependency to determine its dependencies, and so on. To be clear - this proposal is not to rebuild that lint rule in the same way. Our lint rule wouldn't need to store any state because we have access to type information. We can rely on the fact that TS has already analysed every file and knows the dependency graph of the project. This is the basis of this proposal - the |
Is circular graph error / problem? I think I recall that it can be more a problem with CJS than ESM but I don’t find really supporting documentation. Webpack used to warn about this but it no longer does that by default. What I’m after here, is some good but short explanation why user would like to enable this rule and when not to use it. This will probably be filled in the opened PR but same time to help that, maybe it would be good to collect some sources :) I tried to look the documentation of other tools. Most do not really have anything to say why you want this. Probably it’s so common knowledge that it does not need stating.
Something similar could be added to the new rule, that it may not be a problem. Reason that it may be problem
|
// fileA.ts
import { b } from './b';
export const a = b;
// fileB.ts
import { a } from './a';
export const b = a; What's the result of a 3rd module doing The tl;dr is that cycles in the dependency graph increase complexity greatly. It makes it hard to reason about code because you need to think about and understand the way in which the underlying ESM infra works. And that's assuming your build tool / bundler transpilers your code in such a way that it works how ESM says it should. Why take on that complexity when the vast, vast majority of cases could be refactors to remove the cycle? Moving a variable or a function to a new module can break the cycle and restore your dep graph to be an acyclic graph and reduce complexity. |
|
The real value IMO isn't 2-module cycles like you always see in examples. Those cases are always simple and often are easy to spot by hand. The more interesting cases are when you've got a cycle where the path is 3 or more. I've seen cases where there are a dozen modules in the cycle - nearly impossible for a human to see. |
The other example that comes to mind is // fileA.ts
import { something } from 'fileB.ts';
console.log('side effect that needs to happen first');
// fileB.ts
import { somethingElse } from './fileThatTransitivelyImportsFileA.ts';
console.log('side effect that needs to happen second');
// main.ts
// transitively import fileA or fileB
// order of console logs can be changed by addition or removal of files in cycle There is of course more than one code smell here, but... it happens in the wild. |
Currently I'm using eslint-plugin-import with eslint-import-resolver-typescript, but it works really slow.
And I was thinking that creation of dependency tree with TS project (that already passed to
@typescript-eslint/eslint-parser
) must be much faster than file system scanning.See also: tslint-no-circular-imports.
The text was updated successfully, but these errors were encountered: