diff options
22 files changed, 449 insertions, 65 deletions
diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index e365207c..b192794e 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -30,14 +30,17 @@ import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompilerEnvironment import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters +import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession import java.io.File @@ -82,28 +85,57 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { return environment } + fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope { + // TODO: Fix when going to implement dokka for JS + return TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) + } + + fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() + + val library = object : ModuleInfo { + override val name: Name = Name.special("<library>") + override fun dependencies(): List<ModuleInfo> = listOf(this) + } val module = object : ModuleInfo { override val name: Name = Name.special("<module>") - override fun dependencies(): List<ModuleInfo> = listOf(this) + override fun dependencies(): List<ModuleInfo> = listOf(this, library) } + val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) + val builtIns = JvmBuiltIns(projectContext.storageManager) val resolverForProject = JvmAnalyzerFacade.setupResolverForProject( "Dokka", projectContext, - listOf(module), - { ModuleContent(sourceFiles, GlobalSearchScope.allScope(environment.project)) }, - JvmPlatformParameters { module }, + listOf(library, module), + { + when (it) { + library -> ModuleContent(emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(sourceFiles, sourcesScope) + else -> throw IllegalArgumentException("Unexpected module info") + } + }, + JvmPlatformParameters { + val file = (it as JavaClassImpl).psi.containingFile.virtualFile + if (file in sourcesScope) + module + else + library + }, CompilerEnvironment, - packagePartProviderFactory = { info, content -> JvmPackagePartProvider(environment, content.moduleContentScope) }, + packagePartProviderFactory = { + info, content -> + JvmPackagePartProvider(environment, content.moduleContentScope) + }, builtIns = builtIns ) - + resolverForProject.resolverForModule(library) // Required before module to initialize library properly val resolverForModule = resolverForProject.resolverForModule(module) val moduleDescriptor = resolverForProject.descriptorForModule(module) builtIns.initialize(moduleDescriptor, true) diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index f24c9c2d..a7a50f91 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -23,11 +23,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, body() if (checkEndsWith && to.endsWith(suffix)) { to.setLength(to.length - suffix.length) - } - else if (to.length > startLength + prefix.length) { + } else if (to.length > startLength + prefix.length) { to.append(suffix) - } - else { + } else { to.setLength(startLength) } } @@ -124,8 +122,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val child = content.children.singleOrNull() if (child is ContentParagraph) { appendContent(child.children) - } - else { + } else { appendContent(content.children) } } @@ -361,7 +358,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } inner class SingleNodePageBuilder(val node: DocumentationNode) - : PageBuilder(listOf(node)) { + : PageBuilder(listOf(node)) { override fun build() { super.build() @@ -372,14 +369,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } appendSection("Packages", node.members(NodeKind.Package)) - appendSection("Types", node.members.filter { it.kind in NodeKind.classLike && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception }) + appendSection("Types", node.members.filter { it.kind in NodeKind.classLike && it.kind != NodeKind.TypeAlias && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception }) appendSection("Annotations", node.members(NodeKind.AnnotationClass)) appendSection("Exceptions", node.members(NodeKind.Exception)) + appendSection("Type Aliases", node.members(NodeKind.TypeAlias)) appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass)) appendSection("Enum Values", node.members(NodeKind.EnumItem), sortMembers = false) appendSection("Constructors", node.members(NodeKind.Constructor)) appendSection("Properties", node.members(NodeKind.Property)) - appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property)) + appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property)) appendSection("Functions", node.members(NodeKind.Function)) appendSection("Inherited Functions", node.inheritedMembers(NodeKind.Function)) appendSection("Companion Object Properties", node.members(NodeKind.CompanionObjectProperty)) @@ -394,6 +392,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, NodeKind.Object, NodeKind.AnnotationClass, NodeKind.Exception, + NodeKind.TypeAlias, NodeKind.Constructor, NodeKind.Property, NodeKind.Package, @@ -472,7 +471,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } inner class AllTypesNodeBuilder(val node: DocumentationNode) - : PageBuilder(listOf(node)) { + : PageBuilder(listOf(node)) { override fun build() { appendContent(node.owner!!.summary) @@ -508,12 +507,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (singleNode != null) { if (singleNode.kind == NodeKind.AllTypes) { AllTypesNodeBuilder(singleNode).build() - } - else { + } else { SingleNodePageBuilder(singleNode).build() } - } - else { + } else { PageBuilder(nodes).build() } } diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index ecb6edf2..f922a25b 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -25,10 +25,7 @@ import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.supertypes @@ -61,13 +58,12 @@ interface PackageDocumentationBuilder { } class DocumentationBuilder - @Inject constructor(val resolutionFacade: DokkaResolutionFacade, - val descriptorDocumentationParser: DescriptorDocumentationParser, - val options: DocumentationOptions, - val refGraph: NodeReferenceGraph, - val logger: DokkaLogger, - val linkResolver: DeclarationLinkResolver) -{ +@Inject constructor(val resolutionFacade: DokkaResolutionFacade, + val descriptorDocumentationParser: DescriptorDocumentationParser, + val options: DocumentationOptions, + val refGraph: NodeReferenceGraph, + val logger: DokkaLogger, + val linkResolver: DeclarationLinkResolver) { val boringBuiltinClasses = setOf( "kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean", "kotlin.Float", "kotlin.Double", "kotlin.String", "kotlin.Array", "kotlin.Any") @@ -97,7 +93,7 @@ class DocumentationBuilder return node } - private fun DocumentationNode.withModifiers(descriptor: DeclarationDescriptor) : DocumentationNode{ + private fun DocumentationNode.withModifiers(descriptor: DeclarationDescriptor): DocumentationNode { if (descriptor is MemberDescriptor) { appendVisibility(descriptor) if (descriptor !is ConstructorDescriptor) { @@ -124,15 +120,15 @@ class DocumentationBuilder appendTextNode(modifier, NodeKind.Modifier) } - fun DocumentationNode.appendSupertypes(descriptor: ClassDescriptor) { - val superTypes = descriptor.typeConstructor.supertypes - for (superType in superTypes) { - if (!ignoreSupertype(superType)) { - appendType(superType, NodeKind.Supertype) - val superclass = superType?.constructor?.declarationDescriptor - link(superclass, descriptor, RefKind.Inheritor) - link(descriptor, superclass, RefKind.Superclass) - } + fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType) { + val unwrappedType = superType.unwrap() + if (unwrappedType is AbbreviatedType) { + appendSupertype(descriptor, unwrappedType.abbreviation) + } else if (!ignoreSupertype(unwrappedType)) { + appendType(unwrappedType, NodeKind.Supertype) + val superclass = unwrappedType.constructor.declarationDescriptor + link(superclass, descriptor, RefKind.Inheritor) + link(descriptor, superclass, RefKind.Superclass) } } @@ -148,8 +144,7 @@ class DocumentationBuilder fun DocumentationNode.appendProjection(projection: TypeProjection, kind: NodeKind = NodeKind.Type) { if (projection.isStarProjection) { appendTextNode("*", NodeKind.Type) - } - else { + } else { appendType(projection.type, kind, projection.projectionKind.label) } } @@ -157,14 +152,17 @@ class DocumentationBuilder fun DocumentationNode.appendType(kotlinType: KotlinType?, kind: NodeKind = NodeKind.Type, prefix: String = "") { if (kotlinType == null) return + (kotlinType.unwrap() as? AbbreviatedType)?.let { + return appendType(it.abbreviation) + } + val classifierDescriptor = kotlinType.constructor.declarationDescriptor val name = when (classifierDescriptor) { is ClassDescriptor -> { if (classifierDescriptor.isCompanionObject) { classifierDescriptor.containingDeclaration.name.asString() + "." + classifierDescriptor.name.asString() - } - else { + } else { classifierDescriptor.name.asString() } } @@ -182,8 +180,7 @@ class DocumentationBuilder val jdkLink = linkResolver.buildJdkLink(classifierDescriptor) if (jdkLink != null) { node.append(DocumentationNode(jdkLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) - } - else { + } else { link(node, classifierDescriptor, if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link) } @@ -197,7 +194,7 @@ class DocumentationBuilder } fun ClassifierDescriptor.isBoringBuiltinClass(): Boolean = - DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses + DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses fun DocumentationNode.appendAnnotations(annotated: Annotated) { annotated.annotations.filter { it.isDocumented() }.forEach { @@ -250,8 +247,7 @@ class DocumentationBuilder link(this, baseDescriptor, inheritedLinkKind) } null - } - else { + } else { val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original appendChild(descriptorToUse, RefKind.Member) } @@ -378,9 +374,25 @@ class DocumentationBuilder is TypeParameterDescriptor -> build() is ValueParameterDescriptor -> build() is ReceiverParameterDescriptor -> build() + is TypeAliasDescriptor -> build() else -> throw IllegalStateException("Descriptor $this is not known") } + fun TypeAliasDescriptor.build(): DocumentationNode { + val node = nodeForDescriptor(this, NodeKind.TypeAlias) + + node.appendAnnotations(this) + node.appendModifiers(this) + node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) + + node.appendType(underlyingType, NodeKind.TypeAliasUnderlyingType) + + node.appendSourceLink(source) + + register(this, node) + return node + } + fun ClassDescriptor.build(): DocumentationNode { val kind = when { kind == ClassKind.OBJECT -> NodeKind.Object @@ -392,7 +404,9 @@ class DocumentationBuilder else -> NodeKind.Class } val node = nodeForDescriptor(this, kind) - node.appendSupertypes(this) + typeConstructor.supertypes.forEach { + node.appendSupertype(this, it) + } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) val constructorsToDocument = if (getKind() == ClassKind.ENUM_CLASS) @@ -572,8 +586,7 @@ class DocumentationBuilder var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!! if ((receiverClass as? ClassDescriptor)?.isCompanionObject ?: false) { receiverClass = receiverClass.containingDeclaration!! - } - else if (receiverClass is TypeParameterDescriptor) { + } else if (receiverClass is TypeParameterDescriptor) { val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor if (upperBoundClass != null) { receiverClass = upperBoundClass @@ -648,11 +661,10 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { } class KotlinJavaDocumentationBuilder - @Inject constructor(val resolutionFacade: DokkaResolutionFacade, - val documentationBuilder: DocumentationBuilder, - val options: DocumentationOptions, - val logger: DokkaLogger) : JavaDocumentationBuilder -{ +@Inject constructor(val resolutionFacade: DokkaResolutionFacade, + val documentationBuilder: DocumentationBuilder, + val options: DocumentationOptions, + val logger: DokkaLogger) : JavaDocumentationBuilder { override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) { val classDescriptors = file.classes.map { val javaDescriptorResolver = resolutionFacade.getFrontendService(JavaDescriptorResolver::class.java) @@ -731,8 +743,12 @@ fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor return null } -fun DeclarationDescriptor.signature(): String = when(this) { - is ClassDescriptor, is PackageFragmentDescriptor, is PackageViewDescriptor -> DescriptorUtils.getFqName(this).asString() +fun DeclarationDescriptor.signature(): String = when (this) { + is ClassDescriptor, + is PackageFragmentDescriptor, + is PackageViewDescriptor, + is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() + is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index a0d8f95d..6fcf3772 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -315,6 +315,7 @@ class KotlinLanguageService : LanguageService { NodeKind.Interface -> keyword("interface ") NodeKind.EnumItem -> keyword("enum val ") NodeKind.Object -> keyword("object ") + NodeKind.TypeAlias -> keyword("typealias ") else -> throw IllegalArgumentException("Node $node is not a class-like object") } @@ -322,6 +323,13 @@ class KotlinLanguageService : LanguageService { renderTypeParametersForNode(node, renderMode) renderSupertypesForNode(node, renderMode) renderExtraTypeParameterConstraints(node, renderMode) + + if (node.kind == NodeKind.TypeAlias) { + nbsp() + symbol("=") + nbsp() + renderType(node.detail(NodeKind.TypeAliasUnderlyingType), renderMode) + } } private fun ContentBlock.renderFunction(node: DocumentationNode, diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 9aacbca0..def0f626 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -13,6 +13,7 @@ enum class NodeKind { Exception, EnumItem, Object, + TypeAlias, Constructor, Function, @@ -30,6 +31,8 @@ enum class NodeKind { UpperBound, LowerBound, + TypeAliasUnderlyingType, + Modifier, NullabilityModifier, @@ -55,7 +58,7 @@ enum class NodeKind { OverloadGroupNote; companion object { - val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object) + val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias) } } diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 7f0922ba..6e4c44c8 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -27,8 +27,6 @@ class MarkdownFormatTest { verifyMarkdownPackage("annotationClass", withKotlinRuntime = true) } - //TODO: Enable after typealias support - @Ignore("Disabled until we will correctly support typealias") @Test fun exceptionClass() { verifyMarkdownNode("exceptionClass", withKotlinRuntime = true) verifyMarkdownPackage("exceptionClass", withKotlinRuntime = true) @@ -229,6 +227,11 @@ class MarkdownFormatTest { verifyMarkdownNodeByName("qualifiedNameLink", "foo", withKotlinRuntime = true) } + @Test fun typeAliases() { + verifyMarkdownNode("typeAliases") + verifyMarkdownPackage("typeAliases") + } + private fun verifyMarkdownPackage(fileName: String, withKotlinRuntime: Boolean = false) { verifyOutput("testdata/format/$fileName.kt", ".package.md", withKotlinRuntime = withKotlinRuntime) { model, output -> markdownService.createOutputBuilder(output, tempLocation).appendNodes(model.members) diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 41d22b47..4c0f7f0f 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka.javadoc +import com.sun.javadoc.Type import org.jetbrains.dokka.DokkaConsoleLogger import org.jetbrains.dokka.tests.verifyModel import org.junit.Assert.* @@ -107,6 +108,22 @@ class JavadocTest { } } + @Test fun testTypeAliases() { + verifyJavadoc("testdata/javadoc/typealiases.kt", withKotlinRuntime = true) { doc -> + assertNull(doc.classNamed("B")) + assertNull(doc.classNamed("D")) + + assertEquals("A", doc.classNamed("C")!!.superclass().name()) + val methodParamType = doc.classNamed("TypealiasesKt")!!.methods() + .find { it.name() == "some" }!!.parameters().first() + .type() + assertEquals("kotlin.jvm.functions.Function1", methodParamType.qualifiedTypeName()) + assertEquals("? super A, C", methodParamType.asParameterizedType().typeArguments() + .map(Type::qualifiedTypeName).joinToString()) + } + } + + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/src/test/kotlin/model/TypeAliasTest.kt b/core/src/test/kotlin/model/TypeAliasTest.kt new file mode 100644 index 00000000..812fd9dc --- /dev/null +++ b/core/src/test/kotlin/model/TypeAliasTest.kt @@ -0,0 +1,123 @@ +package org.jetbrains.dokka.tests + +import junit.framework.TestCase.assertEquals +import org.jetbrains.dokka.Content +import org.jetbrains.dokka.NodeKind +import org.junit.Test + +class TypeAliasTest { + @Test + fun testSimple() { + verifyModel("testdata/typealias/simple.kt") { + val pkg = it.members.single() + with(pkg.member(NodeKind.TypeAlias)) { + assertEquals(Content.Empty, content) + assertEquals("B", name) + assertEquals("A", detail(NodeKind.TypeAliasUnderlyingType).name) + } + } + } + + @Test + fun testInheritanceFromTypeAlias() { + verifyModel("testdata/typealias/inheritanceFromTypeAlias.kt") { + val pkg = it.members.single() + with(pkg.member(NodeKind.TypeAlias)) { + assertEquals(Content.Empty, content) + assertEquals("Same", name) + assertEquals("Some", detail(NodeKind.TypeAliasUnderlyingType).name) + assertEquals("My", inheritors.single().name) + } + with(pkg.members(NodeKind.Class).find { it.name == "My" }!!) { + assertEquals("Same", detail(NodeKind.Supertype).name) + } + } + } + + @Test + fun testChain() { + verifyModel("testdata/typealias/chain.kt") { + val pkg = it.members.single() + with(pkg.members(NodeKind.TypeAlias).find { it.name == "B" }!!) { + assertEquals(Content.Empty, content) + assertEquals("A", detail(NodeKind.TypeAliasUnderlyingType).name) + } + with(pkg.members(NodeKind.TypeAlias).find { it.name == "C" }!!) { + assertEquals(Content.Empty, content) + assertEquals("B", detail(NodeKind.TypeAliasUnderlyingType).name) + } + } + } + + @Test + fun testDocumented() { + verifyModel("testdata/typealias/documented.kt") { + val pkg = it.members.single() + with(pkg.member(NodeKind.TypeAlias)) { + assertEquals("Just typealias", content.summary.toTestString()) + } + } + } + + @Test + fun testDeprecated() { + verifyModel("testdata/typealias/deprecated.kt") { + val pkg = it.members.single() + with(pkg.member(NodeKind.TypeAlias)) { + assertEquals(Content.Empty, content) + assertEquals("Deprecated", deprecation!!.name) + assertEquals("\"Not mainstream now\"", deprecation!!.detail(NodeKind.Parameter).detail(NodeKind.Value).name) + } + } + } + + @Test + fun testGeneric() { + verifyModel("testdata/typealias/generic.kt") { + val pkg = it.members.single() + with(pkg.members(NodeKind.TypeAlias).find { it.name == "B" }!!) { + assertEquals("Any", detail(NodeKind.TypeAliasUnderlyingType).detail(NodeKind.Type).name) + } + + with(pkg.members(NodeKind.TypeAlias).find { it.name == "C" }!!) { + assertEquals("T", detail(NodeKind.TypeAliasUnderlyingType).detail(NodeKind.Type).name) + assertEquals("T", detail(NodeKind.TypeParameter).name) + } + } + } + + @Test + fun testFunctional() { + verifyModel("testdata/typealias/functional.kt") { + val pkg = it.members.single() + with(pkg.member(NodeKind.TypeAlias)) { + assertEquals("Function1", detail(NodeKind.TypeAliasUnderlyingType).name) + val typeParams = detail(NodeKind.TypeAliasUnderlyingType).details(NodeKind.Type) + assertEquals("A", typeParams.first().name) + assertEquals("B", typeParams.last().name) + } + + with(pkg.member(NodeKind.Function)) { + assertEquals("Spell", detail(NodeKind.Parameter).detail(NodeKind.Type).name) + } + } + } + + @Test + fun testAsTypeBoundWithVariance() { + verifyModel("testdata/typealias/asTypeBoundWithVariance.kt") { + val pkg = it.members.single() + with(pkg.members(NodeKind.Class).find { it.name == "C" }!!) { + val tParam = detail(NodeKind.TypeParameter) + assertEquals("out", tParam.detail(NodeKind.Modifier).name) + assertEquals("B", tParam.detail(NodeKind.Type).link(NodeKind.TypeAlias).name) + } + + with(pkg.members(NodeKind.Class).find { it.name == "D" }!!) { + val tParam = detail(NodeKind.TypeParameter) + assertEquals("in", tParam.detail(NodeKind.Modifier).name) + assertEquals("B", tParam.detail(NodeKind.Type).link(NodeKind.TypeAlias).name) + } + } + } +}
\ No newline at end of file diff --git a/core/testdata/format/exceptionClass.md b/core/testdata/format/exceptionClass.md index df3457d7..e3714ecc 100644 --- a/core/testdata/format/exceptionClass.md +++ b/core/testdata/format/exceptionClass.md @@ -2,7 +2,7 @@ # MyException -`class MyException : `[`Exception`](http://docs.oracle.com/javase/6/docs/api/java/lang/Exception.html) +`class MyException : Exception` ### Constructors diff --git a/core/testdata/format/exceptionClass.package.md b/core/testdata/format/exceptionClass.package.md index e27dd0ab..e10478e4 100644 --- a/core/testdata/format/exceptionClass.package.md +++ b/core/testdata/format/exceptionClass.package.md @@ -4,5 +4,5 @@ ### Exceptions -| [MyException](test/-my-exception/index) | `class MyException : `[`Exception`](http://docs.oracle.com/javase/6/docs/api/java/lang/Exception.html) | +| [MyException](test/-my-exception/index) | `class MyException : Exception` | diff --git a/core/testdata/format/typeAliases.kt b/core/testdata/format/typeAliases.kt new file mode 100644 index 00000000..9657963e --- /dev/null +++ b/core/testdata/format/typeAliases.kt @@ -0,0 +1,27 @@ + +class A +class B +class C<T> + +typealias D = A +typealias E = D + +typealias F = (A) -> B + +typealias G = C<A> +typealias H<T> = C<T> + +typealias I<T> = H<T> +typealias J = H<A> + +typealias K = H<J> + +typealias L = (K, B) -> J + +/** + * Documented + */ +typealias M = A + +@Deprecated("!!!") +typealias N = A
\ No newline at end of file diff --git a/core/testdata/format/typeAliases.md b/core/testdata/format/typeAliases.md new file mode 100644 index 00000000..55e9317e --- /dev/null +++ b/core/testdata/format/typeAliases.md @@ -0,0 +1,63 @@ +[test](test/index) / [A](test/-a/index) + +# A + +`class A`[test](test/index) / [B](test/-b/index) + +# B + +`class B`[test](test/index) / [C](test/-c/index) + +# C + +`class C<T>`[test](test/index) / [D](test/-d) + +# D + +`typealias D = `[`A`](test/-a/index)[test](test/index) / [E](test/-e) + +# E + +`typealias E = `[`D`](test/-d)[test](test/index) / [F](test/-f) + +# F + +`typealias F = (`[`A`](test/-a/index)`) -> `[`B`](test/-b/index)[test](test/index) / [G](test/-g) + +# G + +`typealias G = `[`C`](test/-c/index)`<`[`A`](test/-a/index)`>`[test](test/index) / [H](test/-h) + +# H + +`typealias H<T> = `[`C`](test/-c/index)`<T>`[test](test/index) / [I](test/-i) + +# I + +`typealias I<T> = `[`H`](test/-h)`<T>`[test](test/index) / [J](test/-j) + +# J + +`typealias J = `[`H`](test/-h)`<`[`A`](test/-a/index)`>`[test](test/index) / [K](test/-k) + +# K + +`typealias K = `[`H`](test/-h)`<`[`J`](test/-j)`>`[test](test/index) / [L](test/-l) + +# L + +`typealias L = (`[`K`](test/-k)`, `[`B`](test/-b/index)`) -> `[`J`](test/-j)[test](test/index) / [M](test/-m) + +# M + +`typealias M = `[`A`](test/-a/index) + +Documented + +[test](test/index) / [N](test/-n) + +# N + +`typealias ~~N~~ = `[`A`](test/-a/index) +**Deprecated:** !!! + diff --git a/core/testdata/format/typeAliases.package.md b/core/testdata/format/typeAliases.package.md new file mode 100644 index 00000000..0eff1ed5 --- /dev/null +++ b/core/testdata/format/typeAliases.package.md @@ -0,0 +1,24 @@ +[test](test/index) + +## Package <root> + +### Types + +| [A](test/-a/index) | `class A` | +| [B](test/-b/index) | `class B` | +| [C](test/-c/index) | `class C<T>` | + +### Type Aliases + +| [D](test/-d) | `typealias D = `[`A`](test/-a/index) | +| [E](test/-e) | `typealias E = `[`D`](test/-d) | +| [F](test/-f) | `typealias F = (`[`A`](test/-a/index)`) -> `[`B`](test/-b/index) | +| [G](test/-g) | `typealias G = `[`C`](test/-c/index)`<`[`A`](test/-a/index)`>` | +| [H](test/-h) | `typealias H<T> = `[`C`](test/-c/index)`<T>` | +| [I](test/-i) | `typealias I<T> = `[`H`](test/-h)`<T>` | +| [J](test/-j) | `typealias J = `[`H`](test/-h)`<`[`A`](test/-a/index)`>` | +| [K](test/-k) | `typealias K = `[`H`](test/-h)`<`[`J`](test/-j)`>` | +| [L](test/-l) | `typealias L = (`[`K`](test/-k)`, `[`B`](test/-b/index)`) -> `[`J`](test/-j) | +| [M](test/-m) | `typealias M = `[`A`](test/-a/index)<br>Documented | +| [N](test/-n) | `typealias ~~N~~ = `[`A`](test/-a/index) | + diff --git a/core/testdata/javadoc/typealiases.kt b/core/testdata/javadoc/typealiases.kt new file mode 100644 index 00000000..bb09bfad --- /dev/null +++ b/core/testdata/javadoc/typealiases.kt @@ -0,0 +1,11 @@ +class A + +typealias B = A + +class C : B + +typealias D = (A) -> C + +fun some(d: D) { + +}
\ No newline at end of file diff --git a/core/testdata/typealias/asTypeBoundWithVariance.kt b/core/testdata/typealias/asTypeBoundWithVariance.kt new file mode 100644 index 00000000..1aef84d6 --- /dev/null +++ b/core/testdata/typealias/asTypeBoundWithVariance.kt @@ -0,0 +1,7 @@ +package _typealias.astypebound +class A + +typealias B = A + +class C<out T : B> +class D<in T : B>
\ No newline at end of file diff --git a/core/testdata/typealias/chain.kt b/core/testdata/typealias/chain.kt new file mode 100644 index 00000000..520be553 --- /dev/null +++ b/core/testdata/typealias/chain.kt @@ -0,0 +1,8 @@ +package _typealias.chain + +class A + +typealias B = A + +typealias C = B + diff --git a/core/testdata/typealias/deprecated.kt b/core/testdata/typealias/deprecated.kt new file mode 100644 index 00000000..b53d3a20 --- /dev/null +++ b/core/testdata/typealias/deprecated.kt @@ -0,0 +1,7 @@ +package _typealias.deprecated + +class Lol + +@Deprecated("Not mainstream now") +typealias Kek = Lol + diff --git a/core/testdata/typealias/documented.kt b/core/testdata/typealias/documented.kt new file mode 100644 index 00000000..3ca110e5 --- /dev/null +++ b/core/testdata/typealias/documented.kt @@ -0,0 +1,9 @@ +package _typealias.documented + +class A + +/** + * Just typealias + */ +typealias B = A + diff --git a/core/testdata/typealias/functional.kt b/core/testdata/typealias/functional.kt new file mode 100644 index 00000000..dadafa5e --- /dev/null +++ b/core/testdata/typealias/functional.kt @@ -0,0 +1,10 @@ +package _typealias.functional + +class A +class B + +typealias Spell = (A) -> B + +fun magic(spell: Spell) { + +}
\ No newline at end of file diff --git a/core/testdata/typealias/generic.kt b/core/testdata/typealias/generic.kt new file mode 100644 index 00000000..43bc0e23 --- /dev/null +++ b/core/testdata/typealias/generic.kt @@ -0,0 +1,7 @@ +package _typealias.generic + +interface A<T> + +typealias B = A<Any> + +typealias C<T> = A<T>
\ No newline at end of file diff --git a/core/testdata/typealias/inheritanceFromTypeAlias.kt b/core/testdata/typealias/inheritanceFromTypeAlias.kt new file mode 100644 index 00000000..f929ecd0 --- /dev/null +++ b/core/testdata/typealias/inheritanceFromTypeAlias.kt @@ -0,0 +1,7 @@ +package _typealias.inheritance + +open class Some + +typealias Same = Some + +class My : Same
\ No newline at end of file diff --git a/core/testdata/typealias/simple.kt b/core/testdata/typealias/simple.kt new file mode 100644 index 00000000..d688a84d --- /dev/null +++ b/core/testdata/typealias/simple.kt @@ -0,0 +1,5 @@ +package _typealias.simple + +class A + +typealias B = A
\ No newline at end of file |