aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Jemerov <yole@jetbrains.com>2015-10-30 18:43:48 +0100
committerDmitry Jemerov <yole@jetbrains.com>2015-10-30 18:43:48 +0100
commite4b2ae90bf0e84f76ceb7c56b7c128d28adad917 (patch)
treeb1e7d86b808b41909679d44da8ac97bec1928c44
parent17492c5f48c459dd44eafb0e747c1164193ca7f7 (diff)
downloaddokka-e4b2ae90bf0e84f76ceb7c56b7c128d28adad917.tar.gz
dokka-e4b2ae90bf0e84f76ceb7c56b7c128d28adad917.tar.bz2
dokka-e4b2ae90bf0e84f76ceb7c56b7c128d28adad917.zip
initial support for generating javadoc from Kotlin light classes
-rw-r--r--javadoc/src/main/kotlin/docbase.kt15
-rw-r--r--javadoc/src/main/kotlin/dokka-adapters.kt9
-rw-r--r--src/Formats/FormatDescriptor.kt4
-rw-r--r--src/Formats/StandardFormats.kt12
-rw-r--r--src/Generation/FileGenerator.kt4
-rw-r--r--src/Java/JavaDocumentationBuilder.kt10
-rw-r--r--src/Kotlin/DocumentationBuilder.kt145
-rw-r--r--src/Kotlin/KotlinAsJavaDocumentationBuilder.kt27
-rw-r--r--src/Utilities/GuiceModule.kt7
-rw-r--r--src/main.kt24
-rw-r--r--test/src/TestAPI.kt12
-rw-r--r--test/src/model/KotlinAsJavaTest.kt32
12 files changed, 221 insertions, 80 deletions
diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt
index 9cb0148d..06bbaa58 100644
--- a/javadoc/src/main/kotlin/docbase.kt
+++ b/javadoc/src/main/kotlin/docbase.kt
@@ -15,7 +15,7 @@ private interface HasDocumentationNode {
}
open class DocumentationNodeBareAdapter(override val node: DocumentationNode) : Doc, HasDocumentationNode {
- private var rawCommentText_ = rawCommentText
+ private var rawCommentText_: String? = null
override fun name(): String = node.name
override fun position(): SourcePosition? = SourcePositionAdapter(node)
@@ -31,7 +31,7 @@ open class DocumentationNodeBareAdapter(override val node: DocumentationNode) :
rawCommentText_ = rawDocumentation ?: ""
}
- override fun getRawCommentText(): String = rawCommentText_
+ override fun getRawCommentText(): String = rawCommentText_ ?: ""
override fun isError(): Boolean = false
override fun isException(): Boolean = node.kind == DocumentationNode.Kind.Exception
@@ -357,7 +357,14 @@ class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : Documen
override fun isVolatile(): Boolean = node.hasAnnotation(Volatile::class)
}
-open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode) : DocumentationNodeAdapter(module, classNode), Type by TypeAdapter(module, classNode), ProgramElementDoc by ProgramElementAdapter(module, classNode), ClassDoc {
+open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode, val name: String = classNode.name)
+ : DocumentationNodeAdapter(module, classNode),
+ Type by TypeAdapter(module, classNode),
+ ProgramElementDoc by ProgramElementAdapter(module, classNode),
+ ClassDoc {
+
+ override fun name(): String = name
+
override fun constructors(filter: Boolean): Array<out ConstructorDoc> = classNode.members(DocumentationNode.Kind.Constructor).map { ConstructorAdapter(module, it) }.toTypedArray()
override fun constructors(): Array<out ConstructorDoc> = constructors(true)
override fun importedPackages(): Array<out PackageDoc> = emptyArray()
@@ -419,7 +426,7 @@ open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNod
return false
}
- override fun innerClasses(): Array<out ClassDoc> = classNode.members(DocumentationNode.Kind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray()
+ override fun innerClasses(): Array<out ClassDoc> = classNode.members(DocumentationNode.Kind.Class).map { ClassDocumentationNodeAdapter(module, it, name + "." + it.name) }.toTypedArray()
override fun innerClasses(filter: Boolean): Array<out ClassDoc> = innerClasses()
}
diff --git a/javadoc/src/main/kotlin/dokka-adapters.kt b/javadoc/src/main/kotlin/dokka-adapters.kt
index 0f7c53d7..a863faf7 100644
--- a/javadoc/src/main/kotlin/dokka-adapters.kt
+++ b/javadoc/src/main/kotlin/dokka-adapters.kt
@@ -1,10 +1,11 @@
package org.jetbrains.dokka.javadoc
+import com.google.inject.Inject
import com.sun.tools.doclets.formats.html.HtmlDoclet
import org.jetbrains.dokka.*
import org.jetbrains.dokka.Formats.FormatDescriptor
-class JavadocGenerator(val conf: DokkaGenerator) : Generator {
+class JavadocGenerator @Inject constructor (val conf: DokkaGenerator) : Generator {
override fun buildPages(nodes: Iterable<DocumentationNode>) {
val module = nodes.single() as DocumentationModule
@@ -24,6 +25,8 @@ class JavadocFormatDescriptor : FormatDescriptor {
get() = null
override val generatorServiceClass: Class<out Generator>
- get() = javaClass<JavadocGenerator>()
-}
+ get() = JavadocGenerator::class.java
+ override val packageDocumentationBuilderServiceClass: Class<out PackageDocumentationBuilder>?
+ get() = KotlinAsJavaDocumentationBuilder::class.java
+}
diff --git a/src/Formats/FormatDescriptor.kt b/src/Formats/FormatDescriptor.kt
index beff730f..cc12dfb9 100644
--- a/src/Formats/FormatDescriptor.kt
+++ b/src/Formats/FormatDescriptor.kt
@@ -3,9 +3,11 @@ package org.jetbrains.dokka.Formats
import org.jetbrains.dokka.FormatService
import org.jetbrains.dokka.Generator
import org.jetbrains.dokka.OutlineFormatService
+import org.jetbrains.dokka.PackageDocumentationBuilder
public interface FormatDescriptor {
val formatServiceClass: Class<out FormatService>?
val outlineServiceClass: Class<out OutlineFormatService>?
val generatorServiceClass: Class<out Generator>
-} \ No newline at end of file
+ val packageDocumentationBuilderServiceClass: Class<out PackageDocumentationBuilder>?
+}
diff --git a/src/Formats/StandardFormats.kt b/src/Formats/StandardFormats.kt
index 658735c0..12b5d85d 100644
--- a/src/Formats/StandardFormats.kt
+++ b/src/Formats/StandardFormats.kt
@@ -11,6 +11,9 @@ class HtmlFormatDescriptor : FormatDescriptor {
override val generatorServiceClass: Class<out Generator>
get() = FileGenerator::class.java
+
+ override val packageDocumentationBuilderServiceClass: Class<out PackageDocumentationBuilder>?
+ get() = null
}
class KotlinWebsiteFormatDescriptor : FormatDescriptor {
@@ -22,6 +25,9 @@ class KotlinWebsiteFormatDescriptor : FormatDescriptor {
override val generatorServiceClass: Class<out Generator>
get() = FileGenerator::class.java
+
+ override val packageDocumentationBuilderServiceClass: Class<out PackageDocumentationBuilder>?
+ get() = null
}
class JekyllFormatDescriptor : FormatDescriptor {
@@ -33,6 +39,9 @@ class JekyllFormatDescriptor : FormatDescriptor {
override val generatorServiceClass: Class<out Generator>
get() = FileGenerator::class.java
+
+ override val packageDocumentationBuilderServiceClass: Class<out PackageDocumentationBuilder>?
+ get() = null
}
class MarkdownFormatDescriptor : FormatDescriptor {
@@ -44,4 +53,7 @@ class MarkdownFormatDescriptor : FormatDescriptor {
override val generatorServiceClass: Class<out Generator>
get() = FileGenerator::class.java
+
+ override val packageDocumentationBuilderServiceClass: Class<out PackageDocumentationBuilder>?
+ get() = null
}
diff --git a/src/Generation/FileGenerator.kt b/src/Generation/FileGenerator.kt
index c4025088..810038fa 100644
--- a/src/Generation/FileGenerator.kt
+++ b/src/Generation/FileGenerator.kt
@@ -6,10 +6,10 @@ import java.io.FileOutputStream
import java.io.IOException
import java.io.OutputStreamWriter
-public class FileGenerator @Inject constructor(val locationService: FileLocationService,
- val formatService: FormatService) : Generator {
+public class FileGenerator @Inject constructor(val locationService: FileLocationService) : Generator {
@set:Inject(optional = true) var outlineService: OutlineFormatService? = null
+ @set:Inject(optional = true) lateinit var formatService: FormatService
override fun buildPages(nodes: Iterable<DocumentationNode>) {
val specificLocationService = locationService.withExtension(formatService.extension)
diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaDocumentationBuilder.kt
index f3cedc07..660ac4a8 100644
--- a/src/Java/JavaDocumentationBuilder.kt
+++ b/src/Java/JavaDocumentationBuilder.kt
@@ -15,7 +15,11 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions,
return
}
val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap())
- packageNode.appendChildren(file.classes) { build() }
+ appendClasses(packageNode, file.classes)
+ }
+
+ fun appendClasses(packageNode: DocumentationNode, classes: Array<PsiClass>) {
+ packageNode.appendChildren(classes) { build() }
}
data class JavadocParseResult(val content: Content, val deprecatedContent: Content?)
@@ -47,9 +51,9 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions,
private fun PsiDocTag.contentElements(): Iterable<PsiElement> {
val tagValueElements = children
- .dropWhile { it.node.elementType == JavaDocTokenType.DOC_TAG_NAME }
+ .dropWhile { it.node?.elementType == JavaDocTokenType.DOC_TAG_NAME }
.dropWhile { it is PsiWhiteSpace }
- .filterNot { it.node.elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS }
+ .filterNot { it.node?.elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS }
return if (getSubjectName() != null) tagValueElements.dropWhile { it is PsiDocTagValue } else tagValueElements
}
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt
index 2d3105ac..375ca4bd 100644
--- a/src/Kotlin/DocumentationBuilder.kt
+++ b/src/Kotlin/DocumentationBuilder.kt
@@ -1,5 +1,6 @@
package org.jetbrains.dokka
+import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.dokka.DocumentationNode.Kind
@@ -43,6 +44,14 @@ private fun isSamePackage(descriptor1: DeclarationDescriptor, descriptor2: Decla
return package1 != null && package2 != null && package1.fqName == package2.fqName
}
+interface PackageDocumentationBuilder {
+ fun buildPackageDocumentation(project: Project,
+ packageName: FqName,
+ packageNode: DocumentationNode,
+ declarations: List<DeclarationDescriptor>,
+ options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger)
+}
+
class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
val session: ResolveSession,
val options: DocumentationOptions,
@@ -124,10 +133,6 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
return null
}
- fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any {
- DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated"
- } || (this is ConstructorDescriptor && containingDeclaration.isDeprecated())
-
fun DeclarationDescriptor.signature(): String = when(this) {
is ClassDescriptor, is PackageFragmentDescriptor -> DescriptorUtils.getFqName(this).asString()
is PropertyDescriptor -> containingDeclaration.signature() + "#" + name + receiverSignature()
@@ -353,17 +358,6 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
}
}
- private fun AnnotationDescriptor.isDocumented(): Boolean {
- if (source.getPsi() != null && mustBeDocumented()) return true
- val annotationClassName = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
- return annotationClassName == "kotlin.Extension"
- }
-
- fun AnnotationDescriptor.mustBeDocumented(): Boolean {
- val annotationClass = type.constructor.declarationDescriptor as? Annotated ?: return false
- return annotationClass.isDocumentedAnnotation()
- }
-
fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) {
val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return
KtTokens.MODIFIER_KEYWORDS_ARRAY.filter { it !in knownModifiers }.forEach {
@@ -400,12 +394,6 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
(!options.skipDeprecated || !isDeprecated())
}
- fun DeclarationDescriptor.isDocumentationSuppressed(): Boolean {
- val doc = KDocFinder.findKDoc(this)
- return doc is KDocSection && doc.findTagByName("suppress") != null
- }
-
-
fun DocumentationNode.appendMembers(descriptors: Iterable<DeclarationDescriptor>) {
descriptors.forEach { descriptor ->
if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
@@ -427,40 +415,18 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
}
}
- fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor,
- externalClassNodes: MutableMap<FqName, DocumentationNode>): DocumentationNode {
- if (descriptor is CallableMemberDescriptor) {
- val extensionClassDescriptor = descriptor.getExtensionClassDescriptor()
- if (extensionClassDescriptor != null && !isSamePackage(descriptor, extensionClassDescriptor) &&
- !ErrorUtils.isError(extensionClassDescriptor)) {
- val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor)
- return externalClassNodes.getOrPut(fqName, {
- val newNode = DocumentationNode(fqName.asString(), Content.Empty, Kind.ExternalClass)
- append(newNode, DocumentationReference.Kind.Member)
- newNode
- })
- }
- }
- return this
- }
-
fun DocumentationModule.appendFragments(fragments: Collection<PackageFragmentDescriptor>,
- packageContent: Map<String, Content>) {
- val descriptors = hashMapOf<String, List<DeclarationDescriptor>>()
- for ((name, parts) in fragments.groupBy { it.fqName }) {
- descriptors.put(name.asString(), parts.flatMap { it.getMemberScope().getAllDescriptors() })
- }
- for ((packageName, declarations) in descriptors) {
- if (options.skipEmptyPackages && declarations.none { it.isDocumented()}) continue
+ packageContent: Map<String, Content>,
+ packageDocumentationBuilder: PackageDocumentationBuilder = KotlinPackageDocumentationBuilder()) {
+ val allFqNames = fragments.map { it.fqName }.distinct()
+
+ for (packageName in allFqNames) {
+ val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getAllDescriptors() }
+
+ if (options.skipEmptyPackages && declarations.none { it.isDocumented() }) continue
logger.info(" package $packageName: ${declarations.count()} declarations")
- val packageNode = findOrCreatePackageNode(packageName, packageContent)
- val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
- declarations.forEach { descriptor ->
- if (descriptor.isDocumented()) {
- val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes)
- parent.appendChild(descriptor, DocumentationReference.Kind.Member)
- }
- }
+ val packageNode = findOrCreatePackageNode(packageName.asString(), packageContent)
+ packageDocumentationBuilder.buildPackageDocumentation(resolutionFacade.project, packageName, packageNode, declarations, options, refGraph, logger)
}
}
@@ -526,15 +492,6 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false
}
- fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? {
- val extensionReceiver = extensionReceiverParameter
- if (extensionReceiver != null) {
- val type = extensionReceiver.type
- return type.constructor.declarationDescriptor as? ClassDescriptor
- }
- return null
- }
-
fun FunctionDescriptor.build(): DocumentationNode {
if (ErrorUtils.containsErrorType(this)) {
logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}")
@@ -707,4 +664,68 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade,
DocumentationNode(valueString, Content.Empty, DocumentationNode.Kind.Value)
}
}
+
+ inner class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
+ override fun buildPackageDocumentation(project: Project,
+ packageName: FqName,
+ packageNode: DocumentationNode,
+ declarations: List<DeclarationDescriptor>,
+ options: DocumentationOptions,
+ refGraph: NodeReferenceGraph, logger: DokkaLogger) {
+ val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
+ declarations.forEach { descriptor ->
+ if (descriptor.isDocumented()) {
+ val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes)
+ parent.appendChild(descriptor, DocumentationReference.Kind.Member)
+ }
+ }
+ }
+ }
+}
+
+private fun AnnotationDescriptor.isDocumented(): Boolean {
+ if (source.getPsi() != null && mustBeDocumented()) return true
+ val annotationClassName = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
+ return annotationClassName == "kotlin.Extension"
+}
+
+fun AnnotationDescriptor.mustBeDocumented(): Boolean {
+ val annotationClass = type.constructor.declarationDescriptor as? Annotated ?: return false
+ return annotationClass.isDocumentedAnnotation()
+}
+
+fun DeclarationDescriptor.isDocumentationSuppressed(): Boolean {
+ val doc = KDocFinder.findKDoc(this)
+ return doc is KDocSection && doc.findTagByName("suppress") != null
+}
+
+fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any {
+ DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated"
+} || (this is ConstructorDescriptor && containingDeclaration.isDeprecated())
+
+fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor,
+ externalClassNodes: MutableMap<FqName, DocumentationNode>): DocumentationNode {
+ if (descriptor is CallableMemberDescriptor) {
+ val extensionClassDescriptor = descriptor.getExtensionClassDescriptor()
+ if (extensionClassDescriptor != null && !isSamePackage(descriptor, extensionClassDescriptor) &&
+ !ErrorUtils.isError(extensionClassDescriptor)) {
+ val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor)
+ return externalClassNodes.getOrPut(fqName, {
+ val newNode = DocumentationNode(fqName.asString(), Content.Empty, Kind.ExternalClass)
+ append(newNode, DocumentationReference.Kind.Member)
+ newNode
+ })
+ }
+ }
+ return this
}
+
+fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? {
+ val extensionReceiver = extensionReceiverParameter
+ if (extensionReceiver != null) {
+ val type = extensionReceiver.type
+ return type.constructor.declarationDescriptor as? ClassDescriptor
+ }
+ return null
+}
+
diff --git a/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt
new file mode 100644
index 00000000..ae295769
--- /dev/null
+++ b/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt
@@ -0,0 +1,27 @@
+package org.jetbrains.dokka
+
+import com.intellij.openapi.project.Project
+import com.intellij.psi.JavaPsiFacade
+import org.jetbrains.kotlin.asJava.KotlinLightElement
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.name.FqName
+
+class KotlinAsJavaDocumentationBuilder() : PackageDocumentationBuilder {
+ override fun buildPackageDocumentation(project: Project,
+ packageName: FqName,
+ packageNode: DocumentationNode,
+ declarations: List<DeclarationDescriptor>,
+ options: DocumentationOptions,
+ refGraph: NodeReferenceGraph,
+ logger: DokkaLogger) {
+ val psiPackage = JavaPsiFacade.getInstance(project).findPackage(packageName.asString())
+ if (psiPackage == null) {
+ logger.error("Cannot find Java package by qualified name: ${packageName.asString()}")
+ return
+ }
+ val javaDocumentationBuilder = JavaDocumentationBuilder(options, refGraph)
+ psiPackage.classes.filter { it is KotlinLightElement<*, *> }.forEach {
+ javaDocumentationBuilder.appendClasses(packageNode, arrayOf(it))
+ }
+ }
+}
diff --git a/src/Utilities/GuiceModule.kt b/src/Utilities/GuiceModule.kt
index 855d70b6..e852ae19 100644
--- a/src/Utilities/GuiceModule.kt
+++ b/src/Utilities/GuiceModule.kt
@@ -4,6 +4,7 @@ import com.google.inject.Binder
import com.google.inject.Module
import com.google.inject.Provider
import com.google.inject.name.Names
+import com.google.inject.util.Providers
import org.jetbrains.dokka.*
import org.jetbrains.dokka.Formats.FormatDescriptor
import java.io.File
@@ -40,6 +41,12 @@ class GuiceModule(val config: DokkaGenerator) : Module {
descriptor.formatServiceClass?.let { clazz ->
binder.bind(FormatService::class.java).to(clazz)
}
+ if (descriptor.packageDocumentationBuilderServiceClass != null) {
+ binder.bind(PackageDocumentationBuilder::class.java).to(descriptor.packageDocumentationBuilderServiceClass)
+ } else {
+ binder.bind(PackageDocumentationBuilder::class.java).toProvider(Providers.of(null))
+ }
+
binder.bind(Generator::class.java).to(descriptor.generatorServiceClass)
}
diff --git a/src/main.kt b/src/main.kt
index 1d2442f2..d0e693e9 100644
--- a/src/main.kt
+++ b/src/main.kt
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.config.CommonConfigurationKeys
+import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzerForTopLevel
+import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import kotlin.util.measureTimeMillis
@@ -153,14 +155,21 @@ class DokkaGenerator(val logger: DokkaLogger,
val startAnalyse = System.currentTimeMillis()
val options = DocumentationOptions(false, sourceLinks = sourceLinks, skipDeprecated = skipDeprecated)
- val documentation = buildDocumentationModule(environment, moduleName, options, includes, { isSample(it) }, logger)
+
+ val injector = Guice.createInjector(GuiceModule(this))
+ val generator = injector.getInstance(Generator::class.java)
+
+ val packageDocumentationBuilder = injector.getInstance(PackageDocumentationBuilder::class.java)
+
+ val documentation = buildDocumentationModule(environment, moduleName, options, includes, { isSample(it) },
+ packageDocumentationBuilder, logger)
val timeAnalyse = System.currentTimeMillis() - startAnalyse
logger.info("done in ${timeAnalyse / 1000} secs")
val timeBuild = measureTimeMillis {
logger.info("Generating pages... ")
- Guice.createInjector(GuiceModule(this)).getInstance(Generator::class.java).buildAll(documentation)
+ generator.buildAll(documentation)
}
logger.info("done in ${timeBuild / 1000} secs")
@@ -196,9 +205,13 @@ fun buildDocumentationModule(environment: AnalysisEnvironment,
options: DocumentationOptions,
includes: List<String> = listOf(),
filesToDocumentFilter: (PsiFile) -> Boolean = { file -> true },
+ packageDocumentationBuilder: PackageDocumentationBuilder? = null,
logger: DokkaLogger): DocumentationModule {
val documentation = environment.withContext { environment, resolutionFacade, session ->
val fragmentFiles = environment.getSourceFiles().filter(filesToDocumentFilter)
+ val analyzer = resolutionFacade.getFrontendService(LazyTopDownAnalyzerForTopLevel::class.java)
+ analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, fragmentFiles)
+
val fragments = fragmentFiles.map { session.getPackageFragment(it.packageFqName) }.filterNotNull().distinct()
val refGraph = NodeReferenceGraph()
@@ -210,7 +223,12 @@ fun buildDocumentationModule(environment: AnalysisEnvironment,
val documentationModule = DocumentationModule(moduleName, packageDocs.moduleContent)
with(documentationBuilder) {
- documentationModule.appendFragments(fragments, packageDocs.packageContent)
+ if (packageDocumentationBuilder != null) {
+ documentationModule.appendFragments(fragments, packageDocs.packageContent, packageDocumentationBuilder)
+ }
+ else {
+ documentationModule.appendFragments(fragments, packageDocs.packageContent)
+ }
}
val javaFiles = environment.getJavaSourceFiles().filter(filesToDocumentFilter)
diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt
index 59b6495b..c4be6623 100644
--- a/test/src/TestAPI.kt
+++ b/test/src/TestAPI.kt
@@ -16,6 +16,7 @@ import kotlin.test.fail
public fun verifyModel(vararg roots: ContentRoot,
withJdk: Boolean = false,
withKotlinRuntime: Boolean = false,
+ packageDocumentationBuilder: PackageDocumentationBuilder? = null,
verifier: (DocumentationModule) -> Unit) {
val messageCollector = object : MessageCollector {
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
@@ -46,7 +47,9 @@ public fun verifyModel(vararg roots: ContentRoot,
addRoots(roots.toList())
}
val options = DocumentationOptions(includeNonPublic = true, skipEmptyPackages = false, sourceLinks = listOf<SourceLinkDefinition>())
- val documentation = buildDocumentationModule(environment, "test", options, logger = DokkaConsoleLogger)
+ val documentation = buildDocumentationModule(environment, "test", options,
+ packageDocumentationBuilder = packageDocumentationBuilder,
+ logger = DokkaConsoleLogger)
verifier(documentation)
Disposer.dispose(environment)
}
@@ -54,8 +57,13 @@ public fun verifyModel(vararg roots: ContentRoot,
public fun verifyModel(source: String,
withJdk: Boolean = false,
withKotlinRuntime: Boolean = false,
+ packageDocumentationBuilder: PackageDocumentationBuilder? = null,
verifier: (DocumentationModule) -> Unit) {
- verifyModel(contentRootFromPath(source), withJdk = withJdk, withKotlinRuntime = withKotlinRuntime, verifier = verifier)
+ verifyModel(contentRootFromPath(source),
+ withJdk = withJdk,
+ withKotlinRuntime = withKotlinRuntime,
+ packageDocumentationBuilder = packageDocumentationBuilder,
+ verifier = verifier)
}
public fun verifyPackageMember(kotlinSource: String,
diff --git a/test/src/model/KotlinAsJavaTest.kt b/test/src/model/KotlinAsJavaTest.kt
new file mode 100644
index 00000000..25ee5fad
--- /dev/null
+++ b/test/src/model/KotlinAsJavaTest.kt
@@ -0,0 +1,32 @@
+package org.jetbrains.dokka.tests
+
+import org.jetbrains.dokka.DocumentationModule
+import org.jetbrains.dokka.DocumentationNode
+import org.jetbrains.dokka.KotlinAsJavaDocumentationBuilder
+import org.junit.Test
+import kotlin.test.assertEquals
+
+class KotlinAsJavaTest {
+ @Test fun function() {
+ verifyModelAsJava("test/data/functions/function.kt") { model ->
+ val pkg = model.members.single()
+
+ val facadeClass = pkg.members.single { it.name == "FunctionKt" }
+ assertEquals(DocumentationNode.Kind.Class, facadeClass.kind)
+
+ val fn = facadeClass.members.single()
+ assertEquals("fn", fn.name)
+ assertEquals(DocumentationNode.Kind.CompanionObjectFunction, fn.kind)
+ }
+ }
+}
+
+fun verifyModelAsJava(source: String,
+ withJdk: Boolean = false,
+ withKotlinRuntime: Boolean = false,
+ verifier: (DocumentationModule) -> Unit) {
+ verifyModel(source,
+ withJdk = withJdk, withKotlinRuntime = withKotlinRuntime,
+ packageDocumentationBuilder = KotlinAsJavaDocumentationBuilder(),
+ verifier = verifier)
+}