@@ -98,9 +98,10 @@ abstract class ProjectGraphBuilder : DefaultTask() {
98
98
warnings.add(" [WARNING] The following modules are not included in the platform: $missingPlatformDependencies " )
99
99
}
100
100
val cycles = mutableSetOf<Pair <String , String >>()
101
- val projects = sortByDependents(projectToMetadata, cycles)
102
- cycles.forEach {
103
- val warning = " [WARNING] A cycle exists between ${it.first} and ${it.second} "
101
+ val cyclePaths = mutableSetOf<String >()
102
+ val projects = sortByDependents(projectToMetadata, cycles, cyclePaths)
103
+ cyclePaths.forEach {
104
+ val warning = " [WARNING] A cycle was detected: $it "
104
105
System .err.println (warning)
105
106
warnings.add(warning)
106
107
}
@@ -240,7 +241,7 @@ abstract class ProjectGraphBuilder : DefaultTask() {
240
241
}
241
242
}
242
243
243
- private fun sortByDependents (projectToMetadata : Map <String , ModuleMetadata >, cycles : MutableSet <Pair <String , String >>): List <String > {
244
+ private fun sortByDependents (projectToMetadata : Map <String , ModuleMetadata >, cycles : MutableSet <Pair <String , String >>, cyclePaths : MutableSet < String > ): List <String > {
244
245
val remaining = projectToMetadata.keys.toTypedArray()
245
246
var i = 0
246
247
while (i < remaining.size) {
@@ -255,6 +256,9 @@ abstract class ProjectGraphBuilder : DefaultTask() {
255
256
if (t2.contains(p1)) {
256
257
if (! cycles.contains(p2 to p1)) {
257
258
cycles.add(p1 to p2)
259
+ p1.findPathTo(projectToMetadata, p2)?.also {
260
+ cyclePaths.add(it)
261
+ }
258
262
}
259
263
j++
260
264
} else {
@@ -379,6 +383,31 @@ abstract class ProjectGraphBuilder : DefaultTask() {
379
383
return transitive
380
384
}
381
385
386
+ fun String.findPathTo (deps : Map <String , ModuleMetadata >, target : String ): String? {
387
+ val path = findPathTo(deps, target, this , mutableSetOf ())
388
+ if (path != null ) {
389
+ return " $path -> $this "
390
+ }
391
+ return null
392
+ }
393
+
394
+ fun String.findPathTo (deps : Map <String , ModuleMetadata >, target : String , currentPath : String , visited : MutableSet <String >): String? {
395
+ if (visited.add(this )) {
396
+ val dependencies = deps[this ]?.dependencies ? : emptySet()
397
+ dependencies.forEach {
398
+ val path = " $currentPath -> $it "
399
+ if (it == target) {
400
+ return path
401
+ }
402
+ val candidate = it.findPathTo(deps, target, path, visited)
403
+ if (candidate != null ) {
404
+ return candidate
405
+ }
406
+ }
407
+ }
408
+ return null ;
409
+ }
410
+
382
411
private fun String.transitiveDeps (deps : Map <String , ModuleMetadata >, visited : MutableSet <String >): Unit {
383
412
val dependencies = deps[this ]?.dependencies ? : emptySet()
384
413
if (visited.add(this )) {
0 commit comments