diff options
author | Sergey Mashkov <sergey.mashkov@jetbrains.com> | 2015-07-31 15:35:34 +0300 |
---|---|---|
committer | Dmitry Jemerov <yole@jetbrains.com> | 2015-10-29 13:21:47 +0100 |
commit | c9d59e9ae85f76e021d53c77ef18bfce0ff7ec7c (patch) | |
tree | d5e86994c762318008f7beaf781cdeafde573802 | |
parent | ff77b8e0ad0b5089e940227dfdd94ba21cfc6bd8 (diff) | |
download | dokka-c9d59e9ae85f76e021d53c77ef18bfce0ff7ec7c.tar.gz dokka-c9d59e9ae85f76e021d53c77ef18bfce0ff7ec7c.tar.bz2 dokka-c9d59e9ae85f76e021d53c77ef18bfce0ff7ec7c.zip |
Use Guice injector and ServiceLocator to load implementations on the fly
46 files changed, 416 insertions, 108 deletions
diff --git a/.idea/encodings.xml b/.idea/encodings.xml index e206d70d..f7589596 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> -</project> - + <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false"> + <file url="PROJECT" charset="UTF-8" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 00b45e99..01f55e26 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,6 +12,11 @@ </set> </option> <option name="useAutoImport" value="true" /> + <option name="myModules"> + <set> + <option value="$PROJECT_DIR$/dokka-fatjar" /> + </set> + </option> </GradleProjectSettings> <GradleProjectSettings> <option name="distributionType" value="DEFAULT_WRAPPED" /> @@ -22,6 +27,11 @@ </set> </option> <option name="useAutoImport" value="true" /> + <option name="myModules"> + <set> + <option value="$PROJECT_DIR$/gradle-plugin" /> + </set> + </option> </GradleProjectSettings> <GradleProjectSettings> <option name="distributionType" value="DEFAULT_WRAPPED" /> @@ -33,6 +43,11 @@ </set> </option> <option name="useAutoImport" value="true" /> + <option name="myModules"> + <set> + <option value="$PROJECT_DIR$/javadoc" /> + </set> + </option> </GradleProjectSettings> </option> </component> diff --git a/.idea/libraries/Gradle__org_fusesource_jansi_jansi_1_11.xml b/.idea/libraries/Gradle__org_fusesource_jansi_jansi_1_11.xml deleted file mode 100644 index 8c78e1dc..00000000 --- a/.idea/libraries/Gradle__org_fusesource_jansi_jansi_1_11.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<component name="libraryTable"> - <library name="Gradle: org.fusesource.jansi:jansi:1.11"> - <CLASSES> - <root url="jar://$MAVEN_REPOSITORY$/org/fusesource/jansi/jansi/1.11/jansi-1.11.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - </library> -</component>
\ No newline at end of file diff --git a/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_0_0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_1_0_0_beta_1038.xml index 1328f8e8..eee2b80d 100644 --- a/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_0_0_1_SNAPSHOT.xml +++ b/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_1_0_0_beta_1038.xml @@ -1,12 +1,11 @@ -<?xml version="1.0" encoding="UTF-8"?> <component name="libraryTable"> - <library name="Gradle: org.jetbrains.dokka:dokka-fatjar:0.0.1-SNAPSHOT"> + <library name="Gradle: org.jetbrains.dokka:dokka-fatjar:1.0.0-beta-1038"> <CLASSES> - <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/0.0.1-SNAPSHOT/dokka-fatjar-0.0.1-SNAPSHOT.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/1.0.0-beta-1038/dokka-fatjar-1.0.0-beta-1038.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES> - <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/0.0.1-SNAPSHOT/dokka-fatjar-0.0.1-SNAPSHOT-sources.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/1.0.0-beta-1038/dokka-fatjar-1.0.0-beta-1038-sources.jar!/" /> </SOURCES> </library> </component>
\ No newline at end of file diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml new file mode 100644 index 00000000..7269fee8 --- /dev/null +++ b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component name="libraryTable"> + <library name="Gradle: org.jetbrains.kotlin:kotlin-runtime:0.1-SNAPSHOT"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/0.1-SNAPSHOT/kotlin-runtime-0.1-SNAPSHOT.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/0.1-SNAPSHOT/kotlin-runtime-0.1-SNAPSHOT-sources.jar!/" /> + </SOURCES> + </library> +</component>
\ No newline at end of file diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml new file mode 100644 index 00000000..7ee2d16e --- /dev/null +++ b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component name="libraryTable"> + <library name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/0.1-SNAPSHOT/kotlin-stdlib-0.1-SNAPSHOT.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/0.1-SNAPSHOT/kotlin-stdlib-0.1-SNAPSHOT-sources.jar!/" /> + </SOURCES> + </library> +</component>
\ No newline at end of file diff --git a/.idea/libraries/com_google_inject_guice_4_0.xml b/.idea/libraries/com_google_inject_guice_4_0.xml new file mode 100644 index 00000000..99d2a5e4 --- /dev/null +++ b/.idea/libraries/com_google_inject_guice_4_0.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component name="libraryTable"> + <library name="com.google.inject:guice:4.0" type="repository"> + <properties maven-id="com.google.inject:guice:4.0" /> + <CLASSES> + <root url="jar://$PROJECT_DIR$/lib/guice-4.0.jar!/" /> + <root url="jar://$PROJECT_DIR$/lib/javax.inject-1.jar!/" /> + <root url="jar://$PROJECT_DIR$/lib/aopalliance-1.0.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> +</component>
\ No newline at end of file diff --git a/dokka-fatjar/dokka-fatjar.iml b/dokka-fatjar/dokka-fatjar.iml index dcf9d922..e8948bfb 100644 --- a/dokka-fatjar/dokka-fatjar.iml +++ b/dokka-fatjar/dokka-fatjar.iml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.id="dokka-fatjar" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="0.0.1-SNAPSHOT" type="JAVA_MODULE" version="4"> +<module external.linked.project.id="dokka-fatjar" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="1.0.0-beta-1038" type="JAVA_MODULE" version="4"> <component name="NewModuleRootManager" inherit-compiler-output="false"> <output url="file://$MODULE_DIR$/build/classes/main" /> <output-test url="file://$MODULE_DIR$/build/classes/test" /> @@ -24,6 +24,7 @@ <orderEntry type="library" name="protobuf" level="project" /> <orderEntry type="library" name="asm" level="project" /> <orderEntry type="library" name="jps-model" level="project" /> + <orderEntry type="library" name="com.google.inject:guice:4.0" level="project" /> <orderEntry type="library" name="jansi" level="project" /> </component> </module>
\ No newline at end of file diff --git a/gradle-plugin/dokka-gradle-plugin.iml b/gradle-plugin/dokka-gradle-plugin.iml index 3098979d..03f8028f 100644 --- a/gradle-plugin/dokka-gradle-plugin.iml +++ b/gradle-plugin/dokka-gradle-plugin.iml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.id="dokka-gradle-plugin" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="0.1-SNAPSHOT" type="JAVA_MODULE" version="4"> +<module external.linked.project.id="dokka-gradle-plugin" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="1.0.0-beta-1038" type="JAVA_MODULE" version="4"> <component name="NewModuleRootManager" inherit-compiler-output="false"> <output url="file://$MODULE_DIR$/build/classes/main" /> <output-test url="file://$MODULE_DIR$/build/classes/test" /> @@ -1466,7 +1466,6 @@ </SOURCES> </library> </orderEntry> - <orderEntry type="library" name="Gradle: org.jetbrains.dokka:dokka-fatjar:0.0.1-SNAPSHOT" level="project" /> - <orderEntry type="library" name="Gradle: org.fusesource.jansi:jansi:1.11" level="project" /> + <orderEntry type="library" name="Gradle: org.jetbrains.dokka:dokka-fatjar:1.0.0-beta-1038" level="project" /> </component> </module>
\ No newline at end of file diff --git a/javadoc/build.gradle b/javadoc/build.gradle index 5c1d464d..ac079b99 100644 --- a/javadoc/build.gradle +++ b/javadoc/build.gradle @@ -33,7 +33,7 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - compile "org.jetbrains.dokka:dokka-fatjar:(,0.2)" + compile "org.jetbrains.dokka:dokka-fatjar:(1.0,1.1)" compile files("${System.properties['java.home']}/../lib/tools.jar") compile gradleApi() diff --git a/javadoc/javadoc.iml b/javadoc/javadoc.iml index bc2537e7..e62f617f 100644 --- a/javadoc/javadoc.iml +++ b/javadoc/javadoc.iml @@ -16,8 +16,6 @@ </content> <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" /> <orderEntry type="sourceFolder" forTests="false" /> - <orderEntry type="library" name="Gradle: org.jetbrains.dokka:dokka-fatjar:0.0.1-SNAPSHOT" level="project" /> - <orderEntry type="library" name="Gradle: org.fusesource.jansi:jansi:1.11" level="project" /> <orderEntry type="module-library"> <library name="Gradle: gradle-core-2.5"> <CLASSES> @@ -1473,11 +1471,12 @@ <orderEntry type="module-library"> <library name="Gradle: tools"> <CLASSES> - <root url="jar:///usr/java/jdk1.8.0_51/lib/tools.jar!/" /> + <root url="jar:///Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/lib/tools.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES /> </library> </orderEntry> + <orderEntry type="library" name="Gradle: org.jetbrains.dokka:dokka-fatjar:1.0.0-beta-1038" level="project" /> </component> </module>
\ No newline at end of file diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index fe66a672..36371ad8 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -63,7 +63,7 @@ open class DocumentationNodeAdapter(val module: ModuleNodeAdapter, docNode: Docu }).toTypedArray() } -private val allClassKinds = setOf(DocumentationNode.Kind.Class, DocumentationNode.Kind.Enum, DocumentationNode.Kind.Interface, DocumentationNode.Kind.Object, DocumentationNode.Kind.Exception) +val allClassKinds = setOf(DocumentationNode.Kind.Class, DocumentationNode.Kind.Enum, DocumentationNode.Kind.Interface, DocumentationNode.Kind.Object, DocumentationNode.Kind.Exception) class PackageAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc { private val allClasses = node.members.filter { it.kind in allClassKinds }.toMap { it.name } @@ -472,7 +472,7 @@ fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) = .map { module.allTypes[it?.qualifiedName] } .filterNotNull() -class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { +class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { val allPackages = module.members(DocumentationNode.Kind.Package).toMap { it.name } val allTypes = module.members(DocumentationNode.Kind.Package) .flatMap { it.members(DocumentationNode.Kind.Class) + it.members(DocumentationNode.Kind.Interface) + it.members(DocumentationNode.Kind.Enum) } @@ -486,8 +486,10 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR .toTypedArray() override fun options(): Array<out Array<String>> = arrayOf( - arrayOf("-d", "out/javadoc"), - arrayOf("-docencoding", "UTF-8") + arrayOf("-d", outputPath), + arrayOf("-docencoding", "UTF-8"), + arrayOf("-charset", "UTF-8"), + arrayOf("-keywords") ) override fun specifiedPackages(): Array<out PackageDoc>? = module.members(DocumentationNode.Kind.Package).map { PackageAdapter(this, it) }.toTypedArray() diff --git a/javadoc/src/main/kotlin/dokka-adapters.kt b/javadoc/src/main/kotlin/dokka-adapters.kt new file mode 100644 index 00000000..c9183d50 --- /dev/null +++ b/javadoc/src/main/kotlin/dokka-adapters.kt @@ -0,0 +1,29 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.tools.doclets.formats.html.HtmlDoclet +import org.jetbrains.dokka.* +import org.jetbrains.dokka.Formats.FormatDescriptor + +class JavadocGenerator(val conf: DokkaGenerator) : Generator { + override fun buildPages(nodes: Iterable<DocumentationNode>) { + val module = nodes.single() as DocumentationModule + + DokkaConsoleLogger.report() + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter, conf.outputDir)) + } + + override fun buildOutlines(nodes: Iterable<DocumentationNode>) { + // no outline could be generated separately + } +} + +class JavadocFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class<out FormatService>? + get() = null + override val outlineServiceClass: Class<out OutlineFormatService>? + get() = null + + override val generatorServiceClass: Class<out Generator> + get() = javaClass<JavadocGenerator>() +} + diff --git a/javadoc/src/main/kotlin/main.kt b/javadoc/src/main/kotlin/main.kt deleted file mode 100644 index 0c3821c3..00000000 --- a/javadoc/src/main/kotlin/main.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.tools.doclets.formats.html.HtmlDoclet -import org.jetbrains.dokka.DocumentationOptions -import org.jetbrains.dokka.DokkaConsoleLogger -import org.jetbrains.dokka.DokkaGenerator -import org.jetbrains.dokka.buildDocumentationModule -import java.io.File - -/** - * Test me, my friend - */ -public fun main(args: Array<String>) { - val generator = DokkaGenerator(DokkaConsoleLogger, System.getProperty("java.class.path").split(File.pathSeparator), listOf(File("test").absolutePath), emptyList(), emptyList(), "me", "out/dokka", "html", emptyList(), false) - val env = generator.createAnalysisEnvironment() - val module = buildDocumentationModule(env, generator.moduleName, DocumentationOptions(includeNonPublic = true, sourceLinks = emptyList()), emptyList(), { - generator.isSample(it) - }, generator.logger) - - DokkaConsoleLogger.report() - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter)) -} - -public fun String.a(): Int = 1
\ No newline at end of file diff --git a/javadoc/src/main/kotlin/tags.kt b/javadoc/src/main/kotlin/tags.kt index 120154f9..6f0ebca0 100644 --- a/javadoc/src/main/kotlin/tags.kt +++ b/javadoc/src/main/kotlin/tags.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.javadoc import com.sun.javadoc.* import org.jetbrains.dokka.* -import java.util.ArrayList +import java.util.* class TextTag(val holder: Doc, val content: ContentText) : Tag { val plainText: String @@ -66,7 +66,7 @@ class SeeClassTagAdapter(holder: Doc, val clazz: ClassDocumentationNodeAdapter, override fun firstSentenceTags(): Array<out Tag> = inlineTags() // TODO } -class ParamTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val parameterName: String, val isTypeParameter: Boolean, val content: List<ContentNode>) : ParamTag { +class ParamTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val parameterName: String, val typeParameter: Boolean, val content: List<ContentNode>) : ParamTag { constructor(module: ModuleNodeAdapter, holder: Doc, parameterName: String, isTypeParameter: Boolean, content: ContentNode) : this(module, holder, parameterName, isTypeParameter, listOf(content)) override fun name(): String = "@param" @@ -78,7 +78,7 @@ class ParamTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val parame override fun inlineTags(): Array<out Tag> = content.flatMap { buildInlineTags(module, holder, it) }.toTypedArray() override fun firstSentenceTags(): Array<out Tag> = arrayOf(TextTag(holder, ContentText(text()))) - override fun isTypeParameter(): Boolean = isTypeParameter + override fun isTypeParameter(): Boolean = typeParameter override fun parameterComment(): String = content.toString() // TODO override fun parameterName(): String = parameterName } diff --git a/javadoc/src/main/resources/dokka/generator/javadoc.properties b/javadoc/src/main/resources/dokka/generator/javadoc.properties new file mode 100644 index 00000000..4075704f --- /dev/null +++ b/javadoc/src/main/resources/dokka/generator/javadoc.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.javadoc.JavadocGenerator +description=Produces output via JDK javadoc tool
\ No newline at end of file diff --git a/javadoc/src/main/resources/format/javadoc.properties b/javadoc/src/main/resources/format/javadoc.properties new file mode 100644 index 00000000..a58317fc --- /dev/null +++ b/javadoc/src/main/resources/format/javadoc.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.javadoc.JavadocFormatDescriptor
\ No newline at end of file diff --git a/lib/aopalliance-1.0.jar b/lib/aopalliance-1.0.jar Binary files differnew file mode 100644 index 00000000..578b1a0c --- /dev/null +++ b/lib/aopalliance-1.0.jar diff --git a/lib/guice-4.0.jar b/lib/guice-4.0.jar Binary files differnew file mode 100644 index 00000000..f4fc9ffd --- /dev/null +++ b/lib/guice-4.0.jar diff --git a/lib/javax.inject-1.jar b/lib/javax.inject-1.jar Binary files differnew file mode 100644 index 00000000..b2a9d0bf --- /dev/null +++ b/lib/javax.inject-1.jar diff --git a/resources/dokka/format/html.properties b/resources/dokka/format/html.properties new file mode 100644 index 00000000..7881dfae --- /dev/null +++ b/resources/dokka/format/html.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.HtmlFormatDescriptor +description=Produces output in HTML format
\ No newline at end of file diff --git a/resources/dokka/format/jekyll.properties b/resources/dokka/format/jekyll.properties new file mode 100644 index 00000000..b11401a4 --- /dev/null +++ b/resources/dokka/format/jekyll.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.JekyllFormatDescriptor +description=Produces documentation in Jekyll format
\ No newline at end of file diff --git a/resources/dokka/format/kotlin-website.properties b/resources/dokka/format/kotlin-website.properties new file mode 100644 index 00000000..c13e7675 --- /dev/null +++ b/resources/dokka/format/kotlin-website.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.KotlinWebsiteFormatDescriptor +description=Generates Kotlin website documentation
\ No newline at end of file diff --git a/resources/dokka/format/markdown.properties b/resources/dokka/format/markdown.properties new file mode 100644 index 00000000..6217a6df --- /dev/null +++ b/resources/dokka/format/markdown.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.MarkdownFormatDescriptor +description=Produces documentation in markdown format
\ No newline at end of file diff --git a/resources/dokka/generator/default.properties b/resources/dokka/generator/default.properties new file mode 100644 index 00000000..a4a16200 --- /dev/null +++ b/resources/dokka/generator/default.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.FileGenerator +description=Default documentation generator
\ No newline at end of file diff --git a/resources/dokka/language/java.properties b/resources/dokka/language/java.properties new file mode 100644 index 00000000..ab42f532 --- /dev/null +++ b/resources/dokka/language/java.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.JavaLanguageService
\ No newline at end of file diff --git a/resources/dokka/language/kotlin.properties b/resources/dokka/language/kotlin.properties new file mode 100644 index 00000000..16092007 --- /dev/null +++ b/resources/dokka/language/kotlin.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.KotlinLanguageService
\ No newline at end of file diff --git a/resources/dokka/outline/yaml.properties b/resources/dokka/outline/yaml.properties new file mode 100644 index 00000000..7268af37 --- /dev/null +++ b/resources/dokka/outline/yaml.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.YamlOutlineService
\ No newline at end of file diff --git a/src/Formats/FormatDescriptor.kt b/src/Formats/FormatDescriptor.kt new file mode 100644 index 00000000..beff730f --- /dev/null +++ b/src/Formats/FormatDescriptor.kt @@ -0,0 +1,11 @@ +package org.jetbrains.dokka.Formats + +import org.jetbrains.dokka.FormatService +import org.jetbrains.dokka.Generator +import org.jetbrains.dokka.OutlineFormatService + +public interface FormatDescriptor { + val formatServiceClass: Class<out FormatService>? + val outlineServiceClass: Class<out OutlineFormatService>? + val generatorServiceClass: Class<out Generator> +}
\ No newline at end of file diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt index 8e38a32c..e810ef7f 100644 --- a/src/Formats/HtmlFormatService.kt +++ b/src/Formats/HtmlFormatService.kt @@ -1,10 +1,12 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File -public open class HtmlFormatService(locationService: LocationService, +public open class HtmlFormatService @Inject constructor(@Named("folders") locationService: LocationService, signatureGenerator: LanguageService, - val templateService: HtmlTemplateService = HtmlTemplateService.default()) + val templateService: HtmlTemplateService) : StructuredFormatService(locationService, signatureGenerator, "html"), OutlineFormatService { override public fun formatText(text: String): String { return text.htmlEscape() diff --git a/src/Formats/JekyllFormatService.kt b/src/Formats/JekyllFormatService.kt index 98958293..75684ac2 100644 --- a/src/Formats/JekyllFormatService.kt +++ b/src/Formats/JekyllFormatService.kt @@ -1,6 +1,8 @@ package org.jetbrains.dokka -public open class JekyllFormatService(locationService: LocationService, +import com.google.inject.Inject + +public open class JekyllFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : MarkdownFormatService(locationService, signatureGenerator) { diff --git a/src/Formats/KotlinWebsiteFormatService.kt b/src/Formats/KotlinWebsiteFormatService.kt index 71eb7753..25491cb3 100644 --- a/src/Formats/KotlinWebsiteFormatService.kt +++ b/src/Formats/KotlinWebsiteFormatService.kt @@ -1,6 +1,8 @@ package org.jetbrains.dokka -public class KotlinWebsiteFormatService(locationService: LocationService, +import com.google.inject.Inject + +public class KotlinWebsiteFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : JekyllFormatService(locationService, signatureGenerator) { private var needHardLineBreaks = false diff --git a/src/Formats/MarkdownFormatService.kt b/src/Formats/MarkdownFormatService.kt index ba7d8f7b..29a9f5c4 100644 --- a/src/Formats/MarkdownFormatService.kt +++ b/src/Formats/MarkdownFormatService.kt @@ -1,7 +1,9 @@ package org.jetbrains.dokka +import com.google.inject.Inject -public open class MarkdownFormatService(locationService: LocationService, + +public open class MarkdownFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : StructuredFormatService(locationService, signatureGenerator, "md") { override public fun formatBreadcrumbs(items: Iterable<FormatLink>): String { diff --git a/src/Formats/StandardFormats.kt b/src/Formats/StandardFormats.kt new file mode 100644 index 00000000..1d5ffe13 --- /dev/null +++ b/src/Formats/StandardFormats.kt @@ -0,0 +1,47 @@ +package org.jetbrains.dokka.Formats + +import org.jetbrains.dokka.* + +class HtmlFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class<out FormatService> + get() = javaClass<HtmlFormatService>() + + override val outlineServiceClass: Class<out OutlineFormatService> + get() = javaClass<HtmlFormatService>() + + override val generatorServiceClass: Class<out Generator> + get() = javaClass<FileGenerator>() +} + +class KotlinWebsiteFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class<out FormatService> + get() = javaClass<KotlinWebsiteFormatService>() + + override val outlineServiceClass: Class<out OutlineFormatService> + get() = javaClass<YamlOutlineService>() + + override val generatorServiceClass: Class<out Generator> + get() = javaClass<FileGenerator>() +} + +class JekyllFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class<out FormatService> + get() = javaClass<JekyllFormatService>() + + override val outlineServiceClass: Class<out OutlineFormatService>? + get() = null + + override val generatorServiceClass: Class<out Generator> + get() = javaClass<FileGenerator>() +} + +class MarkdownFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class<out FormatService> + get() = javaClass<MarkdownFormatService>() + + override val outlineServiceClass: Class<out OutlineFormatService>? + get() = null + + override val generatorServiceClass: Class<out Generator> + get() = javaClass<FileGenerator>() +} diff --git a/src/Formats/YamlOutlineService.kt b/src/Formats/YamlOutlineService.kt index cdab4eeb..7968824c 100644 --- a/src/Formats/YamlOutlineService.kt +++ b/src/Formats/YamlOutlineService.kt @@ -1,8 +1,9 @@ package org.jetbrains.dokka +import com.google.inject.Inject import java.io.File -class YamlOutlineService(val locationService: LocationService, +class YamlOutlineService @Inject constructor(val locationService: LocationService, val languageService: LanguageService) : OutlineFormatService { override fun getOutlineFileName(location: Location): File = File("${location.path}.yml") diff --git a/src/Generation/FileGenerator.kt b/src/Generation/FileGenerator.kt index 40645b51..08a885ab 100644 --- a/src/Generation/FileGenerator.kt +++ b/src/Generation/FileGenerator.kt @@ -1,36 +1,41 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import java.io.File import java.io.FileOutputStream +import java.io.IOException import java.io.OutputStreamWriter -public class FileGenerator(val signatureGenerator: LanguageService, - val locationService: FileLocationService, +public class FileGenerator @Inject constructor(val locationService: FileLocationService, val formatService: FormatService, - val outlineService: OutlineFormatService?) { + @Inject(optional = true) val outlineService: OutlineFormatService?) : Generator { - public fun buildPage(node: DocumentationNode): Unit = buildPages(listOf(node)) - public fun buildOutline(node: DocumentationNode): Unit = buildOutlines(listOf(node)) + override fun buildPages(nodes: Iterable<DocumentationNode>) { + val specificLocationService = locationService.withExtension(formatService.extension) - public fun buildPages(nodes: Iterable<DocumentationNode>) { - for ((location, items) in nodes.groupBy { locationService.location(it) }) { + for ((location, items) in nodes.groupBy { specificLocationService.location(it) }) { val file = location.file - file.parentFile?.mkdirs() - FileOutputStream(file).use { - OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(formatService.format(location, items)) + file.parentFile?.mkdirsOrFail() + try { + FileOutputStream(file).use { + OutputStreamWriter(it, Charsets.UTF_8).use { + it.write(formatService.format(location, items)) + } } + } catch (e: Throwable) { + println(e) } buildPages(items.flatMap { it.members }) } } - public fun buildOutlines(nodes: Iterable<DocumentationNode>) { + override fun buildOutlines(nodes: Iterable<DocumentationNode>) { if (outlineService == null) { return } for ((location, items) in nodes.groupBy { locationService.location(it) }) { val file = outlineService.getOutlineFileName(location) - file.parentFile?.mkdirs() + file.parentFile?.mkdirsOrFail() FileOutputStream(file).use { OutputStreamWriter(it, Charsets.UTF_8).use { it.write(outlineService.formatOutline(location, items)) @@ -38,4 +43,10 @@ public class FileGenerator(val signatureGenerator: LanguageService, } } } +} + +private fun File.mkdirsOrFail() { + if (!mkdirs() && !exists()) { + throw IOException("Failed to create directory $this") + } }
\ No newline at end of file diff --git a/src/Generation/Generator.kt b/src/Generation/Generator.kt new file mode 100644 index 00000000..7dcabb0b --- /dev/null +++ b/src/Generation/Generator.kt @@ -0,0 +1,15 @@ +package org.jetbrains.dokka + +public interface Generator { + fun buildPages(nodes: Iterable<DocumentationNode>) + fun buildOutlines(nodes: Iterable<DocumentationNode>) + + final fun buildAll(nodes: Iterable<DocumentationNode>) { + buildPages(nodes) + buildOutlines(nodes) + } + + final fun buildPage(node: DocumentationNode): Unit = buildPages(listOf(node)) + final fun buildOutline(node: DocumentationNode): Unit = buildOutlines(listOf(node)) + final fun buildAll(node: DocumentationNode): Unit = buildAll(listOf(node)) +} diff --git a/src/Locations/FoldersLocationService.kt b/src/Locations/FoldersLocationService.kt index e85c2c98..8a0cf6be 100644 --- a/src/Locations/FoldersLocationService.kt +++ b/src/Locations/FoldersLocationService.kt @@ -1,9 +1,12 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File public fun FoldersLocationService(root: String): FoldersLocationService = FoldersLocationService(File(root), "") -public class FoldersLocationService(val root: File, val extension: String) : FileLocationService { +public class FoldersLocationService @Inject constructor(@Named("outputDir") val root: File, val extension: String) : FileLocationService { + override fun withExtension(newExtension: String): FileLocationService { return if (extension.isEmpty()) FoldersLocationService(root, newExtension) else this } diff --git a/src/Locations/LocationService.kt b/src/Locations/LocationService.kt index a43054ce..4f587361 100644 --- a/src/Locations/LocationService.kt +++ b/src/Locations/LocationService.kt @@ -55,6 +55,8 @@ public interface LocationService { public interface FileLocationService: LocationService { + override fun withExtension(newExtension: String): FileLocationService = this + override fun location(node: DocumentationNode): FileLocation = location(node.path.map { it.name }, node.members.any()) override fun location(qualifiedName: List<String>, hasMembers: Boolean): FileLocation } diff --git a/src/Locations/SingleFolderLocationService.kt b/src/Locations/SingleFolderLocationService.kt index c26d2b34..049636c0 100644 --- a/src/Locations/SingleFolderLocationService.kt +++ b/src/Locations/SingleFolderLocationService.kt @@ -1,10 +1,12 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File public fun SingleFolderLocationService(root: String): SingleFolderLocationService = SingleFolderLocationService(File(root), "") -public class SingleFolderLocationService(val root: File, val extension: String) : FileLocationService { - override fun withExtension(newExtension: String): LocationService = +public class SingleFolderLocationService @Inject constructor(@Named("outputDir") val root: File, val extension: String) : FileLocationService { + override fun withExtension(newExtension: String): FileLocationService = SingleFolderLocationService(root, newExtension) override fun location(qualifiedName: List<String>, hasMembers: Boolean): FileLocation { diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt index 34181b6a..468cb878 100644 --- a/src/Model/DocumentationNode.kt +++ b/src/Model/DocumentationNode.kt @@ -143,7 +143,6 @@ fun DocumentationNode.findOrCreatePackageNode(packageName: String, packageConten fun DocumentationNode.append(child: DocumentationNode, kind: DocumentationReference.Kind) { addReferenceTo(child, kind) - @suppress("NON_EXHAUSTIVE_WHEN") when (kind) { DocumentationReference.Kind.Detail -> child.addReferenceTo(this, DocumentationReference.Kind.Owner) DocumentationReference.Kind.Member -> child.addReferenceTo(this, DocumentationReference.Kind.Owner) diff --git a/src/Utilities/GuiceModule.kt b/src/Utilities/GuiceModule.kt new file mode 100644 index 00000000..57bad468 --- /dev/null +++ b/src/Utilities/GuiceModule.kt @@ -0,0 +1,58 @@ +package org.jetbrains.dokka.Utilities + +import com.google.inject.Binder +import com.google.inject.Module +import com.google.inject.Provider +import com.google.inject.name.Names +import org.jetbrains.dokka.* +import org.jetbrains.dokka.Formats.FormatDescriptor +import java.io.File + +class GuiceModule(val config: DokkaGenerator) : Module { + override fun configure(binder: Binder) { + binder.bind(javaClass<DokkaGenerator>()).toInstance(config) + binder.bind(javaClass<File>()).annotatedWith(Names.named("outputDir")).toInstance(File(config.outputDir)) + + binder.bindNameAnnotated<LocationService, SingleFolderLocationService>("singleFolder") + binder.bindNameAnnotated<FileLocationService, SingleFolderLocationService>("singleFolder") + binder.bindNameAnnotated<LocationService, FoldersLocationService>("folders") + binder.bindNameAnnotated<FileLocationService, FoldersLocationService>("folders") + + // defaults + binder.bind(javaClass<LocationService>()).to(javaClass<FoldersLocationService>()) + binder.bind(javaClass<FileLocationService>()).to(javaClass<FoldersLocationService>()) + binder.bind(javaClass<LanguageService>()).to(javaClass<KotlinLanguageService>()) + + binder.bind(javaClass<HtmlTemplateService>()).toProvider(object : Provider<HtmlTemplateService> { + override fun get(): HtmlTemplateService = HtmlTemplateService.default("/dokka/styles/style.css") + }) + + binder.registerCategory<LanguageService>("language") + binder.registerCategory<OutlineFormatService>("outline") + binder.registerCategory<FormatService>("format") + binder.registerCategory<Generator>("generator") + + val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", config.outputFormat, config) + + descriptor.outlineServiceClass?.let { clazz -> + binder.bind(javaClass<OutlineFormatService>()).to(clazz) + } + descriptor.formatServiceClass?.let { clazz -> + binder.bind(javaClass<FormatService>()).to(clazz) + } + binder.bind(javaClass<Generator>()).to(descriptor.generatorServiceClass) + } + +} + +private inline fun <reified T: Any> Binder.registerCategory(category: String) { + ServiceLocator.allServices(category).forEach { + @Suppress("UNCHECKED_CAST") + bind(javaClass<T>()).annotatedWith(Names.named(it.name)).to(javaClass<T>().classLoader.loadClass(it.className) as Class<T>) + } +} + +private inline fun <reified Base : Any, reified T : Base> Binder.bindNameAnnotated(name: String) { + bind(javaClass<Base>()).annotatedWith(Names.named(name)).to(javaClass<T>()) +} + diff --git a/src/Utilities/ServiceLocator.kt b/src/Utilities/ServiceLocator.kt new file mode 100644 index 00000000..bc04238f --- /dev/null +++ b/src/Utilities/ServiceLocator.kt @@ -0,0 +1,105 @@ +package org.jetbrains.dokka.Utilities + +import org.jetbrains.dokka.DokkaGenerator +import java.io.File +import java.util.* +import java.util.jar.JarFile +import java.util.zip.ZipEntry + +data class ServiceDescriptor(val name: String, val category: String, val description: String?, val className: String) + +class ServiceLookupException(message: String) : Exception(message) + +public object ServiceLocator { + public fun <T : Any> lookup(clazz: Class<T>, category: String, implementationName: String, conf: DokkaGenerator): T { + val descriptor = lookupDescriptor(category, implementationName) + val loadedClass = javaClass.classLoader.loadClass(descriptor.className) + val constructor = loadedClass.constructors + .filter { it.parameterTypes.isEmpty() || (it.parameterTypes.size() == 1 && conf.javaClass.isInstance(it.parameterTypes[0])) } + .sortedByDescending { it.parameterTypes.size() } + .firstOrNull() ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor") + + val implementationRawType: Any = if (constructor.parameterTypes.isEmpty()) constructor.newInstance() else constructor.newInstance(constructor) + + if (!clazz.isInstance(implementationRawType)) { + throw ServiceLookupException("Class ${descriptor.className} is not a subtype of ${clazz.name}") + } + + @Suppress("UNCHECKED_CAST") + return implementationRawType as T + } + + public fun <T> lookupClass(clazz: Class<T>, category: String, implementationName: String): Class<T> = lookupDescriptor(category, implementationName).className.let { className -> + javaClass.classLoader.loadClass(className).let { loaded -> + if (!clazz.isAssignableFrom(loaded)) { + throw ServiceLookupException("Class $className is not a subtype of ${clazz.name}") + } + + @Suppress("UNCHECKED_CAST") + val casted = loaded as Class<T> + + casted + } + } + + private fun lookupDescriptor(category: String, implementationName: String): ServiceDescriptor { + val properties = javaClass.classLoader.getResourceAsStream("dokka/$category/$implementationName.properties")?.use { stream -> + Properties().let { properties -> + properties.load(stream) + properties + } + } ?: throw ServiceLookupException("No implementation with name $implementationName found in category $category") + + val className = properties["class"]?.toString() ?: throw ServiceLookupException("Implementation $implementationName has no class configured") + + return ServiceDescriptor(implementationName, category, properties["description"]?.toString(), className) + } + + fun allServices(category: String): List<ServiceDescriptor> = javaClass.classLoader.getResourceAsStream("dokka/$category")?.use { stream -> + val entries = this.javaClass.classLoader.getResources("dokka/$category")?.toList() ?: emptyList() + + entries.flatMap { + when (it.protocol) { + "file" -> File(it.file).listFiles()?.filter { it.extension == "properties" }?.map { lookupDescriptor(category, it.nameWithoutExtension) } ?: emptyList() + "jar" -> { + val file = JarFile(it.file.removePrefix("file:").substringBefore("!")) + try { + val jarPath = it.file.substringAfterLast("!").removePrefix("/") + file.entries() + .asSequence() + .filter { entry -> !entry.isDirectory && entry.path == jarPath && entry.extension == "properties" } + .map { entry -> + lookupDescriptor(category, entry.fileName.substringBeforeLast(".")) + }.toList() + } finally { + file.close() + } + } + else -> emptyList<ServiceDescriptor>() + } + } + } ?: emptyList() +} + +public inline fun <reified T : Any> ServiceLocator.lookup(category: String, implementationName: String, conf: DokkaGenerator): T = lookup(javaClass<T>(), category, implementationName, conf) +public inline fun <reified T : Any> ServiceLocator.lookupClass(category: String, implementationName: String): Class<T> = lookupClass(javaClass<T>(), category, implementationName) +public inline fun <reified T : Any> ServiceLocator.lookupOrNull(category: String, implementationName: String, conf: DokkaGenerator): T? = try { + lookup(javaClass<T>(), category, implementationName, conf) +} catch (any: Throwable) { + null +} + +fun main(args: Array<String>) { + ServiceLocator.allServices("format").forEach { + println(it) + } +} + +private val ZipEntry.fileName: String + get() = name.substringAfterLast("/", name) + +private val ZipEntry.path: String + get() = name.substringBeforeLast("/", "").removePrefix("/") + +private val ZipEntry.extension: String? + get() = fileName.let { fn -> if ("." in fn) fn.substringAfterLast(".") else null } diff --git a/src/main.kt b/src/main.kt index e7c11fac..a534ffdd 100644 --- a/src/main.kt +++ b/src/main.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import com.google.inject.Guice import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile @@ -7,6 +8,7 @@ import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import com.sampullara.cli.Args import com.sampullara.cli.Argument +import org.jetbrains.dokka.Utilities.GuiceModule import org.jetbrains.kotlin.cli.common.arguments.ValueDescription import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -17,6 +19,7 @@ import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.utils.PathUtil import java.io.File +import kotlin.util.measureTimeMillis class DokkaArguments { @set:Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)") @@ -141,9 +144,9 @@ class DokkaGenerator(val logger: DokkaLogger, fun generate() { val environment = createAnalysisEnvironment() - logger.info("Module: ${moduleName}") + logger.info("Module: $moduleName") logger.info("Output: ${File(outputDir).absolutePath}") - logger.info("Sources: ${environment.sources.joinToString()}") + logger.info("Sources: ${environment.sources.join()}") logger.info("Classpath: ${environment.classpath.joinToString()}") logger.info("Analysing sources and libraries... ") @@ -155,34 +158,12 @@ class DokkaGenerator(val logger: DokkaLogger, val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") - val startBuild = System.currentTimeMillis() - val signatureGenerator = KotlinLanguageService() - val locationService = FoldersLocationService(outputDir) - val templateService = HtmlTemplateService.default("/dokka/styles/style.css") - - val (formatter, outlineFormatter) = when (outputFormat) { - "html" -> { - val htmlFormatService = HtmlFormatService(locationService, signatureGenerator, templateService) - htmlFormatService to htmlFormatService - } - "markdown" -> MarkdownFormatService(locationService, signatureGenerator) to null - "jekyll" -> JekyllFormatService(locationService.withExtension("html"), signatureGenerator) to null - "kotlin-website" -> KotlinWebsiteFormatService(locationService.withExtension("html"), signatureGenerator) to - YamlOutlineService(locationService, signatureGenerator) - else -> { - logger.error("Unrecognized output format ${outputFormat}") - null to null - } + val timeBuild = measureTimeMillis { + logger.info("Generating pages... ") + Guice.createInjector(GuiceModule(this)).getInstance(javaClass<Generator>()).buildAll(documentation) } - if (formatter == null) return - - val generator = FileGenerator(signatureGenerator, locationService.withExtension(formatter.extension), - formatter, outlineFormatter) - logger.info("Generating pages... ") - generator.buildPage(documentation) - generator.buildOutline(documentation) - val timeBuild = System.currentTimeMillis() - startBuild logger.info("done in ${timeBuild / 1000} secs") + Disposer.dispose(environment) } diff --git a/test/src/format/HtmlFormatTest.kt b/test/src/format/HtmlFormatTest.kt index 2f450d0d..66fd0fee 100644 --- a/test/src/format/HtmlFormatTest.kt +++ b/test/src/format/HtmlFormatTest.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.HtmlFormatService +import org.jetbrains.dokka.HtmlTemplateService import org.jetbrains.dokka.KotlinLanguageService import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.KotlinSourceRoot @@ -8,7 +9,7 @@ import org.junit.Test import java.io.File public class HtmlFormatTest { - private val htmlService = HtmlFormatService(InMemoryLocationService, KotlinLanguageService()) + private val htmlService = HtmlFormatService(InMemoryLocationService, KotlinLanguageService(), HtmlTemplateService.default()) @Test fun classWithCompanionObject() { verifyOutput("test/data/format/classWithCompanionObject.kt", ".html") { model, output -> |