Skip to content

Commit

Permalink
feat(schematics): add lint check for circular deps
Browse files Browse the repository at this point in the history
  • Loading branch information
skydever authored and vsavkin committed Mar 14, 2018
1 parent 4f052bb commit 53175f9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
12 changes: 12 additions & 0 deletions packages/schematics/src/tslint/nxEnforceModuleBoundariesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 => {
Expand Down

0 comments on commit 53175f9

Please sign in to comment.