fix(linter): improve error message for forbidden imports of lazy-loaded libs (#17635)

Co-authored-by: Miroslav Jonas <missing.manual@gmail.com>
This commit is contained in:
Miloš Lajtman 2023-06-19 17:33:15 +02:00 committed by GitHub
parent 5a7d6dbf50
commit ef5813a7b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 6 deletions

View File

@ -1221,20 +1221,33 @@ Violation detected in:
target: 'otherName', target: 'otherName',
type: DependencyType.dynamic, type: DependencyType.dynamic,
}, },
{
source: 'mylibName',
target: 'otherName',
type: DependencyType.static,
},
], ],
}, },
}, },
{ {
mylibName: [createFile(`libs/mylib/src/main.ts`)], mylibName: [
createFile(`libs/mylib/src/main.ts`, [
['otherName', 'static'],
['otherName', 'dynamic'],
]),
],
otherName: [createFile(`libs/other/index.ts`)], otherName: [createFile(`libs/other/index.ts`)],
} }
); );
if (importKind === 'type') { if (importKind === 'type') {
expect(failures.length).toEqual(0); expect(failures.length).toEqual(0);
} else { } else {
expect(failures[0].message).toEqual( expect(failures[0].message).toMatchInlineSnapshot(`
'Imports of lazy-loaded libraries are forbidden' "Static imports of lazy-loaded libraries are forbidden.
);
Library "otherName" is lazy-loaded in these files:
- libs/mylib/src/main.ts"
`);
} }
} }
); );

View File

@ -8,6 +8,7 @@ import {
import { isRelativePath } from 'nx/src/utils/fileutils'; import { isRelativePath } from 'nx/src/utils/fileutils';
import { import {
checkCircularPath, checkCircularPath,
findFilesWithDynamicImports,
findFilesInCircularPath, findFilesInCircularPath,
} from '../utils/graph-utils'; } from '../utils/graph-utils';
import { import {
@ -125,7 +126,7 @@ export default createESLintRule<Options, MessageIds>({
noImportsOfE2e: 'Imports of e2e projects are forbidden', noImportsOfE2e: 'Imports of e2e projects are forbidden',
noImportOfNonBuildableLibraries: noImportOfNonBuildableLibraries:
'Buildable libraries cannot import or export from non-buildable libraries', 'Buildable libraries cannot import or export from non-buildable libraries',
noImportsOfLazyLoadedLibraries: `Imports of lazy-loaded libraries are forbidden`, noImportsOfLazyLoadedLibraries: `Static imports of lazy-loaded libraries are forbidden.\n\nLibrary "{{targetProjectName}}" is lazy-loaded in these files:\n{{filePaths}}`,
projectWithoutTagsCannotHaveDependencies: `A project without tags matching at least one constraint cannot depend on any libraries`, projectWithoutTagsCannotHaveDependencies: `A project without tags matching at least one constraint cannot depend on any libraries`,
bannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package`, bannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package`,
nestedBannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package. Nested import found at {{childProjectName}}`, nestedBannedExternalImportsViolation: `A project tagged with "{{sourceTag}}" is not allowed to import the "{{package}}" package. Nested import found at {{childProjectName}}`,
@ -515,7 +516,18 @@ export default createESLintRule<Options, MessageIds>({
[] []
) )
) { ) {
const filesWithLazyImports = findFilesWithDynamicImports(
projectFileMap,
sourceProject.name,
targetProject.name
);
context.report({ context.report({
data: {
filePaths: filesWithLazyImports
.map(({ file }) => `- ${file}`)
.join('\n'),
targetProjectName: targetProject.name,
},
node, node,
messageId: 'noImportsOfLazyLoadedLibraries', messageId: 'noImportsOfLazyLoadedLibraries',
}); });

View File

@ -4,7 +4,11 @@ import type {
ProjectGraph, ProjectGraph,
ProjectGraphProjectNode, ProjectGraphProjectNode,
} from '@nx/devkit'; } from '@nx/devkit';
import { fileDataDepTarget } from 'nx/src/config/project-graph'; import {
DependencyType,
fileDataDepTarget,
fileDataDepType,
} from 'nx/src/config/project-graph';
interface Reach { interface Reach {
graph: ProjectGraph; graph: ProjectGraph;
@ -158,3 +162,25 @@ export function findFilesInCircularPath(
return filePathChain; return filePathChain;
} }
export function findFilesWithDynamicImports(
projectFileMap: ProjectFileMap,
sourceProjectName: string,
targetProjectName: string
): FileData[] {
const files: FileData[] = [];
projectFileMap[sourceProjectName].forEach((file) => {
if (!file.deps) return;
if (
file.deps.some(
(d) =>
fileDataDepTarget(d) === targetProjectName &&
fileDataDepType(d) === DependencyType.dynamic
)
) {
files.push(file);
}
});
return files;
}