15
15
16
16
package modulecheck.builds
17
17
18
+ import com.vanniktech.maven.publish.tasks.JavadocJar
19
+ import org.gradle.api.GradleException
18
20
import org.gradle.api.Plugin
19
21
import org.gradle.api.Project
22
+ import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
23
+ import org.gradle.api.tasks.TaskCollection
24
+ import org.gradle.language.base.plugins.LifecycleBasePlugin
25
+ import org.jetbrains.dokka.DokkaConfiguration
20
26
import org.jetbrains.dokka.gradle.AbstractDokkaLeafTask
27
+ import org.jetbrains.dokka.gradle.AbstractDokkaTask
28
+ import org.jetbrains.dokka.gradle.DokkaMultiModuleTask
29
+ import org.jetbrains.dokka.gradle.DokkaTaskPartial
30
+ import org.jetbrains.dokka.versioning.VersioningConfiguration
31
+ import org.jetbrains.dokka.versioning.VersioningPlugin
21
32
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
22
33
import org.jmailen.gradle.kotlinter.tasks.FormatTask
23
34
import org.jmailen.gradle.kotlinter.tasks.LintTask
@@ -28,53 +39,137 @@ abstract class DokkaConventionPlugin : Plugin<Project> {
28
39
29
40
target.plugins.applyOnce(" org.jetbrains.dokka" )
30
41
31
- target.tasks.withType(AbstractDokkaLeafTask ::class .java).configureEach { task ->
42
+ target.tasks.withType(AbstractDokkaLeafTask ::class .java).configureEach { dokkaTask ->
32
43
33
44
// Dokka doesn't support configuration caching
34
- task .notCompatibleWithConfigurationCache(" Dokka doesn't support configuration caching" )
45
+ dokkaTask .notCompatibleWithConfigurationCache(" Dokka doesn't support configuration caching" )
35
46
36
- // Dokka uses their outputs but doesn't explicitly depend upon them.
37
- task.mustRunAfter(target.tasks.withType(KotlinCompile ::class .java))
38
- task.mustRunAfter(target.tasks.withType(LintTask ::class .java))
39
- task.mustRunAfter(target.tasks.withType(FormatTask ::class .java))
47
+ dokkaTask.setMustRunAfter(target)
40
48
41
- // The default moduleName for each module in the module list is its unqualified "name",
42
- // meaning the list would be full of "api", "impl", etc. Instead, use the module's maven
43
- // artifact ID, if it has one, or default to its full Gradle path for internal modules.
44
- val fullModuleName = target.artifactId ? : target.path.removePrefix(" :" )
45
- task.moduleName.set(fullModuleName)
49
+ val fullModuleName = target.path.removePrefix(" :" )
50
+ dokkaTask.moduleName.set(fullModuleName)
46
51
47
- if (! target.isRootProject()) {
48
- task.dokkaSourceSets.getByName(" main" ) { builder ->
52
+ if (target != target.rootProject && target.file(" src/main" ).exists()) {
53
+ dokkaTask.configureSourceSets(target)
54
+ }
55
+ }
49
56
50
- builder.samples.setFrom(
51
- target.fileTree(target.projectDir) { tree ->
52
- tree.include(" samples/**" )
53
- }
54
- )
57
+ target.dependencies.add(
58
+ " dokkaPlugin" ,
59
+ target.libsCatalog.dependency(" dokka-versioning" )
60
+ )
55
61
56
- val readmeFile = target.file( " ${target.projectDir} /README.md " )
62
+ fun TaskCollection < out AbstractDokkaTask >. configureVersioning () = configureEach { task ->
57
63
58
- if (readmeFile.exists()) {
59
- builder.includes.from(readmeFile)
60
- }
64
+ val dokkaArchiveBuildDir = target.rootDir.resolve(" build/tmp/dokka-archive" )
65
+
66
+ require(task is DokkaTaskPartial || task is DokkaMultiModuleTask ) {
67
+ """
68
+ DO NOT JUST CONFIGURE `AbstractDokkaTask`!!!
69
+ This will bundle the full dokka archive (all versions) into the javadoc.jar for every single
70
+ module, which currently adds about 8MB per version in the archive. Set up versioning for the
71
+ Multi-Module tasks ONLY. (DokkaTaskPartial is part of the multi-module tasks).
72
+ """ .trimIndent()
73
+ }
74
+
75
+ task.pluginConfiguration<VersioningPlugin , VersioningConfiguration > {
76
+ version = VERSION_NAME
77
+ olderVersionsDir = dokkaArchiveBuildDir
78
+ renderVersionsNavigationOnAllPages = true
79
+ }
80
+ }
61
81
62
- builder.sourceLink { sourceLinkBuilder ->
63
- sourceLinkBuilder.localDirectory.set(target.file( " src/main " ) )
82
+ target.tasks.withType( DokkaTaskPartial :: class .java).configureVersioning()
83
+ target.tasks.withType( DokkaMultiModuleTask :: class .java).configureVersioning( )
64
84
65
- val modulePath = target.path.replace(" :" , " /" )
66
- .replaceFirst(" /" , " " )
85
+ target.plugins.withType(MavenPublishPlugin ::class .java).configureEach {
67
86
68
- // URL showing where the source code can be accessed through the web browser
69
- sourceLinkBuilder.remoteUrl.set(
70
- URL (" https://github.com/RBusarow/ModuleCheck/blob/main/$modulePath /src/main" )
71
- )
72
- // Suffix which is used to append the line number to the URL. Use #L for GitHub
73
- sourceLinkBuilder.remoteLineSuffix.set(" #L" )
87
+ val checkJavadocJarIsNotVersioned = target.tasks
88
+ .register(
89
+ " checkJavadocJarIsNotVersioned" ,
90
+ ModuleCheckBuildTask ::class .java
91
+ ) { task ->
92
+ task.description =
93
+ " Ensures that generated javadoc.jar artifacts don't include old Dokka versions"
94
+ task.group = " dokka versioning"
95
+
96
+ val javadocTasks = target.tasks.withType(JavadocJar ::class .java)
97
+ task.dependsOn(javadocTasks)
98
+
99
+ task.inputs.files(javadocTasks.map { it.outputs })
100
+
101
+ val zipTrees = javadocTasks.map { target.zipTree(it.archiveFile) }
102
+
103
+ task.doLast {
104
+
105
+ val jsonReg = """ older\/($SEMVER_REGEX )\/version\.json""" .toRegex()
106
+
107
+ val versions = zipTrees.flatMap { tree ->
108
+ tree
109
+ .filter { it.path.startsWith(" older/" ) }
110
+ .filter { it.isFile }
111
+ .mapNotNull { jsonReg.find(it.path)?.groupValues?.get(1 ) }
112
+ }
113
+
114
+ if (versions.isNotEmpty()) {
115
+ throw GradleException (" Found old Dokka versions in javadoc.jar: $versions " )
116
+ }
74
117
}
75
118
}
76
- }
119
+
120
+ target.tasks.named(LifecycleBasePlugin .CHECK_TASK_NAME )
121
+ .dependsOn(checkJavadocJarIsNotVersioned)
77
122
}
123
+ }
124
+
125
+ private fun AbstractDokkaLeafTask.setMustRunAfter (target : Project ) {
126
+
127
+ // Dokka uses their outputs but doesn't explicitly depend upon them.
128
+ mustRunAfter(target.tasks.withType(KotlinCompile ::class .java))
129
+ mustRunAfter(target.tasks.withType(LintTask ::class .java))
130
+ mustRunAfter(target.tasks.withType(FormatTask ::class .java))
131
+ mustRunAfter(target.tasks.matchingName(" generateProtos" ))
132
+ }
133
+
134
+ private fun AbstractDokkaLeafTask.configureSourceSets (target : Project ) {
135
+
136
+ dokkaSourceSets.named(" main" ) { sourceSet ->
137
+
138
+ sourceSet.documentedVisibilities.set(
139
+ setOf (
140
+ DokkaConfiguration .Visibility .PUBLIC ,
141
+ DokkaConfiguration .Visibility .PRIVATE ,
142
+ DokkaConfiguration .Visibility .PROTECTED ,
143
+ DokkaConfiguration .Visibility .INTERNAL ,
144
+ DokkaConfiguration .Visibility .PACKAGE
145
+ )
146
+ )
78
147
148
+ sourceSet.languageVersion.set(target.KOTLIN_API )
149
+ sourceSet.jdkVersion.set(target.JVM_TARGET_INT )
150
+
151
+ // include all project sources when resolving kdoc samples
152
+ sourceSet.samples.setFrom(target.fileTree(target.file(" src" )))
153
+
154
+ val readmeFile = target.projectDir.resolve(" README.md" )
155
+
156
+ if (readmeFile.exists()) {
157
+ sourceSet.includes.from(readmeFile)
158
+ }
159
+
160
+ sourceSet.sourceLink { sourceLinkBuilder ->
161
+ sourceLinkBuilder.localDirectory.set(target.file(" src/main" ))
162
+
163
+ val modulePath = project.path.replace(" :" , " /" )
164
+ .replaceFirst(" /" , " " )
165
+
166
+ // URL showing where the source code can be accessed through the web browser
167
+ sourceLinkBuilder.remoteUrl.set(
168
+ URL (" https://github.com/RBusarow/ModuleCheck/blob/main/$modulePath /src/main" )
169
+ )
170
+ // Suffix which is used to append the line number to the URL. Use #L for GitHub
171
+ sourceLinkBuilder.remoteLineSuffix.set(" #L" )
172
+ }
173
+ }
79
174
}
80
175
}
0 commit comments