TP-00000 | Dependency Graph (#7710)
This commit is contained in:
@@ -17,6 +17,7 @@ plugins {
|
||||
|
||||
apply from: 'spotless.gradle'
|
||||
apply from: 'dependencies.gradle'
|
||||
apply from: 'projectDependencyGraph.gradle'
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
||||
124
projectDependencyGraph.gradle
Normal file
124
projectDependencyGraph.gradle
Normal file
@@ -0,0 +1,124 @@
|
||||
tasks.register('projectDependencyGraph') {
|
||||
doLast {
|
||||
def dot = new File(rootProject.buildDir, 'reports/dependency-graph/project.dot')
|
||||
dot.parentFile.mkdirs()
|
||||
dot.delete()
|
||||
|
||||
dot << 'digraph {\n'
|
||||
dot << " graph [label=\"${rootProject.name}\\n \",labelloc=t,fontsize=30,ranksep=1.4];\n"
|
||||
dot << ' node [style=filled, fillcolor="#bbbbbb"];\n'
|
||||
dot << ' rankdir=TB;\n'
|
||||
|
||||
def rootProjects = []
|
||||
def queue = [rootProject]
|
||||
while (!queue.isEmpty()) {
|
||||
def project = queue.remove(0)
|
||||
rootProjects.add(project)
|
||||
queue.addAll(project.childProjects.values())
|
||||
}
|
||||
|
||||
def projects = new LinkedHashSet<Project>()
|
||||
def dependencies = new LinkedHashMap<Tuple2<Project, Project>, List<String>>()
|
||||
def multiplatformProjects = []
|
||||
def jsProjects = []
|
||||
def androidProjects = []
|
||||
def dynamicProjects = []
|
||||
def javaProjects = []
|
||||
|
||||
queue = [rootProject]
|
||||
while (!queue.isEmpty()) {
|
||||
def project = queue.remove(0)
|
||||
queue.addAll(project.childProjects.values())
|
||||
|
||||
if (project.plugins.hasPlugin('org.jetbrains.kotlin.multiplatform')) {
|
||||
multiplatformProjects.add(project)
|
||||
}
|
||||
if (project.plugins.hasPlugin('org.jetbrains.kotlin.js')) {
|
||||
jsProjects.add(project)
|
||||
}
|
||||
if (project.plugins.hasPlugin('com.android.library') || project.plugins.hasPlugin('com.android.application')) {
|
||||
androidProjects.add(project)
|
||||
}
|
||||
if (project.plugins.hasPlugin('com.android.dynamic-feature')) {
|
||||
dynamicProjects.add(project)
|
||||
}
|
||||
if (project.plugins.hasPlugin('java-library') || project.plugins.hasPlugin('java')) {
|
||||
javaProjects.add(project)
|
||||
}
|
||||
|
||||
project.configurations.configureEach { config ->
|
||||
config.dependencies
|
||||
.withType(ProjectDependency)
|
||||
.collect { it.dependencyProject }
|
||||
.each { dependency ->
|
||||
projects.add(project)
|
||||
projects.add(dependency)
|
||||
rootProjects.remove(dependency)
|
||||
|
||||
def graphKey = new Tuple2<Project, Project>(project, dependency)
|
||||
def traits = dependencies.computeIfAbsent(graphKey) { new ArrayList<String>() }
|
||||
|
||||
if (config.name.toLowerCase().endsWith('implementation') && !traits.contains('style=dotted')) {
|
||||
traits.add('style=dotted')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
projects = projects.sort { it.path }
|
||||
|
||||
dot << '\n # Projects\n\n'
|
||||
for (project in projects) {
|
||||
def traits = []
|
||||
|
||||
if (rootProjects.contains(project)) {
|
||||
traits.add('shape=box')
|
||||
}
|
||||
|
||||
if (multiplatformProjects.contains(project)) {
|
||||
traits.add('fillcolor="#ffd2b3"')
|
||||
} else if (jsProjects.contains(project)) {
|
||||
traits.add('fillcolor="#ffffba"')
|
||||
} else if (androidProjects.contains(project)) {
|
||||
traits.add('fillcolor="#baffc9"')
|
||||
} else if (dynamicProjects.contains(project)) {
|
||||
traits.add('fillcolor="#bad4ff"')
|
||||
} else if (javaProjects.contains(project)) {
|
||||
traits.add('fillcolor="#ffb3ba"')
|
||||
} else {
|
||||
traits.add('fillcolor="#eeeeee"')
|
||||
}
|
||||
|
||||
dot << " \"${project.path}\" [${traits.join(", ")}];\n"
|
||||
}
|
||||
|
||||
dot << '\n {rank = same;'
|
||||
for (project in projects) {
|
||||
if (rootProjects.contains(project)) {
|
||||
dot << " \"${project.path}\";"
|
||||
}
|
||||
}
|
||||
dot << '}\n'
|
||||
|
||||
dot << '\n # Dependencies\n\n'
|
||||
dependencies.forEach { key, traits ->
|
||||
if (key.v1.path != key.v2.path) {
|
||||
dot << " \"${key.v1.path}\" -> \"${key.v2.path}\""
|
||||
if (!traits.isEmpty()) {
|
||||
dot << " [${traits.join(", ")}]"
|
||||
}
|
||||
dot << '\n'
|
||||
}
|
||||
}
|
||||
|
||||
dot << '}\n'
|
||||
|
||||
def p = 'dot -Tpng -O project.dot'.execute([], dot.parentFile)
|
||||
p.waitFor()
|
||||
if (p.exitValue() != 0) {
|
||||
throw new RuntimeException(p.errorStream.text)
|
||||
}
|
||||
|
||||
println("Project module dependency graph created at ${dot.absolutePath}.png")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user