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

feat(linter): automatic fixes for noRelativeOrAbsoluteImportsAcrossLibraries and noSelfCircularDependencies #8901

Merged
merged 2 commits into from Mar 9, 2022

Conversation

juristr
Copy link
Member

@juristr juristr commented Feb 8, 2022

Current Behavior

Expected Behavior

adds a Lint rule fixer for automatically adjusting noRelativeOrAbsoluteImportsAcrossLibraries and noSelfCircularDependencies violations of the Nx enforce-module-boundaries rule.

Related Issue(s)

Fixes #

@nx-cloud
Copy link

nx-cloud bot commented Feb 8, 2022

☁️ Nx Cloud Report

CI ran the following commands for commit 63fc1b4. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this branch


✅ Successfully ran 7 targets

Sent with 💌 from NxCloud.

@vercel
Copy link

vercel bot commented Feb 8, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/nrwl/nx-dev/7toHFRSqF41vx78BFjEHnN4yfpxR
✅ Preview: Canceled

[Deployment for 63fc1b4 canceled]

@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from bc55bf1 to 5c031db Compare February 8, 2022 13:27
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 5c031db to 87c387b Compare February 9, 2022 14:37
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 87c387b to 22521f6 Compare February 9, 2022 20:25
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 22521f6 to 043b333 Compare February 9, 2022 20:28
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from af8732a to 0690d25 Compare February 9, 2022 21:57
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 0690d25 to 4d66187 Compare February 10, 2022 20:18
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 4d66187 to c6a44c4 Compare February 11, 2022 16:30
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from c6a44c4 to 27543b3 Compare February 11, 2022 20:21
@juristr juristr marked this pull request as ready for review February 11, 2022 20:22
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 27543b3 to 814732b Compare February 11, 2022 20:55
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 814732b to f0498a5 Compare February 24, 2022 14:37
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from f0498a5 to 0ff5e39 Compare February 24, 2022 20:52
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 0ff5e39 to cd4fd89 Compare February 26, 2022 16:24
@juristr
Copy link
Member Author

juristr commented Feb 28, 2022

@meeroslav @JamesHenry can some of you please have a look at this? Whether this fits into the current Nx linter setup and anything I might have missed. Thanks a lot :)

Copy link
Contributor

@meeroslav meeroslav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this extensive addition. I left some notes.

@@ -228,6 +238,95 @@ export default createESLintRule<Options, MessageIds>({
data: {
npmScope,
},
fix(fixer) {
const targetImportProject = getTargetProjectBasedOnRelativeImport(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are running the isRelative twice - as part of isRelativeImportIntoAnotherProject and again at getTargetProjectBasedOnRelativeImport.

I think we should split the condition on line 225 to check for relative and absolute import separately. That way we don't have to check for targetProjectImport twice.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly changed the current implementation to avoid duplicate calls. I guess the only concern there would be mostly around findTargetProject that gets called as part of getTargetProjectBasedOnRelativeImport

sourceProject: ProjectGraphProjectNode
): boolean {
sourceFilePath: string
) {
if (!isRelative(imp)) return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The boolean return doesn't seem right based on the function's name. It should be null or undefined. Please add also return type to the function.

(node.source.parent as any).specifiers || []
).map((specifier) => specifier.imported.name);

// ignore non-named imports for now, like "import '../../some-other-lib/src'"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been picked up above where we check if it's an import into another package.
Additionally, the example shows relative import, while the condition on line 354 explicitly checks against those.

What is the purpose of this early bail? Can we document this in the E2E test or unit test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have been picked up above where we check if it's an import into another package.

Where exactly?

Additionally, the example shows relative import, while the condition on line 354 explicitly checks against those.

Yeah this is a copy & paste comment error 😉. I'll adjust it. Basically this just documents the fact that imports like import '@myorg/somelib' are not touched by the fixer implementation for now.

What is the purpose of this early bail? Can we document this in the E2E test or unit test?

😅 it's mostly because I didn't implement this case. Might be scope of a future improvement of this fix. So in the case of a relative import across library boundaries, the fix would be pretty easy, like

  • import from '../../../someotherlib/src' => import from '@myorg/someotherlib'

In the case of a local import to the same lib, the resolution would probably not be what we want:

  • import from '@myorg/samelib' => import from '../' or whatever the current file location is relative to index.ts of the same lib

I feel this would probably not be what the dev intended though, but rather you'd want to import directly from the relative file in the same lib. Which would be hard to find without a named import.

In general I think these are edge cases though, but we might totally add it (I'd prefer in a future PR)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave a TODO as a reminder

});
} else {
// we cannot remap, so leave it as is
importsToRemap.push({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be the scenario when this happens? A missing path in tsconfig?

Can we have this scenario in tests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this is basically the exit path for all the scenarios which I've either not considered, or which result due to some weird path mapping or something. In those cases the fixer should behave as if it isn't there, therefore defaulting back to not doing anything and just having the error surface to the dev

}

// group imports from the same relative path
const importsToRemapGrouped = importsToRemap.reduce(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the two importToRemap reducers be extracted to a runtime linter util function?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ofc, fixing it

@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from cd4fd89 to ebb34b2 Compare March 2, 2022 17:18
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from ebb34b2 to f87e990 Compare March 2, 2022 17:53
@meeroslav meeroslav added the scope: linter Issues related to Eslint support in Nx label Mar 3, 2022
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from f87e990 to 485e1ef Compare March 3, 2022 14:46
@juristr juristr force-pushed the no-self-circular-dep-rule-fix branch from 485e1ef to df122e6 Compare March 3, 2022 16:24
@juristr juristr requested a review from meeroslav March 3, 2022 16:25
@meeroslav meeroslav self-assigned this Mar 7, 2022
@@ -134,16 +134,18 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
this.projectPath
);
const sourceProject = findSourceProject(this.projectGraph, filePath);
const targetImportProject = getTargetProjectBasedOnRelativeImport(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If targetImportProject is defined, we can skip the findProjectUsingImport on line 159.

It should be something like:

const targetProject = targetImportProject || findProjectUsingImport(
  this.projectGraph,
  this.targetProjectLocator,
  filePath,
  imp,
  this.npmScope
);


function tryReadBaseJson() {
try {
return JSON.parse(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devkit has readJson that wraps this segment

@meeroslav meeroslav enabled auto-merge (squash) March 8, 2022 14:39
@meeroslav meeroslav force-pushed the no-self-circular-dep-rule-fix branch from d0d08b7 to 63fc1b4 Compare March 9, 2022 07:40
@meeroslav meeroslav merged commit 45bf0e5 into nrwl:master Mar 9, 2022
@github-actions
Copy link

This pull request has already been merged/closed. If you experience issues related to these changes, please open a new issue referencing this pull request.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
scope: linter Issues related to Eslint support in Nx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants