<lambda>null1 package org.jetbrains.dokka
2
3
4 import com.sampullara.cli.Args
5 import com.sampullara.cli.Argument
6 import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
7 import org.jetbrains.dokka.Utilities.DownloadSamples
8
9 import java.io.File
10 import java.net.MalformedURLException
11 import java.net.URL
12 import java.net.URLClassLoader
13
14 class DokkaArguments {
15 @set:Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)")
16 var src: String = ""
17
18 @set:Argument(value = "srcLink", description = "Mapping between a source directory and a Web site for browsing the code")
19 var srcLink: String = ""
20
21 @set:Argument(value = "include", description = "Markdown files to load (allows many paths separated by the system path separator)")
22 var include: String = ""
23
24 @set:Argument(value = "samples", description = "Source root for samples")
25 var samples: String = ""
26
27 @set:Argument(value = "useSamplesURL", description = "Download samples from URL into root folder")
28 var useSamplesURL: Boolean = false
29
30 @set:Argument(value = "output", description = "Output directory path")
31 var outputDir: String = "out/doc/"
32
33 @set:Argument(value = "format", description = "Output format (text, html, markdown, jekyll, kotlin-website)")
34 var outputFormat: String = "html"
35
36 @set:Argument(value = "module", description = "Name of the documentation module")
37 var moduleName: String = ""
38
39 @set:Argument(value = "classpath", description = "Classpath for symbol resolution")
40 var classpath: String = ""
41
42 @set:Argument(value = "nodeprecated", description = "Exclude deprecated members from documentation")
43 var nodeprecated: Boolean = false
44
45 @set:Argument(value = "jdkVersion", description = "Version of JDK to use for linking to JDK JavaDoc")
46 var jdkVersion: Int = 6
47
48 @set:Argument(value = "impliedPlatforms", description = "List of implied platforms (comma-separated)")
49 var impliedPlatforms: String = ""
50
51 @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ")
52 var packageOptions: String = ""
53
54 @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...")
55 var links: String = ""
56
57 @set:Argument(value = "noStdlibLink", description = "Disable documentation link to stdlib")
58 var noStdlibLink: Boolean = false
59
60 @set:Argument(value = "noJdkLink", description = "Disable documentation link to jdk")
61 var noJdkLink: Boolean = false
62
63 @set:Argument(value = "cacheRoot", description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled")
64 var cacheRoot: String? = null
65
66 @set:Argument(value = "languageVersion", description = "Language Version to pass to Kotlin Analysis")
67 var languageVersion: String? = null
68
69 @set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis")
70 var apiVersion: String? = null
71
72 @set:Argument(value = "collectInheritedExtensionsFromLibraries", description = "Search for applicable extensions in libraries")
73 var collectInheritedExtensionsFromLibraries: Boolean = false
74
75 @set:Argument(value = "generateClassIndexPage", description = "Generate classes.html index page. [Deprecated]: use noGenerateClassIndexPage instead.")
76 @Deprecated("There is no way to set this to false.", replaceWith = ReplaceWith(
77 expression ="noGenerateClassIndexPage"))
78 var generateClassIndexPage: Boolean = true
79
80 @set:Argument(value = "generatePackageIndexPage", description = "Generate packages.html index page. [Deprecated]: use noGeneratePackageIndexPage instead.")
81 @Deprecated("There is no way to set this to false.", replaceWith = ReplaceWith(
82 expression ="noGeneratePackageIndexPage"))
83 var generatePackageIndexPage: Boolean = true
84
85 @set:Argument(value = "noGenerateClassIndexPage", description = "Disable classes.html index page.")
86 var noGenerateClassIndexPage: Boolean = false
87
88 @set:Argument(value = "noGeneratePackageIndexPage", description = "Disable packages.html index page.")
89 var noGeneratePackageIndexPage: Boolean = false
90
91 @set:Argument(value = "outlineRoot", description = "Relative root directory the outline files. I.e. androidx/core/")
92 var outlineRoot: String = ""
93
94 @set:Argument(value = "dacRoot", description = "Root directory in DAC of this library. I.e: /reference/kotlin")
95 var dacRoot: String = ""
96 }
97
98
99 object MainKt {
100
parseLinksnull101 fun parseLinks(links: String): List<ExternalDocumentationLink> {
102 val (parsedLinks, parsedOfflineLinks) = links.split("^^")
103 .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
104 .filter { it.isNotEmpty() }
105 .partition { it.size == 1 }
106
107 return parsedLinks.map { (root) -> ExternalDocumentationLink.Builder(root).build() } +
108 parsedOfflineLinks.map { (root, packageList) ->
109 val rootUrl = URL(root)
110 val packageListUrl =
111 try {
112 URL(packageList)
113 } catch (ex: MalformedURLException) {
114 File(packageList).toURI().toURL()
115 }
116 ExternalDocumentationLink.Builder(rootUrl, packageListUrl).build()
117 }
118 }
119
120 @JvmStatic
entrynull121 fun entry(args: Array<String>) {
122 val arguments = DokkaArguments()
123 val freeArgs: List<String> = Args.parse(arguments, args) ?: listOf()
124 val sources = if (arguments.src.isNotEmpty()) arguments.src.split(File.pathSeparatorChar).toList() + freeArgs else freeArgs
125 val samples = if (arguments.samples.isNotEmpty()) arguments.samples.split(File.pathSeparatorChar).toList() else listOf()
126 val includes = if (arguments.include.isNotEmpty()) arguments.include.split(File.pathSeparatorChar).toList() else listOf()
127
128 val sourceLinks = if (arguments.srcLink.isNotEmpty() && arguments.srcLink.contains("="))
129 listOf(SourceLinkDefinitionImpl.parseSourceLinkDefinition(arguments.srcLink))
130 else {
131 if (arguments.srcLink.isNotEmpty()) {
132 println("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
133 }
134 listOf()
135 }
136
137 val classPath = arguments.classpath.split(File.pathSeparatorChar).toList()
138
139 if (arguments.useSamplesURL) DownloadSamples.downloadSamples()
140
141 val documentationOptions = DocumentationOptions(
142 arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' },
143 arguments.outputFormat,
144 skipDeprecated = arguments.nodeprecated,
145 sourceLinks = sourceLinks,
146 impliedPlatforms = arguments.impliedPlatforms.split(','),
147 perPackageOptions = parsePerPackageOptions(arguments.packageOptions),
148 jdkVersion = arguments.jdkVersion,
149 externalDocumentationLinks = parseLinks(arguments.links),
150 noStdlibLink = arguments.noStdlibLink,
151 cacheRoot = arguments.cacheRoot,
152 languageVersion = arguments.languageVersion,
153 apiVersion = arguments.apiVersion,
154 collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries,
155 generateClassIndexPage = !arguments.noGenerateClassIndexPage,
156 generatePackageIndexPage = !arguments.noGeneratePackageIndexPage,
157 outlineRoot = arguments.outlineRoot,
158 dacRoot = arguments.dacRoot,
159 noJdkLink = arguments.noJdkLink
160 )
161
162 val generator = DokkaGenerator(
163 DokkaConsoleLogger,
164 classPath,
165 sources.map(SourceRootImpl.Companion::parseSourceRoot),
166 samples,
167 includes,
168 arguments.moduleName,
169 documentationOptions)
170
171 generator.generate()
172 DokkaConsoleLogger.report()
173 }
174
findToolsJarnull175 fun findToolsJar(): File {
176 val javaHome = System.getProperty("java.home")
177 val default = File(javaHome, "../lib/tools.jar")
178 val mac = File(javaHome, "../Classes/classes.jar")
179 when {
180 default.exists() -> return default
181 mac.exists() -> return mac
182 else -> {
183 throw Exception("tools.jar not found, please check it, also you can provide it manually, using -cp")
184 }
185 }
186 }
187
createClassLoaderWithToolsnull188 fun createClassLoaderWithTools(): ClassLoader {
189 val toolsJar = findToolsJar().canonicalFile.toURI().toURL()
190 val originalUrls = (javaClass.classLoader as? URLClassLoader)?.urLs
191 val dokkaJar = javaClass.protectionDomain.codeSource.location
192 val urls = if (originalUrls != null) arrayOf(toolsJar, *originalUrls) else arrayOf(toolsJar, dokkaJar)
193 return URLClassLoader(urls, ClassLoader.getSystemClassLoader().parent)
194 }
195
startWithToolsJarnull196 fun startWithToolsJar(args: Array<String>) {
197 try {
198 javaClass.classLoader.loadClass("com.sun.tools.doclets.formats.html.HtmlDoclet")
199 entry(args)
200 } catch (e: ClassNotFoundException) {
201 val classLoader = createClassLoaderWithTools()
202 classLoader.loadClass("org.jetbrains.dokka.MainKt")
203 .methods.find { it.name == "entry" }!!
204 .invoke(null, args)
205 }
206 }
207
208 @JvmStatic
mainnull209 fun main(args: Array<String>) {
210 val arguments = DokkaArguments()
211 Args.parse(arguments, args)
212
213 if (arguments.outputFormat == "javadoc")
214 startWithToolsJar(args)
215 else
216 entry(args)
217 }
218 }
219
220
221
222