diff options
45 files changed, 770 insertions, 180 deletions
diff --git a/src/Analysis/AnalysisEnvironment.kt b/src/Analysis/AnalysisEnvironment.kt index 561ac2f0..af9859d6 100644 --- a/src/Analysis/AnalysisEnvironment.kt +++ b/src/Analysis/AnalysisEnvironment.kt @@ -4,9 +4,13 @@ import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreModuleManager import com.intellij.mock.MockComponentManager import com.intellij.openapi.Disposable +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import com.intellij.openapi.roots.OrderEnumerationHandler import com.intellij.openapi.roots.ProjectFileIndex +import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope @@ -70,12 +74,24 @@ public class AnalysisEnvironment(val messageCollector: MessageCollector, body: A val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) val projectComponentManager = environment.project as MockComponentManager - val moduleManager = CoreModuleManager(environment.project, this) + val projectFileIndex = CoreProjectFileIndex(environment.project, + environment.configuration.getList(CommonConfigurationKeys.CONTENT_ROOTS)) + + val moduleManager = object : CoreModuleManager(environment.project, this) { + override fun getModules(): Array<out Module> = arrayOf(projectFileIndex.module) + } + CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.picoContainer, ModuleManager::class.java, moduleManager) + Extensions.registerAreaClass("IDEA_MODULE", null) + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), + OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java) + projectComponentManager.registerService(ProjectFileIndex::class.java, - CoreProjectFileIndex()) + projectFileIndex) + projectComponentManager.registerService(ProjectRootManager::class.java, + CoreProjectRootManager(projectFileIndex)) projectComponentManager.registerService(LibraryModificationTracker::class.java, LibraryModificationTracker(environment.project)) projectComponentManager.registerService(KotlinCacheService::class.java, diff --git a/src/Analysis/CoreProjectFileIndex.kt b/src/Analysis/CoreProjectFileIndex.kt index 916eab73..a1362fde 100644 --- a/src/Analysis/CoreProjectFileIndex.kt +++ b/src/Analysis/CoreProjectFileIndex.kt @@ -1,17 +1,409 @@ package org.jetbrains.dokka +import com.intellij.openapi.Disposable +import com.intellij.openapi.components.BaseComponent +import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.module.Module -import com.intellij.openapi.roots.ContentIterator -import com.intellij.openapi.roots.OrderEntry -import com.intellij.openapi.roots.ProjectFileIndex +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.projectRoots.SdkAdditionalData +import com.intellij.openapi.projectRoots.SdkModificator +import com.intellij.openapi.projectRoots.SdkTypeId +import com.intellij.openapi.roots.* +import com.intellij.openapi.roots.impl.ProjectOrderEnumerator +import com.intellij.openapi.util.Condition +import com.intellij.openapi.util.Key +import com.intellij.openapi.util.UserDataHolderBase +import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.util.messages.MessageBus import org.jetbrains.jps.model.module.JpsModuleSourceRootType +import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot +import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot +import org.jetbrains.kotlin.config.ContentRoot +import org.jetbrains.kotlin.config.KotlinSourceRoot +import org.picocontainer.PicoContainer +import java.io.File /** * Workaround for the lack of ability to create a ProjectFileIndex implementation using only * classes from projectModel-{api,impl}. */ -class CoreProjectFileIndex(): ProjectFileIndex { +class CoreProjectFileIndex(val project: Project, contentRoots: List<ContentRoot>) : ProjectFileIndex, ModuleFileIndex { + val sourceRoots = contentRoots.filter { it !is JvmClasspathRoot } + val classpathRoots = contentRoots.filterIsInstance<JvmClasspathRoot>() + + val module: Module = object : UserDataHolderBase(), Module { + override fun isDisposed(): Boolean { + throw UnsupportedOperationException() + } + + override fun getOptionValue(p0: String): String? { + throw UnsupportedOperationException() + } + + override fun clearOption(p0: String) { + throw UnsupportedOperationException() + } + + override fun getName(): String = "<Dokka module>" + + override fun getModuleWithLibrariesScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleWithDependentsScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleContentScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun isLoaded(): Boolean { + throw UnsupportedOperationException() + } + + override fun setOption(p0: String, p1: String) { + throw UnsupportedOperationException() + } + + override fun getModuleWithDependenciesScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleWithDependenciesAndLibrariesScope(p0: Boolean): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getProject(): Project = project + + override fun getModuleContentWithDependenciesScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleFilePath(): String { + throw UnsupportedOperationException() + } + + override fun getModuleTestsWithDependentsScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleScope(): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleScope(p0: Boolean): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleRuntimeScope(p0: Boolean): GlobalSearchScope { + throw UnsupportedOperationException() + } + + override fun getModuleFile(): VirtualFile? { + throw UnsupportedOperationException() + } + + override fun <T : Any?> getExtensions(p0: ExtensionPointName<T>): Array<out T> { + throw UnsupportedOperationException() + } + + override fun getComponent(p0: String): BaseComponent? { + throw UnsupportedOperationException() + } + + override fun <T : Any?> getComponent(p0: Class<T>, p1: T): T { + throw UnsupportedOperationException() + } + + override fun <T : Any?> getComponent(interfaceClass: Class<T>): T? { + if (interfaceClass == ModuleRootManager::class.java) { + return moduleRootManager as T + } + throw UnsupportedOperationException() + } + + override fun getDisposed(): Condition<*> { + throw UnsupportedOperationException() + } + + override fun <T : Any?> getComponents(p0: Class<T>): Array<out T> { + throw UnsupportedOperationException() + } + + override fun getPicoContainer(): PicoContainer { + throw UnsupportedOperationException() + } + + override fun hasComponent(p0: Class<*>): Boolean { + throw UnsupportedOperationException() + } + + override fun getMessageBus(): MessageBus { + throw UnsupportedOperationException() + } + + override fun dispose() { + throw UnsupportedOperationException() + } + } + + private val sdk: Sdk = object : Sdk, RootProvider { + override fun getFiles(rootType: OrderRootType): Array<out VirtualFile> = classpathRoots + .map { StandardFileSystems.local().findFileByPath(it.file.path) } + .filterNotNull() + .toTypedArray() + + override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener) { + throw UnsupportedOperationException() + } + + override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener, p1: Disposable) { + throw UnsupportedOperationException() + } + + override fun getUrls(p0: OrderRootType): Array<out String> { + throw UnsupportedOperationException() + } + + override fun removeRootSetChangedListener(p0: RootProvider.RootSetChangedListener) { + throw UnsupportedOperationException() + } + + override fun getSdkModificator(): SdkModificator { + throw UnsupportedOperationException() + } + + override fun getName(): String = "<dokka SDK>" + + override fun getRootProvider(): RootProvider = this + + override fun getHomePath(): String? { + throw UnsupportedOperationException() + } + + override fun getVersionString(): String? { + throw UnsupportedOperationException() + } + + override fun getSdkAdditionalData(): SdkAdditionalData? { + throw UnsupportedOperationException() + } + + override fun clone(): Any { + throw UnsupportedOperationException() + } + + override fun getSdkType(): SdkTypeId { + throw UnsupportedOperationException() + } + + override fun getHomeDirectory(): VirtualFile? { + throw UnsupportedOperationException() + } + + override fun <T : Any?> getUserData(p0: Key<T>): T? { + throw UnsupportedOperationException() + } + + override fun <T : Any?> putUserData(p0: Key<T>, p1: T?) { + throw UnsupportedOperationException() + } + } + + private val moduleSourceOrderEntry = object : ModuleSourceOrderEntry { + override fun getFiles(p0: OrderRootType?): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getPresentableName(): String { + throw UnsupportedOperationException() + } + + override fun getUrls(p0: OrderRootType?): Array<out String> { + throw UnsupportedOperationException() + } + + override fun getOwnerModule(): Module = module + + override fun <R : Any?> accept(p0: RootPolicy<R>?, p1: R?): R { + throw UnsupportedOperationException() + } + + override fun isValid(): Boolean { + throw UnsupportedOperationException() + } + + override fun compareTo(other: OrderEntry?): Int { + throw UnsupportedOperationException() + } + + override fun getRootModel(): ModuleRootModel = moduleRootManager + + override fun isSynthetic(): Boolean { + throw UnsupportedOperationException() + } + } + + private val sdkOrderEntry = object : JdkOrderEntry { + override fun getJdkName(): String? { + throw UnsupportedOperationException() + } + + override fun getJdk(): Sdk = sdk + + override fun getFiles(p0: OrderRootType?): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getPresentableName(): String { + throw UnsupportedOperationException() + } + + override fun getUrls(p0: OrderRootType?): Array<out String> { + throw UnsupportedOperationException() + } + + override fun getOwnerModule(): Module { + throw UnsupportedOperationException() + } + + override fun <R : Any?> accept(p0: RootPolicy<R>?, p1: R?): R { + throw UnsupportedOperationException() + } + + override fun isValid(): Boolean { + throw UnsupportedOperationException() + } + + override fun getRootFiles(p0: OrderRootType?): Array<out VirtualFile>? { + throw UnsupportedOperationException() + } + + override fun getRootUrls(p0: OrderRootType?): Array<out String>? { + throw UnsupportedOperationException() + } + + override fun compareTo(other: OrderEntry?): Int { + throw UnsupportedOperationException() + } + + override fun isSynthetic(): Boolean { + throw UnsupportedOperationException() + } + + } + + inner class MyModuleRootManager : ModuleRootManager() { + override fun getExcludeRoots(): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getContentEntries(): Array<out ContentEntry> { + throw UnsupportedOperationException() + } + + override fun getExcludeRootUrls(): Array<out String> { + throw UnsupportedOperationException() + } + + override fun <R : Any?> processOrder(p0: RootPolicy<R>?, p1: R): R { + throw UnsupportedOperationException() + } + + override fun getSourceRoots(p0: Boolean): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getSourceRoots(): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getSourceRoots(p0: JpsModuleSourceRootType<*>): MutableList<VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getSourceRoots(p0: MutableSet<out JpsModuleSourceRootType<*>>): MutableList<VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getContentRoots(): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun orderEntries(): OrderEnumerator = + ProjectOrderEnumerator(project, null).using(object : RootModelProvider { + override fun getModules(): Array<out Module> = arrayOf(module) + + override fun getRootModel(p0: Module): ModuleRootModel = this@MyModuleRootManager + }) + + override fun <T : Any?> getModuleExtension(p0: Class<T>?): T { + throw UnsupportedOperationException() + } + + override fun getDependencyModuleNames(): Array<out String> { + throw UnsupportedOperationException() + } + + override fun getModule(): Module = module + + override fun isSdkInherited(): Boolean { + throw UnsupportedOperationException() + } + + override fun getOrderEntries(): Array<out OrderEntry> = arrayOf(moduleSourceOrderEntry, sdkOrderEntry) + + override fun getSourceRootUrls(): Array<out String> { + throw UnsupportedOperationException() + } + + override fun getSourceRootUrls(p0: Boolean): Array<out String> { + throw UnsupportedOperationException() + } + + override fun getSdk(): Sdk? { + throw UnsupportedOperationException() + } + + override fun getContentRootUrls(): Array<out String> { + throw UnsupportedOperationException() + } + + override fun getModuleDependencies(): Array<out Module> { + throw UnsupportedOperationException() + } + + override fun getModuleDependencies(p0: Boolean): Array<out Module> { + throw UnsupportedOperationException() + } + + override fun getModifiableModel(): ModifiableRootModel { + throw UnsupportedOperationException() + } + + override fun isDependsOn(p0: Module?): Boolean { + throw UnsupportedOperationException() + } + + override fun getFileIndex(): ModuleFileIndex { + return this@CoreProjectFileIndex + } + + override fun getDependencies(): Array<out Module> { + throw UnsupportedOperationException() + } + + override fun getDependencies(p0: Boolean): Array<out Module> { + throw UnsupportedOperationException() + } + } + + val moduleRootManager = MyModuleRootManager() + override fun getContentRootForFile(p0: VirtualFile): VirtualFile? { throw UnsupportedOperationException() } @@ -24,19 +416,15 @@ class CoreProjectFileIndex(): ProjectFileIndex { throw UnsupportedOperationException() } - override fun isInLibrarySource(p0: VirtualFile): Boolean { - throw UnsupportedOperationException() - } + override fun isInLibrarySource(file: VirtualFile): Boolean = false - override fun getClassRootForFile(p0: VirtualFile): VirtualFile? { - throw UnsupportedOperationException() - } + override fun getClassRootForFile(file: VirtualFile): VirtualFile? = + classpathRoots.firstOrNull { it.contains(file) }?.let { StandardFileSystems.local().findFileByPath(it.file.path) } - override fun getOrderEntriesForFile(p0: VirtualFile): List<OrderEntry> = emptyList() + override fun getOrderEntriesForFile(file: VirtualFile): List<OrderEntry> = + if (classpathRoots.contains(file)) listOf(sdkOrderEntry) else emptyList() - override fun isInLibraryClasses(p0: VirtualFile): Boolean { - throw UnsupportedOperationException() - } + override fun isInLibraryClasses(file: VirtualFile): Boolean = classpathRoots.contains(file) override fun isExcluded(p0: VirtualFile): Boolean { throw UnsupportedOperationException() @@ -54,7 +442,10 @@ class CoreProjectFileIndex(): ProjectFileIndex { throw UnsupportedOperationException() } - override fun getModuleForFile(p0: VirtualFile): Module? = null + override fun getModuleForFile(file: VirtualFile): Module? = + if (sourceRoots.contains(file)) module else null + + private fun List<ContentRoot>.contains(file: VirtualFile): Boolean = any { it.contains(file) } override fun getModuleForFile(p0: VirtualFile, p1: Boolean): Module? { throw UnsupportedOperationException() @@ -72,7 +463,7 @@ class CoreProjectFileIndex(): ProjectFileIndex { throw UnsupportedOperationException() } - override fun isInSourceContent(p0: VirtualFile): Boolean = false + override fun isInSourceContent(file: VirtualFile): Boolean = sourceRoots.contains(file) override fun iterateContent(p0: ContentIterator): Boolean { throw UnsupportedOperationException() @@ -86,12 +477,74 @@ class CoreProjectFileIndex(): ProjectFileIndex { throw UnsupportedOperationException() } - override fun isInTestSourceContent(p0: VirtualFile): Boolean { + override fun isInTestSourceContent(file: VirtualFile): Boolean = false + + override fun isUnderSourceRootOfType(p0: VirtualFile, p1: MutableSet<out JpsModuleSourceRootType<*>>): Boolean { throw UnsupportedOperationException() } - override fun isUnderSourceRootOfType(p0: VirtualFile, p1: MutableSet<out JpsModuleSourceRootType<*>>): Boolean { + override fun getOrderEntryForFile(p0: VirtualFile): OrderEntry? { + throw UnsupportedOperationException() + } +} + +class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : ProjectRootManager() { + override fun orderEntries(): OrderEnumerator { + throw UnsupportedOperationException() + } + + override fun orderEntries(p0: MutableCollection<out Module>): OrderEnumerator { throw UnsupportedOperationException() } + + override fun getContentRootsFromAllModules(): Array<out VirtualFile>? { + throw UnsupportedOperationException() + } + + override fun setProjectSdk(p0: Sdk?) { + throw UnsupportedOperationException() + } + + override fun setProjectSdkName(p0: String?) { + throw UnsupportedOperationException() + } + + override fun getModuleSourceRoots(p0: MutableSet<out JpsModuleSourceRootType<*>>): MutableList<VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getContentSourceRoots(): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getFileIndex(): ProjectFileIndex = projectFileIndex + + override fun getProjectSdkName(): String? { + throw UnsupportedOperationException() + } + + override fun getProjectSdk(): Sdk? { + throw UnsupportedOperationException() + } + + override fun getContentRoots(): Array<out VirtualFile> { + throw UnsupportedOperationException() + } + + override fun getContentRootUrls(): MutableList<String> { + throw UnsupportedOperationException() + } + } +fun ContentRoot.contains(file: VirtualFile) = when (this) { + is JvmContentRoot -> { + val path = if (file.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL) + StandardFileSystems.getVirtualFileForJar(file)?.path ?: file.path + else + file.path + File(path).startsWith(this.file.absoluteFile) + } + is KotlinSourceRoot -> File(file.path).startsWith(File(this.path).absoluteFile) + else -> false +} diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaPsiDocumentationBuilder.kt index e0cc53a0..a5ee891e 100644 --- a/src/Java/JavaDocumentationBuilder.kt +++ b/src/Java/JavaPsiDocumentationBuilder.kt @@ -197,10 +197,14 @@ private fun mapTypeName(psiType: PsiType): String = when (psiType) { else -> psiType.canonicalText } -class JavaDocumentationBuilder(private val options: DocumentationOptions, - private val refGraph: NodeReferenceGraph, - private val docParser: JavaDocumentationParser = JavadocParser(refGraph)) { - fun appendFile(file: PsiJavaFile, module: DocumentationModule) { +interface JavaDocumentationBuilder { + fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) +} + +class JavaPsiDocumentationBuilder(private val options: DocumentationOptions, + private val refGraph: NodeReferenceGraph, + private val docParser: JavaDocumentationParser = JavadocParser(refGraph)) : JavaDocumentationBuilder { + override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) { if (file.classes.all { skipElement(it) }) { return } diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index b5b079de..7dc4075b 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -1,7 +1,9 @@ package org.jetbrains.dokka -import com.intellij.openapi.project.Project import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiDocCommentOwner +import com.intellij.psi.PsiJavaFile +import com.intellij.psi.PsiNamedElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.dokka.DocumentationNode.Kind import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -9,6 +11,8 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService +import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo import org.jetbrains.kotlin.idea.kdoc.KDocFinder import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink import org.jetbrains.kotlin.idea.resolve.ResolutionFacade @@ -16,6 +20,9 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor +import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtParameter @@ -25,6 +32,8 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.isDocumentedAnnotation +import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi @@ -55,7 +64,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, val session: ResolveSession, val options: DocumentationOptions, val refGraph: NodeReferenceGraph, - val logger: DokkaLogger) { + val logger: DokkaLogger) : JavaDocumentationBuilder { val visibleToDocumentation = setOf(Visibilities.PROTECTED, Visibilities.PUBLIC) val boringBuiltinClasses = setOf( "kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean", @@ -65,7 +74,14 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.ABSTRACT_KEYWORD, KtTokens.SEALED_KEYWORD, KtTokens.OVERRIDE_KEYWORD) - fun parseDocumentation(descriptor: DeclarationDescriptor): Content { + + fun parseDocumentation(descriptor: DeclarationDescriptor): Content = parseDocumentationAndDetails(descriptor).first + + fun parseDocumentationAndDetails(descriptor: DeclarationDescriptor): Pair<Content, (DocumentationNode) -> Unit> { + if (descriptor is JavaClassDescriptor || descriptor is JavaCallableMemberDescriptor) { + return parseJavadoc(descriptor) + } + val kdoc = KDocFinder.findKDoc(descriptor) ?: findStdlibKDoc(descriptor) if (kdoc == null) { if (options.reportUndocumented && !descriptor.isDeprecated() && @@ -73,7 +89,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, descriptor !is PropertyAccessorDescriptor) { logger.warn("No documentation for ${descriptor.signatureWithSourceLocation()}") } - return Content.Empty + return Content.Empty to { node -> } } var kdocText = kdoc.getContent() // workaround for code fence parsing problem in IJ markdown parser @@ -100,7 +116,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } } - return content + return content to { node -> } } /** @@ -132,6 +148,20 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return null } + fun parseJavadoc(descriptor: DeclarationDescriptor): Pair<Content, (DocumentationNode) -> Unit> { + val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi + if (psi is PsiDocCommentOwner) { + val parseResult = JavadocParser(refGraph).parseDocumentation(psi as PsiNamedElement) + return parseResult.content to { node -> + parseResult.deprecatedContent?.let { + val deprecationNode = DocumentationNode("", it, DocumentationNode.Kind.Modifier) + node.append(deprecationNode, DocumentationReference.Kind.Deprecation) + } + } + } + return Content.Empty to { node -> } + } + fun DeclarationDescriptor.signature(): String = when(this) { is ClassDescriptor, is PackageFragmentDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "#" + name + receiverSignature() @@ -246,8 +276,9 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun <T> DocumentationNode(descriptor: T, kind: Kind): DocumentationNode where T : DeclarationDescriptor, T : Named { - val doc = parseDocumentation(descriptor) + val (doc, callback) = parseDocumentationAndDetails(descriptor) val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor) + callback(node) return node } @@ -274,7 +305,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun DocumentationNode.appendVisibility(descriptor: DeclarationDescriptorWithVisibility) { - val modifier = descriptor.visibility.toString() + val modifier = descriptor.visibility.normalize().displayName appendTextNode(modifier, DocumentationNode.Kind.Modifier) } @@ -393,18 +424,20 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, (!options.skipDeprecated || !isDeprecated()) } - fun DocumentationNode.appendMembers(descriptors: Iterable<DeclarationDescriptor>) { - descriptors.forEach { descriptor -> + fun DocumentationNode.appendMembers(descriptors: Iterable<DeclarationDescriptor>): List<DocumentationNode> { + val nodes = descriptors.map { descriptor -> if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { val baseDescriptor = descriptor.overriddenDescriptors.firstOrNull() if (baseDescriptor != null) { link(this, baseDescriptor, DocumentationReference.Kind.InheritedMember) } + null } else { appendChild(descriptor, DocumentationReference.Kind.Member) } } + return nodes.filterNotNull() } fun DocumentationNode.appendInPageChildren(descriptors: Iterable<DeclarationDescriptor>, kind: DocumentationReference.Kind) { @@ -464,6 +497,9 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } val members = defaultType.memberScope.getAllDescriptors().filter { it != companionObjectDescriptor } node.appendMembers(members) + node.appendMembers(staticScope.getDescriptors()).forEach { + it.appendTextNode("static", Kind.Modifier) + } val companionObjectDescriptor = companionObjectDescriptor if (companionObjectDescriptor != null) { node.appendMembers(companionObjectDescriptor.defaultType.memberScope.getAllDescriptors()) @@ -583,6 +619,9 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } node.appendAnnotations(this) node.appendModifiers(this) + if (varargElementType != null && node.details(Kind.Modifier).none { it.name == "vararg" }) { + node.appendTextNode("vararg", Kind.Modifier) + } register(this, node) return node } @@ -678,6 +717,23 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } } + + override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) { + val packageNode = module.findOrCreatePackageNode(file.packageName, packageContent) + + file.classes.forEach { + val javaDescriptorResolver = KotlinCacheService.getInstance(file.project).getProjectService(JvmPlatform, + it.getModuleInfo(), javaClass<JavaDescriptorResolver>()) + + val descriptor = javaDescriptorResolver.resolveClass(JavaClassImpl(it)) + if (descriptor == null) { + logger.warn("Cannot find descriptor for Java class ${it.qualifiedName}") + } + else { + packageNode.appendChild(descriptor, DocumentationReference.Kind.Member) + } + } + } } private fun AnnotationDescriptor.isDocumented(): Boolean { diff --git a/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt index a32e9a1f..1bd930e2 100644 --- a/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt +++ b/src/Kotlin/KotlinAsJavaDocumentationBuilder.kt @@ -20,7 +20,7 @@ class KotlinAsJavaDocumentationBuilder() : PackageDocumentationBuilder { return } - val javaDocumentationBuilder = JavaDocumentationBuilder(documentationBuilder.options, + val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.options, documentationBuilder.refGraph, KotlinAsJavaDocumentationParser(documentationBuilder)) diff --git a/src/main.kt b/src/main.kt index d0e693e9..46b9a2dc 100644 --- a/src/main.kt +++ b/src/main.kt @@ -162,7 +162,7 @@ class DokkaGenerator(val logger: DokkaLogger, val packageDocumentationBuilder = injector.getInstance(PackageDocumentationBuilder::class.java) val documentation = buildDocumentationModule(environment, moduleName, options, includes, { isSample(it) }, - packageDocumentationBuilder, logger) + packageDocumentationBuilder, null, logger) val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") @@ -206,9 +206,10 @@ fun buildDocumentationModule(environment: AnalysisEnvironment, includes: List<String> = listOf(), filesToDocumentFilter: (PsiFile) -> Boolean = { file -> true }, packageDocumentationBuilder: PackageDocumentationBuilder? = null, + javaDocumentationBuilder: JavaDocumentationBuilder? = null, logger: DokkaLogger): DocumentationModule { - val documentation = environment.withContext { environment, resolutionFacade, session -> - val fragmentFiles = environment.getSourceFiles().filter(filesToDocumentFilter) + val documentation = environment.withContext { coreEnvironment, resolutionFacade, session -> + val fragmentFiles = coreEnvironment.getSourceFiles().filter(filesToDocumentFilter) val analyzer = resolutionFacade.getFrontendService(LazyTopDownAnalyzerForTopLevel::class.java) analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, fragmentFiles) @@ -231,9 +232,10 @@ fun buildDocumentationModule(environment: AnalysisEnvironment, } } - val javaFiles = environment.getJavaSourceFiles().filter(filesToDocumentFilter) - val javaDocumentationBuilder = JavaDocumentationBuilder(options, refGraph) - javaFiles.map { javaDocumentationBuilder.appendFile(it, documentationModule) } + val javaFiles = coreEnvironment.getJavaSourceFiles().filter(filesToDocumentFilter) + with(javaDocumentationBuilder ?: documentationBuilder) { + javaFiles.map { appendFile(it, documentationModule, packageDocs.packageContent) } + } refGraph.resolveReferences() diff --git a/test/data/format/javaCodeInParam.java b/test/data/format/javaCodeInParam.java index d1cdf6cd..73025fcc 100644 --- a/test/data/format/javaCodeInParam.java +++ b/test/data/format/javaCodeInParam.java @@ -1,5 +1,3 @@ -package test; - /** * @param T this is {@code some code} and other text */ diff --git a/test/data/format/javaCodeInParam.md b/test/data/format/javaCodeInParam.md index 88cb6912..b1d2d871 100644 --- a/test/data/format/javaCodeInParam.md +++ b/test/data/format/javaCodeInParam.md @@ -1,9 +1,9 @@ -[test](test/index) / [test](test/test/index) / [C](test/test/-c) +[test](test/index) / [C](test/-c/index) # C -`open class C<T>` +`protected open class C<T : Any>` @@ -13,3 +13,9 @@ `T` - this is `some code` and other text + +### Constructors + + +| [<init>](test/-c/-init-) | `C()` | + diff --git a/test/data/format/javaCodeLiteralTags.java b/test/data/format/javaCodeLiteralTags.java index cf071f07..e71ddaa7 100644 --- a/test/data/format/javaCodeLiteralTags.java +++ b/test/data/format/javaCodeLiteralTags.java @@ -1,5 +1,3 @@ -package test; - /** * <p>{@code A<B>C}</p> * <p>{@literal A<B>C}</p> diff --git a/test/data/format/javaCodeLiteralTags.md b/test/data/format/javaCodeLiteralTags.md index 17438bff..83c9cc33 100644 --- a/test/data/format/javaCodeLiteralTags.md +++ b/test/data/format/javaCodeLiteralTags.md @@ -1,9 +1,9 @@ -[test](test/index) / [test](test/test/index) / [C](test/test/-c) +[test](test/index) / [C](test/-c/index) # C -`open class C` +`protected open class C` `A<B>C` @@ -15,3 +15,9 @@ A<B>C + +### Constructors + + +| [<init>](test/-c/-init-) | `C()` | + diff --git a/test/data/format/javaDeprecated.html b/test/data/format/javaDeprecated.html index 9e8958a2..236c6490 100644 --- a/test/data/format/javaDeprecated.html +++ b/test/data/format/javaDeprecated.html @@ -1,13 +1,13 @@ <HTML> <HEAD> -<title>test / test.Foo.foo</title> +<title>test / Foo.foo</title> </HEAD> <BODY> -<a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-foo/index">Foo</a> / <a href="test/test/-foo/foo">foo</a><br/> +<a href="test/index">test</a> / <a href="test/-foo/index">Foo</a> / <a href="test/-foo/foo">foo</a><br/> <br/> <h1>foo</h1> <code><span class="keyword">open</span> <span class="keyword">fun </span><s><span class="identifier">foo</span></s><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code><br/> -<strong>Deprecated:</strong> use <code><a href="test/test/-foo/bar">#bar</a></code> instead <p></p> +<strong>Deprecated:</strong> use <code><a href="test/-foo/bar">#bar</a></code> instead <p></p> <br/> <br/> </BODY> diff --git a/test/data/format/javaDeprecated.java b/test/data/format/javaDeprecated.java index 4216f205..9694a444 100644 --- a/test/data/format/javaDeprecated.java +++ b/test/data/format/javaDeprecated.java @@ -1,5 +1,3 @@ -package test; - class Foo { /** @deprecated use {@link #bar} instead */ public void foo() {} diff --git a/test/data/format/javaLinkTag.html b/test/data/format/javaLinkTag.html index af63710d..1b6921ab 100644 --- a/test/data/format/javaLinkTag.html +++ b/test/data/format/javaLinkTag.html @@ -1,21 +1,32 @@ <HTML> <HEAD> -<title>test / test.Foo</title> +<title>test / Foo</title> </HEAD> <BODY> -<a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-foo/index">Foo</a><br/> +<a href="test/index">test</a> / <a href="test/-foo/index">Foo</a><br/> <br/> <h1>Foo</h1> -<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code><br/> -<p>Call <code><a href="test/test/-foo/bar">#bar()</a></code> to do the job. </p> +<code><span class="keyword">protected</span> <span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code><br/> +<p>Call <code><a href="test/-foo/bar">#bar()</a></code> to do the job. </p> <br/> <br/> +<h3>Constructors</h3> +<table> +<tbody> +<tr> +<td> +<a href="test/-foo/-init-"><init></a></td> +<td> +<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code></td> +</tr> +</tbody> +</table> <h3>Functions</h3> <table> <tbody> <tr> <td> -<a href="test/test/-foo/bar">bar</a></td> +<a href="test/-foo/bar">bar</a></td> <td> <code><span class="keyword">open</span> <span class="keyword">fun </span><span class="identifier">bar</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td> </tr> diff --git a/test/data/format/javaLinkTag.java b/test/data/format/javaLinkTag.java index 06452f16..84f761c6 100644 --- a/test/data/format/javaLinkTag.java +++ b/test/data/format/javaLinkTag.java @@ -1,5 +1,3 @@ -package test; - /** * Call {@link #bar()} to do the job. */ diff --git a/test/data/format/javaLinkTagWithLabel.html b/test/data/format/javaLinkTagWithLabel.html index ccf3c712..aabfbc58 100644 --- a/test/data/format/javaLinkTagWithLabel.html +++ b/test/data/format/javaLinkTagWithLabel.html @@ -1,21 +1,32 @@ <HTML> <HEAD> -<title>test / test.Foo</title> +<title>test / Foo</title> </HEAD> <BODY> -<a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-foo/index">Foo</a><br/> +<a href="test/index">test</a> / <a href="test/-foo/index">Foo</a><br/> <br/> <h1>Foo</h1> -<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code><br/> -<p>Call <code><a href="test/test/-foo/bar">this wonderful method</a></code> to do the job. </p> +<code><span class="keyword">protected</span> <span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code><br/> +<p>Call <code><a href="test/-foo/bar">this wonderful method</a></code> to do the job. </p> <br/> <br/> +<h3>Constructors</h3> +<table> +<tbody> +<tr> +<td> +<a href="test/-foo/-init-"><init></a></td> +<td> +<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code></td> +</tr> +</tbody> +</table> <h3>Functions</h3> <table> <tbody> <tr> <td> -<a href="test/test/-foo/bar">bar</a></td> +<a href="test/-foo/bar">bar</a></td> <td> <code><span class="keyword">open</span> <span class="keyword">fun </span><span class="identifier">bar</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td> </tr> diff --git a/test/data/format/javaLinkTagWithLabel.java b/test/data/format/javaLinkTagWithLabel.java index 7226f1c9..1db5ad70 100644 --- a/test/data/format/javaLinkTagWithLabel.java +++ b/test/data/format/javaLinkTagWithLabel.java @@ -1,5 +1,3 @@ -package test; - /** * Call {@link #bar() this wonderful method} to do the job. */ diff --git a/test/data/format/javaSeeTag.html b/test/data/format/javaSeeTag.html index cf7b7941..a6813df3 100644 --- a/test/data/format/javaSeeTag.html +++ b/test/data/format/javaSeeTag.html @@ -1,23 +1,34 @@ <HTML> <HEAD> -<title>test / test.Foo</title> +<title>test / Foo</title> </HEAD> <BODY> -<a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-foo/index">Foo</a><br/> +<a href="test/index">test</a> / <a href="test/-foo/index">Foo</a><br/> <br/> <h1>Foo</h1> <code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code><br/> <p></p> <strong>See Also</strong><br/> -<a href="test/test/-foo/bar">#bar</a><br/> +<a href="test/-foo/bar">#bar</a><br/> <br/> <br/> +<h3>Constructors</h3> +<table> +<tbody> +<tr> +<td> +<a href="test/-foo/-init-"><init></a></td> +<td> +<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code></td> +</tr> +</tbody> +</table> <h3>Functions</h3> <table> <tbody> <tr> <td> -<a href="test/test/-foo/bar">bar</a></td> +<a href="test/-foo/bar">bar</a></td> <td> <code><span class="keyword">open</span> <span class="keyword">fun </span><span class="identifier">bar</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td> </tr> diff --git a/test/data/format/javaSeeTag.java b/test/data/format/javaSeeTag.java index e0b95f11..94a24606 100644 --- a/test/data/format/javaSeeTag.java +++ b/test/data/format/javaSeeTag.java @@ -1,8 +1,6 @@ -package test; - /** * @see #bar */ -class Foo { +public class Foo { public void bar() {} }
\ No newline at end of file diff --git a/test/data/format/javaSpaceInAuthor.java b/test/data/format/javaSpaceInAuthor.java index b96f5884..f980ae07 100644 --- a/test/data/format/javaSpaceInAuthor.java +++ b/test/data/format/javaSpaceInAuthor.java @@ -1,5 +1,3 @@ -package test; - /** * @author Dmitry Jemerov */ diff --git a/test/data/format/javaSpaceInAuthor.md b/test/data/format/javaSpaceInAuthor.md index 425d4c9a..4d19ed01 100644 --- a/test/data/format/javaSpaceInAuthor.md +++ b/test/data/format/javaSpaceInAuthor.md @@ -1,9 +1,9 @@ -[test](test/index) / [test](test/test/index) / [C](test/test/-c) +[test](test/index) / [C](test/-c/index) # C -`open class C` +`protected open class C` @@ -11,3 +11,9 @@ Dmitry Jemerov + +### Constructors + + +| [<init>](test/-c/-init-) | `C()` | + diff --git a/test/data/format/javaSupertype.html b/test/data/format/javaSupertype.html index 2bcc2fce..4c847281 100644 --- a/test/data/format/javaSupertype.html +++ b/test/data/format/javaSupertype.html @@ -1,22 +1,33 @@ <HTML> <HEAD> -<title>test / test.C.Bar</title> +<title>test / C.Bar</title> </HEAD> <BODY> -<a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-c/index">C</a> / <a href="test/test/-c/-bar/index">Bar</a><br/> +<a href="test/index">test</a> / <a href="test/-c/index">C</a> / <a href="test/-c/-bar/index">Bar</a><br/> <br/> <h1>Bar</h1> -<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Bar</span> <span class="symbol">:</span> <a href="test/test/-c/-foo"><span class="identifier">Foo</span></a></code><br/> +<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Bar</span> <span class="symbol">:</span> <a href="test/-c/-foo/index"><span class="identifier">Foo</span></a></code><br/> <br/> <br/> +<h3>Constructors</h3> +<table> +<tbody> +<tr> +<td> +<a href="test/-c/-bar/-init-"><init></a></td> +<td> +<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td> +</tr> +</tbody> +</table> <h3>Functions</h3> <table> <tbody> <tr> <td> -<a href="test/test/-c/-bar/return-foo">returnFoo</a></td> +<a href="test/-c/-bar/return-foo">returnFoo</a></td> <td> -<code><span class="keyword">open</span> <span class="keyword">fun </span><span class="identifier">returnFoo</span><span class="symbol">(</span><span class="identifier">foo</span><span class="symbol">:</span> <a href="test/test/-c/-foo"><span class="identifier">Foo</span></a><span class="symbol">)</span><span class="symbol">: </span><a href="test/test/-c/-foo"><span class="identifier">Foo</span></a></code></td> +<code><span class="keyword">open</span> <span class="keyword">fun </span><span class="identifier">returnFoo</span><span class="symbol">(</span><span class="identifier">foo</span><span class="symbol">:</span> <a href="test/-c/-foo/index"><span class="identifier">Foo</span></a><span class="symbol">)</span><span class="symbol">: </span><a href="test/-c/-foo/index"><span class="identifier">Foo</span></a></code></td> </tr> </tbody> </table> diff --git a/test/data/format/javaSupertype.java b/test/data/format/javaSupertype.java index 295c319f..b3142ff6 100644 --- a/test/data/format/javaSupertype.java +++ b/test/data/format/javaSupertype.java @@ -1,5 +1,3 @@ -package test; - class C { public static class Foo { } diff --git a/test/data/format/javadocHtml.java b/test/data/format/javadocHtml.java index bcb2cf91..622116b2 100644 --- a/test/data/format/javadocHtml.java +++ b/test/data/format/javadocHtml.java @@ -1,5 +1,3 @@ -package test; - /** * <b>Bold</b> * <strong>Strong</strong> diff --git a/test/data/format/javadocHtml.md b/test/data/format/javadocHtml.md index a75ebf35..db71cc3b 100644 --- a/test/data/format/javadocHtml.md +++ b/test/data/format/javadocHtml.md @@ -1,4 +1,4 @@ -[test](test/index) / [test](test/test/index) / [C](test/test/-c) +[test](test/index) / [C](test/-c/index) # C @@ -19,3 +19,9 @@ Block code + +### Constructors + + +| [<init>](test/-c/-init-) | `C()` | + diff --git a/test/data/format/javadocOrderedList.java b/test/data/format/javadocOrderedList.java index 1c7f8a3e..c32d9032 100644 --- a/test/data/format/javadocOrderedList.java +++ b/test/data/format/javadocOrderedList.java @@ -1,5 +1,3 @@ -package test; - /** * <ol> * <li>Rinse</li> diff --git a/test/data/format/javadocOrderedList.md b/test/data/format/javadocOrderedList.md index acd3e809..02a3c095 100644 --- a/test/data/format/javadocOrderedList.md +++ b/test/data/format/javadocOrderedList.md @@ -1,4 +1,4 @@ -[test](test/index) / [test](test/test/index) / [Bar](test/test/-bar) +[test](test/index) / [Bar](test/-bar/index) # Bar @@ -12,3 +12,9 @@ + +### Constructors + + +| [<init>](test/-bar/-init-) | `Bar()` | + diff --git a/test/data/java/annotatedAnnotation.java b/test/data/java/annotatedAnnotation.java index d9fae956..6296e400 100644 --- a/test/data/java/annotatedAnnotation.java +++ b/test/data/java/annotatedAnnotation.java @@ -1,6 +1,5 @@ -package test; +import java.lang.annotation.*; -@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) public @interface Attribute { String value() default ""; diff --git a/test/data/java/arrayType.java b/test/data/java/arrayType.java index a50e3bf6..dc42a207 100644 --- a/test/data/java/arrayType.java +++ b/test/data/java/arrayType.java @@ -1,5 +1,3 @@ -package test; - class Test { public String[] arrayToString(int[] data) { return null; diff --git a/test/data/java/constructors.java b/test/data/java/constructors.java index 3b1838dd..6f899d18 100644 --- a/test/data/java/constructors.java +++ b/test/data/java/constructors.java @@ -1,5 +1,3 @@ -package test; - class Test { public Test() {} diff --git a/test/data/java/deprecation.java b/test/data/java/deprecation.java index 07cbd901..be8decd6 100644 --- a/test/data/java/deprecation.java +++ b/test/data/java/deprecation.java @@ -1,5 +1,6 @@ -package test; - class C { - @Deprecated("This should no longer be used") void fn() {} + /** + * @deprecated This should no longer be used + */ + void fn() {} }
\ No newline at end of file diff --git a/test/data/java/enumValues.java b/test/data/java/enumValues.java index 0f622946..d8dda934 100644 --- a/test/data/java/enumValues.java +++ b/test/data/java/enumValues.java @@ -1,5 +1,3 @@ -package test; - enum E { Foo }
\ No newline at end of file diff --git a/test/data/java/field.java b/test/data/java/field.java index 47dac0a4..d9ae75f9 100644 --- a/test/data/java/field.java +++ b/test/data/java/field.java @@ -1,5 +1,3 @@ -package test; - class Test { public int i; public static final String s; diff --git a/test/data/java/inheritorLinks.java b/test/data/java/inheritorLinks.java index 96caeb1d..2378f5c6 100644 --- a/test/data/java/inheritorLinks.java +++ b/test/data/java/inheritorLinks.java @@ -1,5 +1,3 @@ -package test; - class C { public static class Foo { } diff --git a/test/data/java/innerClass.java b/test/data/java/innerClass.java index dd08e100..0f1be948 100644 --- a/test/data/java/innerClass.java +++ b/test/data/java/innerClass.java @@ -1,5 +1,3 @@ -package test; - class Test { public class D { } diff --git a/test/data/java/javaLangObject.java b/test/data/java/javaLangObject.java index 8f16629c..be3dd570 100644 --- a/test/data/java/javaLangObject.java +++ b/test/data/java/javaLangObject.java @@ -1,5 +1,3 @@ -package test; - class Test { public Object fn() { return null; } } diff --git a/test/data/java/member.java b/test/data/java/member.java index a417ff7e..d4f4b8d5 100644 --- a/test/data/java/member.java +++ b/test/data/java/member.java @@ -1,5 +1,3 @@ -package test - class Test { /** * Summary for Function diff --git a/test/data/java/memberWithModifiers.java b/test/data/java/memberWithModifiers.java index 7c236224..ea645c21 100644 --- a/test/data/java/memberWithModifiers.java +++ b/test/data/java/memberWithModifiers.java @@ -1,6 +1,4 @@ -package test - -abstract class Test { +public abstract class Test { /** * Summary for Function * @param name is String parameter diff --git a/test/data/java/staticMethod.java b/test/data/java/staticMethod.java index 2bbbbf1b..a2ecd7f1 100644 --- a/test/data/java/staticMethod.java +++ b/test/data/java/staticMethod.java @@ -1,5 +1,3 @@ -package test; - class C { public static void foo() { } diff --git a/test/data/java/superClass.java b/test/data/java/superClass.java index 99535813..31b5fa96 100644 --- a/test/data/java/superClass.java +++ b/test/data/java/superClass.java @@ -1,4 +1,2 @@ -package test; - public class Foo extends Exception implements Cloneable { } diff --git a/test/data/java/typeParameter.java b/test/data/java/typeParameter.java index 98a6aee9..5a24b30a 100644 --- a/test/data/java/typeParameter.java +++ b/test/data/java/typeParameter.java @@ -1,5 +1,3 @@ -package test - class Foo<T extends Comparable<T>> { public <E> E foo(); } diff --git a/test/data/java/varargs.java b/test/data/java/varargs.java index a6af6a8d..d184564e 100644 --- a/test/data/java/varargs.java +++ b/test/data/java/varargs.java @@ -1,5 +1,3 @@ -package test - class Foo { public void bar(String... x); } diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt index 4a0e4fb4..82353610 100644 --- a/test/src/TestAPI.kt +++ b/test/src/TestAPI.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka.tests import com.intellij.openapi.application.PathManager import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.io.FileUtil import org.jetbrains.dokka.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -66,11 +67,34 @@ public fun verifyModel(source: String, verifier = verifier) } -public fun verifyPackageMember(kotlinSource: String, +public fun verifyPackageMember(source: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, verifier: (DocumentationNode) -> Unit) { - verifyModel(kotlinSource, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime) { model -> + verifyModel(source, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime) { model -> + val pkg = model.members.single() + verifier(pkg.members.single()) + } +} + +public fun verifyJavaModel(source: String, + withKotlinRuntime: Boolean = false, + verifier: (DocumentationModule) -> Unit) { + val tempDir = FileUtil.createTempDirectory("dokka", "") + try { + val sourceFile = File(source) + FileUtil.copy(sourceFile, File(tempDir, sourceFile.name)) + verifyModel(JavaSourceRoot(tempDir), withJdk = true, withKotlinRuntime = withKotlinRuntime, verifier = verifier) + } + finally { + FileUtil.delete(tempDir) + } +} + +public fun verifyJavaPackageMember(source: String, + withKotlinRuntime: Boolean = false, + verifier: (DocumentationNode) -> Unit) { + verifyJavaModel(source, withKotlinRuntime) { model -> val pkg = model.members.single() verifier(pkg.members.single()) } @@ -82,15 +106,22 @@ public fun verifyOutput(roots: Array<ContentRoot>, withKotlinRuntime: Boolean = false, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { verifyModel(*roots, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime) { - val output = StringBuilder() - outputGenerator(it, output) - val ext = outputExtension.removePrefix(".") - val path = roots.first().path - val expectedOutput = File(path.replaceAfterLast(".", ext, path + "." + ext)).readText() - assertEqualsIgnoringSeparators(expectedOutput, output.toString()) + verifyModelOutput(it, outputExtension, outputGenerator, roots.first().path) } } +private fun verifyModelOutput(it: DocumentationModule, + outputExtension: String, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit, + sourcePath: String) { + val output = StringBuilder() + outputGenerator(it, output) + val ext = outputExtension.removePrefix(".") + val path = sourcePath + val expectedOutput = File(path.replaceAfterLast(".", ext, path + "." + ext)).readText() + assertEqualsIgnoringSeparators(expectedOutput, output.toString()) +} + public fun verifyOutput(path: String, outputExtension: String, withJdk: Boolean = false, @@ -99,6 +130,15 @@ public fun verifyOutput(path: String, verifyOutput(arrayOf(contentRootFromPath(path)), outputExtension, withJdk, withKotlinRuntime, outputGenerator) } +public fun verifyJavaOutput(path: String, + outputExtension: String, + withKotlinRuntime: Boolean = false, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { + verifyJavaModel(path, withKotlinRuntime) { model -> + verifyModelOutput(model, outputExtension, outputGenerator, path) + } +} + public fun assertEqualsIgnoringSeparators(expectedOutput: String, output: String) { Assert.assertEquals(expectedOutput.replace("\r\n", "\n"), output.replace("\r\n", "\n")) } diff --git a/test/src/format/HtmlFormatTest.kt b/test/src/format/HtmlFormatTest.kt index 66fd0fee..752e4424 100644 --- a/test/src/format/HtmlFormatTest.kt +++ b/test/src/format/HtmlFormatTest.kt @@ -99,31 +99,31 @@ public class HtmlFormatTest { } @Test fun javaSupertypeLink() { - verifyOutput("test/data/format/javaSupertype.java", ".html") { model, output -> + verifyJavaOutput("test/data/format/javaSupertype.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.single { it.name == "C"}.members.filter { it.name == "Bar"} ) } } @Test fun javaLinkTag() { - verifyOutput("test/data/format/javaLinkTag.java", ".html", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javaLinkTag.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } @Test fun javaLinkTagWithLabel() { - verifyOutput("test/data/format/javaLinkTagWithLabel.java", ".html", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javaLinkTagWithLabel.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } @Test fun javaSeeTag() { - verifyOutput("test/data/format/javaSeeTag.java", ".html", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javaSeeTag.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } @Test fun javaDeprecated() { - verifyOutput("test/data/format/javaDeprecated.java", ".html") { model, output -> + verifyJavaOutput("test/data/format/javaDeprecated.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.single { it.name == "Foo" }.members.filter { it.name == "foo" }) } } diff --git a/test/src/format/MarkdownFormatTest.kt b/test/src/format/MarkdownFormatTest.kt index bb61fa1c..1a09ae60 100644 --- a/test/src/format/MarkdownFormatTest.kt +++ b/test/src/format/MarkdownFormatTest.kt @@ -121,25 +121,25 @@ public class MarkdownFormatTest { } @Test fun javadocHtml() { - verifyOutput("test/data/format/javadocHtml.java", ".md", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javadocHtml.java", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } @Test fun javaCodeLiteralTags() { - verifyOutput("test/data/format/javaCodeLiteralTags.java", ".md", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javaCodeLiteralTags.java", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } @Test fun javaCodeInParam() { - verifyOutput("test/data/format/javaCodeInParam.java", ".md", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javaCodeInParam.java", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } @Test fun javaSpaceInAuthor() { - verifyOutput("test/data/format/javaSpaceInAuthor.java", ".md", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javaSpaceInAuthor.java", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } @@ -157,7 +157,7 @@ public class MarkdownFormatTest { } @Test fun javadocOrderedList() { - verifyOutput("test/data/format/javadocOrderedList.java", ".md", withJdk = true) { model, output -> + verifyJavaOutput("test/data/format/javadocOrderedList.java", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) } } diff --git a/test/src/model/JavaTest.kt b/test/src/model/JavaTest.kt index 5ec29b25..0633a5cc 100644 --- a/test/src/model/JavaTest.kt +++ b/test/src/model/JavaTest.kt @@ -9,12 +9,11 @@ import kotlin.test.assertTrue public class JavaTest { @Test fun function() { - verifyPackageMember("test/data/java/member.java") { cls -> + verifyJavaPackageMember("test/data/java/member.java") { cls -> assertEquals("Test", cls.name) assertEquals(DocumentationNode.Kind.Class, cls.kind) - with(cls.members.single()) { + with(cls.members(DocumentationNode.Kind.Function).single()) { assertEquals("fn", name) - assertEquals(DocumentationNode.Kind.Function, kind) assertEquals("Summary for Function", content.summary.toTestString().trimEnd()) assertEquals(3, content.sections.size) with(content.sections[0]) { @@ -47,8 +46,9 @@ public class JavaTest { } @Test fun memberWithModifiers() { - verifyPackageMember("test/data/java/memberWithModifiers.java") { cls -> - assertEquals("abstract", cls.details[0].name) + verifyJavaPackageMember("test/data/java/memberWithModifiers.java") { cls -> + val modifiers = cls.details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("abstract" in modifiers) with(cls.members.single { it.name == "fn" }) { assertEquals("protected", details[0].name) } @@ -59,7 +59,7 @@ public class JavaTest { } @Test fun superClass() { - verifyPackageMember("test/data/java/superClass.java") { cls -> + verifyJavaPackageMember("test/data/java/superClass.java") { cls -> val superTypes = cls.details(DocumentationNode.Kind.Supertype) assertEquals(2, superTypes.size) assertEquals("Exception", superTypes[0].name) @@ -68,22 +68,21 @@ public class JavaTest { } @Test fun arrayType() { - verifyPackageMember("test/data/java/arrayType.java") { cls -> - with(cls.members.single()) { + verifyJavaPackageMember("test/data/java/arrayType.java") { cls -> + with(cls.members(DocumentationNode.Kind.Function).single()) { val type = detail(DocumentationNode.Kind.Type) assertEquals("Array", type.name) assertEquals("String", type.detail(DocumentationNode.Kind.Type).name) with(details(DocumentationNode.Kind.Parameter).single()) { val parameterType = detail(DocumentationNode.Kind.Type) - assertEquals("Array", parameterType.name) - assertEquals("Int", parameterType.detail(DocumentationNode.Kind.Type).name) + assertEquals("IntArray", parameterType.name) } } } } @Test fun typeParameter() { - verifyPackageMember("test/data/java/typeParameter.java") { cls -> + verifyJavaPackageMember("test/data/java/typeParameter.java") { cls -> val typeParameters = cls.details(DocumentationNode.Kind.TypeParameter) with(typeParameters.single()) { assertEquals("T", name) @@ -92,7 +91,7 @@ public class JavaTest { assertEquals("T", detail(DocumentationNode.Kind.Type).name) } } - with(cls.members.single()) { + with(cls.members(DocumentationNode.Kind.Function).single()) { val methodTypeParameters = details(DocumentationNode.Kind.TypeParameter) with(methodTypeParameters.single()) { assertEquals("E", name) @@ -102,7 +101,7 @@ public class JavaTest { } @Test fun constructors() { - verifyPackageMember("test/data/java/constructors.java") { cls -> + verifyJavaPackageMember("test/data/java/constructors.java") { cls -> val constructors = cls.members(DocumentationNode.Kind.Constructor) assertEquals(2, constructors.size) with(constructors[0]) { @@ -112,17 +111,17 @@ public class JavaTest { } @Test fun innerClass() { - verifyPackageMember("test/data/java/innerClass.java") { cls -> + verifyJavaPackageMember("test/data/java/innerClass.java") { cls -> val innerClass = cls.members(DocumentationNode.Kind.Class).single() assertEquals("D", innerClass.name) } } @Test fun varargs() { - verifyPackageMember("test/data/java/varargs.java") { cls -> + verifyJavaPackageMember("test/data/java/varargs.java") { cls -> val fn = cls.members(DocumentationNode.Kind.Function).single() val param = fn.detail(DocumentationNode.Kind.Parameter) - assertEquals("vararg", param.annotations.first().name) + assertEquals("vararg", param.details(DocumentationNode.Kind.Modifier).first().name) val psiType = param.detail(DocumentationNode.Kind.Type) assertEquals("String", psiType.name) assertTrue(psiType.details(DocumentationNode.Kind.Type).isEmpty()) @@ -130,26 +129,28 @@ public class JavaTest { } @Test fun fields() { - verifyPackageMember("test/data/java/field.java") { cls -> + verifyJavaPackageMember("test/data/java/field.java") { cls -> val i = cls.members(DocumentationNode.Kind.Property).single { it.name == "i" } assertEquals("Int", i.detail(DocumentationNode.Kind.Type).name) assertTrue("var" in i.details(DocumentationNode.Kind.Modifier).map { it.name }) - val s = cls.members(DocumentationNode.Kind.CompanionObjectProperty).single { it.name == "s" } + + val s = cls.members(DocumentationNode.Kind.Property).single { it.name == "s" } assertEquals("String", s.detail(DocumentationNode.Kind.Type).name) assertFalse("var" in s.details(DocumentationNode.Kind.Modifier).map { it.name }) + assertTrue("static" in s.details(DocumentationNode.Kind.Modifier).map { it.name }) } } @Test fun staticMethod() { - verifyPackageMember("test/data/java/staticMethod.java") { cls -> - val m = cls.members(DocumentationNode.Kind.CompanionObjectFunction).single { it.name == "foo" } - assertFalse("static" in m.details(DocumentationNode.Kind.Modifier).map { it.name }) + verifyJavaPackageMember("test/data/java/staticMethod.java") { cls -> + val m = cls.members(DocumentationNode.Kind.Function).single { it.name == "foo" } + assertTrue("static" in m.details(DocumentationNode.Kind.Modifier).map { it.name }) } } @Test fun annotatedAnnotation() { - verifyPackageMember("test/data/java/annotatedAnnotation.java") { cls -> - assertEquals(2, cls.annotations.size) + verifyJavaPackageMember("test/data/java/annotatedAnnotation.java") { cls -> + assertEquals(1, cls.annotations.size) with(cls.annotations[0]) { assertEquals(1, details.count()) with(details[0]) { @@ -157,7 +158,7 @@ public class JavaTest { assertEquals(1, details.count()) with(details[0]) { assertEquals(DocumentationNode.Kind.Value, kind) - assertEquals("RetentionPolicy.RUNTIME", name) + assertEquals("[AnnotationTarget.FIELD, AnnotationTarget.CLASS, AnnotationTarget.FILE, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER]", name) } } } @@ -165,31 +166,21 @@ public class JavaTest { } @Test fun deprecation() { - verifyPackageMember("test/data/java/deprecation.java", withJdk = true) { cls -> + verifyJavaPackageMember("test/data/java/deprecation.java") { cls -> val fn = cls.members(DocumentationNode.Kind.Function).single() - with(fn.deprecation!!) { - assertEquals(1, details.count()) - with(details[0]) { - assertEquals(DocumentationNode.Kind.Parameter, kind) - assertEquals(1, details.count()) - with(details[0]) { - assertEquals(DocumentationNode.Kind.Value, kind) - assertEquals("This should no longer be used", name) - } - } - } + assertEquals("This should no longer be used", fn.deprecation!!.content.toTestString()) } } @Test fun javaLangObject() { - verifyPackageMember("test/data/java/javaLangObject.java", withJdk = true) { cls -> + verifyJavaPackageMember("test/data/java/javaLangObject.java") { cls -> val fn = cls.members(DocumentationNode.Kind.Function).single() assertEquals("Any", fn.detail(DocumentationNode.Kind.Type).name) } } @Test fun enumValues() { - verifyPackageMember("test/data/java/enumValues.java", withJdk = true) { cls -> + verifyJavaPackageMember("test/data/java/enumValues.java") { cls -> val superTypes = cls.details(DocumentationNode.Kind.Supertype) assertEquals(0, superTypes.size) assertEquals(1, cls.members(DocumentationNode.Kind.EnumItem).size) @@ -197,7 +188,7 @@ public class JavaTest { } @Test fun inheritorLinks() { - verifyPackageMember("test/data/java/inheritorLinks.java") { cls -> + verifyJavaPackageMember("test/data/java/inheritorLinks.java") { cls -> val fooClass = cls.members.single { it.name == "Foo" } val inheritors = fooClass.references(DocumentationReference.Kind.Inheritor) assertEquals(1, inheritors.size) |