<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