Skip to content

Commit b856a6a

Browse files
add gradle task
1 parent 02fc950 commit b856a6a

1 file changed

Lines changed: 116 additions & 0 deletions

File tree

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
task projectDependencyGraph {
2+
doLast {
3+
def dot = new File(rootProject.rootDir, 'gradle/dependency-graph/project.dot')
4+
dot.parentFile.mkdirs()
5+
dot.delete()
6+
7+
dot << 'digraph {\n'
8+
dot << " graph [label=\"${rootProject.name}\\n \",labelloc=t,fontsize=30,ranksep=1.4];\n"
9+
dot << ' node [style=filled, fillcolor="#bbbbbb"];\n'
10+
dot << ' rankdir=TB;\n'
11+
12+
def rootProjects = []
13+
def queue = [rootProject]
14+
while (!queue.isEmpty()) {
15+
def project = queue.remove(0)
16+
rootProjects.add(project)
17+
queue.addAll(project.childProjects.values())
18+
}
19+
20+
def projects = new LinkedHashSet<Project>()
21+
def dependencies = new LinkedHashMap<Tuple2<Project, Project>, List<String>>()
22+
def multiplatformProjects = []
23+
def jsProjects = []
24+
def androidProjects = []
25+
def javaProjects = []
26+
27+
queue = [rootProject]
28+
while (!queue.isEmpty()) {
29+
def project = queue.remove(0)
30+
queue.addAll(project.childProjects.values())
31+
32+
if (project.plugins.hasPlugin('org.jetbrains.kotlin.multiplatform')) {
33+
multiplatformProjects.add(project)
34+
}
35+
if (project.plugins.hasPlugin('org.jetbrains.kotlin.js')) {
36+
jsProjects.add(project)
37+
}
38+
if (project.plugins.hasPlugin('com.android.library') || project.plugins.hasPlugin('com.android.application')) {
39+
androidProjects.add(project)
40+
}
41+
if (project.plugins.hasPlugin('java-library') || project.plugins.hasPlugin('java')) {
42+
javaProjects.add(project)
43+
}
44+
45+
project.configurations.all { config ->
46+
config.dependencies
47+
.withType(ProjectDependency)
48+
.collect { it.dependencyProject }
49+
.each { dependency ->
50+
projects.add(project)
51+
projects.add(dependency)
52+
rootProjects.remove(dependency)
53+
54+
def graphKey = new Tuple2<Project, Project>(project, dependency)
55+
def traits = dependencies.computeIfAbsent(graphKey) { new ArrayList<String>() }
56+
57+
if (config.name.toLowerCase().endsWith('implementation')) {
58+
traits.add('style=dotted')
59+
}
60+
}
61+
}
62+
}
63+
64+
projects = projects.sort { it.path }
65+
66+
dot << '\n # Projects\n\n'
67+
for (project in projects) {
68+
def traits = []
69+
70+
if (rootProjects.contains(project)) {
71+
traits.add('shape=box')
72+
}
73+
74+
if (multiplatformProjects.contains(project)) {
75+
traits.add('fillcolor="#ffd2b3"')
76+
} else if (jsProjects.contains(project)) {
77+
traits.add('fillcolor="#ffffba"')
78+
} else if (androidProjects.contains(project)) {
79+
traits.add('fillcolor="#baffc9"')
80+
} else if (javaProjects.contains(project)) {
81+
traits.add('fillcolor="#ffb3ba"')
82+
} else {
83+
traits.add('fillcolor="#eeeeee"')
84+
}
85+
86+
dot << " \"${project.path}\" [${traits.join(", ")}];\n"
87+
}
88+
89+
dot << '\n {rank = same;'
90+
for (project in projects) {
91+
if (rootProjects.contains(project)) {
92+
dot << " \"${project.path}\";"
93+
}
94+
}
95+
dot << '}\n'
96+
97+
dot << '\n # Dependencies\n\n'
98+
dependencies.forEach { key, traits ->
99+
dot << " \"${key.first.path}\" -> \"${key.second.path}\""
100+
if (!traits.isEmpty()) {
101+
dot << " [${traits.join(", ")}]"
102+
}
103+
dot << '\n'
104+
}
105+
106+
dot << '}\n'
107+
108+
def p = 'dot -Tpng -O project.dot'.execute([], dot.parentFile)
109+
p.waitFor()
110+
if (p.exitValue() != 0) {
111+
throw new RuntimeException(p.errorStream.text)
112+
}
113+
114+
println("Project module dependency graph created at ${dot.absolutePath}.png")
115+
}
116+
}

0 commit comments

Comments
 (0)