feat(schematics): add lint check for circular deps
This commit is contained in:
parent
4f052bb3e6
commit
53175f925e
@ -321,6 +321,41 @@ describe('Enforce Module Boundaries', () => {
|
||||
);
|
||||
expect(failures[0].getFailure()).toEqual('imports of apps are forbidden');
|
||||
});
|
||||
|
||||
it('should error when circular dependency detected', () => {
|
||||
const failures = runRule(
|
||||
{},
|
||||
`${process.cwd()}/proj/libs/anotherlib/src/main.ts`,
|
||||
'import "@mycompany/mylib"',
|
||||
[
|
||||
{
|
||||
name: 'mylib',
|
||||
root: 'libs/mylib/src',
|
||||
type: ProjectType.lib,
|
||||
tags: [],
|
||||
files: [`libs/mylib/src/main.ts`]
|
||||
},
|
||||
{
|
||||
name: 'anotherlib',
|
||||
root: 'libs/anotherlib/src',
|
||||
type: ProjectType.lib,
|
||||
tags: [],
|
||||
files: [`libs/anotherlib/src/main.ts`]
|
||||
},
|
||||
{
|
||||
name: 'myapp',
|
||||
root: 'apps/myapp/src',
|
||||
type: ProjectType.app,
|
||||
tags: [],
|
||||
files: [`apps/myapp/index.ts`]
|
||||
}
|
||||
],
|
||||
{
|
||||
mylib: [{ projectName: 'anotherlib', type: DependencyType.es6Import }]
|
||||
}
|
||||
);
|
||||
expect(failures[0].getFailure()).toEqual('Circular dependency between \"anotherlib\" and \"mylib\" detected');
|
||||
});
|
||||
});
|
||||
|
||||
function runRule(
|
||||
|
||||
@ -98,6 +98,13 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
|
||||
return;
|
||||
}
|
||||
|
||||
// check for circular dependency
|
||||
if (this.isCircular(sourceProject, targetProject)) {
|
||||
const error = `Circular dependency between "${sourceProject.name}" and "${targetProject.name}" detected`;
|
||||
this.addFailureAt(node.getStart(), node.getWidth(), error);
|
||||
return;
|
||||
}
|
||||
|
||||
// same project => allow
|
||||
if (sourceProject === targetProject) {
|
||||
super.visitImportDeclaration(node);
|
||||
@ -146,6 +153,11 @@ class EnforceModuleBoundariesWalker extends Lint.RuleWalker {
|
||||
super.visitImportDeclaration(node);
|
||||
}
|
||||
|
||||
private isCircular(sourceProject: ProjectNode, targetProject: ProjectNode): boolean {
|
||||
if (!this.deps[targetProject.name]) return false;
|
||||
return this.deps[targetProject.name].some(dep => dep.projectName == sourceProject.name);
|
||||
}
|
||||
|
||||
private onlyLoadChildren(sourceProjectName: string, targetProjectName: string, visited: string[]) {
|
||||
if (visited.indexOf(sourceProjectName) > -1) return false;
|
||||
return (this.deps[sourceProjectName] || []).filter(d => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user