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:
parent
5a7d6dbf50
commit
ef5813a7b7
@ -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"
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -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',
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user