diff options
9 files changed, 68 insertions, 189 deletions
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt index 57ac96e5..cc78ab6f 100644 --- a/core/src/main/kotlin/links/DRI.kt +++ b/core/src/main/kotlin/links/DRI.kt @@ -56,6 +56,8 @@ data class DRI( } } +val DriOfUnit = DRI("kotlin", "Unit") + fun DRI.withClass(name: String) = copy(classNames = if (classNames.isNullOrBlank()) name else "$classNames.$name") val DRI.parent: DRI diff --git a/core/src/main/kotlin/model/Documentable.kt b/core/src/main/kotlin/model/Documentable.kt index 176647fa..b697f4e4 100644 --- a/core/src/main/kotlin/model/Documentable.kt +++ b/core/src/main/kotlin/model/Documentable.kt @@ -58,7 +58,7 @@ interface WithVisibility { } interface WithType { - val type: TypeWrapper + val type: Bound } interface WithAbstraction { @@ -203,7 +203,7 @@ data class Function( override val documentation: PlatformDependent<DocumentationNode>, override val sources: PlatformDependent<DocumentableSource>, override val visibility: PlatformDependent<Visibility>, - override val type: TypeWrapper, + override val type: Bound, override val generics: List<TypeParameter>, override val receiver: Parameter?, override val modifier: Modifier, @@ -282,7 +282,7 @@ data class Property( override val documentation: PlatformDependent<DocumentationNode>, override val sources: PlatformDependent<DocumentableSource>, override val visibility: PlatformDependent<Visibility>, - override val type: TypeWrapper, + override val type: Bound, override val receiver: Parameter?, val setter: Function?, val getter: Function?, @@ -301,7 +301,7 @@ data class Parameter( override val dri: DRI, override val name: String?, override val documentation: PlatformDependent<DocumentationNode>, - val type: TypeWrapper, + val type: Bound, override val platformData: List<PlatformData>, override val extra: PropertyContainer<Parameter> = PropertyContainer.empty() ) : Documentable(), WithExtraProperties<Parameter> { @@ -334,6 +334,9 @@ data class Nullable(val inner: Bound) : Bound() data class Variance(val kind: Kind, val inner: Bound) : Projection() { enum class Kind { In, Out } } +data class PrimitiveJavaType(val name: String): Bound() + +val VoidBound = PrimitiveJavaType("void") enum class ExtraModifiers { STATIC, INLINE, INFIX, SUSPEND, REIFIED, CROSSINLINE, NOINLINE, diff --git a/core/src/main/kotlin/model/typeWrappers.kt b/core/src/main/kotlin/model/typeWrappers.kt deleted file mode 100644 index b26a3f6d..00000000 --- a/core/src/main/kotlin/model/typeWrappers.kt +++ /dev/null @@ -1,101 +0,0 @@ -package org.jetbrains.dokka.model - -import com.intellij.psi.PsiArrayType -import com.intellij.psi.PsiEllipsisType -import com.intellij.psi.PsiPrimitiveType -import com.intellij.psi.PsiType -import com.intellij.psi.impl.source.PsiClassReferenceType -import org.jetbrains.dokka.links.DRI -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe -import org.jetbrains.kotlin.types.KotlinType - -interface TypeWrapper { - val constructorFqName: String? - val constructorNamePathSegments: List<String> - val arguments: List<TypeWrapper> - val dri: DRI? -} - -class KotlinTypeWrapper(private val kotlinType: KotlinType) : TypeWrapper { - private val declarationDescriptor = kotlinType.constructor.declarationDescriptor - private val fqNameSafe = declarationDescriptor?.fqNameSafe - override val constructorFqName = fqNameSafe?.asString() - override val constructorNamePathSegments: List<String> = - fqNameSafe?.pathSegments()?.map { it.asString() } ?: emptyList() - override val arguments: List<KotlinTypeWrapper> by lazy { - kotlinType.arguments.map { - KotlinTypeWrapper( - it.type - ) - } - } - override val dri: DRI? by lazy { declarationDescriptor?.let { DRI.from(it) } } -} - -class JavaTypeWrapper : TypeWrapper { - - override val constructorFqName: String? - override val constructorNamePathSegments: List<String> - override val arguments: List<TypeWrapper> - override val dri: DRI? - val isPrimitive: Boolean - - constructor( - constructorNamePathSegments: List<String>, - arguments: List<TypeWrapper>, - dri: DRI?, - isPrimitiveType: Boolean - ) { - this.constructorFqName = constructorNamePathSegments.joinToString(".") - this.constructorNamePathSegments = constructorNamePathSegments - this.arguments = arguments - this.dri = dri - this.isPrimitive = isPrimitiveType - } - - constructor(type: PsiType) { - if (type is PsiClassReferenceType) { - val resolved = type.resolve() - constructorFqName = resolved?.qualifiedName - constructorNamePathSegments = resolved?.qualifiedName?.split('.') ?: emptyList() - arguments = type.parameters.mapNotNull { - if (it is PsiClassReferenceType) JavaTypeWrapper(it) else null - } - dri = fromPsi(type) - this.isPrimitive = false - } else if (type is PsiEllipsisType) { - constructorFqName = type.canonicalText - constructorNamePathSegments = listOf(type.canonicalText) // TODO - arguments = emptyList() - dri = DRI("java.lang", "Object") // TODO - this.isPrimitive = false - } else if (type is PsiArrayType) { - constructorFqName = type.canonicalText - constructorNamePathSegments = listOf(type.canonicalText) - arguments = emptyList() - dri = (type as? PsiClassReferenceType)?.let { fromPsi(it) } // TODO - this.isPrimitive = false - } else { - type as PsiPrimitiveType - constructorFqName = type.name - constructorNamePathSegments = type.name.split('.') - arguments = emptyList() - dri = null - this.isPrimitive = true - } - } - - private fun fromPsi(type: PsiClassReferenceType): DRI { - val className = type.className - val pkg = type.canonicalText.removeSuffix(className).removeSuffix(".") - return DRI(packageName = pkg, classNames = className) - } - - override fun toString(): String { - return constructorFqName.orEmpty() - } - - companion object { - val VOID = JavaTypeWrapper(listOf("void"), listOf(), null, true) - } -} diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt index b468c56b..3c4698fe 100644 --- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt +++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt @@ -2,6 +2,8 @@ package org.jetbrains.dokka.base.signatures import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.links.DriOfUnit import org.jetbrains.dokka.links.sureClassNames import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.Annotation @@ -53,25 +55,25 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog platformText(f.visibility) { (it.takeIf { it !in ignoredVisibilities }?.name ?: "") + " " } text(f.modifier.name + " ") text("fun ") + list(f.generics, prefix = "<", suffix = "> ") { + +buildSignature(it) + } f.receiver?.also { - type(it.type) + signatureForProjection(it.type) text(".") } link(f.name, f.dri) - list(f.generics, prefix = "<", suffix = ">") { - +buildSignature(it) - } text("(") list(f.parameters) { text(it.name!!) text(": ") - type(it.type) + signatureForProjection(it.type) } text(")") val returnType = f.type - if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) { + if (!f.isConstructor && returnType is TypeConstructor && returnType.dri != DriOfUnit) { text(": ") - type(returnType) + signatureForProjection(returnType) } } @@ -103,5 +105,12 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog signatureForProjection(p.inner) text("?") } + + is PrimitiveJavaType -> signatureForProjection(p.translateToKotlin()) } } + +private fun PrimitiveJavaType.translateToKotlin() = TypeConstructor( + dri = DRI("kotlin", name.capitalize()), + projections = emptyList() +) diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt index 2b73dc7f..9a71145f 100644 --- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt @@ -223,7 +223,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv visibility = PlatformDependent(mapOf(platformData to descriptor.visibility.toDokkaVisibility())), documentation = descriptor.resolveDescriptorData(platformData), modifier = descriptor.modifier(), - type = KotlinTypeWrapper(descriptor.returnType!!), + type = descriptor.returnType!!.toBound(), platformData = listOf(platformData), extra = descriptor.additionalExtras() ) @@ -248,7 +248,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv generics = descriptor.typeParameters.map { it.toTypeParameter() }, documentation = descriptor.resolveDescriptorData(platformData), modifier = descriptor.modifier(), - type = KotlinTypeWrapper(descriptor.returnType!!), + type = descriptor.returnType!!.toBound(), platformData = listOf(platformData), extra = descriptor.additionalExtras() ) @@ -270,7 +270,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv sources = actual, visibility = PlatformDependent(mapOf(platformData to descriptor.visibility.toDokkaVisibility())), documentation = descriptor.resolveDescriptorData(platformData), - type = KotlinTypeWrapper(descriptor.returnType), + type = descriptor.returnType.toBound(), modifier = descriptor.modifier(), generics = descriptor.typeParameters.map { it.toTypeParameter() }, platformData = listOf(platformData), @@ -284,7 +284,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv ) = Parameter( dri = parent.dri.copy(target = 0), name = null, - type = KotlinTypeWrapper(descriptor.type), + type = descriptor.type.toBound(), documentation = descriptor.resolveDescriptorData(platformData), platformData = listOf(platformData) ) @@ -301,7 +301,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv Parameter( parent.copy(target = 1), this.name.asString(), - type = KotlinTypeWrapper(this.type), + type = this.type.toBound(), documentation = descriptor.resolveDescriptorData(platformData), platformData = listOf(platformData), extra = descriptor.additionalExtras() @@ -327,7 +327,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv parameters = parameters, visibility = PlatformDependent(mapOf(platformData to descriptor.visibility.toDokkaVisibility())), documentation = descriptor.resolveDescriptorData(platformData), - type = KotlinTypeWrapper(descriptor.returnType!!), + type = descriptor.returnType!!.toBound(), generics = descriptor.typeParameters.map { it.toTypeParameter() }, modifier = descriptor.modifier(), receiver = descriptor.extensionReceiverParameter?.let { @@ -346,7 +346,7 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv Parameter( dri = parent.dri.copy(target = index + 1), name = descriptor.name.asString(), - type = KotlinTypeWrapper(descriptor.type), + type = descriptor.type.toBound(), documentation = descriptor.resolveDescriptorData(platformData), platformData = listOf(platformData), extra = descriptor.additionalExtras() @@ -393,15 +393,15 @@ private class DokkaDescriptorVisitor( // TODO: close this class and make it priv private fun TypeParameterDescriptor.toTypeParameter() = TypeParameter( DRI.from(this), - fqNameSafe.asString(), + name.identifier, PlatformDependent.from(platformData, getDocumentation()), upperBounds.map { it.toBound() }, listOf(platformData), extra = additionalExtras() ) - private fun KotlinType.toBound(): Bound = when (constructor.declarationDescriptor) { - is TypeParameterDescriptor -> OtherParameter(fqName.toString()).let { + private fun KotlinType.toBound(): Bound = when (val ctor = constructor.declarationDescriptor) { + is TypeParameterDescriptor -> OtherParameter(ctor.name.asString()).let { if (isMarkedNullable) Nullable(it) else it } else -> TypeConstructor( diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt index f5880656..681b8c71 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt @@ -3,9 +3,7 @@ package org.jetbrains.dokka.base.translators.documentables import org.jetbrains.dokka.base.signatures.SignatureProvider import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.PlatformDependent -import org.jetbrains.dokka.model.TypeWrapper +import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.doc.DocTag import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.pages.* @@ -256,21 +254,6 @@ open class PageContentBuilder( ) = ContentText(text, DCI(setOf(mainDRI), kind), platformData, styles, extra) - fun type(t: TypeWrapper) { - if (t.constructorNamePathSegments.isNotEmpty() && t.dri != null) - link(t.constructorNamePathSegments.last(), t.dri!!) - else if (t.constructorNamePathSegments.isNotEmpty() && t.dri == null) - text(t.toString()) - else { - logger.error("type $t cannot be resolved") - text("???") - } - list(t.arguments, prefix = "<", suffix = ">") { - type(it) - } - } - - fun <T> platformText( value: PlatformDependent<T>, transform: (T) -> String diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt index b07d248d..8bf556af 100644 --- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt @@ -3,6 +3,7 @@ package org.jetbrains.dokka.base.translators.psi import com.intellij.lang.jvm.JvmModifier import com.intellij.lang.jvm.types.JvmReferenceType import com.intellij.psi.* +import com.intellij.psi.impl.source.PsiClassReferenceType import org.jetbrains.dokka.links.Callable import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.links.JavaClassReference @@ -63,7 +64,7 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator { private val javadocParser: JavaDocumentationParser = JavadocParser(logger) - private val typeWrappers = hashMapOf<String, TypeWrapper>() + private val cachedBounds = hashMapOf<String, Bound>() private fun PsiModifierListOwner.getVisibility() = modifierList?.children?.toList()?.let { ml -> when { @@ -226,14 +227,14 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator { dri.copy(target = index + 1), psiParameter.name, javadocParser.parseDocumentation(psiParameter).toPlatformDependant(), - getTypeWrapper(psiParameter.type), + getBound(psiParameter.type), listOf(platformData) ) }, javadocParser.parseDocumentation(psi).toPlatformDependant(), PsiDocumentableSource(psi).toPlatformDependant(), psi.getVisibility().toPlatformDependant(), - psi.returnType?.let { getTypeWrapper(type = it) } ?: JavaTypeWrapper.VOID, + psi.returnType?.let { getBound(type = it) } ?: VoidBound, psi.mapTypeParameters(dri), null, psi.getModifier(), @@ -244,8 +245,22 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator { ) } - private fun getTypeWrapper(type: PsiType) : TypeWrapper = - typeWrappers.getOrPut(type.canonicalText, { JavaTypeWrapper(type) }) + private fun getBound(type: PsiType): Bound = + cachedBounds.getOrPut(type.canonicalText) { + when (type) { + is PsiClassReferenceType -> { + val resolved: PsiClass = type.resolve() + ?: throw IllegalStateException("${type.presentableText} cannot be resolved") + val arguments = type.parameters.map { getProjection(it) } + TypeConstructor(DRI.from(resolved), arguments) + } + is PsiArrayType -> TypeConstructor(DRI("kotlin", "Array"), listOf(getProjection(type.componentType))) + is PsiPrimitiveType -> PrimitiveJavaType(type.name) + else -> throw IllegalStateException("${type.presentableText} is not supported by PSI parser") + } + } + + private fun getProjection(type: PsiType): Projection = if (type is PsiEllipsisType) Star else getBound(type) private fun PsiModifierListOwner.getModifier() = when { hasModifier(JvmModifier.ABSTRACT) -> JavaModifier.Abstract @@ -278,7 +293,8 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator { getAnnotation(DescriptorUtils.JVM_NAME.asString())?.findAttributeValue("name")?.text ?: when { JvmAbi.isGetterName(name) -> propertyNameByGetMethodName(Name.identifier(name))?.asString() - JvmAbi.isSetterName(name) -> propertyNamesBySetMethodName(Name.identifier(name)).firstOrNull()?.asString() + JvmAbi.isSetterName(name) -> propertyNamesBySetMethodName(Name.identifier(name)).firstOrNull() + ?.asString() else -> null } @@ -311,7 +327,7 @@ object DefaultPsiToDocumentableTranslator : PsiToDocumentableTranslator { javadocParser.parseDocumentation(psi).toPlatformDependant(), PsiDocumentableSource(psi).toPlatformDependant(), psi.getVisibility().toPlatformDependant(), - getTypeWrapper(psi.type), + getBound(psi.type), null, accessors.firstOrNull { it.hasParameters() }?.let { parseFunction(it, parent) }, accessors.firstOrNull { it.returnType == psi.type }?.let { parseFunction(it, parent) }, diff --git a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt index 3b0f69f6..cf777e67 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt @@ -75,7 +75,7 @@ internal fun Property.asJava(isTopLevel: Boolean = false, relocateToClass: Strin visibility = visibility.copy( map = visibility.mapValues { JavaVisibility.Private } ), - type = type.asJava(isTopLevel), // TODO: check + type = type.asJava(), // TODO: check setter = null, getter = null, // Removing getters and setters as they will be available as functions extra = if (isTopLevel) extra.plus(extra.mergeAdditionalModifiers(setOf(ExtraModifiers.STATIC))) else extra @@ -98,7 +98,7 @@ internal fun Property.javaAccessors(isTopLevel: Boolean = false, relocateToClass visibility = visibility.copy( map = visibility.mapValues { JavaVisibility.Public } ), - type = type.asJava(isTopLevel), // TODO: check + type = type.asJava(), // TODO: check extra = if (isTopLevel) getter!!.extra.plus(getter!!.extra.mergeAdditionalModifiers(setOf(ExtraModifiers.STATIC))) else getter!!.extra ), setter?.copy( @@ -116,7 +116,7 @@ internal fun Property.javaAccessors(isTopLevel: Boolean = false, relocateToClass visibility = visibility.copy( map = visibility.mapValues { JavaVisibility.Public } ), - type = type.asJava(isTopLevel), // TODO: check + type = type.asJava(), // TODO: check extra = if (isTopLevel) setter!!.extra.plus(setter!!.extra.mergeAdditionalModifiers(setOf(ExtraModifiers.STATIC))) else setter!!.extra ) ) @@ -204,13 +204,7 @@ internal fun Object.asJava(): Object = copy( it to JavaVisibility.Public }.toMap() ), - type = JavaTypeWrapper( - dri.packageName?.split(".").orEmpty() + - dri.classNames?.split(".").orEmpty(), - emptyList(), - dri, - false - ), + type = TypeConstructor(dri, emptyList()), setter = null, getter = null, platformData = platformData, @@ -250,36 +244,9 @@ internal fun String.getAsPrimitive(): JvmPrimitiveType? = org.jetbrains.kotlin.b .find { it.typeFqName.asString() == this } ?.let { JvmPrimitiveType.get(it) } -internal fun TypeWrapper.getAsType(classId: ClassId, fqName: String, top: Boolean): TypeWrapper { - val fqNameSplit = fqName - .takeIf { top } - ?.getAsPrimitive() - ?.name?.toLowerCase() - ?.let(::listOf) - ?: classId.asString().split("/") - - return JavaTypeWrapper( - fqNameSplit, - arguments.map { it.asJava(false) }, - classId.toDRI(dri), - fqNameSplit.last()[0].isLowerCase() - ) -} - private fun DRI.partialFqName() = packageName?.let { "$it." } + classNames private fun DRI.possiblyAsJava() = this.partialFqName().mapToJava()?.toDRI(this) ?: this -internal fun TypeWrapper.asJava(top: Boolean = true): TypeWrapper = constructorFqName - ?.let { if (it.endsWith(".Unit")) return VoidTypeWrapper() else it } - ?.let { fqName -> fqName.mapToJava()?.let { getAsType(it, fqName, top) } } ?: this - -private data class VoidTypeWrapper( - override val constructorFqName: String = "void", - override val constructorNamePathSegments: List<String> = listOf("void"), - override val arguments: List<TypeWrapper> = emptyList(), - override val dri: DRI = DRI("java.lang", "Void") -) : TypeWrapper - private fun String.mapToJava(): ClassId? = JavaToKotlinClassMap.mapKotlinToJava(FqName(this).toUnsafe()) diff --git a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt index 91e5164d..265e05cd 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt @@ -62,9 +62,7 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge private fun signature(f: Function) = contentBuilder.contentFor(f, ContentKind.Symbol) { text(f.modifier.takeIf { it !in ignoredModifiers }?.name.orEmpty() + " ") val returnType = f.type - if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) { - type(returnType) - } + signatureForProjection(returnType) text(" ") link(f.name, f.dri) list(f.generics, prefix = "<", suffix = ">") { @@ -72,7 +70,7 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge } text("(") list(f.parameters) { - type(it.type) + signatureForProjection(it.type) text(" ") link(it.name!!, it.dri) } @@ -98,12 +96,14 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge } is Variance -> group { - text(p.kind.toString() + " ") + text(p.kind.toString() + " ") // TODO: "super" && "extends" signatureForProjection(p.inner) } is Star -> text("?") is Nullable -> signatureForProjection(p.inner) + + is PrimitiveJavaType -> text(p.name) } }
\ No newline at end of file |