aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--.gitignore3
-rw-r--r--.idea/.name1
-rw-r--r--.idea/artifacts/dokka_jar.xml9
-rw-r--r--.idea/artifacts/dokka_zip.xml27
-rw-r--r--.idea/artifacts/javadoc_jar.xml8
-rw-r--r--.idea/compiler.xml40
-rw-r--r--.idea/copyright/profiles_settings.xml4
-rw-r--r--.idea/encodings.xml2
-rw-r--r--.idea/inspectionProfiles/Project_Default.xml7
-rw-r--r--.idea/inspectionProfiles/profiles_settings.xml8
-rw-r--r--.idea/kotlinc.xml2
-rw-r--r--.idea/misc.xml27
-rw-r--r--.idea/modules.xml39
-rw-r--r--.idea/runConfigurations/All_tests.xml7
-rw-r--r--.idea/runConfigurations/Core_tests.xml21
-rw-r--r--.idea/runConfigurations/Dokka.xml23
-rw-r--r--.idea/runConfigurations/Gradle_integration_tests.xml21
-rw-r--r--.idea/runConfigurations/Playground.xml9
-rw-r--r--.idea/runConfigurations/Stdlib.xml23
-rw-r--r--.idea/runConfigurations/Stdlib_Javadoc.xml15
-rw-r--r--README.md480
-rw-r--r--build.gradle44
-rw-r--r--buildSrc/build.gradle4
-rw-r--r--buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy9
-rw-r--r--core/build.gradle10
-rw-r--r--core/src/main/kotlin/Analysis/AnalysisEnvironment.kt221
-rw-r--r--core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt3
-rw-r--r--core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt164
-rw-r--r--core/src/main/kotlin/DokkaBootstrapImpl.kt70
-rw-r--r--core/src/main/kotlin/Formats/FormatDescriptor.kt1
-rw-r--r--core/src/main/kotlin/Formats/FormatService.kt2
-rw-r--r--core/src/main/kotlin/Formats/HtmlFormatService.kt6
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt224
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt136
-rw-r--r--core/src/main/kotlin/Formats/MarkdownFormatService.kt39
-rw-r--r--core/src/main/kotlin/Formats/PackageListService.kt11
-rw-r--r--core/src/main/kotlin/Formats/StandardFormats.kt11
-rw-r--r--core/src/main/kotlin/Formats/StructuredFormatService.kt756
-rw-r--r--core/src/main/kotlin/Formats/YamlOutlineService.kt2
-rw-r--r--core/src/main/kotlin/Generation/DocumentationMerger.kt229
-rw-r--r--core/src/main/kotlin/Generation/DokkaGenerator.kt93
-rw-r--r--core/src/main/kotlin/Generation/FileGenerator.kt87
-rw-r--r--core/src/main/kotlin/Generation/configurationImpl.kt64
-rw-r--r--core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt29
-rw-r--r--core/src/main/kotlin/Java/JavadocParser.kt7
-rw-r--r--core/src/main/kotlin/Kotlin/ContentBuilder.kt2
-rw-r--r--core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt11
-rw-r--r--core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt8
-rw-r--r--core/src/main/kotlin/Kotlin/DocumentationBuilder.kt172
-rw-r--r--core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt115
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt5
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt11
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinLanguageService.kt4
-rw-r--r--core/src/main/kotlin/Languages/JavaLanguageService.kt8
-rw-r--r--core/src/main/kotlin/Locations/Location.kt19
-rw-r--r--core/src/main/kotlin/Model/Content.kt14
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt39
-rw-r--r--core/src/main/kotlin/Model/DocumentationReference.kt68
-rw-r--r--core/src/main/kotlin/Model/PackageDocs.kt2
-rw-r--r--core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt8
-rw-r--r--core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt86
-rw-r--r--core/src/main/kotlin/Utilities/DokkaModules.kt25
-rw-r--r--core/src/main/kotlin/Utilities/ServiceLocator.kt7
-rw-r--r--core/src/main/kotlin/javadoc/docbase.kt119
-rw-r--r--core/src/main/kotlin/javadoc/dokka-adapters.kt9
-rw-r--r--core/src/main/resources/dokka/format/kotlin-website-samples.properties2
-rw-r--r--core/src/main/resources/dokka/format/kotlin-website.properties2
-rw-r--r--core/src/test/kotlin/DokkaConfigurationTestImplementations.kt81
-rw-r--r--core/src/test/kotlin/TestAPI.kt302
-rw-r--r--core/src/test/kotlin/format/GFMFormatTest.kt18
-rw-r--r--core/src/test/kotlin/format/HtmlFormatTest.kt161
-rw-r--r--core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt73
-rw-r--r--core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt79
-rw-r--r--core/src/test/kotlin/format/KotlinWebSiteRunnableSamplesFormatTest.kt39
-rw-r--r--core/src/test/kotlin/format/MarkdownFormatTest.kt453
-rw-r--r--core/src/test/kotlin/issues/IssuesTest.kt16
-rw-r--r--core/src/test/kotlin/javadoc/JavadocTest.kt90
-rw-r--r--core/src/test/kotlin/model/ClassTest.kt125
-rw-r--r--core/src/test/kotlin/model/CommentTest.kt36
-rw-r--r--core/src/test/kotlin/model/FunctionTest.kt69
-rw-r--r--core/src/test/kotlin/model/JavaTest.kt34
-rw-r--r--core/src/test/kotlin/model/KotlinAsJavaTest.kt17
-rw-r--r--core/src/test/kotlin/model/LinkTest.kt32
-rw-r--r--core/src/test/kotlin/model/PackageTest.kt57
-rw-r--r--core/src/test/kotlin/model/PropertyTest.kt68
-rw-r--r--core/src/test/kotlin/model/SourceLinksErrorTest.kt5
-rw-r--r--core/src/test/kotlin/model/SourceLinksTest.kt5
-rw-r--r--core/src/test/kotlin/model/TypeAliasTest.kt20
-rw-r--r--core/testdata/format/JavaSupertype.html6
-rw-r--r--core/testdata/format/accessor.md2
-rw-r--r--core/testdata/format/annotatedTypeParameter.md2
-rw-r--r--core/testdata/format/annotationClass.md2
-rw-r--r--core/testdata/format/annotationClass.package.md2
-rw-r--r--core/testdata/format/annotationParams.md2
-rw-r--r--core/testdata/format/annotations.md2
-rw-r--r--core/testdata/format/arrayAverage.md2
-rw-r--r--core/testdata/format/backtickInCodeBlock.md2
-rw-r--r--core/testdata/format/blankLineInsideCodeBlock.html2
-rw-r--r--core/testdata/format/blankLineInsideCodeBlock.md2
-rw-r--r--core/testdata/format/bracket.html2
-rw-r--r--core/testdata/format/brokenLink.html2
-rw-r--r--core/testdata/format/classWithCompanionObject.html8
-rw-r--r--core/testdata/format/classWithCompanionObject.md2
-rw-r--r--core/testdata/format/codeBlock.html18
-rw-r--r--core/testdata/format/codeBlock.md12
-rw-r--r--core/testdata/format/codeBlockNoHtmlEscape.md2
-rw-r--r--core/testdata/format/codeSpan.html2
-rw-r--r--core/testdata/format/companionImplements.md4
-rw-r--r--core/testdata/format/companionObjectExtension.md4
-rw-r--r--core/testdata/format/crossLanguage/kotlinExtendsJava/Bar.html7
-rw-r--r--core/testdata/format/deprecated.class.html14
-rw-r--r--core/testdata/format/deprecated.package.html8
-rw-r--r--core/testdata/format/dynamicExtension.md2
-rw-r--r--core/testdata/format/dynamicType.md2
-rw-r--r--core/testdata/format/emptyDescription.md2
-rw-r--r--core/testdata/format/entity.html7
-rw-r--r--core/testdata/format/enumClass.md2
-rw-r--r--core/testdata/format/enumClass.value.md2
-rw-r--r--core/testdata/format/enumRef.md2
-rw-r--r--core/testdata/format/exceptionClass.md2
-rw-r--r--core/testdata/format/exceptionClass.package.md2
-rw-r--r--core/testdata/format/exclInCodeBlock.md2
-rw-r--r--core/testdata/format/extensionFunctionParameter.md2
-rw-r--r--core/testdata/format/extensionScope.md2
-rw-r--r--core/testdata/format/extensionWithDocumentedReceiver.md2
-rw-r--r--core/testdata/format/extensions.class.md4
-rw-r--r--core/testdata/format/externalReferenceLink.md2
-rw-r--r--core/testdata/format/functionWithDefaultParameter.md2
-rw-r--r--core/testdata/format/functionalTypeWithNamedParameters.html26
-rw-r--r--core/testdata/format/functionalTypeWithNamedParameters.md20
-rw-r--r--core/testdata/format/genericInheritedExtensions.md2
-rw-r--r--core/testdata/format/gfm/listInTableCell.md4
-rw-r--r--core/testdata/format/gfm/sample.md8
-rw-r--r--core/testdata/format/htmlEscaping.html2
-rw-r--r--core/testdata/format/inapplicableExtensionFunctions.md2
-rw-r--r--core/testdata/format/indentedCodeBlock.html2
-rw-r--r--core/testdata/format/indentedCodeBlock.md2
-rw-r--r--core/testdata/format/inheritedCompanionObjectProperties.md2
-rw-r--r--core/testdata/format/inheritedExtensions.md2
-rw-r--r--core/testdata/format/inheritedMembers.md2
-rw-r--r--core/testdata/format/inlineSuspendFunction.kt2
-rw-r--r--core/testdata/format/inlineSuspendFunction.md4
-rw-r--r--core/testdata/format/javaCodeInParam.md2
-rw-r--r--core/testdata/format/javaCodeLiteralTags.md4
-rw-r--r--core/testdata/format/javaDeprecated.html2
-rw-r--r--core/testdata/format/javaLinkTag.html9
-rw-r--r--core/testdata/format/javaLinkTagWithLabel.html9
-rw-r--r--core/testdata/format/javaSeeTag.html6
-rw-r--r--core/testdata/format/javaSpaceInAuthor.md2
-rw-r--r--core/testdata/format/javadocHtml.md4
-rw-r--r--core/testdata/format/javadocOrderedList.md6
-rw-r--r--core/testdata/format/jdkLinks.md4
-rw-r--r--core/testdata/format/linkWithLabel.html9
-rw-r--r--core/testdata/format/linkWithStarProjection.html4
-rw-r--r--core/testdata/format/linksInEmphasis.md4
-rw-r--r--core/testdata/format/linksInHeaders.md4
-rw-r--r--core/testdata/format/linksInStrong.md4
-rw-r--r--core/testdata/format/markdownInLinks.html2
-rw-r--r--core/testdata/format/memberExtension.md2
-rw-r--r--core/testdata/format/multiplatform/breadcrumbsInMemberOfMemberOfGroupNode/multiplatform.md7
-rw-r--r--core/testdata/format/multiplatform/groupNode/multiplatform.md12
-rw-r--r--core/testdata/format/multiplatform/groupNode/multiplatform.package.md8
-rw-r--r--core/testdata/format/multiplatform/implied/foo.md16
-rw-r--r--core/testdata/format/multiplatform/merge/multiplatform.package.md4
-rw-r--r--core/testdata/format/multiplatform/mergeMembers/foo.md18
-rw-r--r--core/testdata/format/multiplatform/omitRedundant/foo.md10
-rw-r--r--core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.index.md4
-rw-r--r--core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.package.md4
-rw-r--r--core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.index.md4
-rw-r--r--core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.package.md4
-rw-r--r--core/testdata/format/multiplatform/simple/multiplatform.package.md4
-rw-r--r--core/testdata/format/multipleTypeParameterConstraints.md12
-rw-r--r--core/testdata/format/nestedLists.md4
-rw-r--r--core/testdata/format/newlineInTableCell.package.md4
-rw-r--r--core/testdata/format/notPublishedTypeAliasAutoExpansion.md2
-rw-r--r--core/testdata/format/nullability.md2
-rw-r--r--core/testdata/format/nullableTypeParameterFunction.md2
-rw-r--r--core/testdata/format/operatorOverloading.md2
-rw-r--r--core/testdata/format/orderedList.html7
-rw-r--r--core/testdata/format/overloads.html9
-rw-r--r--core/testdata/format/overloadsWithDescription.html2
-rw-r--r--core/testdata/format/overloadsWithDifferentDescriptions.html2
-rw-r--r--core/testdata/format/overridingFunction.md2
-rw-r--r--core/testdata/format/paramTag.md2
-rw-r--r--core/testdata/format/parameterAnchor.html2
-rw-r--r--core/testdata/format/parenthesis.html2
-rw-r--r--core/testdata/format/propertyVar.md2
-rw-r--r--core/testdata/format/qualifiedNameLink.md2
-rw-r--r--core/testdata/format/receiverParameterTypeBound.md2
-rw-r--r--core/testdata/format/receiverReference.md4
-rw-r--r--core/testdata/format/reifiedTypeParameter.kt2
-rw-r--r--core/testdata/format/reifiedTypeParameter.md4
-rw-r--r--core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md2
-rw-r--r--core/testdata/format/returnWithLink.html2
-rw-r--r--core/testdata/format/see.html12
-rw-r--r--core/testdata/format/shadowedExtensionFunctions.md2
-rw-r--r--core/testdata/format/sinceKotlin.html10
-rw-r--r--core/testdata/format/sinceKotlin.md6
-rw-r--r--core/testdata/format/sinceKotlin.package.md6
-rw-r--r--core/testdata/format/sinceKotlinWide.package.md8
-rw-r--r--core/testdata/format/starProjection.md2
-rw-r--r--core/testdata/format/summarizeSignatures.md2
-rw-r--r--core/testdata/format/summarizeSignaturesProperty.md2
-rw-r--r--core/testdata/format/suspendInlineFunction.md4
-rw-r--r--core/testdata/format/suspendParam.md2
-rw-r--r--core/testdata/format/suspendParam.package.md2
-rw-r--r--core/testdata/format/throwsTag.md2
-rw-r--r--core/testdata/format/tokensInEmphasis.md4
-rw-r--r--core/testdata/format/tokensInHeaders.md4
-rw-r--r--core/testdata/format/tokensInStrong.md4
-rw-r--r--core/testdata/format/tripleBackticks.html2
-rw-r--r--core/testdata/format/typeAliases.md56
-rw-r--r--core/testdata/format/typeAliases.package.md7
-rw-r--r--core/testdata/format/typeLink.html4
-rw-r--r--core/testdata/format/typeParameterBounds.md2
-rw-r--r--core/testdata/format/typeParameterReference.md2
-rw-r--r--core/testdata/format/typeParameterVariance.md2
-rw-r--r--core/testdata/format/typeProjectionVariance.md2
-rw-r--r--core/testdata/format/uninterpretedEmphasisCharacters.html2
-rw-r--r--core/testdata/format/unorderedLists.md4
-rw-r--r--core/testdata/format/varargsFunction.md2
-rw-r--r--core/testdata/format/website-html/dataTags/multiplatform.package.html139
-rw-r--r--core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.html61
-rw-r--r--core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.package.html54
-rw-r--r--core/testdata/format/website-html/dropImport.html8
-rw-r--r--core/testdata/format/website-html/newLinesInImportList.html8
-rw-r--r--core/testdata/format/website-html/newLinesInSamples.html8
-rw-r--r--core/testdata/format/website-html/overloadGroup.html12
-rw-r--r--core/testdata/format/website-html/returnTag.html6
-rw-r--r--core/testdata/format/website-html/sample.html14
-rw-r--r--core/testdata/format/website-html/sampleWithAsserts.html10
-rw-r--r--core/testdata/format/website-html/sampleWithAsserts.kt2
-rw-r--r--core/testdata/functions/inlineFunction.kt2
-rw-r--r--core/testdata/functions/inlineSuspendFunction.kt2
-rw-r--r--core/testdata/functions/suspendInlineFunction.kt2
-rw-r--r--core/testdata/javadoc/functionParameters.java17
-rw-r--r--core/testdata/links/linkToExternalSite.kt4
-rw-r--r--gradle.properties15
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin54708 -> 56172 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--gradlew.bat168
-rw-r--r--integration/build.gradle11
-rw-r--r--integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt128
-rw-r--r--integration/src/main/kotlin/org/jetbrains/dokka/defaultConfiguration.kt73
-rw-r--r--runners/android-gradle-plugin/build.gradle101
-rw-r--r--runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt40
-rw-r--r--runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties2
-rw-r--r--runners/ant/build.gradle4
-rw-r--r--runners/ant/src/main/kotlin/ant/dokka.kt221
-rw-r--r--runners/cli/build.gradle8
-rw-r--r--runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt185
-rw-r--r--runners/cli/src/main/kotlin/cli/main.kt334
-rw-r--r--runners/gradle-integration-tests/build.gradle15
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt4
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt8
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt2
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt4
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt54
-rw-r--r--runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt10
-rw-r--r--runners/gradle-integration-tests/testData/androidApp/app/build.gradle9
-rw-r--r--runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle5
-rw-r--r--runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle14
-rw-r--r--runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle18
-rw-r--r--runners/gradle-integration-tests/testData/basic/build.gradle6
-rw-r--r--runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle11
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/build.gradle60
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt17
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle1
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt14
-rw-r--r--runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt20
-rw-r--r--runners/gradle-integration-tests/testData/sourcesChange/build.gradle6
-rw-r--r--runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle53
-rw-r--r--runners/gradle-plugin/build.gradle17
-rw-r--r--runners/gradle-plugin/src/main/kotlin/main.kt499
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt217
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt353
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt (renamed from runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt)8
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt150
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt58
-rw-r--r--runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt19
-rw-r--r--runners/maven-plugin/build.gradle4
-rw-r--r--runners/maven-plugin/src/main/kotlin/DokkaMojo.kt122
-rw-r--r--settings.gradle1
284 files changed, 5718 insertions, 3853 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..1c119d95
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+gradlew binary
+gradlew.bat binary \ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 59243df5..0c5476ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+*.ipr
+*.iml
doc
### Maven template
@@ -34,6 +36,7 @@ hs_err_pid*
.idea/vcs.xml
.idea/shelf
.idea/jsLibraryMappings.xml
+.idea/modules.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
diff --git a/.idea/.name b/.idea/.name
deleted file mode 100644
index c8bb43f2..00000000
--- a/.idea/.name
+++ /dev/null
@@ -1 +0,0 @@
-dokka \ No newline at end of file
diff --git a/.idea/artifacts/dokka_jar.xml b/.idea/artifacts/dokka_jar.xml
deleted file mode 100644
index 5998df7b..00000000
--- a/.idea/artifacts/dokka_jar.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<component name="ArtifactManager">
- <artifact type="jar" name="dokka:jar">
- <output-path>$PROJECT_DIR$/out/artifacts/</output-path>
- <root id="archive" name="dokka.jar">
- <element id="module-output" name="dokka" />
- <element id="module-output" name="ant" />
- </root>
- </artifact>
-</component> \ No newline at end of file
diff --git a/.idea/artifacts/dokka_zip.xml b/.idea/artifacts/dokka_zip.xml
deleted file mode 100644
index b636e097..00000000
--- a/.idea/artifacts/dokka_zip.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<component name="ArtifactManager">
- <artifact name="dokka:zip">
- <output-path>$PROJECT_DIR$/out/artifacts</output-path>
- <root id="root">
- <element id="archive" name="dokka.zip">
- <element id="directory" name="lib">
- <element id="artifact" artifact-name="dokka:jar" />
- <element id="library" level="project" name="trove4j" />
- <element id="library" level="project" name="jps-model" />
- <element id="library" level="project" name="asm" />
- <element id="library" level="project" name="protobuf" />
- <element id="library" level="project" name="picocontainer" />
- <element id="library" level="project" name="intellij-core-analysis" />
- <element id="library" level="project" name="markdown" />
- <element id="library" level="project" name="kotlin-for-upsource" />
- <element id="library" level="project" name="jsoup" />
- <element id="library" level="project" name="jdom" />
- <element id="library" level="project" name="ant-1.9.4" />
- <element id="library" level="project" name="cli-parser" />
- <element id="library" level="project" name="guava" />
- <element id="library" level="project" name="com.google.inject:guice:4.0" />
- <element id="artifact" artifact-name="javadoc:jar" />
- </element>
- </element>
- </root>
- </artifact>
-</component> \ No newline at end of file
diff --git a/.idea/artifacts/javadoc_jar.xml b/.idea/artifacts/javadoc_jar.xml
deleted file mode 100644
index 0f0eee5b..00000000
--- a/.idea/artifacts/javadoc_jar.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<component name="ArtifactManager">
- <artifact type="jar" name="javadoc:jar">
- <output-path>$PROJECT_DIR$/out/artifacts/javadoc_jar</output-path>
- <root id="archive" name="javadoc.jar">
- <element id="module-output" name="javadoc" />
- </root>
- </artifact>
-</component> \ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 9700d3cc..71547e0e 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -30,6 +30,26 @@
<module name="cli_test" target="1.8" />
<module name="core_main" target="1.8" />
<module name="core_test" target="1.8" />
+ <module name="dokka.buildSrc.main" target="1.8" />
+ <module name="dokka.buildSrc.test" target="1.8" />
+ <module name="dokka.core.main" target="1.8" />
+ <module name="dokka.core.test" target="1.8" />
+ <module name="dokka.integration.main" target="1.8" />
+ <module name="dokka.integration.test" target="1.8" />
+ <module name="dokka.runners.android-gradle-plugin.main" target="1.8" />
+ <module name="dokka.runners.android-gradle-plugin.test" target="1.8" />
+ <module name="dokka.runners.ant.main" target="1.8" />
+ <module name="dokka.runners.ant.test" target="1.8" />
+ <module name="dokka.runners.cli.main" target="1.8" />
+ <module name="dokka.runners.cli.test" target="1.8" />
+ <module name="dokka.runners.fatjar.main" target="1.8" />
+ <module name="dokka.runners.fatjar.test" target="1.8" />
+ <module name="dokka.runners.gradle-integration-tests.main" target="1.8" />
+ <module name="dokka.runners.gradle-integration-tests.test" target="1.8" />
+ <module name="dokka.runners.gradle-plugin.main" target="1.8" />
+ <module name="dokka.runners.gradle-plugin.test" target="1.8" />
+ <module name="dokka.runners.maven-plugin.main" target="1.8" />
+ <module name="dokka.runners.maven-plugin.test" target="1.8" />
<module name="fatjar_main" target="1.8" />
<module name="fatjar_test" target="1.8" />
<module name="gradle-integration-tests_main" target="1.8" />
@@ -40,6 +60,26 @@
<module name="integration_test" target="1.8" />
<module name="maven-plugin_main" target="1.8" />
<module name="maven-plugin_test" target="1.8" />
+ <module name="org.jetbrains.dokka.android-gradle-plugin.main" target="1.8" />
+ <module name="org.jetbrains.dokka.android-gradle-plugin.test" target="1.8" />
+ <module name="org.jetbrains.dokka.ant.main" target="1.8" />
+ <module name="org.jetbrains.dokka.ant.test" target="1.8" />
+ <module name="org.jetbrains.dokka.buildSrc.main" target="1.8" />
+ <module name="org.jetbrains.dokka.buildSrc.test" target="1.8" />
+ <module name="org.jetbrains.dokka.cli.main" target="1.8" />
+ <module name="org.jetbrains.dokka.cli.test" target="1.8" />
+ <module name="org.jetbrains.dokka.core.main" target="1.8" />
+ <module name="org.jetbrains.dokka.core.test" target="1.8" />
+ <module name="org.jetbrains.dokka.fatjar.main" target="1.8" />
+ <module name="org.jetbrains.dokka.fatjar.test" target="1.8" />
+ <module name="org.jetbrains.dokka.gradle-integration-tests.main" target="1.8" />
+ <module name="org.jetbrains.dokka.gradle-integration-tests.test" target="1.8" />
+ <module name="org.jetbrains.dokka.gradle-plugin.main" target="1.8" />
+ <module name="org.jetbrains.dokka.gradle-plugin.test" target="1.8" />
+ <module name="org.jetbrains.dokka.integration.main" target="1.8" />
+ <module name="org.jetbrains.dokka.integration.test" target="1.8" />
+ <module name="org.jetbrains.dokka.maven-plugin.main" target="1.8" />
+ <module name="org.jetbrains.dokka.maven-plugin.test" target="1.8" />
</bytecodeTargetLevel>
</component>
</project> \ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
deleted file mode 100644
index f4aa08e3..00000000
--- a/.idea/copyright/profiles_settings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<component name="CopyrightManager">
- <settings default="" />
-</component> \ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index f7589596..97626ba4 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
- <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
+ <component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project> \ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 06bda8c9..00000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<component name="InspectionProjectProfileManager">
- <profile version="1.0">
- <option name="myName" value="Project Default" />
- <inspection_tool class="MemberVisibilityCanPrivate" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
- <inspection_tool class="PackageDirectoryMismatch" enabled="false" level="WARNING" enabled_by_default="false" />
- </profile>
-</component> \ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 8c1e55e8..00000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<component name="InspectionProjectProfileManager">
- <settings>
- <option name="PROJECT_PROFILE" value="Project Default" />
- <option name="USE_PROJECT_PROFILE" value="true" />
- <version value="1.0" />
- </settings>
-</component> \ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index b072dc00..38d23597 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -6,6 +6,6 @@
</component>
<component name="KotlinCommonCompilerArguments">
<option name="apiVersion" value="1.1" />
- <option name="languageVersion" value="1.1" />
+ <option name="languageVersion" value="1.2" />
</component>
</project> \ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 537aa8e4..e208459b 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,31 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
- <component name="ASMPluginConfiguration">
- <asm skipDebug="false" skipFrames="false" skipCode="false" expandFrames="false" />
- <groovy codeStyle="LEGACY" />
- </component>
- <component name="EntryPointsManager">
- <list size="5">
- <item index="0" class="java.lang.String" itemvalue="org.apache.maven.plugins.annotations.Mojo" />
- <item index="1" class="java.lang.String" itemvalue="org.gradle.api.tasks.InputFiles" />
- <item index="2" class="java.lang.String" itemvalue="org.gradle.api.tasks.OutputDirectory" />
- <item index="3" class="java.lang.String" itemvalue="org.gradle.api.tasks.TaskAction" />
- <item index="4" class="java.lang.String" itemvalue="org.junit.BeforeClass" />
- </list>
- </component>
- <component name="FrameworkDetectionExcludesConfiguration">
- <file type="web" url="file://$PROJECT_DIR$/dokka-fatjar" />
- <file type="web" url="file://$PROJECT_DIR$/gradle-plugin" />
- <file type="web" url="file://$PROJECT_DIR$/javadoc" />
- </component>
- <component name="MavenProjectsManager">
- <option name="originalFiles">
- <list>
- <option value="$PROJECT_DIR$/maven-plugin/pom.xml" />
- </list>
- </option>
- </component>
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 7e6aaef5..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ProjectModuleManager">
- <modules>
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/android-gradle-plugin/android-gradle-plugin.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/android-gradle-plugin/android-gradle-plugin.iml" group="runners/android-gradle-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/android-gradle-plugin/android-gradle-plugin_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/android-gradle-plugin/android-gradle-plugin_main.iml" group="runners/android-gradle-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/android-gradle-plugin/android-gradle-plugin_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/android-gradle-plugin/android-gradle-plugin_test.iml" group="runners/android-gradle-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/ant/ant.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/ant/ant.iml" group="runners/ant" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/ant/ant_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/ant/ant_main.iml" group="runners/ant" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/ant/ant_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/ant/ant_test.iml" group="runners/ant" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/buildSrc.iml" filepath="$PROJECT_DIR$/.idea/modules/buildSrc.iml" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/buildSrc_main.iml" filepath="$PROJECT_DIR$/.idea/modules/buildSrc_main.iml" group="buildSrc" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/buildSrc_test.iml" filepath="$PROJECT_DIR$/.idea/modules/buildSrc_test.iml" group="buildSrc" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/cli/cli.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/cli/cli.iml" group="runners/cli" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/cli/cli_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/cli/cli_main.iml" group="runners/cli" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/cli/cli_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/cli/cli_test.iml" group="runners/cli" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/core/core.iml" filepath="$PROJECT_DIR$/.idea/modules/core/core.iml" group="core" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/core/core_main.iml" filepath="$PROJECT_DIR$/.idea/modules/core/core_main.iml" group="core" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/core/core_test.iml" filepath="$PROJECT_DIR$/.idea/modules/core/core_test.iml" group="core" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/dokka.iml" filepath="$PROJECT_DIR$/.idea/modules/dokka.iml" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/fatjar/fatjar.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/fatjar/fatjar.iml" group="runners/fatjar" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/fatjar/fatjar_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/fatjar/fatjar_main.iml" group="runners/fatjar" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/fatjar/fatjar_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/fatjar/fatjar_test.iml" group="runners/fatjar" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/gradle-integration-tests/gradle-integration-tests.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/gradle-integration-tests/gradle-integration-tests.iml" group="runners/gradle-integration-tests" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/gradle-integration-tests/gradle-integration-tests_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/gradle-integration-tests/gradle-integration-tests_main.iml" group="runners/gradle-integration-tests" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/gradle-integration-tests/gradle-integration-tests_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/gradle-integration-tests/gradle-integration-tests_test.iml" group="runners/gradle-integration-tests" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/gradle-plugin/gradle-plugin.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/gradle-plugin/gradle-plugin.iml" group="runners/gradle-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/gradle-plugin/gradle-plugin_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/gradle-plugin/gradle-plugin_main.iml" group="runners/gradle-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/gradle-plugin/gradle-plugin_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/gradle-plugin/gradle-plugin_test.iml" group="runners/gradle-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/integration/integration.iml" filepath="$PROJECT_DIR$/.idea/modules/integration/integration.iml" group="integration" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/integration/integration_main.iml" filepath="$PROJECT_DIR$/.idea/modules/integration/integration_main.iml" group="integration" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/integration/integration_test.iml" filepath="$PROJECT_DIR$/.idea/modules/integration/integration_test.iml" group="integration" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/maven-plugin/maven-plugin.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/maven-plugin/maven-plugin.iml" group="runners/maven-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/maven-plugin/maven-plugin_main.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/maven-plugin/maven-plugin_main.iml" group="runners/maven-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/maven-plugin/maven-plugin_test.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/maven-plugin/maven-plugin_test.iml" group="runners/maven-plugin" />
- <module fileurl="file://$PROJECT_DIR$/.idea/modules/runners/runners.iml" filepath="$PROJECT_DIR$/.idea/modules/runners/runners.iml" group="runners" />
- </modules>
- </component>
-</project> \ No newline at end of file
diff --git a/.idea/runConfigurations/All_tests.xml b/.idea/runConfigurations/All_tests.xml
deleted file mode 100644
index dffc1e09..00000000
--- a/.idea/runConfigurations/All_tests.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="All tests" type="CompoundRunConfigurationType" factoryName="Compound Run Configuration">
- <toRun type="GradleRunConfiguration" name="Core tests" />
- <toRun type="GradleRunConfiguration" name="Gradle integration tests" />
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/.idea/runConfigurations/Core_tests.xml b/.idea/runConfigurations/Core_tests.xml
deleted file mode 100644
index 50476737..00000000
--- a/.idea/runConfigurations/Core_tests.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Core tests" type="GradleRunConfiguration" factoryName="Gradle">
- <ExternalSystemSettings>
- <option name="executionName" />
- <option name="externalProjectPath" value="$PROJECT_DIR$" />
- <option name="externalSystemIdString" value="GRADLE" />
- <option name="scriptParameters" value="" />
- <option name="taskDescriptions">
- <list />
- </option>
- <option name="taskNames">
- <list>
- <option value=":core:cleanTest" />
- <option value=":core:test" />
- </list>
- </option>
- <option name="vmOptions" value="" />
- </ExternalSystemSettings>
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/.idea/runConfigurations/Dokka.xml b/.idea/runConfigurations/Dokka.xml
deleted file mode 100644
index 1f7da97f..00000000
--- a/.idea/runConfigurations/Dokka.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Dokka" type="JetRunConfigurationType" factoryName="Kotlin" singleton="true">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <option name="MAIN_CLASS_NAME" value="org.jetbrains.dokka.MainKt" />
- <option name="VM_PARAMETERS" value="" />
- <option name="PROGRAM_PARAMETERS" value="core/src -output doc -module dokka -format javadoc -classpath &quot;$KOTLIN_BUNDLED$/lib/kotlin-compiler.jar:$KOTLIN_BUNDLED$/lib/kotlin-runtime.jar&quot;" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="fatjar_main" />
- <envs />
- <RunnerSettings RunnerId="Debug">
- <option name="DEBUG_PORT" value="" />
- <option name="TRANSPORT" value="0" />
- <option name="LOCAL" value="true" />
- </RunnerSettings>
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Debug" />
- <ConfigurationWrapper RunnerId="Run" />
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/.idea/runConfigurations/Gradle_integration_tests.xml b/.idea/runConfigurations/Gradle_integration_tests.xml
deleted file mode 100644
index 9589199f..00000000
--- a/.idea/runConfigurations/Gradle_integration_tests.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Gradle integration tests" type="GradleRunConfiguration" factoryName="Gradle">
- <ExternalSystemSettings>
- <option name="executionName" />
- <option name="externalProjectPath" value="$PROJECT_DIR$" />
- <option name="externalSystemIdString" value="GRADLE" />
- <option name="scriptParameters" value="" />
- <option name="taskDescriptions">
- <list />
- </option>
- <option name="taskNames">
- <list>
- <option value=":runners:gradle-integration-tests:cleanTest" />
- <option value=":runners:gradle-integration-tests:test" />
- </list>
- </option>
- <option name="vmOptions" value="" />
- </ExternalSystemSettings>
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/.idea/runConfigurations/Playground.xml b/.idea/runConfigurations/Playground.xml
deleted file mode 100644
index 8322447c..00000000
--- a/.idea/runConfigurations/Playground.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Playground" type="Application" factoryName="Application">
- <option name="MAIN_CLASS_NAME" value="org.jetbrains.dokka.MainKt" />
- <module name="fatjar_main" />
- <option name="PROGRAM_PARAMETERS" value="-module playground test -format html -output out/html" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/.idea/runConfigurations/Stdlib.xml b/.idea/runConfigurations/Stdlib.xml
deleted file mode 100644
index 7cc2d62c..00000000
--- a/.idea/runConfigurations/Stdlib.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Stdlib" type="KotlinRunConfigurationType" factoryName="Kotlin">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <option name="MAIN_CLASS_NAME" value="org.jetbrains.dokka.MainKt" />
- <option name="VM_PARAMETERS" value="-Xmx2048m -Xms256m" />
- <option name="PROGRAM_PARAMETERS" value="JVM::../kotlin/libraries/stdlib/src JVM::../kotlin/core/builtins JVM::../kotlin/core/reflection.jvm JVM::../kotlin/core/runtime.jvm JVM,JRE7::../kotlin/libraries/stdlib/jre7/src JVM,JRE8::../kotlin/libraries/stdlib/jre8/src JS::../kotlin/core/builtins JS::../kotlin/dist/kotlin-stdlib-js-sources -samples ../kotlin/libraries/stdlib/test -output ../kotlin-web-site/pages/api/latest/jvm -module stdlib -include ../kotlin/libraries/stdlib/src/Module.md -format kotlin-website-samples -nodeprecated -srcLink ../kotlin=http://github.com/JetBrains/kotlin/blob/master#L -impliedPlatforms JVM,JS" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="fatjar_main" />
- <envs />
- <RunnerSettings RunnerId="Debug">
- <option name="DEBUG_PORT" value="" />
- <option name="TRANSPORT" value="0" />
- <option name="LOCAL" value="true" />
- </RunnerSettings>
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Debug" />
- <ConfigurationWrapper RunnerId="Run" />
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/.idea/runConfigurations/Stdlib_Javadoc.xml b/.idea/runConfigurations/Stdlib_Javadoc.xml
deleted file mode 100644
index 34c97872..00000000
--- a/.idea/runConfigurations/Stdlib_Javadoc.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Stdlib Javadoc" type="KotlinRunConfigurationType" factoryName="Kotlin">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <option name="MAIN_CLASS_NAME" value="org.jetbrains.dokka.MainKt" />
- <option name="VM_PARAMETERS" value="-Xmx2048m -Xms256m" />
- <option name="PROGRAM_PARAMETERS" value="../kotlin/libraries/stdlib/src ../kotlin/core/reflection.jvm -samples ../kotlin/libraries/stdlib/test -output doc/javadoc -module stdlib -include ../kotlin/libraries/stdlib/src/Module.md -format javadoc -nodeprecated -srcLink ../kotlin=http://github.com/JetBrains/kotlin/blob/master#L" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="fatjar_main" />
- <envs />
- <method />
- </configuration>
-</component> \ No newline at end of file
diff --git a/README.md b/README.md
index e60e32d1..43e5ac9d 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,11 @@
-dokka [![official JetBrains project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
-[![TeamCity (build status)](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/Kotlin_Dokka_DokkaAntMavenGradle.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_Dokka_DokkaAntMavenGradle&branch_KotlinTools_Dokka=%3Cdefault%3E&tab=buildTypeStatusDiv) [ ![Download](https://api.bintray.com/packages/kotlin/dokka/dokka/images/download.svg) ](https://bintray.com/kotlin/dokka/dokka/_latestVersion)
-=====
+# dokka [![official JetBrains project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![TeamCity (build status)](https://teamcity.jetbrains.com/app/rest/builds/buildType:(id:Kotlin_Dokka_DokkaAntMavenGradle)/statusIcon)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_Dokka_DokkaAntMavenGradle&branch_KotlinTools_Dokka=%3Cdefault%3E&tab=buildTypeStatusDiv) [![Download](https://api.bintray.com/packages/kotlin/dokka/dokka/images/download.svg)](https://bintray.com/kotlin/dokka/dokka/_latestVersion)
Dokka is a documentation engine for Kotlin, performing the same function as javadoc for Java.
Just like Kotlin itself, Dokka fully supports mixed-language Java/Kotlin projects. It understands
standard Javadoc comments in Java files and [KDoc comments](https://kotlinlang.org/docs/reference/kotlin-doc.html) in Kotlin files,
and can generate documentation in multiple formats including standard Javadoc, HTML and Markdown.
-## Using Dokka
+## Using dokka
### Using the Gradle plugin
@@ -27,136 +25,264 @@ repositories {
apply plugin: 'org.jetbrains.dokka'
```
-or using the new plugins block:
+or using the plugins block:
```groovy
plugins {
- id 'org.jetbrains.dokka' version '0.9.18'
+ id 'org.jetbrains.dokka' version '0.10.0'
}
repositories {
jcenter() // or maven { url 'https://dl.bintray.com/kotlin/dokka' }
}
```
-The plugin adds a task named "dokka" to the project.
+The plugin adds a task named `dokka` to the project.
If you encounter any problems when migrating from older versions of Dokka, please see the [FAQ](https://github.com/Kotlin/dokka/wiki/faq).
Minimal dokka configuration:
+Groovy
```groovy
dokka {
outputFormat = 'html'
- outputDirectory = "$buildDir/javadoc"
+ outputDirectory = "$buildDir/dokka"
+}
+```
+
+Kotlin
+```kotlin
+tasks {
+ val dokka by getting(DokkaTask::class) {
+ outputFormat = "html"
+ outputDirectory = "$buildDir/dokka"
+ }
}
```
[Output formats](#output_formats)
-The available configuration options are shown below:
+The available configuration options for single platform are shown below:
```groovy
dokka {
- moduleName = 'data'
outputFormat = 'html'
outputDirectory = "$buildDir/javadoc"
- // These tasks will be used to determine source directories and classpath
- kotlinTasks {
- defaultKotlinTasks() + [':some:otherCompileKotlin', project("another").compileKotlin]
- }
-
- // List of files with module and package documentation
- // https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation
- includes = ['packages.md', 'extra.md']
-
- // The list of files or directories containing sample code (referenced with @sample tags)
- samples = ['samples/basic.kt', 'samples/advanced.kt']
-
- jdkVersion = 6 // Used for linking to JDK
+ // In case of a Gradle multiproject build, you can include subprojects here to get merged documentation
+ // Note however, that you have to have the Kotlin plugin available in the root project and in the subprojects
+ subProjects = ["subproject1", "subproject2"]
+
+ // Used for disabling auto extraction of sources and platforms in both multi-platform and single-platform modes
+ // When set to true, subProject and kotlinTasks are also omitted
+ disableAutoconfiguration = false
// Use default or set to custom path to cache directory
// to enable package-list caching
- // When set to default, caches stored in $USER_HOME/.cache/dokka
+ // When this is set to default, caches are stored in $USER_HOME/.cache/dokka
cacheRoot = 'default'
- // Use to include or exclude non public members.
- includeNonPublic = false
-
- // Do not output deprecated members. Applies globally, can be overridden by packageOptions
- skipDeprecated = false
-
- // Emit warnings about not documented members. Applies globally, also can be overridden by packageOptions
- reportUndocumented = true
-
- skipEmptyPackages = true // Do not create index pages for empty packages
-
- impliedPlatforms = ["JVM"] // See platforms section of documentation
-
- // Manual adding files to classpath
- // This property doesn't override classpath collected from kotlinTasks but appends to it
- classpath = [new File("$buildDir/other.jar")]
+ configuration {
+ moduleName = 'data'
- // By default, sourceRoots is taken from kotlinTasks, following roots will be appended to it
- // Short form sourceRoots
- sourceDirs = files('src/main/kotlin')
+ // Use to include or exclude non public members.
+ includeNonPublic = false
+
+ // Do not output deprecated members. Applies globally, can be overridden by packageOptions
+ skipDeprecated = false
+
+ // Emit warnings about not documented members. Applies globally, also can be overridden by packageOptions
+ reportUndocumented = true
+
+ // Do not create index pages for empty packages
+ skipEmptyPackages = true
+
+ // This is a list of platform names that will be shown in the final result. See the "Platforms" section of this readme
+ targets = ["JVM"]
+
+ // Platform used for code analysis. See the "Platforms" section of this readme
+ platform = "JVM"
+
+ // Property used for manual addition of files to the classpath
+ // This property does not override the classpath collected automatically but appends to it
+ classpath = [new File("$buildDir/other.jar")]
- // By default, sourceRoots is taken from kotlinTasks, following roots will be appended to it
- // Full form sourceRoot declaration
- // Repeat for multiple sourceRoots
- sourceRoot {
- // Path to source root
- path = "src"
- // See platforms section of documentation
- platforms = ["JVM"]
- }
+ // By default, sourceRoots are taken from Kotlin Plugin, subProjects and kotlinTasks, following roots will be appended to them
+ sourceRoots = [files('src/main/kotlin')]
+
+ // List of files with module and package documentation
+ // https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation
+ includes = ['packages.md', 'extra.md']
- // Specifies the location of the project source code on the Web.
- // If provided, Dokka generates "source" links for each declaration.
- // Repeat for multiple mappings
- linkMapping {
- // Unix based directory relative path to the root of the project (where you execute gradle respectively).
- dir = "src/main/kotlin" // or simply "./"
-
- // URL showing where the source code can be accessed through the web browser
- url = "https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin" //remove src/main/kotlin if you use "./" above
+ // List of files or directories containing sample code (referenced with @sample tags)
+ samples = ['samples/basic.kt', 'samples/advanced.kt']
+
+ // By default, sourceRoots are taken from Kotlin Plugin, subProjects and kotlinTasks, following roots will be appended to them
+ // Full form sourceRoot declaration
+ // Repeat for multiple sourceRoots
+ sourceRoot {
+ // Path to a source root
+ path = "src"
+ }
- // Suffix which is used to append the line number to the URL. Use #L for GitHub
- suffix = "#L"
+ // These tasks will be used to determine source directories and classpath
+ kotlinTasks {
+ defaultKotlinTasks() + [':some:otherCompileKotlin', project("another").compileKotlin]
+ }
+
+ // Specifies the location of the project source code on the Web.
+ // If provided, Dokka generates "source" links for each declaration.
+ // Repeat for multiple mappings
+ sourceLink {
+ // Unix based directory relative path to the root of the project (where you execute gradle respectively).
+ path = "src/main/kotlin" // or simply "./"
+
+ // URL showing where the source code can be accessed through the web browser
+ url = "https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin" //remove src/main/kotlin if you use "./" above
+
+ // Suffix which is used to append the line number to the URL. Use #L for GitHub
+ lineSuffix = "#L"
+ }
+
+ // Used for linking to JDK documentation
+ jdkVersion = 6
+
+ // Disable linking to online kotlin-stdlib documentation
+ noStdlibLink = false
+
+ // Disable linking to online JDK documentation
+ noJdkLink = false
+
+ // Allows linking to documentation of the project's dependencies (generated with Javadoc or Dokka)
+ // Repeat for multiple links
+ externalDocumentationLink {
+ // Root URL of the generated documentation to link with. The trailing slash is required!
+ url = new URL("https://example.com/docs/")
+
+ // If package-list file is located in non-standard location
+ // packageListUrl = new URL("file:///home/user/localdocs/package-list")
+ }
+
+ // Allows to customize documentation generation options on a per-package basis
+ // Repeat for multiple packageOptions
+ perPackageOption {
+ prefix = "kotlin" // will match kotlin and all sub-packages of it
+ // All options are optional, default values are below:
+ skipDeprecated = false
+ reportUndocumented = true // Emit warnings about not documented members
+ includeNonPublic = false
+ }
+ // Suppress a package
+ perPackageOption {
+ prefix = "kotlin.internal" // will match kotlin.internal and all sub-packages of it
+ suppress = true
+ }
}
-
- // Disable linking to online kotlin-stdlib documentation
- noStdlibLink = false
-
- // Disable linking to online JDK documentation
- noJdkLink = false
-
- // Allows linking to documentation of the project's dependencies (generated with Javadoc or Dokka)
- // Repeat for multiple links
- externalDocumentationLink {
- // Root URL of the generated documentation to link with. The trailing slash is required!
- url = new URL("https://example.com/docs/")
+}
+```
+
+#### Multiplatform
+Since version 0.10.0 dokka supports multiplatform projects. For a general understanding how a multiplatform documentation is generated, please consult the [FAQ](https://github.com/Kotlin/dokka/wiki/faq).
+In the multiplatform mode, instead of using the `configuration` block, you should use a `multiplatform` block with inner blocks for each platform.
+The `configuration` block's parameters belong to those inner blocks, which can be named arbitrarly, however if you want to use source roots and classpath provided by Kotlin Multiplatform plugin,
+they must have the same names as in the Kotlin Multiplatform plugin. See an example below:
+
+Groovy
+```groovy
+kotlin { // Kotlin Multiplatform plugin configuration
+ jvm()
+ js("customName") // Define a js platform named "customName" If you want to generate docs for it, you need to have this name in dokka configuration below
+}
+
+dokka {
+ outputDirectory = "$buildDir/dokka"
+ outputFormat = "html"
+
+ multiplatform {
+ customName { // The same name as in Kotlin Multiplatform plugin, so the sources are fetched automatically
+ includes = ['packages.md', 'extra.md']
+ samples = ['samples/basic.kt', 'samples/advanced.kt']
+ }
- // If package-list file located in non-standard location
- // packageListUrl = new URL("file:///home/user/localdocs/package-list")
+ differentName { // Different name, so source roots, classpath and platform must be passed explicitly.
+ targets = ["JVM"]
+ platform = "jvm"
+ sourceRoot {
+ path = kotlin.sourceSets.jvmMain.kotlin.srcDirs[0]
+ }
+ sourceRoot {
+ path = kotlin.sourceSets.commonMain.kotlin.srcDirs[0]
+ }
+ }
}
-
- // Allows to customize documentation generation options on a per-package basis
- // Repeat for multiple packageOptions
- packageOptions {
- prefix = "kotlin" // will match kotlin and all sub-packages of it
- // All options are optional, default values are below:
- skipDeprecated = false
- reportUndocumented = true // Emit warnings about not documented members
- includeNonPublic = false
+}
+```
+
+Kotlin
+```kotlin
+kotlin { // Kotlin Multiplatform plugin configuration
+ jvm()
+ js("customName")
+}
+
+val dokka by getting(DokkaTask::class) {
+ outputDirectory = "$buildDir/dokka"
+ outputFormat = "html"
+
+ multiplatform {
+ val customName by creating { // The same name as in Kotlin Multiplatform plugin, so the sources are fetched automatically
+ includes = listOf("packages.md", "extra.md")
+ samples = listOf("samples/basic.kt", "samples/advanced.kt")
+ }
+
+ register("differentName") { // Different name, so source roots must be passed explicitly
+ targets = listOf("JVM")
+ platform = "jvm"
+ sourceRoot {
+ path = kotlin.sourceSets.getByName("jvmMain").kotlin.srcDirs.first().toString()
+ }
+ sourceRoot {
+ path = kotlin.sourceSets.getByName("commonMain").kotlin.srcDirs.first().toString()
+ }
+ }
+ }
}
- // Suppress a package
- packageOptions {
- prefix = "kotlin.internal" // will match kotlin.internal and all sub-packages of it
- suppress = true
+```
+
+For convenience, there is also a reserved block called `global`, which is a top-level configuration of `perPackageOptions`, `externalDocumentationLinks`, and `sourceLinks` shared by every platform. Eg.
+
+```groovy
+dokka {
+ multiplatform {
+ global { // perPackageOptions, sourceLinks and externalDocumentationLinks from here will be copied to every other platform (jvm and js in eg.)
+ perPackageOption {
+ prefix = "com.somePackage"
+ suppress = true
+ }
+ perPackageOption { // You can repeat this block for multiple perPackageOptions
+ prefix = "kotlin"
+ skipDeprecated = false
+ reportUndocumented = true
+ includeNonPublic = false
+ }
+ sourceLink {
+ path = "src/main/kotlin"
+ url = "https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin"
+ lineSuffix = "#L"
+ }
+ externalDocumentationLink {
+ url = new URL("https://example.com/docs/")
+ }
+ }
+ js {}
+ jvm {}
}
}
```
+The parameters from the `global` block are appended to all the other platform configurations (in the example - `js` and `jvm`) and cannot be overriden.
+
+
+Note that `javadoc` output format cannot be used with multiplatform.
To generate the documentation, use the `dokka` Gradle task:
@@ -167,16 +293,16 @@ To generate the documentation, use the `dokka` Gradle task:
More dokka tasks can be added to a project like this:
```groovy
-task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
- outputFormat = 'javadoc'
- outputDirectory = "$buildDir/javadoc"
+task dokkaMarkdown(type: org.jetbrains.dokka.gradle.DokkaTask) {
+ outputFormat = 'markdown'
+ outputDirectory = "$buildDir/markdown"
}
```
Please see the [Dokka Gradle example project](https://github.com/JetBrains/kotlin-examples/tree/master/gradle/dokka-gradle-example) for an example.
#### Dokka Runtime
-If you are using Gradle plugin and you want to change the version of Dokka, you can do it by setting `dokkaRuntime`:
+If you are using Gradle plugin and you want to use a custom version of dokka, you can do it by setting `dokkaRuntime` configuration:
```groovy
buildscript {
@@ -190,16 +316,46 @@ repositories {
}
dependencies {
- dokkaRuntime "org.jetbrains.dokka:dokka-fatjar:0.9.18"
+ dokkaRuntime "org.jetbrains.dokka:dokka-fatjar:0.10.0"
+}
+
+dokka {
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/dokkaHtml"
}
+
```
+To use your Fat Jar, just set the path to it:
+
+ ```groovy
+ buildscript {
+ ...
+ }
+
+ apply plugin: 'org.jetbrains.dokka'
+
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ dokkaRuntime files("/path/to/fatjar/dokka-fatjar-0.10.0.jar")
+ }
+
+ dokka {
+ outputFormat = 'html'
+ outputDirectory = "$buildDir/dokkaHtml"
+ }
+
+ ```
#### FAQ
If you encounter any problems, please see the [FAQ](https://github.com/Kotlin/dokka/wiki/faq).
#### Android
-If you are using Android there is a separate Gradle plugin. Just make sure you apply the plugin after
+Since version 0.10.0 the separate Android plugin is merged with the default one.
+Just make sure you apply the plugin after
`com.android.library` and `kotlin-android`.
```groovy
@@ -208,7 +364,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${dokka_version}"
+ classpath "org.jetbrains.dokka:dokka-gradle-plugin:${dokka_version}"
}
}
repositories {
@@ -216,11 +372,17 @@ repositories {
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
-apply plugin: 'org.jetbrains.dokka-android'
+apply plugin: 'org.jetbrains.dokka'
```
+There is also a `noAndroidSdkLink` configuration parameter that works similar to `noJdkLink` and `noStdlibLink`
+By default the variant documented by dokka is the first release variant encountered. If you want to change that,
+you can disable the autoconfiguration and configure dokka manually.
+
### Using the Maven plugin
+The Maven plugin does not support multiplatform projects.
+
The Maven plugin is available in JCenter. You need to add the JCenter repository to the list of plugin repositories if it's not there:
```xml
@@ -298,9 +460,9 @@ The available configuration options are shown below:
</includes>
<!-- List of sample roots -->
- <samplesDirs>
+ <samples>
<dir>src/test/samples</dir>
- </samplesDirs>
+ </samples>
<!-- Used for linking to JDK, default: 6 -->
<jdkVersion>6</jdkVersion>
@@ -308,15 +470,10 @@ The available configuration options are shown below:
<!-- Do not output deprecated members, applies globally, can be overridden by packageOptions -->
<skipDeprecated>false</skipDeprecated>
<!-- Emit warnings about not documented members, applies globally, also can be overridden by packageOptions -->
- <reportNotDocumented>true</reportNotDocumented>
+ <reportUndocumented>true</reportUndocumented>
<!-- Do not create index pages for empty packages -->
<skipEmptyPackages>true</skipEmptyPackages>
- <!-- See platforms section of documentation -->
- <impliedPlatforms>
- <platform>JVM</platform>
- </impliedPlatforms>
-
<!-- Short form list of sourceRoots, by default, set to ${project.compileSourceRoots} -->
<sourceDirectories>
<dir>src/main/kotlin</dir>
@@ -336,11 +493,11 @@ The available configuration options are shown below:
<sourceLinks>
<link>
<!-- Source directory -->
- <dir>${project.basedir}/src/main/kotlin</dir>
+ <path>${project.basedir}/src/main/kotlin</path>
<!-- URL showing where the source code can be accessed through the web browser -->
<url>https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin</url> <!-- //remove src/main/kotlin if you use "./" above -->
<!--Suffix which is used to append the line number to the URL. Use #L for GitHub -->
- <urlSuffix>#L</urlSuffix>
+ <lineSuffix>#L</lineSuffix>
</link>
</sourceLinks>
@@ -383,61 +540,72 @@ Please see the [Dokka Maven example project](https://github.com/JetBrains/kotlin
### Using the Ant task
-The Ant task definition is also contained in the dokka-fatjar.jar referenced above. Here's an example of using it:
+The Ant task definition is also contained in the dokka-fatjar.jar referenced above. Here's an example usage:
```xml
<project name="Dokka" default="document">
- <typedef resource="dokka-antlib.xml" classpath="dokka-fatjar.jar"/>
+ <typedef resource="dokka-antlib.xml" classpath="dokka-fatjar.jar"/>
- <target name="document">
- <dokka src="src" outputdir="doc" modulename="myproject"/>
- </target>
+ <target name="document">
+ <dokka format="html" outputDir="doc"/>
+ </target>
</project>
```
The Ant task supports the following attributes:
* `outputDir` - the output directory where the documentation is generated
- * `outputFormat` - the output format (see the list of supported formats above)
+ * `format` - the output format (see the list of supported formats below)
+ * `cacheRoot` - Use `default` or set to custom path to cache directory to enable package-list caching. When set to `default`, caches stored in $USER_HOME/.cache/dokka
+
+Inside the `dokka` tag you can create another tags named `<passconfig/>` that support the following attributes:
+
* `classpath` - list of directories or .jar files to include in the classpath (used for resolving references)
* `samples` - list of directories containing sample code (documentation for those directories is not generated but declarations from them can be referenced using the `@sample` tag)
* `moduleName` - the name of the module being documented (used as the root directory of the generated documentation)
* `include` - names of files containing the documentation for the module and individual packages
* `skipDeprecated` - if set, deprecated elements are not included in the generated documentation
* `jdkVersion` - version for linking to JDK
- * `impliedPlatforms` - See [platforms](#platforms) section
- * `<sourceRoot path="src" platforms="JVM" />` - analogue of src, but allows to specify [platforms](#platforms)
+ * `analysisPlatform="jvm"` - platform used for analysing sourceRoots, see the [platforms](#platforms) section
+ * `<sourceRoot path="src" />` - source root
* `<packageOptions prefix="kotlin" includeNonPublic="false" reportUndocumented="true" skipDeprecated="false"/>` -
Per package options for package `kotlin` and sub-packages of it
* `noStdlibLink` - disable linking to online kotlin-stdlib documentation
* `noJdkLink` - disable linking to online JDK documentation
* `<externalDocumentationLink url="https://example.com/docs/" packageListUrl="file:///home/user/localdocs/package-list"/>` -
linking to external documentation, packageListUrl should be used if package-list located not in standard location
- * `cacheRoot` - Use `default` or set to custom path to cache directory to enable package-list caching. When set to `default`, caches stored in $USER_HOME/.cache/dokka
+ * `<target value="JVM"/>` - see the [platforms](#platforms) section
### Using the Command Line
-To run Dokka from the command line, download the [Dokka jar](https://github.com/Kotlin/dokka/releases/download/0.9.10/dokka-fatjar.jar).
+To run Dokka from the command line, download the [Dokka jar](https://github.com/Kotlin/dokka/releases/download/0.10.0/dokka-fatjar.jar).
To generate documentation, run the following command:
- java -jar dokka-fatjar.jar <source directories> <arguments>
+ java -jar dokka-fatjar.jar <arguments>
Dokka supports the following command line arguments:
* `-output` - the output directory where the documentation is generated
* `-format` - the [output format](#output-formats):
- * `-classpath` - list of directories or .jar files to include in the classpath (used for resolving references)
- * `-samples` - list of directories containing sample code (documentation for those directories is not generated but declarations from them can be referenced using the `@sample` tag)
- * `-module` - the name of the module being documented (used as the root directory of the generated documentation)
- * `-include` - names of files containing the documentation for the module and individual packages
- * `-nodeprecated` - if set, deprecated elements are not included in the generated documentation
- * `-impliedPlatforms` - list of implied platforms (comma-separated)
- * `-packageOptions` - list of package options in format `prefix,-deprecated,-privateApi,+warnUndocumented;...`
- * `-links` - external documentation links in format `url^packageListUrl^^url2...`
- * `-noStdlibLink` - disable linking to online kotlin-stdlib documentation
- * `-noJdkLink` - disable linking to online JDK documentation
* `-cacheRoot` - use `default` or set to custom path to cache directory to enable package-list caching. When set to `default`, caches stored in $USER_HOME/.cache/dokka
+ * `-pass` - (repeatable) - configuration for single analyser pass. Following this argument, you can pass other arguments:
+ * `-src` - (repeatable) - source file or directory (allows many paths separated by the system path separator)
+ * `-classpath` - (repeatable) - directory or .jar file to include in the classpath (used for resolving references)
+ * `-sample` - (repeatable) - directory containing a sample code (documentation for those directories is not generated but declarations from them can be referenced using the `@sample` tag)
+ * `-module` - the name of the module being documented (used as the root directory of the generated documentation)
+ * `-include` - (repeatable) - names of files containing the documentation for the module and individual packages
+ * `-skipDeprecated` - if set, deprecated elements are not included in the generated documentation
+ * `-reportUndocumented` - warn about undocumented members
+ * `-skipEmptyPackages` - do not create index pages for empty packages
+ * `-packageOptions` - list of package options in format `prefix,-deprecated,-privateApi,+warnUndocumented;prefix, ...`
+ * `-links` - external documentation links in format `url^packageListUrl^^url2...`
+ * `-srcLink` - (repeatable) - mapping between a source directory and a Web site for browsing the code in format `<path>=<url>[#lineSuffix]`
+ * `-noStdlibLink` - disable linking to online kotlin-stdlib documentation
+ * `-noJdkLink` - disable linking to online JDK documentation
+ * `-jdkVersion` - version of JDK to use for linking to JDK JavaDoc
+ * `-analysisPlatform` - platform used for analysis, see the [Platforms](#platforms) section
+ * `-target` - (repeatable) - generation target
### Output formats<a name="output_formats"></a>
@@ -453,55 +621,23 @@ Dokka supports the following command line arguments:
### Platforms<a name="platforms"></a>
Dokka can annotate elements with special `platform` block with platform requirements
+Example result and usage can be found on [kotlinlang.org](https://kotlinlang.org/api/latest/jvm/stdlib/)
-Example of usage can be found on [kotlinlang.org](https://kotlinlang.org/api/latest/jvm/stdlib/)
-
-Each source root has a list of platforms for which members are suitable.
-Also, the list of 'implied' platforms is passed to Dokka.
-If a member is not available for all platforms in the implied platforms set, its documentation will show
-the list of platforms for which it's available.
-
-## Dokka Internals
-
-### Documentation Model
-
-Dokka uses Kotlin-as-a-service technology to build `code model`, then processes it into `documentation model`.
-`Documentation model` is graph of items describing code elements such as classes, packages, functions, etc.
+Each multiplatform closure has two properties: `platform` and `targets`. If you use autoconfiguration, those are filled automatically.
-Each node has semantic attached, e.g. Value:name -> Type:String means that some value `name` is of type `String`.
+`targets` property is a list of platform names that will be shown in the final result. Note that the value of this property
+doesn't affect analysis of source code, it just changes the result. You can think of this as a `name` property
-Each reference between nodes also has semantic attached, and there are three of them:
-
-1. Member - reference means that target is member of the source, form tree.
-2. Detail - reference means that target describes source in more details, form tree.
-3. Link - any link to any other node, free form.
-
-Member & Detail has reverse Owner reference, while Link's back reference is also Link.
-
-Nodes that are Details of other nodes cannot have Members.
-
-### Rendering Docs
-
-When we have documentation model, we can render docs in various formats, languages and layouts. We have some core services:
-
-* FormatService -- represents output format
-* LocationService -- represents folder and file layout
-* SignatureGenerator -- represents target language by generating class/function/package signatures from model
-
-Basically, given the `documentation` as a model, we do this:
-
-```kotlin
- val signatureGenerator = KotlinSignatureGenerator()
- val locationService = FoldersLocationService(arguments.outputDir)
- val markdown = JekyllFormatService(locationService, signatureGenerator)
- val generator = FileGenerator(signatureGenerator, locationService, markdown)
- generator.generate(documentation)
-```
+`platform` property is used for the analysis of source roots. Available values are:
+ * `jvm`
+ * `js`
+ * `native`
+ * `common`
-## Building Dokka
+## Building dokka
Dokka is built with Gradle. To build it, use `./gradlew build`.
-Alternatively, open the project directory in IntelliJ IDEA and use the IDE to build and run Dokka.
+Alternatively, open the project directory in IntelliJ IDEA and use the IDE to build and run dokka.
Here's how to import and configure Dokka in IntelliJ IDEA:
* Select "Open" from the IDEA welcome screen, or File > Open if a project is
diff --git a/build.gradle b/build.gradle
index 0b5d5dbc..73636b24 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,25 +1,36 @@
import org.jetbrains.DependenciesVersionGetter
allprojects {
+ ext {
+ if (!project.findProperty("dokka_version")) {
+ final String buildNumber = System.getenv("BUILD_NUMBER")
+ dokka_version = dokka_version_base + (buildNumber == null || System.getenv("FORCE_SNAPSHOT") != null ? "-SNAPSHOT" : "-$buildNumber")
+ }
+ }
+
+ if (project == rootProject) {
+ println "Publication version: $dokka_version"
+ }
+
group 'org.jetbrains.dokka'
version dokka_version
def repo = {
artifactPattern("https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/[revision]/internal/[module](.[ext])")
+ artifactPattern("https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/[revision]/[module](.[ext])")
artifactPattern("https://teamcity.jetbrains.com/guestAuth/repository/download/IntelliJMarkdownParser_Build/[revision]/([module]_[ext]/)[module](.[ext])")
}
buildscript {
repositories {
mavenCentral()
- jcenter()
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
maven { url "https://plugins.gradle.org/m2/" }
ivy(repo)
}
dependencies {
- classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7'
+ classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4'
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
classpath "com.gradle.publish:plugin-publish-plugin:0.9.10"
@@ -27,15 +38,17 @@ allprojects {
}
repositories {
+ jcenter()
mavenCentral()
mavenLocal()
- maven { url "https://dl.bintray.com/jetbrains/markdown" }
+ maven { url "https://dl.bintray.com/jetbrains/markdown" }
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
- maven { url 'https://jitpack.io' }
maven { url "https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/$bundled_kotlin_compiler_version/maven" }
ivy(repo)
- maven { url "https://dl.bintray.com/kotlin/kotlinx.html" }
+ maven { url "https://kotlin.bintray.com/kotlinx" }
+ maven { url "https://dl.bintray.com/kotlin/kotlinx" }
+ maven { url "https://dl.bintray.com/orangy/maven" } // TODO: remove this repository when kotlinx.cli is available in maven
}
}
@@ -65,11 +78,6 @@ def bintrayPublication(project, List<String> _publications) {
})
}
-task wrapper(type: Wrapper) {
- gradleVersion = '4.2.1'
- distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
-}
-
def versions = DependenciesVersionGetter.getVersions(project, bundled_kotlin_compiler_version)
ext.ideaVersion = versions["idea.build.id"]
@@ -104,6 +112,22 @@ def ideaRT() {
def repoLocation = uri(file("$buildDir/dist-maven"))
+configurations {
+ kotlin_plugin_full
+}
+
+dependencies {
+ final String ijVersion = "20" + ideaVersion.take(2) + "." + ideaVersion[2]
+ kotlin_plugin_full "teamcity:kotlin-plugin-$bundled_kotlin_compiler_version-IJ$ijVersion-1:$bundled_kotlin_compiler_version@zip"
+}
+
+def kotlinPluginDependency() {
+ return zipTree(configurations.kotlin_plugin_full.singleFile).matching({
+ include("Kotlin/lib/kotlin-plugin.jar")
+ })
+}
+
+
allprojects {
task publishToDistMaven {
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 874dabc9..b62b4150 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -6,5 +6,5 @@ repositories {
maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
}
dependencies {
- compile 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
-} \ No newline at end of file
+ compile 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
+}
diff --git a/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy b/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy
index 58cfdcf7..62cc3d3c 100644
--- a/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy
+++ b/buildSrc/src/main/groovy/org/jetbrains/CorrectShadowPublishing.groovy
@@ -4,22 +4,23 @@ import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.artifacts.SelfResolvingDependency
-import org.gradle.api.publish.internal.ProjectDependencyPublicationResolver
+import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectDependencyPublicationResolver
import org.gradle.api.publish.maven.MavenPom
import org.gradle.api.publish.maven.MavenPublication
+//https://github.com/johnrengelman/shadow/issues/334
static void configure(MavenPublication publication, Project project) {
publication.artifact(project.tasks.shadowJar)
+
publication.pom { MavenPom pom ->
pom.withXml { xml ->
def dependenciesNode = xml.asNode().appendNode('dependencies')
project.configurations.shadow.allDependencies.each {
- //if (! (it instanceof SelfResolvingDependency)) {
if (it instanceof ProjectDependency) {
- def projectDependencyResolver = project.gradle.services.get(ProjectDependencyPublicationResolver)
- ModuleVersionIdentifier identifier = projectDependencyResolver.resolve(it)
+ final ProjectDependencyPublicationResolver projectDependencyResolver = project.gradle.services.get(ProjectDependencyPublicationResolver)
+ final ModuleVersionIdentifier identifier = projectDependencyResolver.resolve(ModuleVersionIdentifier, it)
addDependency(dependenciesNode, identifier)
} else if (!(it instanceof SelfResolvingDependency)) {
addDependency(dependenciesNode, it)
diff --git a/core/build.gradle b/core/build.gradle
index a4538471..697fd726 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -12,8 +12,8 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
- languageVersion = "1.2"
- apiVersion = languageVersion
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
@@ -32,6 +32,8 @@ dependencies {
compile "org.jetbrains:markdown:$markdownVersion"
compile intellijCoreAnalysis()
+
+ compile kotlinPluginDependency()
compile 'org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.8'
@@ -45,6 +47,8 @@ dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlin_version
testCompile "com.nhaarman:mockito-kotlin-kt1.1:1.5.0"
-
+ implementation "com.google.code.gson:gson:$gson_version"
testCompile ideaRT()
+ testImplementation "org.jetbrains.kotlin:kotlin-stdlib-js:$bundled_kotlin_compiler_version"
+ testImplementation "org.jetbrains.kotlin:kotlin-stdlib-common:$bundled_kotlin_compiler_version"
} \ No newline at end of file
diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt
index 8ad7b8bb..c816106e 100644
--- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt
+++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt
@@ -17,8 +17,15 @@ import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.io.URLUtil
+import org.jetbrains.dokka.Analysis.DokkaJsAnalyzerFacade
+import org.jetbrains.dokka.Analysis.DokkaNativeAnalyzerFacade
import org.jetbrains.kotlin.analyzer.*
+import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters
+import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade
+import org.jetbrains.kotlin.builtins.DefaultBuiltIns
+import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns
+import org.jetbrains.kotlin.caches.project.LibraryModuleInfo
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.config.ContentRoot
@@ -38,16 +45,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.js.config.JSConfigurationKeys
+import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
-import org.jetbrains.kotlin.resolve.BindingContext
-import org.jetbrains.kotlin.resolve.BindingTrace
-import org.jetbrains.kotlin.resolve.CompilerEnvironment
+import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
+import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.types.KotlinType
@@ -63,7 +71,7 @@ import java.io.File
* $messageCollector: required by compiler infrastructure and will receive all compiler messages
* $body: optional and can be used to configure environment without creating local variable
*/
-class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
+class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPlatform: Platform) : Disposable {
val configuration = CompilerConfiguration()
init {
@@ -72,12 +80,19 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
fun createCoreEnvironment(): KotlinCoreEnvironment {
System.setProperty("idea.io.use.fallback", "true")
- val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
+
+ val configFiles = when (analysisPlatform) {
+ Platform.jvm, Platform.common -> EnvironmentConfigFiles.JVM_CONFIG_FILES
+ Platform.native -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES
+ Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES
+ }
+ val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles)
val projectComponentManager = environment.project as MockComponentManager
val projectFileIndex = CoreProjectFileIndex(environment.project,
environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS))
+
val moduleManager = object : CoreModuleManager(environment.project, this) {
override fun getModules(): Array<out Module> = arrayOf(projectFileIndex.module)
}
@@ -96,10 +111,11 @@ 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 createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope =
+ when (analysisPlatform) {
+ Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles)
+ Platform.js, Platform.common, Platform.native -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet())
+ }
fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair<DokkaResolutionFacade, DokkaResolutionFacade> {
@@ -108,7 +124,21 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
val sourceFiles = environment.getSourceFiles()
- val library = object : ModuleInfo {
+ val targetPlatform = when (analysisPlatform) {
+ Platform.js -> JsPlatform
+ Platform.common -> TargetPlatform.Common
+ Platform.native -> KonanPlatform
+ Platform.jvm -> JvmPlatform
+ }
+
+ val library = object : LibraryModuleInfo {
+ override val platform: TargetPlatform
+ get() = targetPlatform
+
+ override fun getLibraryRoots(): Collection<String> {
+ return classpath.map { it.absolutePath }
+ }
+
override val name: Name = Name.special("<library>")
override fun dependencies(): List<ModuleInfo> = listOf(this)
}
@@ -118,43 +148,146 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
}
val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles)
+ val modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> = {
+ when (it) {
+ library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope))
+ module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project))
+ else -> throw IllegalArgumentException("Unexpected module info")
+ }
+ }
- val builtIns = JvmBuiltIns(projectContext.storageManager)
+ var builtIns: JvmBuiltIns? = null
+ val resolverForProject = when (analysisPlatform) {
+ Platform.jvm -> {
+ builtIns = JvmBuiltIns(projectContext.storageManager)
+ createJvmResolverForProject(projectContext, module, library, modulesContent, sourcesScope, builtIns)
+ }
+ Platform.common -> createCommonResolverForProject(projectContext, module, library, modulesContent, environment)
+ Platform.js -> createJsResolverForProject(projectContext, module, library, modulesContent)
+ Platform.native -> createNativeResolverForProject(projectContext, module, library, modulesContent)
- val javaRoots = classpath
- .mapNotNull {
- val rootFile = when {
- it.extension == "jar" ->
- StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}")
- else ->
- StandardFileSystems.local().findFileByPath(it.absolutePath)
- }
+ }
+ val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly
+ val resolverForModule = resolverForProject.resolverForModule(module)
+ val libraryModuleDescriptor = resolverForProject.descriptorForModule(library)
+ val moduleDescriptor = resolverForProject.descriptorForModule(module)
+ builtIns?.initialize(moduleDescriptor, true)
+ val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary)
+ val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule)
+ val projectComponentManager = environment.project as MockComponentManager
+ projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created))
- rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) }
+ return created to libraryResolutionFacade
+ }
+
+ private fun createCommonResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>,
+ environment: KotlinCoreEnvironment
+ ): ResolverForProjectImpl<ModuleInfo> {
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(module, library),
+ modulesContent = modulesContent,
+ modulePlatforms = { MultiTargetPlatform.Common },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade },
+ platformParameters = { _ ->
+ CommonAnalysisParameters { content ->
+ environment.createPackagePartProvider(content.moduleContentScope)
+ }
+ },
+ targetEnvironment = CompilerEnvironment,
+ builtIns = DefaultBuiltIns.Instance
+ )
+ }
+
+ private fun createJsResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>
+ ): ResolverForProjectImpl<ModuleInfo> {
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(module, library),
+ modulesContent = modulesContent,
+ modulePlatforms = { JsPlatform.multiTargetPlatform },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { DokkaJsAnalyzerFacade },
+ platformParameters = { _ -> PlatformAnalysisParameters.Empty },
+ targetEnvironment = CompilerEnvironment,
+ builtIns = JsPlatform.builtIns
+ )
+ }
+
+ private fun createNativeResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>
+ ): ResolverForProjectImpl<ModuleInfo> {
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(module, library),
+ modulesContent = modulesContent,
+ modulePlatforms = { KonanPlatform.multiTargetPlatform },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { DokkaNativeAnalyzerFacade },
+ platformParameters = { _ -> PlatformAnalysisParameters.Empty },
+ targetEnvironment = CompilerEnvironment
+ )
+
+ }
+
+ private fun createJvmResolverForProject(
+ projectContext: ProjectContext,
+ module: ModuleInfo,
+ library: LibraryModuleInfo,
+ modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>,
+ sourcesScope: GlobalSearchScope,
+ builtIns: KotlinBuiltIns
+ ): ResolverForProjectImpl<ModuleInfo> {
+ val javaRoots = classpath
+ .mapNotNull {
+ val rootFile = when {
+ it.extension == "jar" ->
+ StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}")
+ else ->
+ StandardFileSystems.local().findFileByPath(it.absolutePath)
}
- val resolverForProject = ResolverForProjectImpl(
- "Dokka",
- projectContext,
- listOf(library, module),
- {
+ rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) }
+ }
+
+ return ResolverForProjectImpl(
+ debugName = "Dokka",
+ projectContext = projectContext,
+ modules = listOf(library, module),
+ modulesContent = {
when (it) {
library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope))
module -> ModuleContent(it, emptyList(), sourcesScope)
else -> throw IllegalArgumentException("Unexpected module info")
}
},
- {
- JvmPlatform.multiTargetPlatform
- },
- LanguageSettingsProvider.Default /* TODO: Fix this */,
- { JvmAnalyzerFacade },
- {
+ modulePlatforms = { JvmPlatform.multiTargetPlatform },
+ moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */,
+ resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade },
+ platformParameters = {
JvmPlatformParameters ({ content ->
- JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply {
- addRoots(javaRoots, messageCollector)
- }
+ JvmPackagePartProvider(
+ configuration.languageVersionSettings,
+ content.moduleContentScope)
+ .apply {
+ addRoots(javaRoots, messageCollector)
+ }
}, {
val file = (it as JavaClassImpl).psi.containingFile.virtualFile
if (file in sourcesScope)
@@ -163,21 +296,9 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
library
})
},
- CompilerEnvironment,
+ targetEnvironment = CompilerEnvironment,
builtIns = builtIns
)
-
- val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly
- val resolverForModule = resolverForProject.resolverForModule(module)
- val libraryModuleDescriptor = resolverForProject.descriptorForModule(library)
- val moduleDescriptor = resolverForProject.descriptorForModule(module)
- builtIns.initialize(moduleDescriptor, true)
- val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary)
- val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule)
- val projectComponentManager = environment.project as MockComponentManager
- projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created))
-
- return created to libraryResolutionFacade
}
fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) {
@@ -197,6 +318,9 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
* $paths: collection of files to add
*/
fun addClasspath(paths: List<File>) {
+ if (analysisPlatform == Platform.js) {
+ configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath })
+ }
configuration.addJvmClasspathRoots(paths)
}
@@ -205,6 +329,9 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
* $path: path to add
*/
fun addClasspath(path: File) {
+ if (analysisPlatform == Platform.js) {
+ configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath)
+ }
configuration.addJvmClasspathRoot(path)
}
diff --git a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt
index 319d85b1..f5fbf991 100644
--- a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt
+++ b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt
@@ -166,8 +166,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont
private val sdk: Sdk = object : Sdk, RootProvider {
override fun getFiles(rootType: OrderRootType): Array<out VirtualFile> = classpathRoots
- .map { StandardFileSystems.local().findFileByPath(it.file.path) }
- .filterNotNull()
+ .mapNotNull { StandardFileSystems.local().findFileByPath(it.file.path) }
.toTypedArray()
override fun addRootSetChangedListener(p0: RootProvider.RootSetChangedListener) {
diff --git a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt
new file mode 100644
index 00000000..874341dd
--- /dev/null
+++ b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt
@@ -0,0 +1,164 @@
+package org.jetbrains.dokka.Analysis
+
+import org.jetbrains.kotlin.analyzer.*
+import org.jetbrains.kotlin.caches.project.LibraryModuleInfo
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.config.TargetPlatformVersion
+import org.jetbrains.kotlin.container.StorageComponentContainer
+import org.jetbrains.kotlin.container.get
+import org.jetbrains.kotlin.container.useImpl
+import org.jetbrains.kotlin.container.useInstance
+import org.jetbrains.kotlin.context.ModuleContext
+import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
+import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
+import org.jetbrains.kotlin.frontend.di.configureModule
+import org.jetbrains.kotlin.ide.konan.KOTLIN_NATIVE_CURRENT_ABI_VERSION
+import org.jetbrains.kotlin.ide.konan.createPackageFragmentProvider
+import org.jetbrains.kotlin.incremental.components.LookupTracker
+import org.jetbrains.kotlin.js.resolve.JsPlatform
+import org.jetbrains.kotlin.konan.file.File
+import org.jetbrains.kotlin.konan.library.createKonanLibrary
+import org.jetbrains.kotlin.resolve.*
+import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
+import org.jetbrains.kotlin.resolve.lazy.ResolveSession
+import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
+import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
+import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
+import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider
+import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
+
+fun createContainerForLazyResolve(
+ moduleContext: ModuleContext,
+ declarationProviderFactory: DeclarationProviderFactory,
+ bindingTrace: BindingTrace,
+ platform: TargetPlatform,
+ targetPlatformVersion: TargetPlatformVersion,
+ targetEnvironment: TargetEnvironment,
+ languageVersionSettings: LanguageVersionSettings
+): StorageComponentContainer = createContainer("LazyResolve", platform) {
+ configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace)
+
+ useInstance(declarationProviderFactory)
+ useInstance(languageVersionSettings)
+
+ useImpl<AnnotationResolverImpl>()
+ useImpl<CompilerDeserializationConfiguration>()
+ targetEnvironment.configure(this)
+
+ useImpl<ResolveSession>()
+ useImpl<LazyTopDownAnalyzer>()
+}
+
+
+object DokkaJsAnalyzerFacade : ResolverForModuleFactory() {
+ override fun <M : ModuleInfo> createResolverForModule(
+ moduleDescriptor: ModuleDescriptorImpl,
+ moduleContext: ModuleContext,
+ moduleContent: ModuleContent<M>,
+ platformParameters: PlatformAnalysisParameters,
+ targetEnvironment: TargetEnvironment,
+ resolverForProject: ResolverForProject<M>,
+ languageVersionSettings: LanguageVersionSettings,
+ targetPlatformVersion: TargetPlatformVersion
+ ): ResolverForModule {
+ val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent
+ val project = moduleContext.project
+ val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
+ project,
+ moduleContext.storageManager,
+ syntheticFiles,
+ moduleContentScope,
+ moduleInfo
+ )
+
+ val container = createContainerForLazyResolve(
+ moduleContext,
+ declarationProviderFactory,
+ BindingTraceContext(),
+ JsPlatform,
+ TargetPlatformVersion.NoVersion,
+ targetEnvironment,
+ languageVersionSettings
+ )
+ var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
+
+ if (moduleInfo is LibraryModuleInfo && moduleInfo.platform == JsPlatform) {
+ val providers = moduleInfo.getLibraryRoots()
+ .flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) }
+ .filter { it.version.isCompatible() }
+ .map { metadata ->
+ val (header, packageFragmentProtos) =
+ KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version)
+ createKotlinJavascriptPackageFragmentProvider(
+ moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, metadata.version,
+ container.get(), LookupTracker.DO_NOTHING
+ )
+ }
+
+ if (providers.isNotEmpty()) {
+ packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers)
+ }
+ }
+
+ return ResolverForModule(packageFragmentProvider, container)
+ }
+
+ override val targetPlatform: TargetPlatform
+ get() = JsPlatform
+}
+
+object DokkaNativeAnalyzerFacade : ResolverForModuleFactory() {
+ override val targetPlatform: TargetPlatform
+ get() = KonanPlatform
+
+ override fun <M : ModuleInfo> createResolverForModule(
+ moduleDescriptor: ModuleDescriptorImpl,
+ moduleContext: ModuleContext,
+ moduleContent: ModuleContent<M>,
+ platformParameters: PlatformAnalysisParameters,
+ targetEnvironment: TargetEnvironment,
+ resolverForProject: ResolverForProject<M>,
+ languageVersionSettings: LanguageVersionSettings,
+ targetPlatformVersion: TargetPlatformVersion
+ ): ResolverForModule {
+
+ val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory(
+ moduleContext.project,
+ moduleContext.storageManager,
+ moduleContent.syntheticFiles,
+ moduleContent.moduleContentScope,
+ moduleContent.moduleInfo
+ )
+
+ val container = createContainerForLazyResolve(
+ moduleContext,
+ declarationProviderFactory,
+ BindingTraceContext(),
+ targetPlatform,
+ TargetPlatformVersion.NoVersion,
+ targetEnvironment,
+ languageVersionSettings
+ )
+
+ val packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
+ val fragmentProviders = mutableListOf(packageFragmentProvider)
+
+ val moduleInfo = moduleContent.moduleInfo
+
+ if (moduleInfo is LibraryModuleInfo) {
+ moduleInfo.getLibraryRoots()
+ .filter { File(it).extension != "jar" }
+ .map { createKonanLibrary(File(it), KOTLIN_NATIVE_CURRENT_ABI_VERSION) }
+ .mapTo(fragmentProviders) {
+ it.createPackageFragmentProvider(
+ moduleContext.storageManager,
+ languageVersionSettings,
+ moduleDescriptor
+ )
+ }
+
+ }
+
+ return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container)
+ }
+}
diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt
index e18ab6cf..b48b62d4 100644
--- a/core/src/main/kotlin/DokkaBootstrapImpl.kt
+++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt
@@ -1,8 +1,8 @@
package org.jetbrains.dokka
+import com.google.gson.Gson
import org.jetbrains.dokka.DokkaConfiguration.PackageOptions
-import ru.yole.jkid.deserialization.deserialize
-import java.io.File
+
import java.util.function.BiConsumer
@@ -39,42 +39,38 @@ class DokkaBootstrapImpl : DokkaBootstrap {
}
lateinit var generator: DokkaGenerator
+ val gson = Gson()
- override fun configure(logger: BiConsumer<String, String>, serializedConfigurationJSON: String)
- = configure(DokkaProxyLogger(logger), deserialize<DokkaConfigurationImpl>(serializedConfigurationJSON))
-
- fun configure(logger: DokkaLogger, configuration: DokkaConfiguration) = with(configuration) {
- generator = DokkaGenerator(
- logger,
- classpath,
- sourceRoots,
- samples,
- includes,
- moduleName,
- DocumentationOptions(
- outputDir = outputDir,
- outputFormat = format,
- includeNonPublic = includeNonPublic,
- includeRootPackage = includeRootPackage,
- reportUndocumented = reportUndocumented,
- skipEmptyPackages = skipEmptyPackages,
- skipDeprecated = skipDeprecated,
- jdkVersion = jdkVersion,
- generateIndexPages = generateIndexPages,
- sourceLinks = sourceLinks,
- impliedPlatforms = impliedPlatforms,
- perPackageOptions = perPackageOptions,
- externalDocumentationLinks = externalDocumentationLinks,
- noStdlibLink = noStdlibLink,
- noJdkLink = noJdkLink,
- languageVersion = languageVersion,
- apiVersion = apiVersion,
- cacheRoot = cacheRoot,
- suppressedFiles = suppressedFiles.map { File(it) }.toSet(),
- collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries
- )
- )
+ fun configure(logger: DokkaLogger, configuration: DokkaConfigurationImpl) = with(configuration) {
+
+ fun defaultLinks(config: PassConfigurationImpl): List<ExternalDocumentationLinkImpl> {
+ val links = mutableListOf<ExternalDocumentationLinkImpl>()
+ if (!config.noJdkLink)
+ links += DokkaConfiguration.ExternalDocumentationLink
+ .Builder("https://docs.oracle.com/javase/${config.jdkVersion}/docs/api/")
+ .build() as ExternalDocumentationLinkImpl
+
+ if (!config.noStdlibLink)
+ links += DokkaConfiguration.ExternalDocumentationLink
+ .Builder("https://kotlinlang.org/api/latest/jvm/stdlib/")
+ .build() as ExternalDocumentationLinkImpl
+ return links
+ }
+
+ val configurationWithLinks =
+ configuration.copy(passesConfigurations =
+ passesConfigurations
+ .map {
+ val links: List<ExternalDocumentationLinkImpl> = it.externalDocumentationLinks + defaultLinks(it)
+ it.copy(externalDocumentationLinks = links)
+ }
+ )
+
+ generator = DokkaGenerator(configurationWithLinks, logger)
}
+ override fun configure(logger: BiConsumer<String, String>, serializedConfigurationJSON: String)
+ = configure(DokkaProxyLogger(logger), gson.fromJson(serializedConfigurationJSON, DokkaConfigurationImpl::class.java))
+
override fun generate() = generator.generate()
-} \ No newline at end of file
+}
diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt
index b497fb0f..4bac8aa0 100644
--- a/core/src/main/kotlin/Formats/FormatDescriptor.kt
+++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt
@@ -25,6 +25,7 @@ abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor {
override fun configureOutput(binder: Binder): Unit = with(binder) {
bind<Generator>() toType NodeLocationAwareGenerator::class
bind<NodeLocationAwareGenerator>() toType generatorServiceClass
+ bind(generatorServiceClass.java) // https://github.com/google/guice/issues/847
bind<LanguageService>() toType languageServiceClass
diff --git a/core/src/main/kotlin/Formats/FormatService.kt b/core/src/main/kotlin/Formats/FormatService.kt
index 63f25008..8f4855e3 100644
--- a/core/src/main/kotlin/Formats/FormatService.kt
+++ b/core/src/main/kotlin/Formats/FormatService.kt
@@ -22,7 +22,7 @@ interface FormatService {
}
interface FormattedOutputBuilder {
- /** Appends formatted content to [StringBuilder](to) using specified [location] */
+ /** Appends formatted content */
fun appendNodes(nodes: Iterable<DocumentationNode>)
}
diff --git a/core/src/main/kotlin/Formats/HtmlFormatService.kt b/core/src/main/kotlin/Formats/HtmlFormatService.kt
index 0ad946be..d36ea0a2 100644
--- a/core/src/main/kotlin/Formats/HtmlFormatService.kt
+++ b/core/src/main/kotlin/Formats/HtmlFormatService.kt
@@ -88,9 +88,7 @@ open class HtmlOutputBuilder(to: StringBuilder,
to.append("&nbsp;")
}
- override fun ensureParagraph() {
-
- }
+ override fun ensureParagraph() {}
}
open class HtmlFormatService @Inject constructor(generator: NodeLocationAwareGenerator,
@@ -144,7 +142,7 @@ fun formatPageTitle(node: DocumentationNode): String {
}
val qName = qualifiedNameForPageTitle(node)
- return qName + " - " + moduleName
+ return "$qName - $moduleName"
}
private fun qualifiedNameForPageTitle(node: DocumentationNode): String {
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
deleted file mode 100644
index a98002d4..00000000
--- a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-package org.jetbrains.dokka
-
-import com.google.inject.Inject
-import com.google.inject.name.Named
-import org.jetbrains.dokka.Utilities.impliedPlatformsName
-import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
-
-
-open class KotlinWebsiteOutputBuilder(
- to: StringBuilder,
- location: Location,
- generator: NodeLocationAwareGenerator,
- languageService: LanguageService,
- extension: String,
- impliedPlatforms: List<String>
-) : JekyllOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) {
- private var needHardLineBreaks = false
- private var insideDiv = 0
-
- override fun appendFrontMatter(nodes: Iterable<DocumentationNode>, to: StringBuilder) {
- super.appendFrontMatter(nodes, to)
- to.appendln("layout: api")
- }
-
- override fun appendBreadcrumbs(path: Iterable<FormatLink>) {
- if (path.count() > 1) {
- to.append("<div class='api-docs-breadcrumbs'>")
- super.appendBreadcrumbs(path)
- to.append("</div>")
- }
- }
-
- override fun appendCode(body: () -> Unit) = wrapIfNotEmpty("<code>", "</code>", body)
-
- override fun appendStrikethrough(body: () -> Unit) = wrapInTag("s", body)
-
- protected fun div(to: StringBuilder, cssClass: String, otherAttributes: String = "", markdown: Boolean = false, block: () -> Unit) {
- to.append("<div class=\"$cssClass\"$otherAttributes")
- if (markdown) to.append(" markdown=\"1\"")
- to.append(">")
- if (!markdown) insideDiv++
- block()
- if (!markdown) insideDiv--
- to.append("</div>\n")
- }
-
- override fun appendAsSignature(node: ContentNode, block: () -> Unit) {
- val contentLength = node.textLength
- if (contentLength == 0) return
- div(to, "signature") {
- needHardLineBreaks = contentLength >= 62
- try {
- block()
- } finally {
- needHardLineBreaks = false
- }
- }
- }
-
- override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
- div(to, "overload-group", calculateDataAttributes(platforms), true) {
- ensureParagraph()
- block()
- ensureParagraph()
- }
- }
-
- override fun appendLink(href: String, body: () -> Unit) = wrap("<a href=\"$href\">", "</a>", body)
-
- override fun appendHeader(level: Int, body: () -> Unit) {
- if (insideDiv > 0) {
- wrapInTag("p", body, newlineAfterClose = true)
- } else {
- super.appendHeader(level, body)
- }
- }
-
- override fun appendLine() {
- if (insideDiv > 0) {
- to.appendln("<br/>")
- } else {
- super.appendLine()
- }
- }
-
- override fun appendTable(vararg columns: String, body: () -> Unit) {
- to.appendln("<table class=\"api-docs-table\">")
- body()
- to.appendln("</table>")
- }
-
- override fun appendTableBody(body: () -> Unit) {
- to.appendln("<tbody>")
- body()
- to.appendln("</tbody>")
- }
-
- override fun appendTableRow(body: () -> Unit) {
- to.appendln("<tr>")
- body()
- to.appendln("</tr>")
- }
-
- override fun appendTableCell(body: () -> Unit) {
- to.appendln("<td markdown=\"1\">")
- body()
- to.appendln("\n</td>")
- }
-
- override fun appendBlockCode(language: String, body: () -> Unit) {
- if (language.isNotEmpty()) {
- super.appendBlockCode(language, body)
- } else {
- wrap("<pre markdown=\"1\">", "</pre>", body)
- }
- }
-
- override fun appendSymbol(text: String) {
- to.append("<span class=\"symbol\">${text.htmlEscape()}</span>")
- }
-
- override fun appendKeyword(text: String) {
- to.append("<span class=\"keyword\">${text.htmlEscape()}</span>")
- }
-
- override fun appendIdentifier(text: String, kind: IdentifierKind, signature: String?) {
- val id = signature?.let { " id=\"$it\"" }.orEmpty()
- to.append("<span class=\"${identifierClassName(kind)}\"$id>${text.htmlEscape()}</span>")
- }
-
- override fun appendSoftLineBreak() {
- if (needHardLineBreaks)
- to.append("<br/>")
-
- }
-
- override fun appendIndentedSoftLineBreak() {
- if (needHardLineBreaks) {
- to.append("<br/>&nbsp;&nbsp;&nbsp;&nbsp;")
- }
- }
-
- private fun identifierClassName(kind: IdentifierKind) = when (kind) {
- IdentifierKind.ParameterName -> "parameterName"
- IdentifierKind.SummarizedTypeName -> "summarizedTypeName"
- else -> "identifier"
- }
-
- fun calculateDataAttributes(platforms: Set<String>): String {
- fun String.isKotlinVersion() = this.startsWith("Kotlin")
- fun String.isJREVersion() = this.startsWith("JRE")
- val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)
- val jreVersion = platforms.singleOrNull(String::isJREVersion)
- val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() }
-
- val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: ""
- val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: ""
- val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: ""
- return "$platformsAttr$kotlinVersionAttr$jreVersionAttr"
- }
-
- override fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
- if (platforms.isNotEmpty())
- wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
- else
- appendTableRow(block)
- }
-
- override fun appendPlatforms(platforms: Set<String>) {
-
- }
-}
-
-class KotlinWebsiteFormatService @Inject constructor(
- generator: NodeLocationAwareGenerator,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>,
- logger: DokkaLogger
-) : JekyllFormatService(generator, signatureGenerator, "html", impliedPlatforms) {
- init {
- logger.warn("Format kotlin-website deprecated and will be removed in next release")
- }
-
- override fun createOutputBuilder(to: StringBuilder, location: Location) =
- KotlinWebsiteOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
-}
-
-
-class KotlinWebsiteRunnableSamplesOutputBuilder(
- to: StringBuilder,
- location: Location,
- generator: NodeLocationAwareGenerator,
- languageService: LanguageService,
- extension: String,
- impliedPlatforms: List<String>
-) : KotlinWebsiteOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) {
-
- override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) {
- div(to, "sample", markdown = true) {
- appendBlockCode(language) {
- imports()
- wrap("\n\nfun main(args: Array<String>) {", "}") {
- wrap("\n//sampleStart\n", "\n//sampleEnd\n", body)
- }
- }
- }
- }
-}
-
-class KotlinWebsiteRunnableSamplesFormatService @Inject constructor(
- generator: NodeLocationAwareGenerator,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>,
- logger: DokkaLogger
-) : JekyllFormatService(generator, signatureGenerator, "html", impliedPlatforms) {
-
- init {
- logger.warn("Format kotlin-website-samples deprecated and will be removed in next release")
- }
-
- override fun createOutputBuilder(to: StringBuilder, location: Location) =
- KotlinWebsiteRunnableSamplesOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
-}
-
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
index 6ced75b5..3cdea156 100644
--- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
+++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
@@ -3,7 +3,6 @@ package org.jetbrains.dokka
import com.google.inject.Inject
import com.google.inject.name.Named
import org.jetbrains.dokka.Utilities.impliedPlatformsName
-import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
import java.io.File
@@ -20,7 +19,7 @@ open class KotlinWebsiteHtmlOutputBuilder(
generator: NodeLocationAwareGenerator,
languageService: LanguageService,
extension: String,
- impliedPlatforms: List<String>,
+ val impliedPlatforms: List<String>,
templateService: HtmlTemplateService
) : HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) {
private var needHardLineBreaks = false
@@ -36,6 +35,12 @@ open class KotlinWebsiteHtmlOutputBuilder(
}
}
+ override fun appendSinceKotlin(version: String) {
+ }
+
+ override fun appendSinceKotlinWrapped(version: String) {
+ }
+
override fun appendCode(body: () -> Unit) = wrapIfNotEmpty("<code>", "</code>", body)
protected fun div(to: StringBuilder, cssClass: String, otherAttributes: String = "", block: () -> Unit) {
@@ -60,7 +65,7 @@ open class KotlinWebsiteHtmlOutputBuilder(
}
}
- override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
+ override fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) {
div(to, "overload-group", calculateDataAttributes(platforms)) {
block()
}
@@ -69,27 +74,29 @@ open class KotlinWebsiteHtmlOutputBuilder(
override fun appendLink(href: String, body: () -> Unit) = wrap("<a href=\"$href\">", "</a>", body)
override fun appendTable(vararg columns: String, body: () -> Unit) {
- to.appendln("<table class=\"api-docs-table\">")
- body()
- to.appendln("</table>")
+ //to.appendln("<table class=\"api-docs-table\">")
+ div(to, "api-declarations-list") {
+ body()
+ }
+ //to.appendln("</table>")
}
override fun appendTableBody(body: () -> Unit) {
- to.appendln("<tbody>")
+ //to.appendln("<tbody>")
body()
- to.appendln("</tbody>")
+ //to.appendln("</tbody>")
}
override fun appendTableRow(body: () -> Unit) {
- to.appendln("<tr>")
+ //to.appendln("<tr>")
body()
- to.appendln("</tr>")
+ //to.appendln("</tr>")
}
override fun appendTableCell(body: () -> Unit) {
- to.appendln("<td>")
+// to.appendln("<td>")
body()
- to.appendln("\n</td>")
+// to.appendln("\n</td>")
}
override fun appendSymbol(text: String) {
@@ -122,34 +129,79 @@ open class KotlinWebsiteHtmlOutputBuilder(
else -> "identifier"
}
- fun calculateDataAttributes(platforms: Set<String>): String {
- fun String.isKotlinVersion() = this.startsWith("Kotlin")
- fun String.isJREVersion() = this.startsWith("JRE")
- val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)
- val jreVersion = platforms.singleOrNull(String::isJREVersion)
- val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() }
+ private data class PlatformsForElement(
+ val platformToVersion: Map<String, String>
+ )
+
+ private fun calculatePlatforms(platforms: PlatformsData): PlatformsForElement {
+ //val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ")
+ val jreVersion = platforms.keys.filter(String::isJREVersion).min()?.takeUnless { it.endsWith("6") }
+ val targetPlatforms = platforms.filterNot { it.key.isJREVersion() } +
+ listOfNotNull(jreVersion?.let { it to platforms[it]!! })
+
+ return PlatformsForElement(
+ targetPlatforms.mapValues { (_, nodes) -> effectiveSinceKotlinForNodes(nodes) }
+ )
+ }
- val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: ""
- val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: ""
- val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: ""
- return "$platformsAttr$kotlinVersionAttr$jreVersionAttr"
+ private fun calculateDataAttributes(platforms: PlatformsData): String {
+ val platformToVersion = calculatePlatforms(platforms).platformToVersion
+ val (platformNames, versions) = platformToVersion.toList().unzip()
+ return "data-platform=\"${platformNames.joinToString()}\" "+
+ "data-kotlin-version=\"${versions.joinToString()}\""
}
- override fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
- if (platforms.isNotEmpty())
- wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
- else
- appendTableRow(block)
+ override fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) {
+// if (platforms.isNotEmpty())
+// wrap("<tr${calculateDataAttributes(platforms)}>", "</tr>", block)
+// else
+// appendTableRow(block)
+ div(to, "declarations", otherAttributes = " ${calculateDataAttributes(platforms)}") {
+ block()
+ }
+ }
+
+ override fun appendPlatforms(platforms: PlatformsData) {
+ val platformToVersion = calculatePlatforms(platforms).platformToVersion
+ div(to, "tags") {
+ div(to, "spacer") {}
+ platformToVersion.entries.sortedBy {
+ platformSortWeight(it.key)
+ }.forEach { (platform, version) ->
+ div(to, "tags__tag platform tag-value-$platform",
+ otherAttributes = " data-tag-version=\"$version\"") {
+ to.append(platform)
+ }
+ }
+ div(to, "tags__tag kotlin-version") {
+ to.append(mergeVersions(platformToVersion.values.toList()))
+ }
+ }
}
- override fun appendPlatforms(platforms: Set<String>) {}
+ override fun appendAsNodeDescription(platforms: PlatformsData, block: () -> Unit) {
+ div(to, "node-page-main", otherAttributes = " ${calculateDataAttributes(platforms)}") {
+ block()
+ }
+
+ }
override fun appendBreadcrumbSeparator() {
to.append(" / ")
}
+ override fun appendPlatformsAsText(platforms: PlatformsData) {
+ appendHeader(5) {
+ val filtered = platforms.keys.filterNot { it.isJREVersion() }.sortedBy { platformSortWeight(it) }
+ if (filtered.isNotEmpty()) {
+ to.append("For ")
+ filtered.joinTo(to)
+ }
+ }
+ }
+
override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) {
- div(to, "sample") {
+ div(to, "sample", otherAttributes = " data-min-compiler-version=\"1.3\"") {
appendBlockCode(language) {
imports()
wrap("\n\nfun main(args: Array<String>) {".htmlEscape(), "}") {
@@ -169,6 +221,29 @@ open class KotlinWebsiteHtmlOutputBuilder(
appendContent(section)
}
}
+
+ override fun appendAsPlatformDependentBlock(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ if (platforms.isNotEmpty())
+ wrap("<div ${calculateDataAttributes(platforms)}>", "</div>") {
+ block(platforms)
+ }
+ else
+ block(platforms)
+ }
+
+ override fun appendAsSummaryGroup(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ div(to, "summary-group", otherAttributes = " ${calculateDataAttributes(platforms)}") {
+ block(platforms)
+ }
+ }
+
+ fun platformSortWeight(name: String) = when(name.toLowerCase()) {
+ "common" -> 0
+ "jvm" -> 1
+ "js" -> 3
+ "native" -> 4
+ else -> 2 // This is hack to support JRE/JUnit and so on
+ }
}
class KotlinWebsiteHtmlFormatService @Inject constructor(
@@ -184,3 +259,6 @@ class KotlinWebsiteHtmlFormatService @Inject constructor(
KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService)
}
+
+private fun String.isKotlinVersion() = this.startsWith("Kotlin")
+private fun String.isJREVersion() = this.startsWith("JRE", ignoreCase=true) \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/MarkdownFormatService.kt b/core/src/main/kotlin/Formats/MarkdownFormatService.kt
index 4265394f..216dd2ef 100644
--- a/core/src/main/kotlin/Formats/MarkdownFormatService.kt
+++ b/core/src/main/kotlin/Formats/MarkdownFormatService.kt
@@ -159,24 +159,35 @@ open class MarkdownOutputBuilder(to: StringBuilder,
}
override fun appendParagraph(body: () -> Unit) {
- if (inTableCell) {
- ensureNewline()
- body()
- } else if (listStack.isNotEmpty()) {
- body()
- ensureNewline()
- } else {
- ensureParagraph()
- body()
- ensureParagraph()
+ when {
+ inTableCell -> {
+ ensureNewline()
+ body()
+ }
+ listStack.isNotEmpty() -> {
+ body()
+ ensureNewline()
+ }
+ else -> {
+ ensureParagraph()
+ body()
+ ensureParagraph()
+ }
}
}
override fun appendHeader(level: Int, body: () -> Unit) {
- ensureParagraph()
- to.append("${"#".repeat(level)} ")
- body()
- ensureParagraph()
+ when {
+ inTableCell -> {
+ body()
+ }
+ else -> {
+ ensureParagraph()
+ to.append("${"#".repeat(level)} ")
+ body()
+ ensureParagraph()
+ }
+ }
}
override fun appendBlockCode(language: String, body: () -> Unit) {
diff --git a/core/src/main/kotlin/Formats/PackageListService.kt b/core/src/main/kotlin/Formats/PackageListService.kt
index 7b68098e..e675d927 100644
--- a/core/src/main/kotlin/Formats/PackageListService.kt
+++ b/core/src/main/kotlin/Formats/PackageListService.kt
@@ -32,10 +32,13 @@ class DefaultPackageListService @Inject constructor(
node.members.forEach { visit(it, relocated = true) }
}
NodeKind.GroupNode -> {
- //only children of top-level GN records interesting for us, since link to top-level ones should point to GN
- node.members.forEach { it.members.forEach { visit(it, relocated = true) } }
- //record signature of GN as signature of type alias and class merged to GN, so link to it should point to GN
- node.detailOrNull(NodeKind.Signature)?.let { visit(it, relocated = true) }
+ if (node.members.isNotEmpty()) {
+ // Only nodes only has single file is need to be relocated
+ // TypeAliases for example
+ node.origins
+ .filter { it.members.isEmpty() }
+ .forEach { visit(it, relocated = true) }
+ }
}
else -> {
if (nodeKind in NodeKind.classLike || nodeKind in NodeKind.memberLike) {
diff --git a/core/src/main/kotlin/Formats/StandardFormats.kt b/core/src/main/kotlin/Formats/StandardFormats.kt
index dd67ac97..86f70a37 100644
--- a/core/src/main/kotlin/Formats/StandardFormats.kt
+++ b/core/src/main/kotlin/Formats/StandardFormats.kt
@@ -31,17 +31,6 @@ class HtmlFormatDescriptor : HtmlFormatDescriptorBase(), DefaultAnalysisComponen
class HtmlAsJavaFormatDescriptor : HtmlFormatDescriptorBase(), DefaultAnalysisComponentServices by KotlinAsJava
-class KotlinWebsiteFormatDescriptor : KotlinFormatDescriptorBase() {
- override val formatServiceClass = KotlinWebsiteFormatService::class
- override val outlineServiceClass = YamlOutlineService::class
-}
-
-class KotlinWebsiteFormatRunnableSamplesDescriptor : KotlinFormatDescriptorBase() {
- override val formatServiceClass = KotlinWebsiteRunnableSamplesFormatService::class
- override val sampleProcessingService = KotlinWebsiteSampleProcessingService::class
- override val outlineServiceClass = YamlOutlineService::class
-}
-
class KotlinWebsiteHtmlFormatDescriptor : KotlinFormatDescriptorBase() {
override val formatServiceClass = KotlinWebsiteHtmlFormatService::class
override val sampleProcessingService = KotlinWebsiteSampleProcessingService::class
diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt
index 410de281..7299670e 100644
--- a/core/src/main/kotlin/Formats/StructuredFormatService.kt
+++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt
@@ -1,18 +1,59 @@
package org.jetbrains.dokka
import org.jetbrains.dokka.LanguageService.RenderMode
+import org.jetbrains.kotlin.utils.keysToMap
import java.util.*
data class FormatLink(val text: String, val href: String)
+private data class Summarized(
+ val data: List<SummarizedBySummary>
+) {
+
+ constructor(data: Map<ContentNode, Map<ContentNode, List<DocumentationNode>>>) : this(
+ data.entries.map { (summary, signatureToMember) ->
+ SummarizedBySummary(
+ summary,
+ signatureToMember.map { (signature, nodes) ->
+ SummarizedNodes(signature, nodes)
+ }
+ )
+ }
+ )
+
+ data class SummarizedNodes(val content: ContentNode, val nodes: List<DocumentationNode>) {
+ val platforms = effectivePlatformsForMembers(nodes)
+ }
+ data class SummarizedBySummary(val content: ContentNode, val signatures: List<SummarizedNodes>) {
+ val platforms = effectivePlatformsForMembers(signatures.flatMap { it.nodes })
+ val platformsOnSignature = !samePlatforms(signatures.map { it.platforms })
+ }
+
+
+ fun computePlatformLevel(): PlatformPlacement {
+ if (data.any { it.platformsOnSignature }) {
+ return PlatformPlacement.Signature
+ }
+ if (samePlatforms(data.map { it.platforms })) {
+ return PlatformPlacement.Row
+ }
+ return PlatformPlacement.Summary
+ }
+ val platformPlacement: PlatformPlacement = computePlatformLevel()
+ val platforms = effectivePlatformsForMembers(data.flatMap { it.signatures.flatMap { it.nodes } })
+
+
+ enum class PlatformPlacement {
+ Row, Summary, Signature
+ }
+}
+
abstract class StructuredOutputBuilder(val to: StringBuilder,
val location: Location,
val generator: NodeLocationAwareGenerator,
val languageService: LanguageService,
val extension: String,
- val impliedPlatforms: List<String>) : FormattedOutputBuilder {
-
- protected fun DocumentationNode.location() = generator.location(this)
+ impliedPlatforms: List<String>) : FormattedOutputBuilder {
protected fun wrap(prefix: String, suffix: String, body: () -> Unit) {
to.append(prefix)
@@ -69,9 +110,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
abstract fun appendText(text: String)
open fun appendSinceKotlin(version: String) {
- appendParagraph {
- appendText("Available since Kotlin: ")
+ appendText("Since: ")
appendCode { appendText(version) }
+ }
+
+ open fun appendSinceKotlinWrapped(version: String) {
+ wrap(" (", ")") {
+ appendSinceKotlin(version)
}
}
@@ -83,6 +128,14 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
+ open fun appendAsPlatformDependentBlock(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ block(platforms)
+ }
+
+ open fun appendAsSummaryGroup(platforms: PlatformsData, block: (PlatformsData) -> Unit) {
+ appendAsPlatformDependentBlock(platforms, block)
+ }
+
open fun appendSymbol(text: String) {
appendText(text)
}
@@ -95,6 +148,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendText(text)
}
+ open fun appendAsNodeDescription(platforms: PlatformsData, block: () -> Unit) {
+ block()
+ }
+
fun appendEntity(text: String) {
to.append(text)
}
@@ -158,7 +215,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
is ContentNodeLink -> {
val node = content.node
- val linkTo = if (node != null) locationHref(location, node) else "#"
+ val linkTo = if (node != null) locationHref(location, node, generator) else "#"
appendLinkIfNotThisPage(linkTo, content)
}
is ContentExternalLink -> appendLinkIfNotThisPage(content.href, content)
@@ -173,14 +230,14 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
content as ContentBlockCode
fun ContentBlockCode.appendBlockCodeContent() {
children
- .dropWhile { it is ContentText && it.text.isBlank() }
- .forEach { appendContent(it) }
+ .dropWhile { it is ContentText && it.text.isBlank() }
+ .forEach { appendContent(it) }
}
when (content) {
is ContentBlockSampleCode ->
- appendSampleBlockCode(content.language, content.importsBlock::appendBlockCodeContent, { content.appendBlockCodeContent() })
+ appendSampleBlockCode(content.language, content.importsBlock::appendBlockCodeContent) { content.appendBlockCodeContent() }
is ContentBlockCode ->
- appendBlockCode(content.language, { content.appendBlockCodeContent() })
+ appendBlockCode(content.language) { content.appendBlockCodeContent() }
}
}
is ContentHeading -> appendHeader(content.level) { appendContent(content.children) }
@@ -196,51 +253,42 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
- open fun link(from: DocumentationNode,
- to: DocumentationNode,
- name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink = link(from, to, extension, name)
-
- open fun link(from: DocumentationNode,
- to: DocumentationNode,
- extension: String,
- name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink {
- if (to.owner?.kind == NodeKind.GroupNode)
- return link(from, to.owner!!, extension, name)
-
- if (from.owner?.kind == NodeKind.GroupNode)
- return link(from.owner!!, to, extension, name)
-
- return FormatLink(name(to), from.location().relativePathTo(to.location()))
- }
+ open fun link(
+ from: DocumentationNode,
+ to: DocumentationNode,
+ name: (DocumentationNode) -> String = DocumentationNode::name
+ ): FormatLink = link(from, to, extension, name)
- fun locationHref(from: Location, to: DocumentationNode): String {
- val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to
- if (topLevelPage != null) {
- val signature = to.detailOrNull(NodeKind.Signature)
- return from.relativePathTo(topLevelPage.location(), signature?.name ?: to.name)
- }
- return from.relativePathTo(to.location())
- }
+ open fun link(
+ from: DocumentationNode,
+ to: DocumentationNode,
+ extension: String,
+ name: (DocumentationNode) -> String = DocumentationNode::name
+ ): FormatLink =
+ FormatLink(name(to), generator.relativePathToLocation(from, to))
private fun DocumentationNode.isModuleOrPackage(): Boolean =
- kind == NodeKind.Module || kind == NodeKind.Package
+ kind == NodeKind.Module || kind == NodeKind.Package
protected open fun appendAsSignature(node: ContentNode, block: () -> Unit) {
block()
}
- protected open fun appendAsOverloadGroup(to: StringBuilder, platforms: Set<String>, block: () -> Unit) {
+ protected open fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) {
block()
}
- protected open fun appendIndexRow(platforms: Set<String>, block: () -> Unit) {
+ protected open fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) {
appendTableRow(block)
}
- protected open fun appendPlatforms(platforms: Set<String>) {
+ protected open fun appendPlatformsAsText(platforms: PlatformsData) {
+ appendPlatforms(platforms)
+ }
+
+ protected open fun appendPlatforms(platforms: PlatformsData) {
if (platforms.isNotEmpty()) {
- appendLine()
- appendText(platforms.joinToString(prefix = "(", postfix = ")"))
+ appendText(platforms.keys.joinToString(prefix = "(", postfix = ") "))
}
}
@@ -254,7 +302,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
fun Content.getSectionsWithSubjects(): Map<String, List<ContentSection>> =
- sections.filter { it.subjectName != null }.groupBy { it.tag }
+ sections.filter { it.subjectName != null }.groupBy { it.tag }
private fun ContentNode.appendSignature() {
if (this is ContentBlock && this.isEmpty()) {
@@ -289,7 +337,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
val packageName = if (singleNode.name.isEmpty()) "<root>" else singleNode.name
appendHeader(2) { appendText("Package $packageName") }
}
- singleNode.appendPlatforms()
appendContent(singleNode.content)
} else {
val breakdownByName = nodes.groupBy { node -> node.name }
@@ -302,45 +349,134 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
private fun appendDocumentation(overloads: Iterable<DocumentationNode>, isSingleNode: Boolean) {
- val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content }
+ val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node ->
+ when (node.kind) {
+ NodeKind.GroupNode -> node.origins.map { it.content }
+ else -> node.content
+ }
+ }
if (breakdownBySummary.size == 1) {
- formatOverloadGroup(breakdownBySummary.values.single(), isSingleNode)
+ val node = breakdownBySummary.values.single()
+ appendAsNodeDescription(effectivePlatformsForMembers(node)) {
+ formatOverloadGroup(node, isSingleNode)
+ }
} else {
for ((_, items) in breakdownBySummary) {
-
- appendAsOverloadGroup(to, platformsOfItems(items)) {
+ appendAsOverloadGroup(to, effectivePlatformsForMembers(items)) {
formatOverloadGroup(items)
}
-
}
}
}
private fun formatOverloadGroup(items: List<DocumentationNode>, isSingleNode: Boolean = false) {
+
+ val platformsPerGroup = samePlatforms(
+ items.flatMap {
+ if (it.kind == NodeKind.GroupNode) {
+ it.origins.groupBy { origin ->
+ languageService.render(origin)
+ }.values.map { origins -> effectivePlatformsForMembers(origins) }
+ } else {
+ listOf(effectivePlatformsForNode(it))
+ }
+ }
+ )
+
+ if (platformsPerGroup) {
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(items)) { platforms ->
+ appendPlatforms(platforms)
+ }
+ }
for ((index, item) in items.withIndex()) {
if (index > 0) appendLine()
+
+ if (item.kind == NodeKind.GroupNode) {
+ renderGroupNode(item, isSingleNode, !platformsPerGroup)
+ } else {
+ renderSimpleNode(item, isSingleNode, !platformsPerGroup)
+ }
+
+ }
+ // All items have exactly the same documentation, so we can use any item to render it
+ val item = items.first()
+ // TODO: remove this block cause there is no one node with OverloadGroupNote detail
+ item.details(NodeKind.OverloadGroupNote).forEach {
+ appendContent(it.content)
+ }
+
+ if (item.kind == NodeKind.GroupNode) {
+ val groupByContent = item.origins.groupBy { it.content }
+ if (groupByContent.count { !it.key.isEmpty() } > 1) {
+ if (groupByContent.size > 1) println("[mult] Found ov diff: ${generator.location(item).path}")
+ }
+ for ((content, origins) in groupByContent) {
+ if (content.isEmpty()) continue
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms ->
+ if (groupByContent.count { !it.key.isEmpty() } > 1) {
+ appendPlatformsAsText(platforms)
+ }
+ appendContent(content.summary)
+ content.appendDescription()
+ }
+ }
+ } else {
+ val platforms = effectivePlatformsForNode(item)
+ appendAsPlatformDependentBlock(platforms) {
+ appendContent(item.summary)
+ item.content.appendDescription()
+ }
+ }
+ }
+
+
+ fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) {
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(listOf(item))) { platforms ->
+ // TODO: use summarizesignatures
val rendered = languageService.render(item)
item.detailOrNull(NodeKind.Signature)?.let {
if (item.kind !in NodeKind.classLike || !isSingleNode)
appendAnchor(it.name)
}
+ if (withPlatforms) {
+ appendPlatforms(platforms)
+ }
appendAsSignature(rendered) {
appendCode { appendContent(rendered) }
item.appendSourceLink()
}
item.appendOverrides()
item.appendDeprecation()
- item.appendPlatforms()
}
- // All items have exactly the same documentation, so we can use any item to render it
- val item = items.first()
- item.details(NodeKind.OverloadGroupNote).forEach {
- appendContent(it.content)
+ }
+
+ fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) {
+ // TODO: use summarizesignatures
+ val groupBySignature = item.origins.groupBy {
+ languageService.render(it)
}
- appendContent(item.content.summary)
- item.appendDescription()
+ for ((sign, nodes) in groupBySignature) {
+ appendAsPlatformDependentBlock(effectivePlatformsForMembers(nodes)) { platforms ->
+ val first = nodes.first()
+ first.detailOrNull(NodeKind.Signature)?.let {
+ if (item.kind !in NodeKind.classLike || !isSingleNode)
+ appendAnchor(it.name)
+ }
+
+ if (withPlatforms) {
+ appendPlatforms(platforms)
+ }
+
+ appendAsSignature(sign) {
+ appendCode { appendContent(sign) }
+ }
+ first.appendOverrides()
+ first.appendDeprecation()
+ }
+
+ }
}
private fun DocumentationNode.appendSourceLink() {
@@ -355,7 +491,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
overrides.forEach {
appendParagraph {
to.append("Overrides ")
- val location = location().relativePathTo(it.location())
+ val location = generator.relativePathToLocation(this, it)
appendLink(FormatLink(it.owner!!.name + "." + it.name, location))
}
@@ -367,82 +503,95 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
val deprecationParameter = deprecation!!.details(NodeKind.Parameter).firstOrNull()
val deprecationValue = deprecationParameter?.details(NodeKind.Value)?.firstOrNull()
appendLine()
- if (deprecationValue != null) {
- appendStrong { to.append("Deprecated:") }
- appendText(" " + deprecationValue.name.removeSurrounding("\""))
- appendLine()
- appendLine()
- } else if (deprecation?.content != Content.Empty) {
- appendStrong { to.append("Deprecated:") }
- to.append(" ")
- appendContent(deprecation!!.content)
- } else {
- appendStrong { to.append("Deprecated") }
- appendLine()
- appendLine()
- }
- }
- }
-
- private fun DocumentationNode.appendPlatforms() {
- val platforms = if (isModuleOrPackage())
- platformsToShow.toSet() + platformsOfItems(members)
- else
- platformsToShow
-
- if (platforms.isEmpty()) return
-
- appendParagraph {
- appendStrong { to.append("Platform and version requirements:") }
- to.append(" " + platforms.joinToString())
- }
- }
-
- protected fun platformsOfItems(items: List<DocumentationNode>): Set<String> {
- val platforms = items.asSequence().map {
- when (it.kind) {
- NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module, NodeKind.GroupNode -> platformsOfItems(it.members)
- else -> it.platformsToShow.toSet()
- }
- }
-
- fun String.isKotlinVersion() = this.startsWith("Kotlin")
-
- // Calculating common platforms for items
- return platforms.reduce { result, platformsOfItem ->
- val otherKotlinVersion = result.find { it.isKotlinVersion() }
- val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
-
- // When no Kotlin version specified, it means that version is 1.0
- if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
- val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct()
-
- val minVersion = allKotlinVersions.min()!!
- val resultVersion = when {
- allKotlinVersions.size == 1 -> allKotlinVersions.single()
- minVersion.endsWith("+") -> minVersion
- else -> minVersion + "+"
+ when {
+ deprecationValue != null -> {
+ appendStrong { to.append("Deprecated:") }
+ appendText(" " + deprecationValue.name.removeSurrounding("\""))
+ appendLine()
+ appendLine()
+ }
+ deprecation?.content != Content.Empty -> {
+ appendStrong { to.append("Deprecated:") }
+ to.append(" ")
+ appendContent(deprecation!!.content)
+ }
+ else -> {
+ appendStrong { to.append("Deprecated") }
+ appendLine()
+ appendLine()
}
-
- result.intersect(otherPlatforms) + resultVersion
- } else {
- result.intersect(platformsOfItem)
}
}
}
- val DocumentationNode.platformsToShow: List<String>
- get() = platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it }
- private fun DocumentationNode.appendDescription() {
- if (content.description != ContentEmpty) {
- appendContent(content.description)
- }
- content.getSectionsWithSubjects().forEach {
+// protected fun platformsOfItems(items: List<DocumentationNode>): Set<String> {
+// val platforms = items.asSequence().map {
+// when (it.kind) {
+// NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members)
+// NodeKind.GroupNode -> platformsOfItems(it.origins)
+// else -> it.platformsToShow.toSet()
+// }
+// }
+//
+// fun String.isKotlinVersion() = this.startsWith("Kotlin")
+//
+// if (platforms.count() == 0) return emptySet()
+//
+// // Calculating common platforms for items
+// return platforms.reduce { result, platformsOfItem ->
+// val otherKotlinVersion = result.find { it.isKotlinVersion() }
+// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
+//
+// // When no Kotlin version specified, it means that version is 1.0
+// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
+// result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions)
+// } else {
+// result.intersect(platformsOfItem)
+// }
+// }
+// }
+//
+// protected fun unionPlatformsOfItems(items: List<DocumentationNode>): Set<String> {
+// val platforms = items.asSequence().map {
+// when (it.kind) {
+// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins)
+// else -> it.platformsToShow.toSet()
+// }
+// }
+//
+// fun String.isKotlinVersion() = this.startsWith("Kotlin")
+//
+// if (platforms.count() == 0) return emptySet()
+//
+// // Calculating common platforms for items
+// return platforms.reduce { result, platformsOfItem ->
+// val otherKotlinVersion = result.find { it.isKotlinVersion() }
+// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
+//
+// // When no Kotlin version specified, it means that version is 1.0
+// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
+// result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions)
+// } else {
+// result.union(otherPlatforms)
+// }
+// }
+// }
+
+// val DocumentationNode.platformsToShow: List<String>
+// get() = platforms
+
+ private fun Content.appendDescription() {
+ if (description != ContentEmpty) {
+ appendContent(description)
+ }
+
+
+ getSectionsWithSubjects().forEach {
appendSectionWithSubject(it.key, it.value)
}
- for (section in content.sections.filter { it.subjectName == null }) {
+ for (section in sections.filter { it.subjectName == null }) {
appendSectionWithTag(section)
}
}
@@ -461,6 +610,38 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
}
+
+ fun appendOriginsGroupByContent(node: DocumentationNode) {
+ require(node.kind == NodeKind.GroupNode)
+ val groupByContent =
+ node.origins.groupBy { it.content }
+ .mapValues { (_, origins) ->
+ effectivePlatformsForMembers(origins)
+ }
+ .filterNot { it.key.isEmpty() }
+ .toList()
+ .sortedByDescending { it.second.size }
+
+ if (groupByContent.size > 1) println("[mult] Found diff: ${generator.location(node).path}")
+ for ((content, platforms) in groupByContent) {
+ appendAsPlatformDependentBlock(platforms) {
+ if (groupByContent.size > 1) {
+ appendPlatformsAsText(platforms)
+ }
+ appendContent(content.summary)
+ content.appendDescription()
+ }
+ }
+ }
+ }
+
+ inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false) :
+ PageBuilder(listOf(node), noHeader) {
+
+ override fun build() {
+ super.build()
+ SectionsBuilder(node).build()
+ }
}
inner class GroupNodePageBuilder(val node: DocumentationNode) : PageBuilder(listOf(node)) {
@@ -473,39 +654,37 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendLine()
appendHeader { appendText(node.name) }
- fun DocumentationNode.priority(): Int = when (kind) {
- NodeKind.TypeAlias -> 1
- NodeKind.Class -> 2
- else -> 3
- }
-
- for (member in node.members.sortedBy(DocumentationNode::priority)) {
-
- appendAsOverloadGroup(to, platformsOfItems(listOf(member))) {
- formatSubNodeOfGroup(member)
- }
+ appendAsNodeDescription(effectivePlatformsForNode(node)) {
+ renderGroupNode(node, true)
+ appendOriginsGroupByContent(node)
}
- }
- fun formatSubNodeOfGroup(member: DocumentationNode) {
- SingleNodePageBuilder(member, true).build()
+ SectionsBuilder(node).build()
}
}
-
- inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false)
- : PageBuilder(listOf(node), noHeader) {
-
+//
+// private fun unionPlatformsOfItems(items: List<DocumentationNode>): Set<String> {
+// val platforms = items.flatMapTo(mutableSetOf<String>()) {
+// when (it.kind) {
+// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins)
+// else -> it.platforms
+// }
+// }
+//
+// return platforms
+// }
+
+
+ inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) {
override fun build() {
- super.build()
-
if (node.kind == NodeKind.ExternalClass) {
appendSection("Extensions for ${node.name}", node.members)
return
}
fun DocumentationNode.membersOrGroupMembers(predicate: (DocumentationNode) -> Boolean): List<DocumentationNode> {
- return members.filter(predicate) + members(NodeKind.GroupNode).flatMap { it.members.filter(predicate) }
+ return members.filter(predicate) + members(NodeKind.GroupNode).filter{ it.origins.isNotEmpty() && predicate(it.origins.first()) }
}
fun DocumentationNode.membersOrGroupMembers(kind: NodeKind): List<DocumentationNode> {
@@ -513,40 +692,39 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
appendSection("Packages", node.members(NodeKind.Package), platformsBasedOnMembers = true)
- appendSection("Types", node.membersOrGroupMembers { it.kind in NodeKind.classLike && it.kind != NodeKind.TypeAlias && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception })
+ appendSection("Types", node.membersOrGroupMembers { it.kind in NodeKind.classLike /*&& it.kind != NodeKind.TypeAlias*/ && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception })
appendSection("Annotations", node.membersOrGroupMembers(NodeKind.AnnotationClass))
appendSection("Exceptions", node.membersOrGroupMembers(NodeKind.Exception))
- appendSection("Type Aliases", node.membersOrGroupMembers(NodeKind.TypeAlias))
appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass))
- appendSection("Enum Values", node.members(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true)
- appendSection("Constructors", node.members(NodeKind.Constructor), omitSamePlatforms = true)
- appendSection("Properties", node.members(NodeKind.Property), omitSamePlatforms = true)
+ appendSection("Enum Values", node.membersOrGroupMembers(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true)
+ appendSection("Constructors", node.membersOrGroupMembers(NodeKind.Constructor), omitSamePlatforms = true)
+ appendSection("Properties", node.membersOrGroupMembers(NodeKind.Property), omitSamePlatforms = true)
appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property))
- appendSection("Functions", node.members(NodeKind.Function), omitSamePlatforms = true)
+ appendSection("Functions", node.membersOrGroupMembers(NodeKind.Function), omitSamePlatforms = true)
appendSection("Inherited Functions", node.inheritedMembers(NodeKind.Function))
- appendSection("Companion Object Properties", node.members(NodeKind.CompanionObjectProperty), omitSamePlatforms = true)
+ appendSection("Companion Object Properties", node.membersOrGroupMembers(NodeKind.CompanionObjectProperty), omitSamePlatforms = true)
appendSection("Inherited Companion Object Properties", node.inheritedCompanionObjectMembers(NodeKind.Property))
- appendSection("Companion Object Functions", node.members(NodeKind.CompanionObjectFunction), omitSamePlatforms = true)
+ appendSection("Companion Object Functions", node.membersOrGroupMembers(NodeKind.CompanionObjectFunction), omitSamePlatforms = true)
appendSection("Inherited Companion Object Functions", node.inheritedCompanionObjectMembers(NodeKind.Function))
appendSection("Other members", node.members.filter {
it.kind !in setOf(
- NodeKind.Class,
- NodeKind.Interface,
- NodeKind.Enum,
- NodeKind.Object,
- NodeKind.AnnotationClass,
- NodeKind.Exception,
- NodeKind.TypeAlias,
- NodeKind.Constructor,
- NodeKind.Property,
- NodeKind.Package,
- NodeKind.Function,
- NodeKind.CompanionObjectProperty,
- NodeKind.CompanionObjectFunction,
- NodeKind.ExternalClass,
- NodeKind.EnumItem,
- NodeKind.AllTypes,
- NodeKind.GroupNode
+ NodeKind.Class,
+ NodeKind.Interface,
+ NodeKind.Enum,
+ NodeKind.Object,
+ NodeKind.AnnotationClass,
+ NodeKind.Exception,
+ NodeKind.TypeAlias,
+ NodeKind.Constructor,
+ NodeKind.Property,
+ NodeKind.Package,
+ NodeKind.Function,
+ NodeKind.CompanionObjectProperty,
+ NodeKind.CompanionObjectFunction,
+ NodeKind.ExternalClass,
+ NodeKind.EnumItem,
+ NodeKind.AllTypes,
+ NodeKind.GroupNode
)
})
@@ -556,12 +734,12 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendSection("Companion Object Extension Properties", allExtensions.filter { it.kind == NodeKind.CompanionObjectProperty })
appendSection("Companion Object Extension Functions", allExtensions.filter { it.kind == NodeKind.CompanionObjectFunction })
appendSection("Inheritors",
- node.inheritors.filter { it.kind != NodeKind.EnumItem })
+ node.inheritors.filter { it.kind != NodeKind.EnumItem })
if (node.kind == NodeKind.Module) {
appendHeader(3) { to.append("Index") }
node.members(NodeKind.AllTypes).singleOrNull()?.let { allTypes ->
- appendLink(link(node, allTypes, { "All Types" }))
+ appendLink(link(node, allTypes) { "All Types" })
}
}
}
@@ -581,27 +759,39 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendTable("Name", "Summary") {
appendTableBody {
- for ((memberLocation, members) in membersMap) {
- val elementPlatforms = platformsOfItems(members, omitSamePlatforms)
- val platforms = if (platformsBasedOnMembers)
- members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms
- else
- elementPlatforms
+ for ((memberLocation, membersList) in membersMap) {
+ val platforms = effectivePlatformsForMembers(membersList)
+// val platforms = if (platformsBasedOnMembers)
+// members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms
+// else
+// elementPlatforms
+
+ val summarized = computeSummarySignatures(membersList)
+
appendIndexRow(platforms) {
appendTableCell {
- appendParagraph {
+ if (summarized.platformPlacement == Summarized.PlatformPlacement.Row) {
+ appendPlatforms(platforms)
+ }
+ appendHeader(level = 4) {
+ // appendParagraph {
appendLink(memberLocation)
- if (members.singleOrNull()?.kind != NodeKind.ExternalClass) {
- appendPlatforms(platforms)
- }
}
+ if (node.sinceKotlin != null) {
+ appendSinceKotlin(node.sinceKotlin.toString())
+ }
+
+ if (membersList.singleOrNull()?.sinceKotlin != null){
+ appendSinceKotlinWrapped(membersList.single().sinceKotlin.toString())
+ }
+// }
+// if (members.singleOrNull()?.kind != NodeKind.ExternalClass) {
+// appendPlatforms(platforms)
+// }
+// }
}
appendTableCell {
- val breakdownBySummary = members.groupBy { it.summary }
- for ((summary, items) in breakdownBySummary) {
- appendSummarySignatures(items)
- appendContent(summary)
- }
+ appendSummarySignatures(summarized)
}
}
}
@@ -609,35 +799,94 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
- private fun platformsOfItems(items: List<DocumentationNode>, omitSamePlatforms: Boolean = true): Set<String> {
- val platforms = platformsOfItems(items)
- if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) {
- return platforms
+//
+// private fun platformsOfItems(items: List<DocumentationNode>, omitSamePlatforms: Boolean = true): Set<String> {
+// if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) {
+// return unionPlatformsOfItems(items)
+// }
+//
+// val platforms = platformsOfItems(items)
+// if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) {
+// return platforms
+// }
+// return emptySet()
+// }
+
+
+
+ private fun computeSummarySignatures(items: List<DocumentationNode>): Summarized =
+ Summarized(items.groupBy { it.summary }.mapValues { (_, nodes) ->
+ val nodesToAppend = nodes.flatMap { if(it.kind == NodeKind.GroupNode) it.origins else listOf(it) }
+
+ val summarySignature = languageService.summarizeSignatures(nodesToAppend)
+ if (summarySignature != null) {
+ mapOf(summarySignature to nodesToAppend)
+ } else {
+ nodesToAppend.groupBy {
+ languageService.render(it, RenderMode.SUMMARY)
+ }
+ }
+ })
+
+
+ private fun appendSummarySignatures(
+ summarized: Summarized
+ ) {
+ for(summary in summarized.data) {
+
+ appendAsSummaryGroup(summary.platforms) {
+ if (summarized.platformPlacement == Summarized.PlatformPlacement.Summary) {
+ appendPlatforms(summary.platforms)
+ }
+ appendContent(summary.content)
+ summary.signatures.subList(0, summary.signatures.size - 1).forEach {
+ appendSignatures(
+ it,
+ summarized.platformPlacement == Summarized.PlatformPlacement.Signature
+ )
+ appendLine()
+ }
+ appendSignatures(
+ summary.signatures.last(),
+ summarized.platformPlacement == Summarized.PlatformPlacement.Signature
+ )
+ }
+
}
- return emptySet()
}
- private fun appendSummarySignatures(items: List<DocumentationNode>) {
- val summarySignature = languageService.summarizeSignatures(items)
- if (summarySignature != null) {
- appendAsSignature(summarySignature) {
- summarySignature.appendSignature()
+ private fun appendSignatures(
+ signature: Summarized.SummarizedNodes,
+ withPlatforms: Boolean
+ ) {
+
+// val platforms = if (platformsBasedOnMembers)
+// items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms
+// else
+// elementPlatforms
+
+
+ appendAsPlatformDependentBlock(signature.platforms) {
+ if (withPlatforms) {
+ appendPlatforms(signature.platforms)
}
- return
- }
- val renderedSignatures = items.map { languageService.render(it, RenderMode.SUMMARY) }
- renderedSignatures.subList(0, renderedSignatures.size - 1).forEach {
- appendAsSignature(it) {
- it.appendSignature()
+ appendAsSignature(signature.content) {
+ signature.content.appendSignature()
}
- appendLine()
- }
- appendAsSignature(renderedSignatures.last()) {
- renderedSignatures.last().appendSignature()
+ appendSoftLineBreak()
}
}
}
+ private fun DocumentationNode.isClassLikeGroupNode(): Boolean {
+ if (kind != NodeKind.GroupNode) {
+ return false
+ }
+
+ return origins.all { it.kind in NodeKind.classLike }
+ }
+
+
inner class AllTypesNodeBuilder(val node: DocumentationNode)
: PageBuilder(listOf(node)) {
@@ -648,21 +897,23 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendTable("Name", "Summary") {
appendTableBody {
for (type in node.members) {
- appendTableRow {
- appendTableCell {
+ val platforms = effectivePlatformsForNode(type)
+ appendIndexRow(platforms) {
+ appendPlatforms(platforms)
+ appendHeader(level = 5) {
appendLink(link(node, type) {
if (it.kind == NodeKind.ExternalClass) it.name else it.qualifiedName()
})
- if (type.kind == NodeKind.ExternalClass) {
- val packageName = type.owner?.name
- if (packageName != null) {
- appendText(" (extensions in package $packageName)")
- }
- }
}
- appendTableCell {
- appendContent(type.summary)
+
+ if (type.kind == NodeKind.ExternalClass) {
+ val packageName = type.owner?.name
+ if (packageName != null) {
+ appendText(" (extensions in package $packageName)")
+ }
}
+
+ appendContent(type.summary)
}
}
}
@@ -687,3 +938,78 @@ abstract class StructuredFormatService(val generator: NodeLocationAwareGenerator
override final val linkExtension: String = extension) : FormatService {
}
+
+typealias PlatformsData = Map<String, Set<DocumentationNode>>
+
+fun memberPlatforms(node: DocumentationNode): PlatformsData {
+ val members = when {
+ node.kind == NodeKind.GroupNode -> node.origins
+ node.kind in NodeKind.classLike -> emptyList()
+ node.kind in NodeKind.memberLike -> emptyList()
+ else -> node.members
+ }
+
+ return members.map(::effectivePlatformsForNode).fold(mapOf(), ::mergePlatforms)
+}
+
+fun mergePlatforms(a: PlatformsData, b: PlatformsData): PlatformsData {
+ val mutable = a.toMutableMap()
+ b.forEach { (name, declarations) ->
+ mutable.merge(name, declarations) { a, b -> a.union(b) }
+ }
+ return mutable
+}
+
+fun effectivePlatformsForNode(node: DocumentationNode): PlatformsData {
+ val platforms = node.platforms + memberPlatforms(node).keys
+ return platforms.keysToMap { setOf(node) }
+}
+
+fun effectivePlatformsForMembers(nodes: Collection<DocumentationNode>): PlatformsData {
+ return nodes.map { effectivePlatformsForNode(it) }.reduce(::mergePlatforms)
+}
+
+fun mergeVersions(kotlinVersions: List<String>): String {
+ return kotlinVersions.distinct().min().orEmpty()
+}
+
+fun effectiveSinceKotlinForNode(node: DocumentationNode, baseVersion: String = "1.0"): String {
+ val members = when {
+ node.kind == NodeKind.GroupNode -> node.origins
+ node.kind in NodeKind.classLike -> emptyList()
+ node.kind in NodeKind.memberLike -> emptyList()
+ else -> node.members
+ }
+ val newBase = node.sinceKotlin ?: baseVersion
+ val memberVersion = if (members.isNotEmpty()) effectiveSinceKotlinForNodes(members, newBase) else newBase
+
+ return node.sinceKotlin ?: memberVersion
+}
+
+fun effectiveSinceKotlinForNodes(nodes: Collection<DocumentationNode>, baseVersion: String = "1.0"): String {
+ val map = nodes.map { effectiveSinceKotlinForNode(it, baseVersion) }
+ return mergeVersions(map)
+}
+
+fun samePlatforms(platformsPerNode: Collection<PlatformsData>): Boolean {
+
+ val first = platformsPerNode.firstOrNull()?.keys ?: return true
+ return platformsPerNode.all { it.keys == first }
+}
+
+fun locationHref(
+ from: Location,
+ to: DocumentationNode,
+ generator: NodeLocationAwareGenerator,
+ pathOnly: Boolean = false
+): String {
+ val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to
+ if (topLevelPage != null) {
+ val signature = to.detailOrNull(NodeKind.Signature)
+ return from.relativePathTo(
+ generator.location(topLevelPage),
+ (signature?.name ?: to.name).takeUnless { pathOnly }
+ )
+ }
+ return from.relativePathTo(generator.location(to))
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/YamlOutlineService.kt b/core/src/main/kotlin/Formats/YamlOutlineService.kt
index c36f98eb..3c92d8ff 100644
--- a/core/src/main/kotlin/Formats/YamlOutlineService.kt
+++ b/core/src/main/kotlin/Formats/YamlOutlineService.kt
@@ -13,7 +13,7 @@ class YamlOutlineService @Inject constructor(
override fun appendOutlineHeader(location: Location, node: DocumentationNode, to: StringBuilder) {
val indent = " ".repeat(outlineLevel)
to.appendln("$indent- title: ${languageService.renderName(node)}")
- to.appendln("$indent url: ${generator.location(node).path}")
+ to.appendln("$indent url: ${generator.relativePathToLocation(node.path.first(), node)}")
}
override fun appendOutlineLevel(to: StringBuilder, body: () -> Unit) {
diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt
new file mode 100644
index 00000000..5d53868a
--- /dev/null
+++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt
@@ -0,0 +1,229 @@
+package org.jetbrains.dokka.Generation
+
+import org.jetbrains.dokka.*
+
+class DocumentationMerger(
+ private val documentationModules: List<DocumentationModule>,
+ val logger: DokkaLogger
+) {
+ private val producedNodeRefGraph: NodeReferenceGraph = NodeReferenceGraph()
+ private val signatureMap: Map<DocumentationNode, String>
+ private val oldToNewNodeMap: MutableMap<DocumentationNode, DocumentationNode> = mutableMapOf()
+
+ init {
+ if (documentationModules.groupBy { it.name }.size > 1) {
+ throw IllegalArgumentException("Modules should have similar names: ${documentationModules.joinToString(", ") {it.name}}")
+ }
+
+ signatureMap = documentationModules
+ .flatMap { it.nodeRefGraph.nodeMapView.entries }
+ .associate { (k, v) -> v to k }
+
+
+ documentationModules.map { it.nodeRefGraph }
+ .flatMap { it.references }
+ .forEach { producedNodeRefGraph.addReference(it) }
+ }
+
+ private fun mergePackageReferences(
+ from: DocumentationNode,
+ packages: List<DocumentationReference>
+ ): List<DocumentationReference> {
+ val packagesByName = packages
+ .map { it.to }
+ .groupBy { it.name }
+
+ val resultReferences = mutableListOf<DocumentationReference>()
+ for ((name, listOfPackages) in packagesByName) {
+ try {
+ val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages)
+ updatePendingReferences()
+
+ resultReferences.add(
+ DocumentationReference(from, producedPackage, RefKind.Member)
+ )
+ } catch (t: Throwable) {
+ val entries = listOfPackages.joinToString(",") { "references:${it.allReferences().size}" }
+ throw Error("Failed to merge package $name from $from with entries $entries. ${t.message}", t)
+ }
+ }
+
+ return resultReferences
+ }
+
+ private fun mergePackagesWithEqualNames(
+ name: String,
+ from: DocumentationNode,
+ packages: List<DocumentationNode>
+ ): DocumentationNode {
+ val mergedPackage = DocumentationNode(name, Content.Empty, NodeKind.Package)
+
+ for (contentToAppend in packages.map { it.content }.distinct()) {
+ mergedPackage.updateContent {
+ for (otherChild in contentToAppend.children) {
+ children.add(otherChild)
+ }
+ }
+ }
+
+ for (node in packages) {
+ oldToNewNodeMap[node] = mergedPackage
+ }
+
+ val references = packages.flatMap { it.allReferences() }
+ val mergedReferences = mergeReferences(mergedPackage, references)
+ for (ref in mergedReferences) {
+ if (ref.kind == RefKind.Owner) {
+ continue
+ }
+ mergedPackage.addReference(ref)
+ }
+
+ from.append(mergedPackage, RefKind.Member)
+
+ return mergedPackage
+ }
+
+ private fun mergeMemberGroupBy(it: DocumentationNode): String {
+ val signature = signatureMap[it]
+
+ if (signature != null) {
+ return signature
+ }
+
+ logger.error("Failed to find signature for $it in \n${it.allReferences().joinToString { "\n ${it.kind} ${it.to}" }}")
+ return "<ERROR>"
+ }
+
+ private fun mergeMemberReferences(
+ from: DocumentationNode,
+ refs: List<DocumentationReference>
+ ): List<DocumentationReference> {
+ val membersBySignature: Map<String, List<DocumentationNode>> = refs.map { it.to }
+ .groupBy(this::mergeMemberGroupBy)
+
+ val mergedMembers: MutableList<DocumentationReference> = mutableListOf()
+ for ((signature, members) in membersBySignature) {
+ val newNode = mergeMembersWithEqualSignature(signature, members)
+
+ producedNodeRefGraph.register(signature, newNode)
+ updatePendingReferences()
+ from.append(newNode, RefKind.Member)
+
+ mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member))
+ }
+
+ return mergedMembers
+ }
+
+ private fun mergeMembersWithEqualSignature(
+ signature: String,
+ nodes: List<DocumentationNode>
+ ): DocumentationNode {
+ require(nodes.isNotEmpty())
+
+ val singleNode = nodes.singleOrNull()
+ if (singleNode != null) {
+ singleNode.dropReferences { it.kind == RefKind.Owner }
+ return singleNode
+ }
+
+ // Specialization processing
+ // Given (Common, JVM, JRE6, JS) and (JVM, JRE6) and (JVM, JRE7)
+ // Sorted: (JVM, JRE6), (JVM, JRE7), (Common, JVM, JRE6, JS)
+ // Should output: (JVM, JRE6), (JVM, JRE7), (Common, JS)
+ // Should not remove first platform
+ val nodesSortedByPlatformCount = nodes.sortedBy { it.platforms.size }
+ val allPlatforms = mutableSetOf<String>()
+ nodesSortedByPlatformCount.forEach { node ->
+ node.platforms
+ .filterNot { allPlatforms.add(it) }
+ .filter { it != node.platforms.first() }
+ .forEach { platform ->
+ node.dropReferences { it.kind == RefKind.Platform && it.to.name == platform }
+ }
+ }
+
+ // TODO: Quick and dirty fox for merging extensions for external classes. Fix this probably in StructuredFormatService
+ // TODO: while refactoring documentation model
+
+ val groupNode = if(nodes.first().kind == NodeKind.ExternalClass){
+ DocumentationNode(nodes.first().name, Content.Empty, NodeKind.ExternalClass)
+ } else {
+ DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode)
+ }
+ groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail)
+
+ for (node in nodes) {
+ node.dropReferences { it.kind == RefKind.Owner }
+ groupNode.append(node, RefKind.Origin)
+ node.append(groupNode, RefKind.TopLevelPage)
+
+ oldToNewNodeMap[node] = groupNode
+ }
+
+ if (groupNode.kind == NodeKind.ExternalClass){
+ val refs = nodes.flatMap { it.allReferences() }.filter { it.kind != RefKind.Owner && it.kind != RefKind.TopLevelPage }
+ refs.forEach { it.to.append(groupNode, RefKind.TopLevelPage); groupNode.append(it.to, RefKind.Member) }
+ }
+
+ // if nodes are classes, nested members should be also merged and
+ // inserted at the same level with class
+ if (nodes.all { it.kind in NodeKind.classLike }) {
+ val members = nodes.flatMap { it.allReferences() }.filter { it.kind == RefKind.Member }
+ val mergedMembers = mergeMemberReferences(groupNode, members)
+
+ for (ref in mergedMembers) {
+ if (ref.kind == RefKind.Owner) {
+ continue
+ }
+
+ groupNode.append(ref.to, RefKind.Member)
+ }
+ }
+
+ return groupNode
+ }
+
+
+ private fun mergeReferences(
+ from: DocumentationNode,
+ refs: List<DocumentationReference>
+ ): List<DocumentationReference> {
+ val (refsToPackages, otherRefs) = refs.partition { it.to.kind == NodeKind.Package }
+ val mergedPackages = mergePackageReferences(from, refsToPackages)
+
+ val (refsToMembers, refsNotToMembers) = otherRefs.partition { it.kind == RefKind.Member }
+ val mergedMembers = mergeMemberReferences(from, refsToMembers)
+
+ return mergedPackages + mergedMembers + refsNotToMembers
+ }
+
+ fun merge(): DocumentationModule {
+ val mergedDocumentationModule = DocumentationModule(
+ name = documentationModules.first().name,
+ content = documentationModules.first().content,
+ nodeRefGraph = producedNodeRefGraph
+ )
+
+ val refs = documentationModules.flatMap {
+ it.allReferences()
+ }
+ mergeReferences(mergedDocumentationModule, refs)
+
+ return mergedDocumentationModule
+ }
+
+ private fun updatePendingReferences() {
+ for (ref in producedNodeRefGraph.references) {
+ ref.lazyNodeFrom.update()
+ ref.lazyNodeTo.update()
+ }
+ }
+
+ private fun NodeResolver.update() {
+ if (this is NodeResolver.Exact && exactNode in oldToNewNodeMap) {
+ exactNode = oldToNewNodeMap[exactNode]!!
+ }
+ }
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt
index a5279772..90d7cfcc 100644
--- a/core/src/main/kotlin/Generation/DokkaGenerator.kt
+++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt
@@ -7,9 +7,10 @@ import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiManager
-import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
+import org.jetbrains.dokka.Generation.DocumentationMerger
import org.jetbrains.dokka.Utilities.DokkaAnalysisModule
import org.jetbrains.dokka.Utilities.DokkaOutputModule
+import org.jetbrains.dokka.Utilities.DokkaRunModule
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -18,63 +19,74 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import kotlin.system.measureTimeMillis
-class DokkaGenerator(val logger: DokkaLogger,
- val classpath: List<String>,
- val sources: List<SourceRoot>,
- val samples: List<String>,
- val includes: List<String>,
- val moduleName: String,
- val options: DocumentationOptions) {
+class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration,
+ val logger: DokkaLogger) {
- private val documentationModule = DocumentationModule(moduleName)
+ private val documentationModules: MutableList<DocumentationModule> = mutableListOf()
+ private val globalInjector = Guice.createInjector(DokkaRunModule(dokkaConfiguration))
- fun generate() {
- val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() }
- for ((platform, roots) in sourcesGroupedByPlatform) {
- appendSourceModule(platform, roots)
+
+ fun generate() = with(dokkaConfiguration) {
+
+
+ for (pass in passesConfigurations) {
+ val documentationModule = DocumentationModule(pass.moduleName)
+ appendSourceModule(pass, documentationModule)
+ documentationModules.add(documentationModule)
}
- documentationModule.prepareForGeneration(options)
+
+ val totalDocumentationModule = DocumentationMerger(documentationModules, logger).merge()
+ totalDocumentationModule.prepareForGeneration(dokkaConfiguration)
val timeBuild = measureTimeMillis {
logger.info("Generating pages... ")
- val outputInjector = Guice.createInjector(DokkaOutputModule(options, logger))
- outputInjector.getInstance(Generator::class.java).buildAll(documentationModule)
+ val outputInjector = globalInjector.createChildInjector(DokkaOutputModule(dokkaConfiguration, logger))
+ val instance = outputInjector.getInstance(Generator::class.java)
+ instance.buildAll(totalDocumentationModule)
}
logger.info("done in ${timeBuild / 1000} secs")
}
- private fun appendSourceModule(defaultPlatform: String?, sourceRoots: List<SourceRoot>) {
- val sourcePaths = sourceRoots.map { it.path }
- val environment = createAnalysisEnvironment(sourcePaths)
+ private fun appendSourceModule(
+ passConfiguration: DokkaConfiguration.PassConfiguration,
+ documentationModule: DocumentationModule
+ ) = with(passConfiguration) {
+
+ val sourcePaths = passConfiguration.sourceRoots.map { it.path }
+ val environment = createAnalysisEnvironment(sourcePaths, passConfiguration)
logger.info("Module: $moduleName")
- logger.info("Output: ${File(options.outputDir)}")
+ logger.info("Output: ${File(dokkaConfiguration.outputDir)}")
logger.info("Sources: ${sourcePaths.joinToString()}")
logger.info("Classpath: ${environment.classpath.joinToString()}")
logger.info("Analysing sources and libraries... ")
val startAnalyse = System.currentTimeMillis()
- val defaultPlatformAsList = defaultPlatform?.let { listOf(it) }.orEmpty()
+ val defaultPlatformAsList = passConfiguration.targets
val defaultPlatformsProvider = object : DefaultPlatformsProvider {
override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List<String> {
- val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath
- ?.let { File(it).absolutePath }
- val sourceRoot = containingFilePath?.let { path -> sourceRoots.find { path.startsWith(it.path) } }
- return sourceRoot?.platforms ?: defaultPlatformAsList
+// val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath
+// ?.let { File(it).absolutePath }
+// val sourceRoot = containingFilePath?.let { path -> sourceRoots.find { path.startsWith(it.path) } }
+ if (descriptor is MemberDescriptor && descriptor.isExpect) {
+ return defaultPlatformAsList.take(1)
+ }
+ return /*sourceRoot?.platforms ?: */defaultPlatformAsList
}
}
- val injector = Guice.createInjector(
- DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentationModule.nodeRefGraph, logger))
+ val injector = globalInjector.createChildInjector(
+ DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger))
- buildDocumentationModule(injector, documentationModule, { isNotSample(it) }, includes)
+ buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes)
val timeAnalyse = System.currentTimeMillis() - startAnalyse
logger.info("done in ${timeAnalyse / 1000} secs")
@@ -82,26 +94,31 @@ class DokkaGenerator(val logger: DokkaLogger,
Disposer.dispose(environment)
}
- fun createAnalysisEnvironment(sourcePaths: List<String>): AnalysisEnvironment {
- val environment = AnalysisEnvironment(DokkaMessageCollector(logger))
+ fun createAnalysisEnvironment(
+ sourcePaths: List<String>,
+ passConfiguration: DokkaConfiguration.PassConfiguration
+ ): AnalysisEnvironment {
+ val environment = AnalysisEnvironment(DokkaMessageCollector(logger), passConfiguration.analysisPlatform)
environment.apply {
- addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
+ if (analysisPlatform == Platform.jvm) {
+ addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
+ }
// addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath())
- for (element in this@DokkaGenerator.classpath) {
+ for (element in passConfiguration.classpath) {
addClasspath(File(element))
}
addSources(sourcePaths)
- addSources(this@DokkaGenerator.samples)
+ addSources(passConfiguration.samples)
- loadLanguageVersionSettings(options.languageVersion, options.apiVersion)
+ loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion)
}
return environment
}
- fun isNotSample(file: PsiFile): Boolean {
+ private fun isNotSample(file: PsiFile, samples: List<String>): Boolean {
val sourceFile = File(file.virtualFile!!.path)
return samples.none { sample ->
val canonicalSample = File(sample).canonicalPath
@@ -140,9 +157,7 @@ fun buildDocumentationModule(injector: Injector,
val analyzer = resolutionFacade.getFrontendService(LazyTopDownAnalyzer::class.java)
analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, fragmentFiles)
- val fragments = fragmentFiles
- .map { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) }
- .filterNotNull()
+ val fragments = fragmentFiles.mapNotNull { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) }
.distinct()
val packageDocs = injector.getInstance(PackageDocs::class.java)
@@ -205,4 +220,4 @@ fun KotlinCoreEnvironment.getJavaSourceFiles(): List<PsiJavaFile> {
}
}
return result
-}
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt
index b7c6cf63..ee2c068e 100644
--- a/core/src/main/kotlin/Generation/FileGenerator.kt
+++ b/core/src/main/kotlin/Generation/FileGenerator.kt
@@ -2,19 +2,52 @@ package org.jetbrains.dokka
import com.google.inject.Inject
import com.google.inject.name.Named
-import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
import java.io.File
-import java.io.FileOutputStream
import java.io.IOException
-import java.io.OutputStreamWriter
+import java.io.PrintWriter
+import java.io.StringWriter
class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator {
@set:Inject(optional = true) var outlineService: OutlineFormatService? = null
@set:Inject(optional = true) lateinit var formatService: FormatService
- @set:Inject(optional = true) lateinit var options: DocumentationOptions
+ @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration
@set:Inject(optional = true) var packageListService: PackageListService? = null
+ private val createdFiles = mutableMapOf<File, List<String>>()
+
+ private fun File.writeFileAndAssert(context: String, action: (File) -> Unit) {
+ //TODO: there is a possible refactoring to drop FileLocation
+ //TODO: aad File from API, Location#path.
+ //TODO: turn [Location] into a final class,
+ //TODO: Use [Location] all over the place without full
+ //TODO: reference to the real target path,
+ //TODO: it opens the way to safely track all files created
+ //TODO: to make sure no files were overwritten by mistake
+ //TODO: also, the NodeLocationAwareGenerator should be removed
+
+ val writes = createdFiles.getOrDefault(this, listOf()) + context
+ createdFiles[this] = writes
+ if (writes.size > 1) {
+ println("ERROR. An attempt to write ${this.relativeTo(root)} several times!")
+ return
+ }
+
+ try {
+ parentFile?.mkdirsOrFail()
+ action(this)
+ } catch (e : Throwable) {
+ println("Failed to write $this. ${e.message}")
+ e.printStackTrace()
+ }
+ }
+
+ private fun File.mkdirsOrFail() {
+ if (!mkdirs() && !exists()) {
+ throw IOException("Failed to create directory $this")
+ }
+ }
+
override fun location(node: DocumentationNode): FileLocation {
return FileLocation(fileForNode(node, formatService.linkExtension))
}
@@ -23,45 +56,36 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F
return File(root, relativePathToNode(node)).appendExtension(extension)
}
- fun locationWithoutExtension(node: DocumentationNode): FileLocation {
+ private fun locationWithoutExtension(node: DocumentationNode): FileLocation {
return FileLocation(fileForNode(node))
}
override fun buildPages(nodes: Iterable<DocumentationNode>) {
for ((file, items) in nodes.groupBy { fileForNode(it, formatService.extension) }) {
-
- file.parentFile?.mkdirsOrFail()
- try {
- FileOutputStream(file).use {
- OutputStreamWriter(it, Charsets.UTF_8).use {
- it.write(formatService.format(location(items.first()), items))
- }
- }
- } catch (e: Throwable) {
- println(e)
+ file.writeFileAndAssert("pages") { it ->
+ it.writeText(formatService.format(location(items.first()), items))
}
- buildPages(items.flatMap { it.members })
+
+ buildPages(items.filterNot { it.kind == NodeKind.AllTypes }.flatMap { it.members })
}
}
override fun buildOutlines(nodes: Iterable<DocumentationNode>) {
val outlineService = this.outlineService ?: return
for ((location, items) in nodes.groupBy { locationWithoutExtension(it) }) {
- val file = outlineService.getOutlineFileName(location)
- file.parentFile?.mkdirsOrFail()
- FileOutputStream(file).use {
- OutputStreamWriter(it, Charsets.UTF_8).use {
- it.write(outlineService.formatOutline(location, items))
- }
+ outlineService.getOutlineFileName(location).writeFileAndAssert("outlines") { file ->
+ file.writeText(outlineService.formatOutline(location, items))
}
}
}
override fun buildSupportFiles() {
formatService.enumerateSupportFiles { resource, targetPath ->
- FileOutputStream(File(root, relativePathToNode(listOf(targetPath), false))).use {
- javaClass.getResourceAsStream(resource).copyTo(it)
+ File(root, relativePathToNode(listOf(targetPath), false)).writeFileAndAssert("support files") { file ->
+ file.outputStream().use {
+ javaClass.getResourceAsStream(resource).copyTo(it)
+ }
}
}
}
@@ -74,16 +98,11 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F
val moduleRoot = location(module).file.parentFile
val packageListFile = File(moduleRoot, "package-list")
- packageListFile.writeText("\$dokka.format:${options.outputFormat}\n" +
- packageListService!!.formatPackageList(module as DocumentationModule))
- }
+ val text = "\$dokka.format:${dokkaConfiguration.format}\n" + packageListService!!.formatPackageList(module as DocumentationModule)
+ packageListFile.writeFileAndAssert("packages-list") { file ->
+ file.writeText(text)
+ }
+ }
}
-
}
-
-private fun File.mkdirsOrFail() {
- if (!mkdirs() && !exists()) {
- throw IOException("Failed to create directory $this")
- }
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt
deleted file mode 100644
index eecf122e..00000000
--- a/core/src/main/kotlin/Generation/configurationImpl.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.jetbrains.dokka
-
-import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition
-import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
-import java.io.File
-
-
-data class SourceLinkDefinitionImpl(override val path: String,
- override val url: String,
- override val lineSuffix: String?) : SourceLinkDefinition {
- companion object {
- fun parseSourceLinkDefinition(srcLink: String): SourceLinkDefinition {
- val (path, urlAndLine) = srcLink.split('=')
- return SourceLinkDefinitionImpl(File(path).canonicalPath,
- urlAndLine.substringBefore("#"),
- urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" })
- }
- }
-}
-
-class SourceRootImpl(path: String, override val platforms: List<String> = emptyList()) : SourceRoot {
- override val path: String = File(path).absolutePath
-
- companion object {
- fun parseSourceRoot(sourceRoot: String): SourceRoot {
- val components = sourceRoot.split("::", limit = 2)
- return SourceRootImpl(components.last(), if (components.size == 1) listOf() else components[0].split(','))
- }
- }
-}
-
-data class PackageOptionsImpl(override val prefix: String,
- override val includeNonPublic: Boolean = false,
- override val reportUndocumented: Boolean = true,
- override val skipDeprecated: Boolean = false,
- override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions
-
-data class DokkaConfigurationImpl(
- override val moduleName: String,
- override val classpath: List<String>,
- override val sourceRoots: List<SourceRootImpl>,
- override val samples: List<String>,
- override val includes: List<String>,
- override val outputDir: String,
- override val format: String,
- override val includeNonPublic: Boolean,
- override val includeRootPackage: Boolean,
- override val reportUndocumented: Boolean,
- override val skipEmptyPackages: Boolean,
- override val skipDeprecated: Boolean,
- override val jdkVersion: Int,
- override val generateIndexPages: Boolean,
- override val sourceLinks: List<SourceLinkDefinitionImpl>,
- override val impliedPlatforms: List<String>,
- override val perPackageOptions: List<PackageOptionsImpl>,
- override val externalDocumentationLinks: List<ExternalDocumentationLinkImpl>,
- override val noStdlibLink: Boolean,
- override val noJdkLink: Boolean,
- override val cacheRoot: String?,
- override val suppressedFiles: List<String>,
- override val languageVersion: String?,
- override val apiVersion: String?,
- override val collectInheritedExtensionsFromLibraries: Boolean
-) : DokkaConfiguration \ No newline at end of file
diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt
index f1f170d7..3b368329 100644
--- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt
+++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtModifierListOwner
-import java.io.File
fun getSignature(element: PsiElement?) = when(element) {
is PsiPackage -> element.qualifiedName
@@ -53,24 +52,24 @@ interface JavaDocumentationBuilder {
}
class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
- private val options: DocumentationOptions
+ private val passConfiguration: DokkaConfiguration.PassConfiguration
private val refGraph: NodeReferenceGraph
private val docParser: JavaDocumentationParser
@Inject constructor(
- options: DocumentationOptions,
- refGraph: NodeReferenceGraph,
- logger: DokkaLogger,
- signatureProvider: ElementSignatureProvider,
- externalDocumentationLinkResolver: ExternalDocumentationLinkResolver
+ passConfiguration: DokkaConfiguration.PassConfiguration,
+ refGraph: NodeReferenceGraph,
+ logger: DokkaLogger,
+ signatureProvider: ElementSignatureProvider,
+ externalDocumentationLinkResolver: ExternalDocumentationLinkResolver
) {
- this.options = options
+ this.passConfiguration = passConfiguration
this.refGraph = refGraph
this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver)
}
- constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) {
- this.options = options
+ constructor(passConfiguration: DokkaConfiguration.PassConfiguration, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) {
+ this.passConfiguration = passConfiguration
this.refGraph = refGraph
this.docParser = docParser
}
@@ -152,7 +151,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
}
}
- private fun skipFile(javaFile: PsiJavaFile): Boolean = options.effectivePackageOptions(javaFile.packageName).suppress
+ private fun skipFile(javaFile: PsiJavaFile): Boolean = passConfiguration.effectivePackageOptions(javaFile.packageName).suppress
private fun skipElement(element: Any) =
skipElementByVisibility(element) ||
@@ -162,13 +161,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
private fun skipElementByVisibility(element: Any): Boolean =
element is PsiModifierListOwner &&
element !is PsiParameter &&
- !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) &&
+ !(passConfiguration.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) &&
(element.hasModifierProperty(PsiModifier.PRIVATE) ||
element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) ||
element.isInternal())
private fun skipElementBySuppressedFiles(element: Any): Boolean =
- element is PsiElement && File(element.containingFile.virtualFile.path).absoluteFile in options.suppressedFiles
+ element is PsiElement && element.containingFile.virtualFile.path in passConfiguration.suppressedFiles
private fun PsiElement.isInternal(): Boolean {
val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false
@@ -317,7 +316,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
val existing = refGraph.lookup(getSignature(psiClass)!!)
if (existing != null) return existing
val new = psiClass.build()
- val packageNode = findOrCreatePackageNode(null, (psiClass.parent as PsiJavaFile).packageName, emptyMap(), refGraph)
+ val packageNode = findOrCreatePackageNode(null, (psiClass.containingFile as PsiJavaFile).packageName, emptyMap(), refGraph)
packageNode.append(new, RefKind.Member)
return new
}
@@ -348,7 +347,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
}
fun hasSuppressDocTag(element: Any?): Boolean {
- val declaration = (element as? KtLightDeclaration<*, *>)?.kotlinOrigin as? KtDeclaration ?: return false
+ val declaration = (element as? KtLightDeclaration<*, *>)?.kotlinOrigin ?: return false
return PsiTreeUtil.findChildrenOfType(declaration.docComment, KDocTag::class.java).any { it.knownTag == KDocKnownTag.SUPPRESS }
}
diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt
index 70af73f9..25a974a3 100644
--- a/core/src/main/kotlin/Java/JavadocParser.kt
+++ b/core/src/main/kotlin/Java/JavadocParser.kt
@@ -192,7 +192,7 @@ class JavadocParser(
return when {
element.hasAttr("docref") -> {
val docref = element.attr("docref")
- ContentNodeLazyLink(docref, { -> refGraph.lookupOrWarn(docref, logger) })
+ ContentNodeLazyLink(docref) { refGraph.lookupOrWarn(docref, logger)}
}
element.hasAttr("href") -> {
val href = element.attr("href")
@@ -234,9 +234,8 @@ class JavadocParser(
linkSignature != null -> {
val linkNode =
ContentNodeLazyLink(
- (tag.valueElement ?: linkElement).text,
- { -> refGraph.lookupOrWarn(linkSignature, logger) }
- )
+ (tag.valueElement ?: linkElement).text
+ ) { refGraph.lookupOrWarn(linkSignature!!, logger) }
linkNode.append(text)
linkNode
}
diff --git a/core/src/main/kotlin/Kotlin/ContentBuilder.kt b/core/src/main/kotlin/Kotlin/ContentBuilder.kt
index c60625a4..573b41b6 100644
--- a/core/src/main/kotlin/Kotlin/ContentBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/ContentBuilder.kt
@@ -168,7 +168,7 @@ fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver: LinkR
}
}
-private fun MarkdownNode.getLabelText() = children.filter { it.type == MarkdownTokenTypes.TEXT || it.type == MarkdownTokenTypes.EMPH }.joinToString("") { it.text }
+private fun MarkdownNode.getLabelText() = children.filter { it.type == MarkdownTokenTypes.TEXT || it.type == MarkdownTokenTypes.EMPH || it.type == MarkdownTokenTypes.COLON }.joinToString("") { it.text }
private fun keepEol(node: ContentNode) = node is ContentParagraph || node is ContentSection || node is ContentBlockCode
private fun processingList(node: ContentNode) = node is ContentOrderedList || node is ContentUnorderedList
diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt
index d73bef4a..88494581 100644
--- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt
+++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt
@@ -10,7 +10,7 @@ class DeclarationLinkResolver
@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
val refGraph: NodeReferenceGraph,
val logger: DokkaLogger,
- val options: DocumentationOptions,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver,
val elementSignatureProvider: ElementSignatureProvider) {
@@ -34,14 +34,15 @@ class DeclarationLinkResolver
val signature = elementSignatureProvider.signature(symbol)
val referencedAt = fromDescriptor.signatureWithSourceLocation()
- return ContentNodeLazyLink(href, { ->
+ return ContentNodeLazyLink(href) {
val target = refGraph.lookup(signature)
if (target == null) {
- logger.warn("Can't find node by signature `$signature`, referenced at $referencedAt")
+ logger.warn("Can't find node by signature `$signature`, referenced at $referencedAt. " +
+ "This is probably caused by invalid configuration of cross-module dependencies")
}
target
- })
+ }
}
if ("/" in href) {
return ContentExternalLink(href)
@@ -63,7 +64,7 @@ class DeclarationLinkResolver
if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
return symbol.overriddenDescriptors.firstOrNull()
}
- if (symbol is TypeAliasDescriptor && !symbol.isDocumented(options)) {
+ if (symbol is TypeAliasDescriptor && !symbol.isDocumented(passConfiguration)) {
return symbol.classDescriptor
}
return symbol
diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
index d1f98184..ce20aeec 100644
--- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
+++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
class DescriptorDocumentationParser
- @Inject constructor(val options: DocumentationOptions,
+ @Inject constructor(val options: DokkaConfiguration.PassConfiguration,
val logger: DokkaLogger,
val linkResolver: DeclarationLinkResolver,
val resolutionFacade: DokkaResolutionFacade,
@@ -74,7 +74,7 @@ class DescriptorDocumentationParser
}
val tree = parseMarkdown(kdocText)
val linkMap = LinkMap.buildLinkMap(tree.node, kdocText)
- val content = buildContent(tree, LinkResolver(linkMap, { href -> linkResolver.resolveContentLink(contextDescriptor, href) }), inline)
+ val content = buildContent(tree, LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) }, inline)
if (kdoc is KDocSection) {
val tags = kdoc.getTags()
tags.forEach {
@@ -87,7 +87,7 @@ class DescriptorDocumentationParser
val section = content.addSection(javadocSectionDisplayName(it.name), it.getSubjectName())
val sectionContent = it.getContent()
val markdownNode = parseMarkdown(sectionContent)
- buildInlineContentTo(markdownNode, section, LinkResolver(linkMap, { href -> linkResolver.resolveContentLink(contextDescriptor, href) }))
+ buildInlineContentTo(markdownNode, section, LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) })
}
}
}
@@ -129,7 +129,7 @@ class DescriptorDocumentationParser
FqName.fromSegments(listOf("kotlin", "Any")), NoLookupLocation.FROM_IDE)
anyClassDescriptors.forEach {
val anyMethod = (it as ClassDescriptor).getMemberScope(listOf())
- .getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS, { it == descriptor.name })
+ .getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS) { it == descriptor.name }
.single()
val kdoc = anyMethod.findKDoc()
if (kdoc != null) {
diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
index 38804e39..eb0399c7 100644
--- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
@@ -3,9 +3,10 @@ package org.jetbrains.dokka
import com.google.inject.Inject
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiJavaFile
-import org.jetbrains.dokka.DokkaConfiguration.*
+import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration
import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
+import org.jetbrains.kotlin.coroutines.hasFunctionOrSuspendFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
@@ -32,64 +33,13 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.*
+import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
+import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
+import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.util.supertypesWithAny
-import java.io.File
-import java.nio.file.Path
-import java.nio.file.Paths
import com.google.inject.name.Named as GuiceNamed
-class DocumentationOptions(val outputDir: String,
- val outputFormat: String,
- includeNonPublic: Boolean = false,
- val includeRootPackage: Boolean = false,
- reportUndocumented: Boolean = true,
- val skipEmptyPackages: Boolean = true,
- skipDeprecated: Boolean = false,
- jdkVersion: Int = 6,
- val generateIndexPages: Boolean = true,
- val sourceLinks: List<SourceLinkDefinition> = emptyList(),
- val impliedPlatforms: List<String> = emptyList(),
- // Sorted by pattern length
- perPackageOptions: List<PackageOptions> = emptyList(),
- externalDocumentationLinks: List<ExternalDocumentationLink> = emptyList(),
- noStdlibLink: Boolean,
- noJdkLink: Boolean = false,
- val languageVersion: String?,
- val apiVersion: String?,
- cacheRoot: String? = null,
- val suppressedFiles: Set<File> = emptySet(),
- val collectInheritedExtensionsFromLibraries: Boolean = false) {
- init {
- if (perPackageOptions.any { it.prefix == "" })
- throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead")
- }
-
- val perPackageOptions = perPackageOptions.sortedByDescending { it.prefix.length }
- val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated)
-
- fun effectivePackageOptions(pack: String): PackageOptions = perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions
- fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString())
-
- val defaultLinks = run {
- val links = mutableListOf<ExternalDocumentationLink>()
- if (!noJdkLink)
- links += ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build()
-
- if (!noStdlibLink)
- links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build()
- links
- }
-
- val externalDocumentationLinks = defaultLinks + externalDocumentationLinks
-
- val cacheRoot: Path? = when {
- cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka")
- cacheRoot != null -> Paths.get(cacheRoot)
- else -> null
- }
-}
-
private fun isExtensionForExternalClass(extensionFunctionDescriptor: DeclarationDescriptor,
extensionReceiverDescriptor: DeclarationDescriptor,
allFqNames: Collection<FqName>): Boolean {
@@ -119,7 +69,7 @@ val ignoredSupertypes = setOf(
class DocumentationBuilder
@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
val descriptorDocumentationParser: DescriptorDocumentationParser,
- val options: DocumentationOptions,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
val refGraph: NodeReferenceGraph,
val platformNodeRegistry: PlatformNodeRegistry,
val logger: DokkaLogger,
@@ -131,7 +81,7 @@ class DocumentationBuilder
val knownModifiers = setOf(
KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.INTERNAL_KEYWORD, KtTokens.PRIVATE_KEYWORD,
KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.ABSTRACT_KEYWORD, KtTokens.SEALED_KEYWORD,
- KtTokens.OVERRIDE_KEYWORD)
+ KtTokens.OVERRIDE_KEYWORD, KtTokens.INLINE_KEYWORD)
fun link(node: DocumentationNode, descriptor: DeclarationDescriptor, kind: RefKind) {
refGraph.link(node, descriptor.signature(), kind)
@@ -189,6 +139,13 @@ class DocumentationBuilder
appendTextNode(modifier, NodeKind.Modifier)
}
+ fun DocumentationNode.appendInline(descriptor: DeclarationDescriptor, psi: KtModifierListOwner) {
+ if (!psi.hasModifier(KtTokens.INLINE_KEYWORD)) return
+ if (descriptor is FunctionDescriptor
+ && descriptor.valueParameters.none { it.hasFunctionOrSuspendFunctionType }) return
+ appendTextNode(KtTokens.INLINE_KEYWORD.value, NodeKind.Modifier)
+ }
+
fun DocumentationNode.appendVisibility(descriptor: DeclarationDescriptorWithVisibility) {
val modifier = descriptor.visibility.normalize().displayName
appendTextNode(modifier, NodeKind.Modifier)
@@ -328,7 +285,13 @@ class DocumentationBuilder
.detail(NodeKind.Value)
.name.removeSurrounding("\"")
- append(platformNodeRegistry["Kotlin " + kotlinVersion], RefKind.Platform)
+ sinceKotlin = kotlinVersion
+ }
+
+ fun DocumentationNode.appendDefaultSinceKotlin() {
+ if (sinceKotlin == null) {
+ sinceKotlin = passConfiguration.sinceKotlin
+ }
}
fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) {
@@ -342,6 +305,7 @@ class DocumentationBuilder
appendTextNode(it.value, NodeKind.Modifier)
}
}
+ appendInline(descriptor, psi)
}
fun DocumentationNode.appendDefaultPlatforms(descriptor: DeclarationDescriptor) {
@@ -355,7 +319,7 @@ class DocumentationBuilder
fun DocumentationNode.isSinceKotlin() = name == "SinceKotlin" && kind == NodeKind.Annotation
fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) {
- appendSourceLink(sourceElement.getPsi(), options.sourceLinks)
+ appendSourceLink(sourceElement.getPsi(), passConfiguration.sourceLinks)
}
fun DocumentationNode.appendSignature(descriptor: DeclarationDescriptor) {
@@ -363,7 +327,7 @@ class DocumentationBuilder
}
fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? {
- if (!descriptor.isGenerated() && descriptor.isDocumented(options)) {
+ if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) {
val node = descriptor.build()
append(node, kind)
return node
@@ -390,7 +354,7 @@ class DocumentationBuilder
fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) {
- if (descriptor.isGenerated() || !descriptor.isDocumented(options)) return
+ if (descriptor.isGenerated() || !descriptor.isDocumented(passConfiguration)) return
val existingNode = refGraph.lookup(descriptor.signature())
if (existingNode != null) {
@@ -462,10 +426,10 @@ class DocumentationBuilder
val allFqNames = fragments.map { it.fqName }.distinct()
for (packageName in allFqNames) {
- if (packageName.isRoot && !options.includeRootPackage) continue
+ if (packageName.isRoot && !passConfiguration.includeRootPackage) continue
val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getContributedDescriptors() }
- if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue
+ if (passConfiguration.skipEmptyPackages && declarations.none { it.isDocumented(passConfiguration) }) continue
logger.info(" package $packageName: ${declarations.count()} declarations")
val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph)
packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode,
@@ -492,7 +456,7 @@ class DocumentationBuilder
}.flatten()
val allDescriptors =
- if (options.collectInheritedExtensionsFromLibraries) {
+ if (passConfiguration.collectInheritedExtensionsFromLibraries) {
allPackageViewDescriptors.map { it.memberScope }
} else {
fragments.asSequence().map { it.getMemberScope() }
@@ -514,13 +478,20 @@ class DocumentationBuilder
.filter { it.extensionReceiverParameter != null }
val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name }
+ fun isIgnoredReceiverType(type: KotlinType) =
+ type.isDynamic() ||
+ type.isAnyOrNullableAny() ||
+ (type.isTypeParameter() && type.immediateSupertypes().all { it.isAnyOrNullableAny() })
+
+
for (extensionFunction in allExtensionFunctions) {
+ val extensionReceiverParameter = extensionFunction.extensionReceiverParameter!!
if (extensionFunction.dispatchReceiverParameter != null) continue
val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name]
?.filter { fn -> fn.canShadow(extensionFunction) }
?: emptyList()
- if (extensionFunction.extensionReceiverParameter?.type?.isDynamic() == true) continue
+ if (isIgnoredReceiverType(extensionReceiverParameter.type)) continue
val subclasses =
classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) }
if (subclasses.isEmpty()) continue
@@ -628,6 +599,7 @@ class DocumentationBuilder
val node = nodeForDescriptor(this, NodeKind.TypeAlias)
if (!external) {
+ node.appendDefaultSinceKotlin()
node.appendAnnotations(this)
}
node.appendModifiers(this)
@@ -665,6 +637,7 @@ class DocumentationBuilder
for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) {
node.appendClassMember(descriptor, inheritedLinkKind, extraModifier)
}
+ node.appendDefaultSinceKotlin()
node.appendAnnotations(this)
}
node.appendModifiers(this)
@@ -697,7 +670,7 @@ class DocumentationBuilder
.mapTo(result) { ClassMember(it, extraModifier = "static") }
val companionObjectDescriptor = companionObjectDescriptor
- if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(options)) {
+ if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(passConfiguration)) {
val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors()
val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() }
descriptorsToDocument.mapTo(result) {
@@ -725,6 +698,7 @@ class DocumentationBuilder
val node = nodeForDescriptor(this, NodeKind.Constructor)
node.appendInPageChildren(valueParameters, RefKind.Detail)
node.appendDefaultPlatforms(this)
+ node.appendDefaultSinceKotlin()
register(this, node)
return node
}
@@ -749,6 +723,9 @@ class DocumentationBuilder
extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
node.appendInPageChildren(valueParameters, RefKind.Detail)
node.appendType(returnType)
+ if (!external) {
+ node.appendDefaultSinceKotlin()
+ }
node.appendAnnotations(this)
node.appendModifiers(this)
if (!external) {
@@ -786,6 +763,9 @@ class DocumentationBuilder
node.appendInPageChildren(typeParameters, RefKind.Detail)
extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
node.appendType(returnType)
+ if (!external) {
+ node.appendDefaultSinceKotlin()
+ }
node.appendAnnotations(this)
node.appendModifiers(this)
if (!external) {
@@ -849,6 +829,7 @@ class DocumentationBuilder
}
}
}
+ node.appendDefaultSinceKotlin()
node.appendAnnotations(this)
node.appendModifiers(this)
if (varargElementType != null && node.details(NodeKind.Modifier).none { it.name == "vararg" }) {
@@ -939,23 +920,27 @@ class DocumentationBuilder
}
- fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor,
- externalClassNodes: MutableMap<FqName, DocumentationNode>,
- allFqNames: Collection<FqName>): DocumentationNode {
+ fun DocumentationNode.getParentForPackageMember(
+ descriptor: DeclarationDescriptor,
+ externalClassNodes: MutableMap<FqName, DocumentationNode>,
+ allFqNames: Collection<FqName>,
+ packageName: FqName
+ ): DocumentationNode {
if (descriptor is CallableMemberDescriptor) {
val extensionClassDescriptor = descriptor.getExtensionClassDescriptor()
if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) &&
!ErrorUtils.isError(extensionClassDescriptor)) {
val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor)
- return externalClassNodes.getOrPut(fqName, {
+ return externalClassNodes.getOrPut(fqName) {
val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass)
val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(extensionClassDescriptor)
if (externalLink != null) {
newNode.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
}
append(newNode, RefKind.Member)
+ refGraph.register("${packageName.asString()}:${extensionClassDescriptor.signature()}", newNode)
newNode
- })
+ }
}
}
return this
@@ -963,12 +948,12 @@ class DocumentationBuilder
}
-fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean {
- return (options.effectivePackageOptions(fqNameSafe).includeNonPublic
+fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean {
+ return (passConfiguration.effectivePackageOptions(fqNameSafe).includeNonPublic
|| this !is MemberDescriptor
|| this.visibility.isPublicAPI)
- && !isDocumentationSuppressed(options)
- && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated())
+ && !isDocumentationSuppressed(passConfiguration)
+ && (!passConfiguration.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated())
}
private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION
@@ -982,8 +967,13 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
declarations.forEach { descriptor ->
with(documentationBuilder) {
- if (descriptor.isDocumented(options)) {
- val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames)
+ if (descriptor.isDocumented(passConfiguration)) {
+ val parent = packageNode.getParentForPackageMember(
+ descriptor,
+ externalClassNodes,
+ allFqNames,
+ packageName
+ )
parent.appendOrUpdateMember(descriptor)
}
}
@@ -994,14 +984,14 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
class KotlinJavaDocumentationBuilder
@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
val documentationBuilder: DocumentationBuilder,
- val options: DocumentationOptions,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
val logger: DokkaLogger) : JavaDocumentationBuilder {
override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) {
val classDescriptors = file.classes.map {
it.getJavaClassDescriptor(resolutionFacade)
}
- if (classDescriptors.any { it != null && it.isDocumented(options) }) {
+ if (classDescriptors.any { it != null && it.isDocumented(passConfiguration) }) {
val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph)
for (descriptor in classDescriptors.filterNotNull()) {
@@ -1031,13 +1021,13 @@ fun AnnotationDescriptor.mustBeDocumented(): Boolean {
return annotationClass.isDocumentedAnnotation()
}
-fun DeclarationDescriptor.isDocumentationSuppressed(options: DocumentationOptions): Boolean {
+fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean {
- if (options.effectivePackageOptions(fqNameSafe).suppress) return true
+ if (passConfiguration.effectivePackageOptions(fqNameSafe).suppress) return true
val path = this.findPsi()?.containingFile?.virtualFile?.path
if (path != null) {
- if (File(path).absoluteFile in options.suppressedFiles) return true
+ if (path in passConfiguration.suppressedFiles) return true
}
val doc = findKDoc()
@@ -1136,8 +1126,8 @@ fun DeclarationDescriptor.sourceLocation(): String? {
return null
}
-fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) {
- if (options.generateIndexPages) {
+fun DocumentationModule.prepareForGeneration(configuration: DokkaConfiguration) {
+ if (configuration.generateIndexPages) {
generateAllTypesNode()
}
nodeRefGraph.resolveReferences()
@@ -1145,7 +1135,9 @@ fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) {
fun DocumentationNode.generateAllTypesNode() {
val allTypes = members(NodeKind.Package)
- .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass } }
+ .flatMap { it.members.filter {
+ it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass
+ || (it.kind == NodeKind.GroupNode && it.origins.all { it.kind in NodeKind.classLike }) } }
.sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() }
val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes)
@@ -1161,4 +1153,12 @@ fun ClassDescriptor.supertypesWithAnyPrecise(): Collection<KotlinType> {
return emptyList()
}
return typeConstructor.supertypesWithAny()
-} \ No newline at end of file
+}
+
+fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions {
+ val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated, false)
+ return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions
+}
+
+fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString())
+
diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt
index a8129793..793f9589 100644
--- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt
+++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt
@@ -22,29 +22,48 @@ import java.net.HttpURLConnection
import java.net.URL
import java.net.URLConnection
import java.nio.file.Path
+import java.nio.file.Paths
import java.security.MessageDigest
import javax.inject.Named
import kotlin.reflect.full.findAnnotation
fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) }
+typealias PackageFqNameToLocation = MutableMap<FqName, PackageListProvider.ExternalDocumentationRoot>
+
@Singleton
-class ExternalDocumentationLinkResolver @Inject constructor(
- val options: DocumentationOptions,
- @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade,
- val logger: DokkaLogger
+class PackageListProvider @Inject constructor(
+ val configuration: DokkaConfiguration,
+ val logger: DokkaLogger
) {
+ val storage = mutableMapOf<DokkaConfiguration.ExternalDocumentationLink, PackageFqNameToLocation>()
- val packageFqNameToLocation = mutableMapOf<FqName, ExternalDocumentationRoot>()
- val formats = mutableMapOf<String, InboundExternalLinkResolutionService>()
+ val cacheDir: Path? = when {
+ configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka")
+ configuration.cacheRoot != null -> Paths.get(configuration.cacheRoot)
+ else -> null
+ }?.resolve("packageListCache")?.apply { createDirectories() }
- class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map<String, String>) {
- override fun toString(): String = rootUrl.toString()
+ val cachedProtocols = setOf("http", "https", "ftp")
+
+ init {
+ for (conf in configuration.passesConfigurations) {
+ for (link in conf.externalDocumentationLinks) {
+ if (link in storage) {
+ continue
+ }
+
+ try {
+ loadPackageList(link)
+ } catch (e: Exception) {
+ throw RuntimeException("Exception while loading package-list from $link", e)
+ }
+ }
+
+ }
}
- val cacheDir: Path? = options.cacheRoot?.resolve("packageListCache")?.apply { createDirectories() }
- val cachedProtocols = setOf("http", "https", "ftp")
fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection {
val connection = this.openConnection()
@@ -120,23 +139,23 @@ class ExternalDocumentationLinkResolver @Inject constructor(
val (params, packages) =
packageListStream
- .bufferedReader()
- .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } }
+ .bufferedReader()
+ .useLines { lines -> lines.partition { it.startsWith(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX) } }
val paramsMap = params.asSequence()
- .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) }
- .groupBy({ (key, _) -> key }, { (_, value) -> value })
+ .map { it.removePrefix(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX).split(":", limit = 2) }
+ .groupBy({ (key, _) -> key }, { (_, value) -> value })
val format = paramsMap["format"]?.singleOrNull() ?: "javadoc"
val locations = paramsMap["location"].orEmpty()
- .map { it.split("\u001f", limit = 2) }
- .map { (key, value) -> key to value }
- .toMap()
+ .map { it.split("\u001f", limit = 2) }
+ .map { (key, value) -> key to value }
+ .toMap()
- val defaultResolverDesc = services["dokka-default"]!!
- val resolverDesc = services[format]
+ val defaultResolverDesc = ExternalDocumentationLinkResolver.services.getValue("dokka-default")
+ val resolverDesc = ExternalDocumentationLinkResolver.services[format]
?: defaultResolverDesc.takeIf { format in formatsWithDefaultResolver }
?: defaultResolverDesc.also {
logger.warn("Couldn't find InboundExternalLinkResolutionService(format = `$format`) for $link, using Dokka default")
@@ -153,16 +172,52 @@ class ExternalDocumentationLinkResolver @Inject constructor(
val rootInfo = ExternalDocumentationRoot(link.url, resolver, locations)
- packages.map { FqName(it) }.forEach { packageFqNameToLocation[it] = rootInfo }
+ val packageFqNameToLocation = mutableMapOf<FqName, ExternalDocumentationRoot>()
+ storage[link] = packageFqNameToLocation
+
+ val fqNames = packages.map { FqName(it) }
+ for(name in fqNames) {
+ packageFqNameToLocation[name] = rootInfo
+ }
+ }
+
+
+
+ class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map<String, String>) {
+ override fun toString(): String = rootUrl.toString()
+ }
+
+ companion object {
+ private val formatsWithDefaultResolver =
+ ServiceLocator
+ .allServices("format")
+ .filter {
+ val desc = ServiceLocator.lookup<FormatDescriptor>(it) as? FileGeneratorBasedFormatDescriptor
+ desc?.generatorServiceClass == FileGenerator::class
+ }.map { it.name }
+ .toSet()
+
}
+}
+
+class ExternalDocumentationLinkResolver @Inject constructor(
+ val configuration: DokkaConfiguration,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
+ @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade,
+ val logger: DokkaLogger,
+ val packageListProvider: PackageListProvider
+) {
+
+ val formats = mutableMapOf<String, InboundExternalLinkResolutionService>()
+ val packageFqNameToLocation = mutableMapOf<FqName, PackageListProvider.ExternalDocumentationRoot>()
+
init {
- options.externalDocumentationLinks.forEach {
- try {
- loadPackageList(it)
- } catch (e: Exception) {
- throw RuntimeException("Exception while loading package-list from $it", e)
- }
+ val fqNameToLocationMaps = passConfiguration.externalDocumentationLinks
+ .mapNotNull { packageListProvider.storage[it] }
+
+ for(map in fqNameToLocationMaps) {
+ packageFqNameToLocation.putAll(map)
}
}
@@ -191,14 +246,6 @@ class ExternalDocumentationLinkResolver @Inject constructor(
companion object {
const val DOKKA_PARAM_PREFIX = "\$dokka."
val services = ServiceLocator.allServices("inbound-link-resolver").associateBy { it.name }
- private val formatsWithDefaultResolver =
- ServiceLocator
- .allServices("format")
- .filter {
- val desc = ServiceLocator.lookup<FormatDescriptor>(it) as? FileGeneratorBasedFormatDescriptor
- desc?.generatorServiceClass == FileGenerator::class
- }.map { it.name }
- .toSet()
}
}
diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt
index 00a795d0..ee9d8c51 100644
--- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt
@@ -30,7 +30,7 @@ class KotlinAsJavaDocumentationBuilder
return
}
- val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.options,
+ val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.passConfiguration,
documentationBuilder.refGraph,
kotlinAsJavaDocumentationParser)
@@ -42,8 +42,7 @@ class KotlinAsJavaDocumentationBuilder
fun PsiClass.isVisibleInDocumentation(): Boolean {
val origin: KtDeclaration = (this as KtLightElement<*, *>).kotlinOrigin as? KtDeclaration ?: return true
- return origin.hasModifier(KtTokens.INTERNAL_KEYWORD) != true &&
- origin.hasModifier(KtTokens.PRIVATE_KEYWORD) != true
+ return !origin.hasModifier(KtTokens.INTERNAL_KEYWORD) && !origin.hasModifier(KtTokens.PRIVATE_KEYWORD)
}
}
diff --git a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt
index bcac0182..c7187b23 100644
--- a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt
+++ b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt
@@ -3,6 +3,7 @@ package org.jetbrains.dokka
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMember
import com.intellij.psi.PsiPackage
+import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.name.FqName
@@ -22,13 +23,11 @@ class KotlinElementSignatureProvider @Inject constructor(
}
-fun PsiElement.extractDescriptor(resolutionFacade: DokkaResolutionFacade): DeclarationDescriptor? {
- val forPsi = this
-
- return when (forPsi) {
- is KtLightElement<*, *> -> return (forPsi.kotlinOrigin!!).extractDescriptor(resolutionFacade)
+fun PsiElement.extractDescriptor(resolutionFacade: DokkaResolutionFacade): DeclarationDescriptor? =
+ when (val forPsi = this) {
+ is KtLightClassForFacade -> resolutionFacade.moduleDescriptor.getPackage(forPsi.fqName)
+ is KtLightElement<*, *> -> (forPsi.kotlinOrigin!!).extractDescriptor(resolutionFacade)
is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName))
is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade)
else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi]
}
-}
diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
index 5f43c22e..7310610f 100644
--- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
+++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
@@ -62,7 +62,7 @@ class KotlinLanguageService : CommonLanguageService() {
}
private fun List<DocumentationNode>.getReceiverKind(): ReceiverKind? {
- val qNames = map { it.getReceiverQName() }.filterNotNull()
+ val qNames = mapNotNull { it.getReceiverQName() }
if (qNames.size != size)
return null
@@ -208,7 +208,7 @@ class KotlinLanguageService : CommonLanguageService() {
nowrap: Boolean
) {
when (node.name) {
- "final", "public", "var" -> {
+ "final", "public", "var", "expect", "actual", "external" -> {
}
else -> {
if (showModifierInSummary(node) || renderMode == RenderMode.FULL) {
diff --git a/core/src/main/kotlin/Languages/JavaLanguageService.kt b/core/src/main/kotlin/Languages/JavaLanguageService.kt
index 59bedd02..ad66123b 100644
--- a/core/src/main/kotlin/Languages/JavaLanguageService.kt
+++ b/core/src/main/kotlin/Languages/JavaLanguageService.kt
@@ -84,7 +84,7 @@ class JavaLanguageService : LanguageService {
return if (constraints.none())
node.name
else {
- node.name + " extends " + constraints.map { renderType(node) }.joinToString()
+ node.name + " extends " + constraints.joinToString { renderType(node) }
}
}
@@ -97,7 +97,7 @@ class JavaLanguageService : LanguageService {
val typeParameters = node.details(NodeKind.TypeParameter)
if (typeParameters.any()) {
append("<")
- append(typeParameters.map { renderTypeParameter(it) }.joinToString())
+ append(typeParameters.joinToString { renderTypeParameter(it) })
append("> ")
}
}.toString()
@@ -142,9 +142,9 @@ class JavaLanguageService : LanguageService {
val receiver = node.details(NodeKind.Receiver).singleOrNull()
append("(")
if (receiver != null)
- (listOf(receiver) + node.details(NodeKind.Parameter)).map { renderParameter(it) }.joinTo(this)
+ (listOf(receiver) + node.details(NodeKind.Parameter)).joinTo(this) { renderParameter(it) }
else
- node.details(NodeKind.Parameter).map { renderParameter(it) }.joinTo(this)
+ node.details(NodeKind.Parameter).joinTo(this) { renderParameter(it) }
append(")")
}.toString()
diff --git a/core/src/main/kotlin/Locations/Location.kt b/core/src/main/kotlin/Locations/Location.kt
index 4cb0ac39..63c9b913 100644
--- a/core/src/main/kotlin/Locations/Location.kt
+++ b/core/src/main/kotlin/Locations/Location.kt
@@ -26,7 +26,7 @@ data class FileLocation(val file: File) : Location {
}
val ownerFolder = file.parentFile!!
val relativePath = ownerFolder.toPath().relativize(other.file.toPath()).toString().replace(File.separatorChar, '/')
- return if (anchor == null) relativePath else relativePath + "#" + anchor
+ return if (anchor == null) relativePath else "$relativePath#$anchor"
}
}
@@ -40,10 +40,25 @@ fun relativePathToNode(qualifiedName: List<String>, hasMembers: Boolean): String
}
}
+fun nodeActualQualifier(node: DocumentationNode): List<DocumentationNode> {
+ val topLevelPage = node.references(RefKind.TopLevelPage).singleOrNull()?.to
+ if (topLevelPage != null) {
+ return nodeActualQualifier(topLevelPage)
+ }
+ return node.owner?.let { nodeActualQualifier(it) }.orEmpty() + node
+}
+
+fun relativePathToNode(node: DocumentationNode): String {
+ val qualifier = nodeActualQualifier(node)
+ return relativePathToNode(
+ qualifier.map { it.name },
+ qualifier.last().members.any()
+ )
+}
-fun relativePathToNode(node: DocumentationNode) = relativePathToNode(node.path.map { it.name }, node.members.any())
fun identifierToFilename(path: String): String {
+ if (path.isEmpty()) return "--root--"
val escaped = path.replace('<', '-').replace('>', '-')
val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() }
return if (lowercase == "index") "--index--" else lowercase
diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt
index c142f4a4..5530e1b4 100644
--- a/core/src/main/kotlin/Model/Content.kt
+++ b/core/src/main/kotlin/Model/Content.kt
@@ -171,10 +171,10 @@ class ContentSection(val tag: String, val subjectName: String?) : ContentBlock()
}
object ContentTags {
- val Description = "Description"
- val SeeAlso = "See Also"
- val Return = "Return"
- val Exceptions = "Exceptions"
+ const val Description = "Description"
+ const val SeeAlso = "See Also"
+ const val Return = "Return"
+ const val Exceptions = "Exceptions"
}
fun content(body: ContentBlock.() -> Unit): ContentBlock {
@@ -227,7 +227,11 @@ open class Content(): ContentBlock() {
sections.firstOrNull { tag.equals(it.tag, ignoreCase = true) }
companion object {
- val Empty = Content()
+ val Empty = object: Content() {
+ override fun toString(): String {
+ return "EMPTY_CONTENT"
+ }
+ }
fun of(vararg child: ContentNode): Content {
val result = MutableContent()
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index ad7801f2..311b46e4 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -76,7 +76,14 @@ open class DocumentationNode(val name: String,
var content: Content = content
private set
- val summary: ContentNode get() = content.summary
+ val summary: ContentNode get() = when (kind) {
+ NodeKind.GroupNode -> this.origins
+ .map { it.content }
+ .firstOrNull { !it.isEmpty() }
+ ?.summary ?: ContentEmpty
+ else -> content.summary
+ }
+
val owner: DocumentationNode?
get() = references(RefKind.Owner).singleOrNull()?.to
@@ -84,6 +91,9 @@ open class DocumentationNode(val name: String,
get() = references(RefKind.Detail).map { it.to }
val members: List<DocumentationNode>
get() = references(RefKind.Member).map { it.to }
+ val origins: List<DocumentationNode>
+ get() = references(RefKind.Origin).map { it.to }
+
val inheritedMembers: List<DocumentationNode>
get() = references(RefKind.InheritedMember).map { it.to }
val allInheritedMembers: List<DocumentationNode>
@@ -109,6 +119,15 @@ open class DocumentationNode(val name: String,
val externalType: DocumentationNode?
get() = references(RefKind.ExternalType).map { it.to }.firstOrNull()
+ var sinceKotlin: String?
+ get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name
+ set(value) {
+ dropReferences { it.kind == RefKind.SinceKotlin }
+ if (value != null) {
+ append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin)
+ }
+ }
+
val supertypes: List<DocumentationNode>
get() = details(NodeKind.Supertype)
@@ -134,6 +153,10 @@ open class DocumentationNode(val name: String,
references.add(DocumentationReference(this, to, kind))
}
+ fun addReference(reference: DocumentationReference) {
+ references.add(reference)
+ }
+
fun dropReferences(predicate: (DocumentationReference) -> Boolean) {
references.removeAll(predicate)
}
@@ -154,10 +177,11 @@ open class DocumentationNode(val name: String,
fun inheritedCompanionObjectMembers(kind: NodeKind): List<DocumentationNode> = inheritedCompanionObjectMembers.filter { it.kind == kind }
fun links(kind: NodeKind): List<DocumentationNode> = links.filter { it.kind == kind }
- fun detail(kind: NodeKind): DocumentationNode = details.filter { it.kind == kind }.single()
- fun detailOrNull(kind: NodeKind): DocumentationNode? = details.filter { it.kind == kind }.singleOrNull()
- fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single()
- fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single()
+ fun detail(kind: NodeKind): DocumentationNode = details.single { it.kind == kind }
+ fun detailOrNull(kind: NodeKind): DocumentationNode? = details.singleOrNull { it.kind == kind }
+ fun member(kind: NodeKind): DocumentationNode = members.single { it.kind == kind }
+ fun link(kind: NodeKind): DocumentationNode = links.single { it.kind == kind }
+
fun references(kind: RefKind): List<DocumentationReference> = references.filter { it.kind == kind }
fun allReferences(): Set<DocumentationReference> = references
@@ -167,9 +191,9 @@ open class DocumentationNode(val name: String,
}
}
-class DocumentationModule(name: String, content: Content = Content.Empty)
+class DocumentationModule(name: String, content: Content = Content.Empty, val nodeRefGraph: NodeReferenceGraph = NodeReferenceGraph())
: DocumentationNode(name, content, NodeKind.Module) {
- val nodeRefGraph = NodeReferenceGraph()
+
}
val DocumentationNode.path: List<DocumentationNode>
@@ -201,6 +225,7 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) {
RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner)
RefKind.Member -> child.addReferenceTo(this, RefKind.Owner)
RefKind.Owner -> child.addReferenceTo(this, RefKind.Member)
+ RefKind.Origin -> child.addReferenceTo(this, RefKind.Owner)
else -> { /* Do not add any links back for other types */
}
}
diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt
index 89ec1b3e..0b890a78 100644
--- a/core/src/main/kotlin/Model/DocumentationReference.kt
+++ b/core/src/main/kotlin/Model/DocumentationReference.kt
@@ -19,42 +19,83 @@ enum class RefKind {
Deprecation,
TopLevelPage,
Platform,
- ExternalType
+ ExternalType,
+ Origin,
+ SinceKotlin
}
data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) {
}
-class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?,
- val lazyNodeTo: () -> DocumentationNode?,
+sealed class NodeResolver {
+ abstract fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode?
+ class BySignature(var signature: String) : NodeResolver() {
+ override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? {
+ return nodeRephGraph.lookup(signature)
+ }
+ }
+
+ class Exact(var exactNode: DocumentationNode) : NodeResolver() {
+ override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? {
+ return exactNode
+ }
+ }
+}
+
+class PendingDocumentationReference(val lazyNodeFrom: NodeResolver,
+ val lazyNodeTo: NodeResolver,
val kind: RefKind) {
- fun resolve() {
- val fromNode = lazyNodeFrom()
- val toNode = lazyNodeTo()
+ fun resolve(nodeRephGraph: NodeReferenceGraph) {
+ val fromNode = lazyNodeFrom.resolve(nodeRephGraph)
+ val toNode = lazyNodeTo.resolve(nodeRephGraph)
if (fromNode != null && toNode != null) {
fromNode.addReferenceTo(toNode, kind)
}
}
}
-class NodeReferenceGraph() {
+class NodeReferenceGraph {
private val nodeMap = hashMapOf<String, DocumentationNode>()
+ val nodeMapView: Map<String, DocumentationNode>
+ get() = HashMap(nodeMap)
+
val references = arrayListOf<PendingDocumentationReference>()
fun register(signature: String, node: DocumentationNode) {
- nodeMap.put(signature, node)
+ nodeMap[signature] = node
}
fun link(fromNode: DocumentationNode, toSignature: String, kind: RefKind) {
- references.add(PendingDocumentationReference({ -> fromNode}, { -> nodeMap[toSignature]}, kind))
+ references.add(
+ PendingDocumentationReference(
+ NodeResolver.Exact(fromNode),
+ NodeResolver.BySignature(toSignature),
+ kind
+ ))
}
fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) {
- references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> toNode}, kind))
+ references.add(
+ PendingDocumentationReference(
+ NodeResolver.BySignature(fromSignature),
+ NodeResolver.Exact(toNode),
+ kind
+ )
+ )
}
fun link(fromSignature: String, toSignature: String, kind: RefKind) {
- references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> nodeMap[toSignature]}, kind))
+ references.add(
+ PendingDocumentationReference(
+ NodeResolver.BySignature(fromSignature),
+ NodeResolver.BySignature(toSignature),
+ kind
+ )
+ )
+ }
+
+ fun addReference(reference: PendingDocumentationReference) {
+ references.add(reference)
}
fun lookup(signature: String) = nodeMap[signature]
@@ -62,13 +103,14 @@ class NodeReferenceGraph() {
fun lookupOrWarn(signature: String, logger: DokkaLogger): DocumentationNode? {
val result = nodeMap[signature]
if (result == null) {
- logger.warn("Can't find node by signature `$signature`")
+ logger.warn("Can't find node by signature `$signature`." +
+ "This is probably caused by invalid configuration of cross-module dependencies")
}
return result
}
fun resolveReferences() {
- references.forEach { it.resolve() }
+ references.forEach { it.resolve(this) }
}
}
diff --git a/core/src/main/kotlin/Model/PackageDocs.kt b/core/src/main/kotlin/Model/PackageDocs.kt
index 9804f68b..b24efc5d 100644
--- a/core/src/main/kotlin/Model/PackageDocs.kt
+++ b/core/src/main/kotlin/Model/PackageDocs.kt
@@ -42,7 +42,7 @@ class PackageDocs
targetContent = findTargetContent(headingText.trimStart())
}
} else {
- buildContentTo(it, targetContent, LinkResolver(linkMap, { resolveContentLink(fileName, it, linkResolveContext) }))
+ buildContentTo(it, targetContent, LinkResolver(linkMap) { resolveContentLink(fileName, it, linkResolveContext) })
}
}
} else {
diff --git a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt
index 116a5c02..da74495f 100644
--- a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt
+++ b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
open class DefaultSampleProcessingService
-@Inject constructor(val options: DocumentationOptions,
+@Inject constructor(val configuration: DokkaConfiguration,
val logger: DokkaLogger,
val resolutionFacade: DokkaResolutionFacade)
: SampleProcessingService {
@@ -45,7 +45,7 @@ open class DefaultSampleProcessingService
val text = processSampleBody(psiElement).trim { it == '\n' || it == '\r' }.trimEnd()
val lines = text.split("\n")
val indent = lines.filter(String::isNotBlank).map { it.takeWhile(Char::isWhitespace).count() }.min() ?: 0
- val finalText = lines.map { it.drop(indent) }.joinToString("\n")
+ val finalText = lines.joinToString("\n") { it.drop(indent) }
return ContentBlockSampleCode(importsBlock = processImports(psiElement)).apply { append(ContentText(finalText)) }
}
@@ -81,9 +81,7 @@ open class DefaultSampleProcessingService
for (part in parts) {
// short name
val symbolName = Name.identifier(part)
- val partSymbol = currentScope.getContributedDescriptors(DescriptorKindFilter.ALL, { it == symbolName })
- .filter { it.name == symbolName }
- .firstOrNull()
+ val partSymbol = currentScope.getContributedDescriptors(DescriptorKindFilter.ALL) { it == symbolName }.firstOrNull { it.name == symbolName }
if (partSymbol == null) {
symbol = null
diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt
index b0988c35..4525e9d9 100644
--- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt
+++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt
@@ -1,7 +1,9 @@
package org.jetbrains.dokka.Samples
import com.google.inject.Inject
+import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.PsiTreeUtil
@@ -9,19 +11,27 @@ import org.jetbrains.dokka.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.allChildren
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.ImportPath
+import java.io.PrintWriter
+import java.io.StringWriter
+
open class KotlinWebsiteSampleProcessingService
-@Inject constructor(options: DocumentationOptions,
+@Inject constructor(dokkaConfiguration: DokkaConfiguration,
logger: DokkaLogger,
resolutionFacade: DokkaResolutionFacade)
- : DefaultSampleProcessingService(options, logger, resolutionFacade) {
+ : DefaultSampleProcessingService(dokkaConfiguration, logger, resolutionFacade) {
private class SampleBuilder : KtTreeVisitorVoid() {
val builder = StringBuilder()
val text: String
get() = builder.toString()
+ val errors = mutableListOf<ConvertError>()
+
+ data class ConvertError(val e: Exception, val text: String, val loc: String)
+
fun KtValueArgument.extractStringArgumentValue() =
(getArgumentExpression() as KtStringTemplateExpression)
.entries.joinToString("") { it.text }
@@ -54,27 +64,42 @@ open class KotlinWebsiteSampleProcessingService
}
fun convertAssertFails(expression: KtCallExpression) {
- val (message, funcArgument) = expression.valueArguments
+ val valueArguments = expression.valueArguments
+
+ val funcArgument: KtValueArgument
+ val message: KtValueArgument?
+
+ if (valueArguments.size == 1) {
+ message = null
+ funcArgument = valueArguments.first()
+ } else {
+ message = valueArguments.first()
+ funcArgument = valueArguments.last()
+ }
+
builder.apply {
- val argument = if (funcArgument.getArgumentExpression() is KtLambdaExpression)
- PsiTreeUtil.findChildOfType(funcArgument, KtBlockExpression::class.java)?.text ?: ""
- else
- funcArgument.text
+ val argument = funcArgument.extractFunctionalArgumentText()
append(argument.lines().joinToString(separator = "\n") { "// $it" })
append(" // ")
- append(message.extractStringArgumentValue())
+ if (message != null) {
+ append(message.extractStringArgumentValue())
+ }
append(" will fail")
}
}
+ private fun KtValueArgument.extractFunctionalArgumentText(): String {
+ return if (getArgumentExpression() is KtLambdaExpression)
+ PsiTreeUtil.findChildOfType(this, KtBlockExpression::class.java)?.text ?: ""
+ else
+ text
+ }
+
fun convertAssertFailsWith(expression: KtCallExpression) {
val (funcArgument) = expression.valueArguments
val (exceptionType) = expression.typeArguments
builder.apply {
- val argument = if (funcArgument.firstChild is KtLambdaExpression)
- PsiTreeUtil.findChildOfType(funcArgument, KtBlockExpression::class.java)?.text ?: ""
- else
- funcArgument.text
+ val argument = funcArgument.extractFunctionalArgumentText()
append(argument.lines().joinToString(separator = "\n") { "// $it" })
append(" // will fail with ")
append(exceptionType.text)
@@ -92,16 +117,51 @@ open class KotlinWebsiteSampleProcessingService
}
}
+ private fun reportProblemConvertingElement(element: PsiElement, e: Exception) {
+ val text = element.text
+ val document = PsiDocumentManager.getInstance(element.project).getDocument(element.containingFile)
+
+ val lineInfo = if (document != null) {
+ val lineNumber = document.getLineNumber(element.startOffset)
+ "$lineNumber, ${element.startOffset - document.getLineStartOffset(lineNumber)}"
+ } else {
+ "offset: ${element.startOffset}"
+ }
+ errors += ConvertError(e, text, lineInfo)
+ }
+
override fun visitElement(element: PsiElement) {
if (element is LeafPsiElement)
builder.append(element.text)
- super.visitElement(element)
+
+ element.acceptChildren(object : PsiElementVisitor() {
+ override fun visitElement(element: PsiElement) {
+ try {
+ element.accept(this@SampleBuilder)
+ } catch (e: Exception) {
+ try {
+ reportProblemConvertingElement(element, e)
+ } finally {
+ builder.append(element.text) //recover
+ }
+ }
+ }
+ })
}
+
}
private fun PsiElement.buildSampleText(): String {
val sampleBuilder = SampleBuilder()
this.accept(sampleBuilder)
+
+ sampleBuilder.errors.forEach {
+ val sw = StringWriter()
+ val pw = PrintWriter(sw)
+ it.e.printStackTrace(pw)
+
+ logger.error("${containingFile.name}: (${it.loc}): Exception thrown while converting \n```\n${it.text}\n```\n$sw")
+ }
return sampleBuilder.text
}
diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt
index 732cbc48..919ec30f 100644
--- a/core/src/main/kotlin/Utilities/DokkaModules.kt
+++ b/core/src/main/kotlin/Utilities/DokkaModules.kt
@@ -13,10 +13,21 @@ import kotlin.reflect.KClass
const val impliedPlatformsName = "impliedPlatforms"
+class DokkaRunModule(val configuration: DokkaConfiguration) : Module {
+ override fun configure(binder: Binder) {
+ binder.bind<DokkaConfiguration>().toInstance(configuration)
+ binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms)
+
+ binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir))
+ }
+
+}
+
class DokkaAnalysisModule(val environment: AnalysisEnvironment,
- val options: DocumentationOptions,
+ val configuration: DokkaConfiguration,
val defaultPlatformsProvider: DefaultPlatformsProvider,
val nodeReferenceGraph: NodeReferenceGraph,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
val logger: DokkaLogger) : Module {
override fun configure(binder: Binder) {
binder.bind<DokkaLogger>().toInstance(logger)
@@ -28,29 +39,25 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment,
binder.bind<DokkaResolutionFacade>().toInstance(dokkaResolutionFacade)
binder.bind<DokkaResolutionFacade>().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade)
- binder.bind<DocumentationOptions>().toInstance(options)
+ binder.bind<DokkaConfiguration.PassConfiguration>().toInstance(passConfiguration)
binder.bind<DefaultPlatformsProvider>().toInstance(defaultPlatformsProvider)
binder.bind<NodeReferenceGraph>().toInstance(nodeReferenceGraph)
- val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", options.outputFormat)
+ val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", configuration.format)
descriptor.configureAnalysis(binder)
}
}
object StringListType : TypeLiteral<@JvmSuppressWildcards List<String>>()
-class DokkaOutputModule(val options: DocumentationOptions,
+class DokkaOutputModule(val configuration: DokkaConfiguration,
val logger: DokkaLogger) : Module {
override fun configure(binder: Binder) {
- binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir))
-
- binder.bind<DocumentationOptions>().toInstance(options)
binder.bind<DokkaLogger>().toInstance(logger)
- binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(options.impliedPlatforms)
- val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", options.outputFormat)
+ val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", configuration.format)
descriptor.configureOutput(binder)
}
diff --git a/core/src/main/kotlin/Utilities/ServiceLocator.kt b/core/src/main/kotlin/Utilities/ServiceLocator.kt
index 83c4c65c..eda83422 100644
--- a/core/src/main/kotlin/Utilities/ServiceLocator.kt
+++ b/core/src/main/kotlin/Utilities/ServiceLocator.kt
@@ -22,10 +22,7 @@ object ServiceLocator {
descriptor: ServiceDescriptor
): T {
val loadedClass = javaClass.classLoader.loadClass(descriptor.className)
- val constructor = loadedClass.constructors
- .filter { it.parameterTypes.isEmpty() }
- .firstOrNull()
- ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor")
+ val constructor = loadedClass.constructors.firstOrNull { it.parameterTypes.isEmpty() } ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor")
val implementationRawType: Any =
if (constructor.parameterTypes.isEmpty()) constructor.newInstance() else constructor.newInstance(constructor)
@@ -70,7 +67,7 @@ object ServiceLocator {
"jar" -> {
val file = JarFile(URL(it.file.substringBefore("!")).toFile())
try {
- val jarPath = it.file.substringAfterLast("!").removePrefix("/")
+ val jarPath = it.file.substringAfterLast("!").removePrefix("/").removeSuffix("/")
file.entries()
.asSequence()
.filter { entry -> !entry.isDirectory && entry.path == jarPath && entry.extension == "properties" }
diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt
index 118b134a..0bf72ccf 100644
--- a/core/src/main/kotlin/javadoc/docbase.kt
+++ b/core/src/main/kotlin/javadoc/docbase.kt
@@ -84,7 +84,7 @@ open class DocumentationNodeAdapter(override val module: ModuleNodeAdapter, node
// should be extension property but can't because of KT-8745
private fun <T> nodeAnnotations(self: T): List<AnnotationDescAdapter> where T : HasModule, T : HasDocumentationNode
- = self.node.annotations.map { AnnotationDescAdapter(self.module, it) }
+ = self.node.annotations.map { AnnotationDescAdapter(self.module, it) }
private fun DocumentationNode.hasAnnotation(klass: KClass<*>) = klass.qualifiedName in annotations.map { it.qualifiedName() }
private fun DocumentationNode.hasModifier(name: String) = details(NodeKind.Modifier).any { it.name == name }
@@ -94,7 +94,7 @@ class PackageAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : Docum
private val allClasses = listOf(node).collectAllTypesRecursively()
override fun findClass(className: String?): ClassDoc? =
- allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) }
+ allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) }
override fun annotationTypes(): Array<out AnnotationTypeDoc> = emptyArray()
override fun annotations(): Array<out AnnotationDesc> = node.members(NodeKind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray()
@@ -126,9 +126,9 @@ open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationN
override fun modifierSpecifier(): Int = visibilityModifier or (if (isStatic) STATIC else 0)
private val visibilityModifier
get() = when {
- isPublic() -> PUBLIC
- isPrivate() -> PRIVATE
- isProtected() -> PROTECTED
+ isPublic -> PUBLIC
+ isPrivate -> PRIVATE
+ isProtected -> PROTECTED
else -> 0
}
override fun qualifiedName(): String? = node.qualifiedName()
@@ -185,24 +185,24 @@ open class TypeAdapter(override val module: ModuleNodeAdapter, override val node
override fun isPrimitive(): Boolean = simpleTypeName() in setOf("int", "long", "short", "byte", "char", "double", "float", "boolean", "void")
override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else
- elementType?.asClassDoc() ?:
- when (node.kind) {
- in NodeKind.classLike,
- NodeKind.ExternalClass,
- NodeKind.Exception -> module.classNamed(qualifiedTypeName()) ?: ClassDocumentationNodeAdapter(module, node)
-
- else -> when {
- node.links.isNotEmpty() -> TypeAdapter(module, node.links.first()).asClassDoc()
- else -> ClassDocumentationNodeAdapter(module, node) // TODO ?
- }
+ elementType?.asClassDoc() ?:
+ when (node.kind) {
+ in NodeKind.classLike,
+ NodeKind.ExternalClass,
+ NodeKind.Exception -> module.classNamed(qualifiedTypeName()) ?: ClassDocumentationNodeAdapter(module, node)
+
+ else -> when {
+ node.links.isNotEmpty() -> TypeAdapter(module, node.links.first()).asClassDoc()
+ else -> ClassDocumentationNodeAdapter(module, node) // TODO ?
}
+ }
override fun asTypeVariable(): TypeVariable? = if (node.kind == NodeKind.TypeParameter) TypeVariableAdapter(module, node) else null
override fun asParameterizedType(): ParameterizedType? =
- if (node.details(NodeKind.Type).isNotEmpty() && javaLanguageService.getArrayElementType(node) == null)
- ParameterizedTypeAdapter(module, node)
- else
- null
+ if (node.details(NodeKind.Type).isNotEmpty() && javaLanguageService.getArrayElementType(node) == null)
+ ParameterizedTypeAdapter(module, node)
+ else
+ null
override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == NodeKind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null
override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null
@@ -258,15 +258,15 @@ class TypeVariableAdapter(module: ModuleNodeAdapter, node: DocumentationNode) :
class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType {
override fun typeArguments(): Array<out Type> = node.details(NodeKind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray()
override fun superclassType(): Type? =
- node.lookupSuperClasses(module)
- .firstOrNull { it.kind == NodeKind.Class || it.kind == NodeKind.ExternalClass }
- ?.let { ClassDocumentationNodeAdapter(module, it) }
+ node.lookupSuperClasses(module)
+ .firstOrNull { it.kind == NodeKind.Class || it.kind == NodeKind.ExternalClass }
+ ?.let { ClassDocumentationNodeAdapter(module, it) }
override fun interfaceTypes(): Array<out Type> =
- node.lookupSuperClasses(module)
- .filter { it.kind == NodeKind.Interface }
- .map { ClassDocumentationNodeAdapter(module, it) }
- .toTypedArray()
+ node.lookupSuperClasses(module)
+ .filter { it.kind == NodeKind.Interface }
+ .map { ClassDocumentationNodeAdapter(module, it) }
+ .toTypedArray()
override fun containingType(): Type? = when (node.owner?.kind) {
NodeKind.Package -> null
@@ -307,7 +307,7 @@ fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode
}
private fun DocumentationNode.hasNonEmptyContent() =
- this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()
+ this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()
open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ProgramElementAdapter(module, node), ExecutableMemberDoc {
@@ -317,17 +317,17 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio
override fun thrownExceptions(): Array<out ClassDoc> = emptyArray() // TODO
override fun throwsTags(): Array<out ThrowsTag> =
- node.content.sections
- .filter { it.tag == ContentTags.Exceptions && it.subjectName != null }
- .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) }
- .toTypedArray()
+ node.content.sections
+ .filter { it.tag == ContentTags.Exceptions && it.subjectName != null }
+ .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) }
+ .toTypedArray()
override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).last().hasModifier("vararg")
override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" }
override fun paramTags(): Array<out ParamTag> =
- collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })
+ collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })
override fun thrownExceptionTypes(): Array<out Type> = emptyArray()
override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) }
@@ -335,14 +335,14 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio
override fun signature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types
override fun parameters(): Array<out Parameter> =
- ((receiverNode()?.let { receiver -> listOf<Parameter>(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList())
- + node.details(NodeKind.Parameter).map { ParameterAdapter(module, it) }
- ).toTypedArray()
+ ((receiverNode()?.let { receiver -> listOf<Parameter>(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList())
+ + node.details(NodeKind.Parameter).map { ParameterAdapter(module, it) }
+ ).toTypedArray()
override fun typeParameters(): Array<out TypeVariable> = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
override fun typeParamTags(): Array<out ParamTag> =
- collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
+ collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->
when {
@@ -400,8 +400,11 @@ class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : Program
}
open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode)
: ProgramElementAdapter(module, classNode),
- Type by TypeAdapter(module, classNode),
- ClassDoc {
+ Type by TypeAdapter(module, classNode),
+ ClassDoc,
+ AnnotationTypeDoc {
+
+ override fun elements(): Array<out AnnotationTypeElementDoc>? = emptyArray() // TODO
override fun name(): String {
val parent = classNode.owner
@@ -427,17 +430,17 @@ open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNod
override fun enumConstants(): Array<out FieldDoc>? = classNode.members(NodeKind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray()
override fun isAbstract(): Boolean = classNode.details(NodeKind.Modifier).any { it.name == "abstract" }
override fun interfaceTypes(): Array<out Type> = classNode.lookupSuperClasses(module)
- .filter { it.kind == NodeKind.Interface }
- .map { ClassDocumentationNodeAdapter(module, it) }
- .toTypedArray()
+ .filter { it.kind == NodeKind.Interface }
+ .map { ClassDocumentationNodeAdapter(module, it) }
+ .toTypedArray()
override fun interfaces(): Array<out ClassDoc> = classNode.lookupSuperClasses(module)
- .filter { it.kind == NodeKind.Interface }
- .map { ClassDocumentationNodeAdapter(module, it) }
- .toTypedArray()
+ .filter { it.kind == NodeKind.Interface }
+ .map { ClassDocumentationNodeAdapter(module, it) }
+ .toTypedArray()
override fun typeParamTags(): Array<out ParamTag> =
- collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
+ collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
override fun fields(): Array<out FieldDoc> = fields(true)
override fun fields(filter: Boolean): Array<out FieldDoc> = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray()
@@ -477,10 +480,8 @@ open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNod
}
fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) =
- details(NodeKind.Supertype)
- .map { it.links.firstOrNull() }
- .map { module.allTypes[it?.qualifiedName()] }
- .filterNotNull()
+ details(NodeKind.Supertype)
+ .map { it.links.firstOrNull() }.mapNotNull { module.allTypes[it?.qualifiedName()] }
fun List<DocumentationNode>.collectAllTypesRecursively(): Map<String, DocumentationNode> {
val result = hashMapOf<String, DocumentationNode>()
@@ -504,19 +505,19 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR
override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) }
override fun classes(): Array<out ClassDoc> =
- allTypes.values.map { ClassDocumentationNodeAdapter(this, it) }.toTypedArray()
+ allTypes.values.map { ClassDocumentationNodeAdapter(this, it) }.toTypedArray()
override fun options(): Array<out Array<String>> = arrayOf(
- arrayOf("-d", outputPath),
- arrayOf("-docencoding", "UTF-8"),
- arrayOf("-charset", "UTF-8"),
- arrayOf("-keywords")
+ arrayOf("-d", outputPath),
+ arrayOf("-docencoding", "UTF-8"),
+ arrayOf("-charset", "UTF-8"),
+ arrayOf("-keywords")
)
override fun specifiedPackages(): Array<out PackageDoc>? = module.members(NodeKind.Package).map { PackageAdapter(this, it) }.toTypedArray()
override fun classNamed(qualifiedName: String?): ClassDoc? =
- allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) }
+ allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) }
override fun specifiedClasses(): Array<out ClassDoc> = classes()
}
@@ -526,9 +527,13 @@ private fun DocumentationNodeAdapter.collectParamTags(kind: NodeKind, sectionFil
.filter(DocumentationNode::hasNonEmptyContent)
.map { ParamTagAdapter(module, this, it.name, true, it.content.children) }
- + node.content.sections
+ + node.content.sections
.filter(sectionFilter)
- .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) }
+ .map {
+ ParamTagAdapter(module, this, it.subjectName ?: "?", true,
+ it.children.filterNot { contentNode -> contentNode is LazyContentBlock }
+ )
+ }
)
.distinctBy { it.parameterName }
.toTypedArray() \ No newline at end of file
diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt
index 483fb3cd..1329876a 100644
--- a/core/src/main/kotlin/javadoc/dokka-adapters.kt
+++ b/core/src/main/kotlin/javadoc/dokka-adapters.kt
@@ -4,16 +4,19 @@ import com.google.inject.Binder
import com.google.inject.Inject
import com.sun.tools.doclets.formats.html.HtmlDoclet
import org.jetbrains.dokka.*
-import org.jetbrains.dokka.Formats.*
+import org.jetbrains.dokka.Formats.DefaultAnalysisComponent
+import org.jetbrains.dokka.Formats.DefaultAnalysisComponentServices
+import org.jetbrains.dokka.Formats.FormatDescriptor
+import org.jetbrains.dokka.Formats.KotlinAsJava
import org.jetbrains.dokka.Utilities.bind
import org.jetbrains.dokka.Utilities.toType
-class JavadocGenerator @Inject constructor(val options: DocumentationOptions, val logger: DokkaLogger) : Generator {
+class JavadocGenerator @Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Generator {
override fun buildPages(nodes: Iterable<DocumentationNode>) {
val module = nodes.single() as DocumentationModule
- HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), options.outputDir))
+ HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), configuration.outputDir))
}
override fun buildOutlines(nodes: Iterable<DocumentationNode>) {
diff --git a/core/src/main/resources/dokka/format/kotlin-website-samples.properties b/core/src/main/resources/dokka/format/kotlin-website-samples.properties
deleted file mode 100644
index bda616a4..00000000
--- a/core/src/main/resources/dokka/format/kotlin-website-samples.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-class=org.jetbrains.dokka.Formats.KotlinWebsiteFormatRunnableSamplesDescriptor
-description=Generates Kotlin website documentation \ No newline at end of file
diff --git a/core/src/main/resources/dokka/format/kotlin-website.properties b/core/src/main/resources/dokka/format/kotlin-website.properties
deleted file mode 100644
index c13e7675..00000000
--- a/core/src/main/resources/dokka/format/kotlin-website.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-class=org.jetbrains.dokka.Formats.KotlinWebsiteFormatDescriptor
-description=Generates Kotlin website documentation \ No newline at end of file
diff --git a/core/src/test/kotlin/DokkaConfigurationTestImplementations.kt b/core/src/test/kotlin/DokkaConfigurationTestImplementations.kt
new file mode 100644
index 00000000..a6f427b1
--- /dev/null
+++ b/core/src/test/kotlin/DokkaConfigurationTestImplementations.kt
@@ -0,0 +1,81 @@
+package org.jetbrains.dokka.tests
+
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.Platform
+import java.io.File
+
+
+data class SourceLinkDefinitionImpl(override val path: String,
+ override val url: String,
+ override val lineSuffix: String?) : DokkaConfiguration.SourceLinkDefinition {
+ companion object {
+ fun parseSourceLinkDefinition(srcLink: String): DokkaConfiguration.SourceLinkDefinition {
+ val (path, urlAndLine) = srcLink.split('=')
+ return SourceLinkDefinitionImpl(
+ File(path).canonicalPath,
+ urlAndLine.substringBefore("#"),
+ urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" })
+ }
+ }
+}
+
+class SourceRootImpl(path: String) : DokkaConfiguration.SourceRoot {
+ override val path: String = File(path).absolutePath
+
+ companion object {
+ fun parseSourceRoot(sourceRoot: String): DokkaConfiguration.SourceRoot = SourceRootImpl(sourceRoot)
+ }
+}
+
+data class PackageOptionsImpl(override val prefix: String,
+ override val includeNonPublic: Boolean = false,
+ override val reportUndocumented: Boolean = true,
+ override val skipDeprecated: Boolean = false,
+ override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions
+
+ class DokkaConfigurationImpl(
+ override val outputDir: String = "",
+ override val format: String = "html",
+ override val generateIndexPages: Boolean = false,
+ override val cacheRoot: String? = null,
+ override val impliedPlatforms: List<String> = emptyList(),
+ override val passesConfigurations: List<DokkaConfiguration.PassConfiguration> = emptyList()
+) : DokkaConfiguration
+
+class PassConfigurationImpl (
+ override val classpath: List<String> = emptyList(),
+ override val moduleName: String = "",
+ override val sourceRoots: List<DokkaConfiguration.SourceRoot> = emptyList(),
+ override val samples: List<String> = emptyList(),
+ override val includes: List<String> = emptyList(),
+ override val includeNonPublic: Boolean = false,
+ override val includeRootPackage: Boolean = false,
+ override val reportUndocumented: Boolean = false,
+ override val skipEmptyPackages: Boolean = false,
+ override val skipDeprecated: Boolean = false,
+ override val jdkVersion: Int = 6,
+ override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition> = emptyList(),
+ override val perPackageOptions: List<DokkaConfiguration.PackageOptions> = emptyList(),
+ externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink> = emptyList(),
+ override val languageVersion: String? = null,
+ override val apiVersion: String? = null,
+ override val noStdlibLink: Boolean = false,
+ override val noJdkLink: Boolean = false,
+ override val suppressedFiles: List<String> = emptyList(),
+ override val collectInheritedExtensionsFromLibraries: Boolean = false,
+ override val analysisPlatform: Platform = Platform.DEFAULT,
+ override val targets: List<String> = emptyList(),
+ override val sinceKotlin: String? = null
+): DokkaConfiguration.PassConfiguration {
+ private val defaultLinks = run {
+ val links = mutableListOf<DokkaConfiguration.ExternalDocumentationLink>()
+ if (!noJdkLink)
+ links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build()
+
+ if (!noStdlibLink)
+ links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build()
+ links
+ }
+ override val externalDocumentationLinks = defaultLinks + externalDocumentationLinks
+}
+
diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt
index 4f77a2f6..4f9af761 100644
--- a/core/src/test/kotlin/TestAPI.kt
+++ b/core/src/test/kotlin/TestAPI.kt
@@ -6,8 +6,8 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.rt.execution.junit.FileComparisonFailure
import org.jetbrains.dokka.*
-import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition
import org.jetbrains.dokka.Utilities.DokkaAnalysisModule
+import org.jetbrains.dokka.Utilities.DokkaRunModule
import org.jetbrains.kotlin.cli.common.config.ContentRoot
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
@@ -15,54 +15,63 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.utils.PathUtil
import org.junit.Assert
import org.junit.Assert.fail
import java.io.File
-fun verifyModel(vararg roots: ContentRoot,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- format: String = "html",
- includeNonPublic: Boolean = true,
- perPackageOptions: List<DokkaConfiguration.PackageOptions> = emptyList(),
- noStdlibLink: Boolean = true,
- collectInheritedExtensionsFromLibraries: Boolean = false,
- sourceLinks: List<SourceLinkDefinition> = emptyList(),
- verifier: (DocumentationModule) -> Unit) {
+data class ModelConfig(
+ val roots: Array<ContentRoot> = arrayOf(),
+ val withJdk: Boolean = false,
+ val withKotlinRuntime: Boolean = false,
+ val format: String = "html",
+ val includeNonPublic: Boolean = true,
+ val perPackageOptions: List<DokkaConfiguration.PackageOptions> = emptyList(),
+ val analysisPlatform: Platform = Platform.DEFAULT,
+ val defaultPlatforms: List<String> = emptyList(),
+ val noStdlibLink: Boolean = true,
+ val collectInheritedExtensionsFromLibraries: Boolean = false,
+ val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition> = emptyList()
+)
+
+fun verifyModel(
+ modelConfig: ModelConfig,
+ verifier: (DocumentationModule) -> Unit
+) {
val documentation = DocumentationModule("test")
- val options = DocumentationOptions(
- "",
- format,
- includeNonPublic = includeNonPublic,
+ val passConfiguration = PassConfigurationImpl(
+ includeNonPublic = modelConfig.includeNonPublic,
skipEmptyPackages = false,
includeRootPackage = true,
- sourceLinks = sourceLinks,
- perPackageOptions = perPackageOptions,
- generateIndexPages = false,
- noStdlibLink = noStdlibLink,
+ sourceLinks = modelConfig.sourceLinks,
+ perPackageOptions = modelConfig.perPackageOptions,
+ noStdlibLink = modelConfig.noStdlibLink,
noJdkLink = false,
- cacheRoot = "default",
languageVersion = null,
apiVersion = null,
- collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries
+ collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries
+ )
+ val configuration = DokkaConfigurationImpl(
+ outputDir = "",
+ format = modelConfig.format,
+ generateIndexPages = false,
+ cacheRoot = "default",
+ passesConfigurations = listOf(passConfiguration)
)
- appendDocumentation(documentation, *roots,
- withJdk = withJdk,
- withKotlinRuntime = withKotlinRuntime,
- options = options)
- documentation.prepareForGeneration(options)
+ appendDocumentation(documentation, configuration, passConfiguration, modelConfig)
+ documentation.prepareForGeneration(configuration)
verifier(documentation)
}
-fun appendDocumentation(documentation: DocumentationModule,
- vararg roots: ContentRoot,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- options: DocumentationOptions,
- defaultPlatforms: List<String> = emptyList()) {
+fun appendDocumentation(
+ documentation: DocumentationModule,
+ dokkaConfiguration: DokkaConfiguration,
+ passConfiguration: DokkaConfiguration.PassConfiguration,
+ modelConfig: ModelConfig
+) {
val messageCollector = object : MessageCollector {
override fun clear() {
@@ -87,143 +96,181 @@ fun appendDocumentation(documentation: DocumentationModule,
override fun hasErrors() = false
}
- val environment = AnalysisEnvironment(messageCollector)
+ val environment = AnalysisEnvironment(messageCollector, modelConfig.analysisPlatform)
environment.apply {
- if (withJdk || withKotlinRuntime) {
- val stringRoot = PathManager.getResourceRoot(String::class.java, "/java/lang/String.class")
- addClasspath(File(stringRoot))
+ if (modelConfig.withJdk || modelConfig.withKotlinRuntime) {
+ addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre())
}
- if (withKotlinRuntime) {
- val kotlinStrictfpRoot = PathManager.getResourceRoot(Strictfp::class.java, "/kotlin/jvm/Strictfp.class")
- addClasspath(File(kotlinStrictfpRoot))
+ if (modelConfig.withKotlinRuntime) {
+ if (analysisPlatform == Platform.jvm) {
+ val kotlinStrictfpRoot = PathManager.getResourceRoot(Strictfp::class.java, "/kotlin/jvm/Strictfp.class")
+ addClasspath(File(kotlinStrictfpRoot))
+ }
+ if (analysisPlatform == Platform.js) {
+ val kotlinStdlibJsRoot = PathManager.getResourceRoot(Any::class.java, "/kotlin/jquery")
+ addClasspath(File(kotlinStdlibJsRoot))
+ }
+
+ if (analysisPlatform == Platform.common) {
+ // TODO: Feels hacky
+ val kotlinStdlibCommonRoot = ClassLoader.getSystemResource("kotlin/UInt.kotlin_metadata")
+ addClasspath(File(kotlinStdlibCommonRoot.file.replace("file:", "").replaceAfter(".jar", "")))
+ }
}
- addRoots(roots.toList())
+ addRoots(modelConfig.roots.toList())
- loadLanguageVersionSettings(options.languageVersion, options.apiVersion)
+ loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion)
}
val defaultPlatformsProvider = object : DefaultPlatformsProvider {
- override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = defaultPlatforms
+ override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms
}
- val injector = Guice.createInjector(
- DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentation.nodeRefGraph, DokkaConsoleLogger))
+
+ val globalInjector = Guice.createInjector(
+ DokkaRunModule(dokkaConfiguration)
+ )
+
+ val injector = globalInjector.createChildInjector(
+ DokkaAnalysisModule(
+ environment,
+ dokkaConfiguration,
+ defaultPlatformsProvider,
+ documentation.nodeRefGraph,
+ passConfiguration,
+ DokkaConsoleLogger
+ )
+ )
+
buildDocumentationModule(injector, documentation)
Disposer.dispose(environment)
}
-fun verifyModel(source: String,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- format: String = "html",
- includeNonPublic: Boolean = true,
- sourceLinks: List<SourceLinkDefinition> = emptyList(),
- verifier: (DocumentationModule) -> Unit) {
- require (File(source).exists()) {
+fun checkSourceExistsAndVerifyModel(
+ source: String,
+ modelConfig: ModelConfig = ModelConfig(),
+ verifier: (DocumentationModule) -> Unit
+) {
+ require(File(source).exists()) {
"Cannot find test data file $source"
}
- verifyModel(contentRootFromPath(source),
- withJdk = withJdk,
- withKotlinRuntime = withKotlinRuntime,
- format = format,
- includeNonPublic = includeNonPublic,
- sourceLinks = sourceLinks,
- verifier = verifier)
+ verifyModel(
+ ModelConfig(
+ roots = arrayOf(contentRootFromPath(source)),
+ withJdk = modelConfig.withJdk,
+ withKotlinRuntime = modelConfig.withKotlinRuntime,
+ format = modelConfig.format,
+ includeNonPublic = modelConfig.includeNonPublic,
+ sourceLinks = modelConfig.sourceLinks,
+ analysisPlatform = modelConfig.analysisPlatform
+ ),
+
+ verifier = verifier
+ )
}
-fun verifyPackageMember(source: String,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- verifier: (DocumentationNode) -> Unit) {
- verifyModel(source, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime) { model ->
+fun verifyPackageMember(
+ source: String,
+ modelConfig: ModelConfig = ModelConfig(),
+ verifier: (DocumentationNode) -> Unit
+) {
+ checkSourceExistsAndVerifyModel(
+ source,
+ modelConfig = ModelConfig(
+ withJdk = modelConfig.withJdk,
+ withKotlinRuntime = modelConfig.withKotlinRuntime,
+ analysisPlatform = modelConfig.analysisPlatform
+ )
+ ) { model ->
val pkg = model.members.single()
verifier(pkg.members.single())
}
}
-fun verifyJavaModel(source: String,
- withKotlinRuntime: Boolean = false,
- verifier: (DocumentationModule) -> Unit) {
+fun verifyJavaModel(
+ source: String,
+ modelConfig: ModelConfig = ModelConfig(),
+ verifier: (DocumentationModule) -> Unit
+) {
val tempDir = FileUtil.createTempDirectory("dokka", "")
try {
val sourceFile = File(source)
FileUtil.copy(sourceFile, File(tempDir, sourceFile.name))
- verifyModel(JavaSourceRoot(tempDir, null), withJdk = true, withKotlinRuntime = withKotlinRuntime, verifier = verifier)
- }
- finally {
+ verifyModel(
+ ModelConfig(
+ roots = arrayOf(JavaSourceRoot(tempDir, null)),
+ withJdk = true,
+ withKotlinRuntime = modelConfig.withKotlinRuntime,
+ analysisPlatform = modelConfig.analysisPlatform
+ ),
+ verifier = verifier
+ )
+ } finally {
FileUtil.delete(tempDir)
}
}
-fun verifyJavaPackageMember(source: String,
- withKotlinRuntime: Boolean = false,
- verifier: (DocumentationNode) -> Unit) {
- verifyJavaModel(source, withKotlinRuntime) { model ->
+fun verifyJavaPackageMember(
+ source: String,
+ modelConfig: ModelConfig = ModelConfig(),
+ verifier: (DocumentationNode) -> Unit
+) {
+ verifyJavaModel(source, modelConfig) { model ->
val pkg = model.members.single()
verifier(pkg.members.single())
}
}
-fun verifyOutput(roots: Array<ContentRoot>,
- outputExtension: String,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- format: String = "html",
- includeNonPublic: Boolean = true,
- noStdlibLink: Boolean = true,
- collectInheritedExtensionsFromLibraries: Boolean = false,
- outputGenerator: (DocumentationModule, StringBuilder) -> Unit) {
- verifyModel(
- *roots,
- withJdk = withJdk,
- withKotlinRuntime = withKotlinRuntime,
- format = format,
- includeNonPublic = includeNonPublic,
- noStdlibLink = noStdlibLink,
- collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries
- ) {
- verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator)
+fun verifyOutput(
+ modelConfig: ModelConfig = ModelConfig(),
+ outputExtension: String,
+ outputGenerator: (DocumentationModule, StringBuilder) -> Unit
+) {
+ verifyModel(modelConfig) {
+ verifyModelOutput(it, outputExtension, modelConfig.roots.first().path, outputGenerator)
}
}
-fun verifyModelOutput(it: DocumentationModule,
- outputExtension: String,
- sourcePath: String,
- outputGenerator: (DocumentationModule, StringBuilder) -> Unit) {
- val output = StringBuilder()
- outputGenerator(it, output)
- val ext = outputExtension.removePrefix(".")
- val expectedFile = File(sourcePath.replaceAfterLast(".", ext, sourcePath + "." + ext))
- assertEqualsIgnoringSeparators(expectedFile, output.toString())
-}
-
fun verifyOutput(
path: String,
outputExtension: String,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- format: String = "html",
- includeNonPublic: Boolean = true,
- noStdlibLink: Boolean = true,
- collectInheritedExtensionsFromLibraries: Boolean = false,
+ modelConfig: ModelConfig = ModelConfig(),
outputGenerator: (DocumentationModule, StringBuilder) -> Unit
) {
verifyOutput(
- arrayOf(contentRootFromPath(path)),
+ ModelConfig(
+ roots = arrayOf(contentRootFromPath(path)) + modelConfig.roots,
+ withJdk = modelConfig.withJdk,
+ withKotlinRuntime = modelConfig.withKotlinRuntime,
+ format = modelConfig.format,
+ includeNonPublic = modelConfig.includeNonPublic,
+ analysisPlatform = modelConfig.analysisPlatform,
+ noStdlibLink = modelConfig.noStdlibLink,
+ collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries
+ ),
outputExtension,
- withJdk,
- withKotlinRuntime,
- format,
- includeNonPublic,
- noStdlibLink,
- collectInheritedExtensionsFromLibraries,
outputGenerator
)
}
-fun verifyJavaOutput(path: String,
- outputExtension: String,
- withKotlinRuntime: Boolean = false,
- outputGenerator: (DocumentationModule, StringBuilder) -> Unit) {
- verifyJavaModel(path, withKotlinRuntime) { model ->
+fun verifyModelOutput(
+ it: DocumentationModule,
+ outputExtension: String,
+ sourcePath: String,
+ outputGenerator: (DocumentationModule, StringBuilder) -> Unit
+) {
+ val output = StringBuilder()
+ outputGenerator(it, output)
+ val ext = outputExtension.removePrefix(".")
+ val expectedFile = File(sourcePath.replaceAfterLast(".", ext, sourcePath + "." + ext))
+ assertEqualsIgnoringSeparators(expectedFile, output.toString())
+}
+
+fun verifyJavaOutput(
+ path: String,
+ outputExtension: String,
+ modelConfig: ModelConfig = ModelConfig(),
+ outputGenerator: (DocumentationModule, StringBuilder) -> Unit
+) {
+ verifyJavaModel(path, modelConfig) { model ->
verifyModelOutput(model, outputExtension, path, outputGenerator)
}
}
@@ -233,7 +280,7 @@ fun assertEqualsIgnoringSeparators(expectedFile: File, output: String) {
val expectedText = expectedFile.readText().replace("\r\n", "\n")
val actualText = output.replace("\r\n", "\n")
- if(expectedText != actualText)
+ if (expectedText != actualText)
throw FileComparisonFailure("", expectedText, actualText, expectedFile.canonicalPath)
}
@@ -281,8 +328,11 @@ fun StringBuilder.appendNode(node: ContentNode): StringBuilder {
append(node.mode)
append(")")
}
- is ContentSymbol -> { append(node.text) }
- is ContentEmpty -> { /* nothing */ }
+ is ContentSymbol -> {
+ append(node.text)
+ }
+ is ContentEmpty -> { /* nothing */
+ }
else -> throw IllegalStateException("Don't know how to format node $node")
}
return this
@@ -296,7 +346,7 @@ fun ContentNode.toTestString(): String {
}
val ContentRoot.path: String
- get() = when(this) {
+ get() = when (this) {
is KotlinSourceRoot -> path
is JavaSourceRoot -> file.path
else -> throw UnsupportedOperationException()
diff --git a/core/src/test/kotlin/format/GFMFormatTest.kt b/core/src/test/kotlin/format/GFMFormatTest.kt
index b90ab2bf..60de7d29 100644
--- a/core/src/test/kotlin/format/GFMFormatTest.kt
+++ b/core/src/test/kotlin/format/GFMFormatTest.kt
@@ -2,23 +2,26 @@ package org.jetbrains.dokka.tests
import org.jetbrains.dokka.GFMFormatService
import org.jetbrains.dokka.KotlinLanguageService
+import org.jetbrains.dokka.Platform
import org.junit.Test
-class GFMFormatTest : FileGeneratorTestCase() {
+abstract class BaseGFMFormatTest(val analysisPlatform: Platform) : FileGeneratorTestCase() {
override val formatService = GFMFormatService(fileGenerator, KotlinLanguageService(), listOf())
+ private val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
+
@Test
fun sample() {
- verifyGFMNodeByName("sample", "Foo")
+ verifyGFMNodeByName("sample", "Foo", defaultModelConfig)
}
@Test
fun listInTableCell() {
- verifyGFMNodeByName("listInTableCell", "Foo")
+ verifyGFMNodeByName("listInTableCell", "Foo", defaultModelConfig)
}
- private fun verifyGFMNodeByName(fileName: String, name: String) {
- verifyOutput("testdata/format/gfm/$fileName.kt", ".md") { model, output ->
+ private fun verifyGFMNodeByName(fileName: String, name: String, modelConfig: ModelConfig) {
+ verifyOutput("testdata/format/gfm/$fileName.kt", ".md", modelConfig) { model, output ->
buildPagesAndReadInto(
model.members.single().members.filter { it.name == name },
output
@@ -26,3 +29,8 @@ class GFMFormatTest : FileGeneratorTestCase() {
}
}
}
+
+
+class JsGFMFormatTest : BaseGFMFormatTest(Platform.js)
+class JvmGFMFormatTest : BaseGFMFormatTest(Platform.jvm)
+class CommonGFMFormatTest : BaseGFMFormatTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/format/HtmlFormatTest.kt b/core/src/test/kotlin/format/HtmlFormatTest.kt
index 807118c5..60e29006 100644
--- a/core/src/test/kotlin/format/HtmlFormatTest.kt
+++ b/core/src/test/kotlin/format/HtmlFormatTest.kt
@@ -6,176 +6,187 @@ import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
import org.junit.Test
import java.io.File
-class HtmlFormatTest: FileGeneratorTestCase() {
+abstract class BaseHtmlFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() {
+ protected val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
override val formatService = HtmlFormatService(fileGenerator, KotlinLanguageService(), HtmlTemplateService.default(), listOf())
@Test fun classWithCompanionObject() {
- verifyHtmlNode("classWithCompanionObject")
+ verifyHtmlNode("classWithCompanionObject", defaultModelConfig)
}
@Test fun htmlEscaping() {
- verifyHtmlNode("htmlEscaping")
+ verifyHtmlNode("htmlEscaping", defaultModelConfig)
}
@Test fun overloads() {
- verifyHtmlNodes("overloads") { model -> model.members }
+ verifyHtmlNodes("overloads", defaultModelConfig) { model -> model.members }
}
@Test fun overloadsWithDescription() {
- verifyHtmlNode("overloadsWithDescription")
+ verifyHtmlNode("overloadsWithDescription", defaultModelConfig)
}
@Test fun overloadsWithDifferentDescriptions() {
- verifyHtmlNode("overloadsWithDifferentDescriptions")
+ verifyHtmlNode("overloadsWithDifferentDescriptions", defaultModelConfig)
}
@Test fun deprecated() {
- verifyOutput("testdata/format/deprecated.kt", ".package.html") { model, output ->
+ verifyOutput("testdata/format/deprecated.kt", ".package.html", defaultModelConfig) { model, output ->
buildPagesAndReadInto(model.members, output)
}
- verifyOutput("testdata/format/deprecated.kt", ".class.html") { model, output ->
+ verifyOutput("testdata/format/deprecated.kt", ".class.html", defaultModelConfig) { model, output ->
buildPagesAndReadInto(model.members.single().members, output)
}
}
@Test fun brokenLink() {
- verifyHtmlNode("brokenLink")
+ verifyHtmlNode("brokenLink", defaultModelConfig)
}
@Test fun codeSpan() {
- verifyHtmlNode("codeSpan")
+ verifyHtmlNode("codeSpan", defaultModelConfig)
}
@Test fun parenthesis() {
- verifyHtmlNode("parenthesis")
+ verifyHtmlNode("parenthesis", defaultModelConfig)
}
@Test fun bracket() {
- verifyHtmlNode("bracket")
+ verifyHtmlNode("bracket", defaultModelConfig)
}
@Test fun see() {
- verifyHtmlNode("see")
+ verifyHtmlNode("see", defaultModelConfig)
}
@Test fun tripleBackticks() {
- verifyHtmlNode("tripleBackticks")
+ verifyHtmlNode("tripleBackticks", defaultModelConfig)
}
@Test fun typeLink() {
- verifyHtmlNodes("typeLink") { model -> model.members.single().members.filter { it.name == "Bar" } }
+ verifyHtmlNodes("typeLink", defaultModelConfig) { model -> model.members.single().members.filter { it.name == "Bar" } }
}
@Test fun parameterAnchor() {
- verifyHtmlNode("parameterAnchor")
- }
-
- @Test fun javaSupertypeLink() {
- verifyJavaHtmlNodes("JavaSupertype") { model ->
- model.members.single().members.single { it.name == "JavaSupertype" }.members.filter { it.name == "Bar" }
- }
+ verifyHtmlNode("parameterAnchor", defaultModelConfig)
}
@Test fun codeBlock() {
- verifyHtmlNode("codeBlock")
- }
-
- @Test fun javaLinkTag() {
- verifyJavaHtmlNode("javaLinkTag")
- }
-
- @Test fun javaLinkTagWithLabel() {
- verifyJavaHtmlNode("javaLinkTagWithLabel")
- }
-
- @Test fun javaSeeTag() {
- verifyJavaHtmlNode("javaSeeTag")
+ verifyHtmlNode("codeBlock", defaultModelConfig)
}
-
- @Test fun javaDeprecated() {
- verifyJavaHtmlNodes("javaDeprecated") { model ->
- model.members.single().members.single { it.name == "Foo" }.members.filter { it.name == "foo" }
- }
- }
-
- @Test fun crossLanguageKotlinExtendsJava() {
- verifyOutput(arrayOf(
- KotlinSourceRoot("testdata/format/crossLanguage/kotlinExtendsJava/Bar.kt", false),
- JavaSourceRoot(File("testdata/format/crossLanguage/kotlinExtendsJava"), null)),
- ".html") { model, output ->
- buildPagesAndReadInto(
- model.members.single().members.filter { it.name == "Bar" },
- output
- )
- }
- }
-
@Test fun orderedList() {
- verifyHtmlNodes("orderedList") { model -> model.members.single().members.filter { it.name == "Bar" } }
+ verifyHtmlNodes("orderedList", defaultModelConfig) { model -> model.members.single().members.filter { it.name == "Bar" } }
}
@Test fun linkWithLabel() {
- verifyHtmlNodes("linkWithLabel") { model -> model.members.single().members.filter { it.name == "Bar" } }
+ verifyHtmlNodes("linkWithLabel", defaultModelConfig) { model -> model.members.single().members.filter { it.name == "Bar" } }
}
@Test fun entity() {
- verifyHtmlNodes("entity") { model -> model.members.single().members.filter { it.name == "Bar" } }
+ verifyHtmlNodes("entity", defaultModelConfig) { model -> model.members.single().members.filter { it.name == "Bar" } }
}
@Test fun uninterpretedEmphasisCharacters() {
- verifyHtmlNode("uninterpretedEmphasisCharacters")
+ verifyHtmlNode("uninterpretedEmphasisCharacters", defaultModelConfig)
}
@Test fun markdownInLinks() {
- verifyHtmlNode("markdownInLinks")
+ verifyHtmlNode("markdownInLinks", defaultModelConfig)
}
@Test fun returnWithLink() {
- verifyHtmlNode("returnWithLink")
+ verifyHtmlNode("returnWithLink", defaultModelConfig)
}
@Test fun linkWithStarProjection() {
- verifyHtmlNode("linkWithStarProjection", withKotlinRuntime = true)
+ verifyHtmlNode("linkWithStarProjection", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun functionalTypeWithNamedParameters() {
- verifyHtmlNode("functionalTypeWithNamedParameters")
+ verifyHtmlNode("functionalTypeWithNamedParameters", defaultModelConfig)
}
@Test fun sinceKotlin() {
- verifyHtmlNode("sinceKotlin")
+ verifyHtmlNode("sinceKotlin", defaultModelConfig)
}
@Test fun blankLineInsideCodeBlock() {
- verifyHtmlNode("blankLineInsideCodeBlock")
+ verifyHtmlNode("blankLineInsideCodeBlock", defaultModelConfig)
}
@Test fun indentedCodeBlock() {
- verifyHtmlNode("indentedCodeBlock")
+ verifyHtmlNode("indentedCodeBlock", defaultModelConfig)
}
- private fun verifyHtmlNode(fileName: String, withKotlinRuntime: Boolean = false) {
- verifyHtmlNodes(fileName, withKotlinRuntime) { model -> model.members.single().members }
+ private fun verifyHtmlNode(fileName: String, modelConfig: ModelConfig = ModelConfig()) {
+ verifyHtmlNodes(fileName, modelConfig) { model -> model.members.single().members }
}
private fun verifyHtmlNodes(fileName: String,
- withKotlinRuntime: Boolean = false,
+ modelConfig: ModelConfig = ModelConfig(),
nodeFilter: (DocumentationModule) -> List<DocumentationNode>) {
- verifyOutput("testdata/format/$fileName.kt", ".html", withKotlinRuntime = withKotlinRuntime) { model, output ->
+ verifyOutput("testdata/format/$fileName.kt", ".html", modelConfig) { model, output ->
buildPagesAndReadInto(nodeFilter(model), output)
}
}
- private fun verifyJavaHtmlNode(fileName: String, withKotlinRuntime: Boolean = false) {
- verifyJavaHtmlNodes(fileName, withKotlinRuntime) { model -> model.members.single().members }
+ protected fun verifyJavaHtmlNode(fileName: String, modelConfig: ModelConfig = ModelConfig()) {
+ verifyJavaHtmlNodes(fileName, modelConfig) { model -> model.members.single().members }
}
- private fun verifyJavaHtmlNodes(fileName: String,
- withKotlinRuntime: Boolean = false,
- nodeFilter: (DocumentationModule) -> List<DocumentationNode>) {
- verifyJavaOutput("testdata/format/$fileName.java", ".html", withKotlinRuntime = withKotlinRuntime) { model, output ->
+ protected fun verifyJavaHtmlNodes(fileName: String,
+ modelConfig: ModelConfig = ModelConfig(),
+ nodeFilter: (DocumentationModule) -> List<DocumentationNode>) {
+ verifyJavaOutput("testdata/format/$fileName.java", ".html", modelConfig) { model, output ->
buildPagesAndReadInto(nodeFilter(model), output)
}
}
}
+class JSHtmlFormatTest: BaseHtmlFormatTest(Platform.js)
+
+class JVMHtmlFormatTest: BaseHtmlFormatTest(Platform.jvm) {
+ @Test
+ fun javaSeeTag() {
+ verifyJavaHtmlNode("javaSeeTag", defaultModelConfig)
+ }
+
+ @Test fun javaDeprecated() {
+ verifyJavaHtmlNodes("javaDeprecated", defaultModelConfig) { model ->
+ model.members.single().members.single { it.name == "Foo" }.members.filter { it.name == "foo" }
+ }
+ }
+
+ @Test fun crossLanguageKotlinExtendsJava() {
+ verifyOutput(
+ ModelConfig(
+ roots = arrayOf(
+ KotlinSourceRoot("testdata/format/crossLanguage/kotlinExtendsJava/Bar.kt", false),
+ JavaSourceRoot(File("testdata/format/crossLanguage/kotlinExtendsJava"), null)
+ ),
+ analysisPlatform = analysisPlatform
+ ), ".html") { model, output ->
+ buildPagesAndReadInto(
+ model.members.single().members.filter { it.name == "Bar" },
+ output
+ )
+ }
+ }
+
+ @Test fun javaLinkTag() {
+ verifyJavaHtmlNode("javaLinkTag", defaultModelConfig)
+ }
+
+ @Test fun javaLinkTagWithLabel() {
+ verifyJavaHtmlNode("javaLinkTagWithLabel", defaultModelConfig)
+ }
+
+ @Test fun javaSupertypeLink() {
+ verifyJavaHtmlNodes("JavaSupertype", defaultModelConfig) { model ->
+ model.members.single().members.single { it.name == "JavaSupertype" }.members.filter { it.name == "Bar" }
+ }
+ }
+
+}
+
+class CommonHtmlFormatTest: BaseHtmlFormatTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt
deleted file mode 100644
index 062cf0b5..00000000
--- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-package org.jetbrains.dokka.tests
-
-import org.jetbrains.dokka.*
-import org.junit.Before
-import org.junit.Ignore
-import org.junit.Test
-
-@Ignore
-class KotlinWebSiteFormatTest: FileGeneratorTestCase() {
- override val formatService = KotlinWebsiteFormatService(fileGenerator, KotlinLanguageService(), listOf(), DokkaConsoleLogger)
-
- @Test fun sample() {
- verifyKWSNodeByName("sample", "foo")
- }
-
- @Test fun returnTag() {
- verifyKWSNodeByName("returnTag", "indexOf")
- }
-
- @Test fun overloadGroup() {
- verifyKWSNodeByName("overloadGroup", "magic")
- }
-
- @Test fun dataTags() {
- val module = buildMultiplePlatforms("dataTags")
- verifyMultiplatformPackage(module, "dataTags")
- }
-
- @Test fun dataTagsInGroupNode() {
- val path = "dataTagsInGroupNode"
- val module = buildMultiplePlatforms(path)
- verifyModelOutput(module, ".md", "testdata/format/website/$path/multiplatform.kt") { model, output ->
- buildPagesAndReadInto(
- listOfNotNull(model.members.single().members.find { it.kind == NodeKind.GroupNode }),
- output
- )
- }
- verifyMultiplatformPackage(module, path)
- }
-
- private fun verifyKWSNodeByName(fileName: String, name: String) {
- verifyOutput("testdata/format/website/$fileName.kt", ".md", format = "kotlin-website") { model, output ->
- buildPagesAndReadInto(
- model.members.single().members.filter { it.name == name },
- output
- )
- }
- }
-
- private fun buildMultiplePlatforms(path: String): DocumentationModule {
- val module = DocumentationModule("test")
- val options = DocumentationOptions(
- outputDir = "",
- outputFormat = "html",
- generateIndexPages = false,
- noStdlibLink = true,
- noJdkLink = true,
- languageVersion = null,
- apiVersion = null
- )
- appendDocumentation(module, contentRootFromPath("testdata/format/website/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options)
- appendDocumentation(module, contentRootFromPath("testdata/format/website/$path/jre7.kt"), defaultPlatforms = listOf("JVM", "JRE7"), options = options)
- appendDocumentation(module, contentRootFromPath("testdata/format/website/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options)
- return module
- }
-
- private fun verifyMultiplatformPackage(module: DocumentationModule, path: String) {
- verifyModelOutput(module, ".package.md", "testdata/format/website/$path/multiplatform.kt") { model, output ->
- buildPagesAndReadInto(model.members, output)
- }
- }
-
-}
diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt
index 8076fb92..ebab5f36 100644
--- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt
+++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt
@@ -1,38 +1,39 @@
package org.jetbrains.dokka.tests
import org.jetbrains.dokka.*
-import org.junit.Before
+import org.jetbrains.dokka.Generation.DocumentationMerger
import org.junit.Test
-class KotlinWebSiteHtmlFormatTest: FileGeneratorTestCase() {
+abstract class BaseKotlinWebSiteHtmlFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() {
+ val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
override val formatService = KotlinWebsiteHtmlFormatService(fileGenerator, KotlinLanguageService(), listOf(), EmptyHtmlTemplateService)
@Test fun dropImport() {
- verifyKWSNodeByName("dropImport", "foo")
+ verifyKWSNodeByName("dropImport", "foo", defaultModelConfig)
}
@Test fun sample() {
- verifyKWSNodeByName("sample", "foo")
+ verifyKWSNodeByName("sample", "foo", defaultModelConfig)
}
@Test fun sampleWithAsserts() {
- verifyKWSNodeByName("sampleWithAsserts", "a")
+ verifyKWSNodeByName("sampleWithAsserts", "a", defaultModelConfig)
}
@Test fun newLinesInSamples() {
- verifyKWSNodeByName("newLinesInSamples", "foo")
+ verifyKWSNodeByName("newLinesInSamples", "foo", defaultModelConfig)
}
@Test fun newLinesInImportList() {
- verifyKWSNodeByName("newLinesInImportList", "foo")
+ verifyKWSNodeByName("newLinesInImportList", "foo", defaultModelConfig)
}
@Test fun returnTag() {
- verifyKWSNodeByName("returnTag", "indexOf")
+ verifyKWSNodeByName("returnTag", "indexOf", defaultModelConfig)
}
@Test fun overloadGroup() {
- verifyKWSNodeByName("overloadGroup", "magic")
+ verifyKWSNodeByName("overloadGroup", "magic", defaultModelConfig)
}
@Test fun dataTags() {
@@ -52,27 +53,60 @@ class KotlinWebSiteHtmlFormatTest: FileGeneratorTestCase() {
verifyMultiplatformPackage(module, path)
}
- private fun verifyKWSNodeByName(fileName: String, name: String) {
- verifyOutput("testdata/format/website-html/$fileName.kt", ".html", format = "kotlin-website-html") { model, output ->
+ private fun verifyKWSNodeByName(fileName: String, name: String, modelConfig: ModelConfig) {
+ verifyOutput(
+ "testdata/format/website-html/$fileName.kt",
+ ".html",
+ ModelConfig(analysisPlatform = modelConfig.analysisPlatform, format = "kotlin-website-html")
+ ) { model, output ->
buildPagesAndReadInto(model.members.single().members.filter { it.name == name }, output)
}
}
private fun buildMultiplePlatforms(path: String): DocumentationModule {
- val module = DocumentationModule("test")
- val options = DocumentationOptions(
- outputDir = "",
- outputFormat = "kotlin-website-html",
- generateIndexPages = false,
+ val moduleName = "test"
+ val passConfiguration = PassConfigurationImpl(
noStdlibLink = true,
noJdkLink = true,
languageVersion = null,
apiVersion = null
)
- appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options)
- appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/jre7.kt"), defaultPlatforms = listOf("JVM", "JRE7"), options = options)
- appendDocumentation(module, contentRootFromPath("testdata/format/website-html/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options)
- return module
+
+ val dokkaConfiguration = DokkaConfigurationImpl(
+ outputDir = "",
+ format = "kotlin-website-html",
+ generateIndexPages = false,
+ passesConfigurations = listOf(
+ passConfiguration
+ )
+
+ )
+
+ val module1 = DocumentationModule(moduleName)
+ appendDocumentation(
+ module1, dokkaConfiguration, passConfiguration, ModelConfig(
+ roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jvm.kt")),
+ defaultPlatforms = listOf("JVM")
+ )
+ )
+
+ val module2 = DocumentationModule(moduleName)
+ appendDocumentation(
+ module2, dokkaConfiguration, passConfiguration, ModelConfig(
+ roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jre7.kt")),
+ defaultPlatforms = listOf("JVM", "JRE7")
+ )
+ )
+
+ val module3 = DocumentationModule(moduleName)
+ appendDocumentation(
+ module3, dokkaConfiguration, passConfiguration, ModelConfig(
+ roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/js.kt")),
+ defaultPlatforms = listOf("JS")
+ )
+ )
+
+ return DocumentationMerger(listOf(module1, module2, module3), DokkaConsoleLogger).merge()
}
private fun verifyMultiplatformPackage(module: DocumentationModule, path: String) {
@@ -82,3 +116,8 @@ class KotlinWebSiteHtmlFormatTest: FileGeneratorTestCase() {
}
}
+class JsKotlinWebSiteHtmlFormatTest: BaseKotlinWebSiteHtmlFormatTest(Platform.js)
+
+class JvmKotlinWebSiteHtmlFormatTest: BaseKotlinWebSiteHtmlFormatTest(Platform.jvm)
+
+class CommonKotlinWebSiteHtmlFormatTest: BaseKotlinWebSiteHtmlFormatTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/format/KotlinWebSiteRunnableSamplesFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteRunnableSamplesFormatTest.kt
deleted file mode 100644
index 453b1de8..00000000
--- a/core/src/test/kotlin/format/KotlinWebSiteRunnableSamplesFormatTest.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package org.jetbrains.dokka.tests
-
-import org.jetbrains.dokka.DokkaConsoleLogger
-import org.jetbrains.dokka.KotlinLanguageService
-import org.jetbrains.dokka.KotlinWebsiteRunnableSamplesFormatService
-import org.junit.Ignore
-import org.junit.Test
-
-@Ignore
-class KotlinWebSiteRunnableSamplesFormatTest {
-// private val kwsService = KotlinWebsiteRunnableSamplesFormatService(InMemoryLocationService, KotlinLanguageService(), listOf(), DokkaConsoleLogger)
-//
-//
-// @Test fun dropImport() {
-// verifyKWSNodeByName("dropImport", "foo")
-// }
-//
-// @Test fun sample() {
-// verifyKWSNodeByName("sample", "foo")
-// }
-//
-// @Test fun sampleWithAsserts() {
-// verifyKWSNodeByName("sampleWithAsserts", "a")
-// }
-//
-// @Test fun newLinesInSamples() {
-// verifyKWSNodeByName("newLinesInSamples", "foo")
-// }
-//
-// @Test fun newLinesInImportList() {
-// verifyKWSNodeByName("newLinesInImportList", "foo")
-// }
-//
-// private fun verifyKWSNodeByName(fileName: String, name: String) {
-// verifyOutput("testdata/format/website-samples/$fileName.kt", ".md", format = "kotlin-website-samples") { model, output ->
-// kwsService.createOutputBuilder(output, tempLocation).appendNodes(model.members.single().members.filter { it.name == name })
-// }
-// }
-}
diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt
index b078292b..4984e1d5 100644
--- a/core/src/test/kotlin/format/MarkdownFormatTest.kt
+++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt
@@ -1,52 +1,36 @@
package org.jetbrains.dokka.tests
import org.jetbrains.dokka.*
-import org.junit.Before
+import org.jetbrains.dokka.Generation.DocumentationMerger
import org.junit.Test
-class MarkdownFormatTest: FileGeneratorTestCase() {
+abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() {
override val formatService = MarkdownFormatService(fileGenerator, KotlinLanguageService(), listOf())
+ protected val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
+
@Test fun emptyDescription() {
- verifyMarkdownNode("emptyDescription")
+ verifyMarkdownNode("emptyDescription", defaultModelConfig)
}
@Test fun classWithCompanionObject() {
- verifyMarkdownNode("classWithCompanionObject")
+ verifyMarkdownNode("classWithCompanionObject", defaultModelConfig)
}
@Test fun annotations() {
- verifyMarkdownNode("annotations")
+ verifyMarkdownNode("annotations", defaultModelConfig)
}
@Test fun annotationClass() {
- verifyMarkdownNode("annotationClass", withKotlinRuntime = true)
- verifyMarkdownPackage("annotationClass", withKotlinRuntime = true)
- }
-
- @Test fun exceptionClass() {
- verifyMarkdownNode("exceptionClass", withKotlinRuntime = true)
- verifyMarkdownPackage("exceptionClass", withKotlinRuntime = true)
- }
-
- @Test fun annotationParams() {
- verifyMarkdownNode("annotationParams", withKotlinRuntime = true)
- }
-
- @Test fun extensions() {
- verifyOutput("testdata/format/extensions.kt", ".package.md") { model, output ->
- buildPagesAndReadInto(model.members, output)
- }
- verifyOutput("testdata/format/extensions.kt", ".class.md") { model, output ->
- buildPagesAndReadInto(model.members.single().members, output)
- }
+ verifyMarkdownNode("annotationClass", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
+ verifyMarkdownPackage("annotationClass", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun enumClass() {
- verifyOutput("testdata/format/enumClass.kt", ".md") { model, output ->
+ verifyOutput("testdata/format/enumClass.kt", ".md", defaultModelConfig) { model, output ->
buildPagesAndReadInto(model.members.single().members, output)
}
- verifyOutput("testdata/format/enumClass.kt", ".value.md") { model, output ->
+ verifyOutput("testdata/format/enumClass.kt", ".value.md", defaultModelConfig) { model, output ->
val enumClassNode = model.members.single().members[0]
buildPagesAndReadInto(
enumClassNode.members.filter { it.name == "LOCAL_CONTINUE_AND_BREAK" },
@@ -56,235 +40,187 @@ class MarkdownFormatTest: FileGeneratorTestCase() {
}
@Test fun varargsFunction() {
- verifyMarkdownNode("varargsFunction")
+ verifyMarkdownNode("varargsFunction", defaultModelConfig)
}
@Test fun overridingFunction() {
- verifyMarkdownNodes("overridingFunction") { model->
+ verifyMarkdownNodes("overridingFunction", defaultModelConfig) { model->
val classMembers = model.members.single().members.first { it.name == "D" }.members
classMembers.filter { it.name == "f" }
}
}
@Test fun propertyVar() {
- verifyMarkdownNode("propertyVar")
+ verifyMarkdownNode("propertyVar", defaultModelConfig)
}
@Test fun functionWithDefaultParameter() {
- verifyMarkdownNode("functionWithDefaultParameter")
+ verifyMarkdownNode("functionWithDefaultParameter", defaultModelConfig)
}
@Test fun accessor() {
- verifyMarkdownNodes("accessor") { model ->
+ verifyMarkdownNodes("accessor", defaultModelConfig) { model ->
model.members.single().members.first { it.name == "C" }.members.filter { it.name == "x" }
}
}
@Test fun paramTag() {
- verifyMarkdownNode("paramTag")
+ verifyMarkdownNode("paramTag", defaultModelConfig)
}
@Test fun throwsTag() {
- verifyMarkdownNode("throwsTag")
+ verifyMarkdownNode("throwsTag", defaultModelConfig)
}
@Test fun typeParameterBounds() {
- verifyMarkdownNode("typeParameterBounds")
+ verifyMarkdownNode("typeParameterBounds", defaultModelConfig)
}
@Test fun typeParameterVariance() {
- verifyMarkdownNode("typeParameterVariance")
+ verifyMarkdownNode("typeParameterVariance", defaultModelConfig)
}
@Test fun typeProjectionVariance() {
- verifyMarkdownNode("typeProjectionVariance")
- }
-
- @Test fun javadocHtml() {
- verifyJavaMarkdownNode("javadocHtml")
- }
-
- @Test fun javaCodeLiteralTags() {
- verifyJavaMarkdownNode("javaCodeLiteralTags")
- }
-
- @Test fun javaCodeInParam() {
- verifyJavaMarkdownNodes("javaCodeInParam") {
- selectNodes(it) {
- subgraphOf(RefKind.Member)
- withKind(NodeKind.Function)
- }
- }
- }
-
- @Test fun javaSpaceInAuthor() {
- verifyJavaMarkdownNode("javaSpaceInAuthor")
- }
-
- @Test fun nullability() {
- verifyMarkdownNode("nullability")
- }
-
- @Test fun operatorOverloading() {
- verifyMarkdownNodes("operatorOverloading") { model->
- model.members.single().members.single { it.name == "C" }.members.filter { it.name == "plus" }
- }
- }
-
- @Test fun javadocOrderedList() {
- verifyJavaMarkdownNodes("javadocOrderedList") { model ->
- model.members.single().members.filter { it.name == "Bar" }
- }
+ verifyMarkdownNode("typeProjectionVariance", defaultModelConfig)
}
@Test fun codeBlockNoHtmlEscape() {
- verifyMarkdownNodeByName("codeBlockNoHtmlEscape", "hackTheArithmetic")
+ verifyMarkdownNodeByName("codeBlockNoHtmlEscape", "hackTheArithmetic", defaultModelConfig)
}
@Test fun companionObjectExtension() {
- verifyMarkdownNodeByName("companionObjectExtension", "Foo")
+ verifyMarkdownNodeByName("companionObjectExtension", "Foo", defaultModelConfig)
}
@Test fun starProjection() {
- verifyMarkdownNode("starProjection")
+ verifyMarkdownNode("starProjection", defaultModelConfig)
}
@Test fun extensionFunctionParameter() {
- verifyMarkdownNode("extensionFunctionParameter")
+ verifyMarkdownNode("extensionFunctionParameter", defaultModelConfig)
}
@Test fun summarizeSignatures() {
- verifyMarkdownNodes("summarizeSignatures") { model -> model.members }
- }
-
- @Test fun summarizeSignaturesProperty() {
- verifyMarkdownNodes("summarizeSignaturesProperty") { model -> model.members }
+ verifyMarkdownNodes("summarizeSignatures", defaultModelConfig) { model -> model.members }
}
@Test fun reifiedTypeParameter() {
- verifyMarkdownNode("reifiedTypeParameter", withKotlinRuntime = true)
+ verifyMarkdownNode("reifiedTypeParameter", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun suspendInlineFunctionOrder() {
- verifyMarkdownNode("suspendInlineFunction", withKotlinRuntime = true)
+ verifyMarkdownNode("suspendInlineFunction", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun inlineSuspendFunctionOrderChanged() {
- verifyMarkdownNode("inlineSuspendFunction", withKotlinRuntime = true)
+ verifyMarkdownNode("inlineSuspendFunction", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun annotatedTypeParameter() {
- verifyMarkdownNode("annotatedTypeParameter", withKotlinRuntime = true)
+ verifyMarkdownNode("annotatedTypeParameter", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun inheritedMembers() {
- verifyMarkdownNodeByName("inheritedMembers", "Bar")
+ verifyMarkdownNodeByName("inheritedMembers", "Bar", defaultModelConfig)
}
@Test fun inheritedExtensions() {
- verifyMarkdownNodeByName("inheritedExtensions", "Bar")
+ verifyMarkdownNodeByName("inheritedExtensions", "Bar", defaultModelConfig)
}
@Test fun genericInheritedExtensions() {
- verifyMarkdownNodeByName("genericInheritedExtensions", "Bar")
+ verifyMarkdownNodeByName("genericInheritedExtensions", "Bar", defaultModelConfig)
}
@Test fun arrayAverage() {
- verifyMarkdownNodeByName("arrayAverage", "XArray")
+ verifyMarkdownNodeByName("arrayAverage", "XArray", defaultModelConfig)
}
@Test fun multipleTypeParameterConstraints() {
- verifyMarkdownNode("multipleTypeParameterConstraints", withKotlinRuntime = true)
+ verifyMarkdownNode("multipleTypeParameterConstraints", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun inheritedCompanionObjectProperties() {
- verifyMarkdownNodeByName("inheritedCompanionObjectProperties", "C")
+ verifyMarkdownNodeByName("inheritedCompanionObjectProperties", "C", defaultModelConfig)
}
@Test fun shadowedExtensionFunctions() {
- verifyMarkdownNodeByName("shadowedExtensionFunctions", "Bar")
+ verifyMarkdownNodeByName("shadowedExtensionFunctions", "Bar", defaultModelConfig)
}
@Test fun inapplicableExtensionFunctions() {
- verifyMarkdownNodeByName("inapplicableExtensionFunctions", "Bar")
+ verifyMarkdownNodeByName("inapplicableExtensionFunctions", "Bar", defaultModelConfig)
}
@Test fun receiverParameterTypeBound() {
- verifyMarkdownNodeByName("receiverParameterTypeBound", "Foo")
+ verifyMarkdownNodeByName("receiverParameterTypeBound", "Foo", defaultModelConfig)
}
@Test fun extensionWithDocumentedReceiver() {
- verifyMarkdownNodes("extensionWithDocumentedReceiver") { model ->
+ verifyMarkdownNodes("extensionWithDocumentedReceiver", defaultModelConfig) { model ->
model.members.single().members.single().members.filter { it.name == "fn" }
}
}
- @Test fun jdkLinks() {
- verifyMarkdownNode("jdkLinks", withKotlinRuntime = true)
- }
-
@Test fun codeBlock() {
- verifyMarkdownNode("codeBlock")
+ verifyMarkdownNode("codeBlock", defaultModelConfig)
}
@Test fun exclInCodeBlock() {
- verifyMarkdownNodeByName("exclInCodeBlock", "foo")
+ verifyMarkdownNodeByName("exclInCodeBlock", "foo", defaultModelConfig)
}
@Test fun backtickInCodeBlock() {
- verifyMarkdownNodeByName("backtickInCodeBlock", "foo")
+ verifyMarkdownNodeByName("backtickInCodeBlock", "foo", defaultModelConfig)
}
@Test fun qualifiedNameLink() {
- verifyMarkdownNodeByName("qualifiedNameLink", "foo", withKotlinRuntime = true)
+ verifyMarkdownNodeByName("qualifiedNameLink", "foo",
+ ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
}
@Test fun functionalTypeWithNamedParameters() {
- verifyMarkdownNode("functionalTypeWithNamedParameters")
+ verifyMarkdownNode("functionalTypeWithNamedParameters", defaultModelConfig)
}
@Test fun typeAliases() {
- verifyMarkdownNode("typeAliases")
- verifyMarkdownPackage("typeAliases")
- }
-
- @Test fun sampleByFQName() {
- verifyMarkdownNode("sampleByFQName")
+ verifyMarkdownNode("typeAliases", defaultModelConfig)
+ verifyMarkdownPackage("typeAliases", defaultModelConfig)
}
@Test fun sampleByShortName() {
- verifyMarkdownNode("sampleByShortName")
+ verifyMarkdownNode("sampleByShortName", defaultModelConfig)
}
@Test fun suspendParam() {
- verifyMarkdownNode("suspendParam")
- verifyMarkdownPackage("suspendParam")
+ verifyMarkdownNode("suspendParam", defaultModelConfig)
+ verifyMarkdownPackage("suspendParam", defaultModelConfig)
}
@Test fun sinceKotlin() {
- verifyMarkdownNode("sinceKotlin")
- verifyMarkdownPackage("sinceKotlin")
+ verifyMarkdownNode("sinceKotlin", defaultModelConfig)
+ verifyMarkdownPackage("sinceKotlin", defaultModelConfig)
}
@Test fun sinceKotlinWide() {
- verifyMarkdownPackage("sinceKotlinWide")
+ verifyMarkdownPackage("sinceKotlinWide", defaultModelConfig)
}
@Test fun dynamicType() {
- verifyMarkdownNode("dynamicType")
+ verifyMarkdownNode("dynamicType", defaultModelConfig)
}
@Test fun dynamicExtension() {
- verifyMarkdownNodes("dynamicExtension") { model -> model.members.single().members.filter { it.name == "Foo" } }
+ verifyMarkdownNodes("dynamicExtension", defaultModelConfig) { model -> model.members.single().members.filter { it.name == "Foo" } }
}
@Test fun memberExtension() {
- verifyMarkdownNodes("memberExtension") { model -> model.members.single().members.filter { it.name == "Foo" } }
+ verifyMarkdownNodes("memberExtension", defaultModelConfig) { model -> model.members.single().members.filter { it.name == "Foo" } }
}
@Test fun renderFunctionalTypeInParenthesisWhenItIsReceiver() {
- verifyMarkdownNode("renderFunctionalTypeInParenthesisWhenItIsReceiver")
+ verifyMarkdownNode("renderFunctionalTypeInParenthesisWhenItIsReceiver", defaultModelConfig)
}
@Test fun multiplePlatforms() {
@@ -321,16 +257,29 @@ class MarkdownFormatTest: FileGeneratorTestCase() {
@Test fun packagePlatformsWithExtExtensions() {
val path = "multiplatform/packagePlatformsWithExtExtensions"
val module = DocumentationModule("test")
- val options = DocumentationOptions(
- outputDir = "",
- outputFormat = "html",
- generateIndexPages = false,
+ val passConfiguration = PassConfigurationImpl(
noStdlibLink = true,
noJdkLink = true,
languageVersion = null,
apiVersion = null
)
- appendDocumentation(module, contentRootFromPath("testdata/format/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), withKotlinRuntime = true, options = options)
+
+ val dokkaConfiguration = DokkaConfigurationImpl(
+ outputDir = "",
+ format = "html",
+ generateIndexPages = false,
+ passesConfigurations = listOf(
+ passConfiguration
+ )
+ )
+
+ appendDocumentation(module, dokkaConfiguration, passConfiguration, ModelConfig(
+ roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")),
+ defaultPlatforms = listOf("JVM"),
+ withKotlinRuntime = true,
+ analysisPlatform = analysisPlatform
+ )
+ )
verifyMultiplatformIndex(module, path)
verifyMultiplatformPackage(module, path)
}
@@ -359,115 +308,120 @@ class MarkdownFormatTest: FileGeneratorTestCase() {
val module = buildMultiplePlatforms(path)
verifyModelOutput(module, ".md", "testdata/format/$path/multiplatform.kt") { model, output ->
buildPagesAndReadInto(
- listOfNotNull(model.members.single().members.find { it.kind == NodeKind.GroupNode }?.member(NodeKind.Class)?.member(NodeKind.Function)),
+ listOfNotNull(model.members.single().members.find { it.kind == NodeKind.GroupNode }?.member(NodeKind.Function)),
output
)
}
}
@Test fun linksInEmphasis() {
- verifyMarkdownNode("linksInEmphasis")
+ verifyMarkdownNode("linksInEmphasis", defaultModelConfig)
}
@Test fun linksInStrong() {
- verifyMarkdownNode("linksInStrong")
+ verifyMarkdownNode("linksInStrong", defaultModelConfig)
}
@Test fun linksInHeaders() {
- verifyMarkdownNode("linksInHeaders")
+ verifyMarkdownNode("linksInHeaders", defaultModelConfig)
}
@Test fun tokensInEmphasis() {
- verifyMarkdownNode("tokensInEmphasis")
+ verifyMarkdownNode("tokensInEmphasis", defaultModelConfig)
}
@Test fun tokensInStrong() {
- verifyMarkdownNode("tokensInStrong")
+ verifyMarkdownNode("tokensInStrong", defaultModelConfig)
}
@Test fun tokensInHeaders() {
- verifyMarkdownNode("tokensInHeaders")
+ verifyMarkdownNode("tokensInHeaders", defaultModelConfig)
}
@Test fun unorderedLists() {
- verifyMarkdownNode("unorderedLists")
+ verifyMarkdownNode("unorderedLists", defaultModelConfig)
}
@Test fun nestedLists() {
- verifyMarkdownNode("nestedLists")
+ verifyMarkdownNode("nestedLists", defaultModelConfig)
}
@Test fun referenceLink() {
- verifyMarkdownNode("referenceLink")
+ verifyMarkdownNode("referenceLink", defaultModelConfig)
}
@Test fun externalReferenceLink() {
- verifyMarkdownNode("externalReferenceLink")
+ verifyMarkdownNode("externalReferenceLink", defaultModelConfig)
}
@Test fun newlineInTableCell() {
- verifyMarkdownPackage("newlineInTableCell")
+ verifyMarkdownPackage("newlineInTableCell", defaultModelConfig)
}
@Test fun indentedCodeBlock() {
- verifyMarkdownNode("indentedCodeBlock")
+ verifyMarkdownNode("indentedCodeBlock", defaultModelConfig)
}
@Test fun receiverReference() {
- verifyMarkdownNode("receiverReference")
+ verifyMarkdownNode("receiverReference", defaultModelConfig)
}
@Test fun extensionScope() {
- verifyMarkdownNodeByName("extensionScope", "test")
+ verifyMarkdownNodeByName("extensionScope", "test", defaultModelConfig)
}
@Test fun typeParameterReference() {
- verifyMarkdownNode("typeParameterReference")
+ verifyMarkdownNode("typeParameterReference", defaultModelConfig)
}
@Test fun notPublishedTypeAliasAutoExpansion() {
- verifyMarkdownNodeByName("notPublishedTypeAliasAutoExpansion", "foo", includeNonPublic = false)
+ verifyMarkdownNodeByName("notPublishedTypeAliasAutoExpansion", "foo", ModelConfig(
+ analysisPlatform = analysisPlatform,
+ includeNonPublic = false
+ ))
}
@Test fun companionImplements() {
- verifyMarkdownNodeByName("companionImplements", "Foo")
- }
-
- @Test fun enumRef() {
- verifyMarkdownNode("enumRef")
- }
-
- @Test fun inheritedLink() {
- val filePath = "testdata/format/inheritedLink"
- verifyOutput(
- arrayOf(
- contentRootFromPath("$filePath.kt"),
- contentRootFromPath("$filePath.1.kt")
- ),
- ".md",
- withJdk = true,
- withKotlinRuntime = true,
- includeNonPublic = false
- ) { model, output ->
- buildPagesAndReadInto(model.members.single { it.name == "p2" }.members.single().members, output)
- }
+ verifyMarkdownNodeByName("companionImplements", "Foo", defaultModelConfig)
}
private fun buildMultiplePlatforms(path: String): DocumentationModule {
- val module = DocumentationModule("test")
- val options = DocumentationOptions(
- outputDir = "",
- outputFormat = "html",
- generateIndexPages = false,
+ val moduleName = "test"
+ val passConfiguration = PassConfigurationImpl(
noStdlibLink = true,
noJdkLink = true,
languageVersion = null,
apiVersion = null
)
- appendDocumentation(module, contentRootFromPath("testdata/format/$path/jvm.kt"), defaultPlatforms = listOf("JVM"), options = options)
- appendDocumentation(module, contentRootFromPath("testdata/format/$path/js.kt"), defaultPlatforms = listOf("JS"), options = options)
- return module
+ val dokkaConfiguration = DokkaConfigurationImpl(
+ outputDir = "",
+ format = "html",
+ generateIndexPages = false,
+ passesConfigurations = listOf(
+ passConfiguration
+ )
+
+ )
+ val module1 = DocumentationModule(moduleName)
+ appendDocumentation(
+ module1, dokkaConfiguration, passConfiguration, ModelConfig(
+ roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")),
+ defaultPlatforms = listOf("JVM"),
+ analysisPlatform = Platform.jvm
+ )
+ )
+
+ val module2 = DocumentationModule(moduleName)
+ appendDocumentation(
+ module2, dokkaConfiguration, passConfiguration, ModelConfig(
+ roots = arrayOf(contentRootFromPath("testdata/format/$path/js.kt")),
+ defaultPlatforms = listOf("JS"),
+ analysisPlatform = Platform.js
+ )
+ )
+
+ return DocumentationMerger(listOf(module1, module2), DokkaConsoleLogger).merge()
}
private fun verifyMultiplatformPackage(module: DocumentationModule, path: String) {
@@ -486,52 +440,49 @@ class MarkdownFormatTest: FileGeneratorTestCase() {
}
@Test fun blankLineInsideCodeBlock() {
- verifyMarkdownNode("blankLineInsideCodeBlock")
+ verifyMarkdownNode("blankLineInsideCodeBlock", defaultModelConfig)
}
- private fun verifyMarkdownPackage(fileName: String, withKotlinRuntime: Boolean = false) {
- verifyOutput("testdata/format/$fileName.kt", ".package.md", withKotlinRuntime = withKotlinRuntime) { model, output ->
+ protected fun verifyMarkdownPackage(fileName: String, modelConfig: ModelConfig = ModelConfig()) {
+ verifyOutput("testdata/format/$fileName.kt", ".package.md", modelConfig) { model, output ->
buildPagesAndReadInto(model.members, output)
}
}
- private fun verifyMarkdownNode(fileName: String, withKotlinRuntime: Boolean = false) {
- verifyMarkdownNodes(fileName, withKotlinRuntime) { model -> model.members.single().members }
+ protected fun verifyMarkdownNode(fileName: String, modelConfig: ModelConfig = ModelConfig()) {
+ verifyMarkdownNodes(fileName, modelConfig) { model -> model.members.single().members }
}
- private fun verifyMarkdownNodes(
+ protected fun verifyMarkdownNodes(
fileName: String,
- withKotlinRuntime: Boolean = false,
- includeNonPublic: Boolean = true,
+ modelConfig: ModelConfig = ModelConfig(),
nodeFilter: (DocumentationModule) -> List<DocumentationNode>
) {
verifyOutput(
"testdata/format/$fileName.kt",
".md",
- withKotlinRuntime = withKotlinRuntime,
- includeNonPublic = includeNonPublic
+ modelConfig
) { model, output ->
buildPagesAndReadInto(nodeFilter(model), output)
}
}
- private fun verifyJavaMarkdownNode(fileName: String, withKotlinRuntime: Boolean = false) {
- verifyJavaMarkdownNodes(fileName, withKotlinRuntime) { model -> model.members.single().members }
+ protected fun verifyJavaMarkdownNode(fileName: String, modelConfig: ModelConfig = ModelConfig()) {
+ verifyJavaMarkdownNodes(fileName, modelConfig) { model -> model.members.single().members }
}
- private fun verifyJavaMarkdownNodes(fileName: String, withKotlinRuntime: Boolean = false, nodeFilter: (DocumentationModule) -> List<DocumentationNode>) {
- verifyJavaOutput("testdata/format/$fileName.java", ".md", withKotlinRuntime = withKotlinRuntime) { model, output ->
+ protected fun verifyJavaMarkdownNodes(fileName: String, modelConfig: ModelConfig = ModelConfig(), nodeFilter: (DocumentationModule) -> List<DocumentationNode>) {
+ verifyJavaOutput("testdata/format/$fileName.java", ".md", modelConfig) { model, output ->
buildPagesAndReadInto(nodeFilter(model), output)
}
}
- private fun verifyMarkdownNodeByName(
+ protected fun verifyMarkdownNodeByName(
fileName: String,
name: String,
- withKotlinRuntime: Boolean = false,
- includeNonPublic: Boolean = true
+ modelConfig: ModelConfig = ModelConfig()
) {
- verifyMarkdownNodes(fileName, withKotlinRuntime, includeNonPublic) { model->
+ verifyMarkdownNodes(fileName, modelConfig) { model->
val nodesWithName = model.members.single().members.filter { it.name == name }
if (nodesWithName.isEmpty()) {
throw IllegalArgumentException("Found no nodes named $name")
@@ -541,6 +492,124 @@ class MarkdownFormatTest: FileGeneratorTestCase() {
}
@Test fun nullableTypeParameterFunction() {
- verifyMarkdownNode("nullableTypeParameterFunction", withKotlinRuntime = true)
+ verifyMarkdownNode("nullableTypeParameterFunction", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
+ }
+}
+
+class JSMarkdownFormatTest: BaseMarkdownFormatTest(Platform.js)
+
+class JVMMarkdownFormatTest: BaseMarkdownFormatTest(Platform.jvm) {
+
+ @Test
+ fun enumRef() {
+ verifyMarkdownNode("enumRef", defaultModelConfig)
+ }
+
+ @Test
+ fun javaCodeLiteralTags() {
+ verifyJavaMarkdownNode("javaCodeLiteralTags", defaultModelConfig)
+ }
+
+ @Test
+ fun nullability() {
+ verifyMarkdownNode("nullability", defaultModelConfig)
+ }
+
+ @Test
+ fun exceptionClass() {
+ verifyMarkdownNode(
+ "exceptionClass", ModelConfig(
+ analysisPlatform = analysisPlatform,
+ withKotlinRuntime = true
+ )
+ )
+ verifyMarkdownPackage(
+ "exceptionClass", ModelConfig(
+ analysisPlatform = analysisPlatform,
+ withKotlinRuntime = true
+ )
+ )
+ }
+
+ @Test
+ fun operatorOverloading() {
+ verifyMarkdownNodes("operatorOverloading", defaultModelConfig) { model->
+ model.members.single().members.single { it.name == "C" }.members.filter { it.name == "plus" }
+ }
+ }
+
+ @Test
+ fun extensions() {
+ verifyOutput("testdata/format/extensions.kt", ".package.md", defaultModelConfig) { model, output ->
+ buildPagesAndReadInto(model.members, output)
+ }
+ verifyOutput("testdata/format/extensions.kt", ".class.md", defaultModelConfig) { model, output ->
+ buildPagesAndReadInto(model.members.single().members, output)
+ }
+ }
+
+ @Test
+ fun summarizeSignaturesProperty() {
+ verifyMarkdownNodes("summarizeSignaturesProperty", defaultModelConfig) { model -> model.members }
+ }
+
+ @Test
+ fun javaSpaceInAuthor() {
+ verifyJavaMarkdownNode("javaSpaceInAuthor", defaultModelConfig)
+ }
+
+ @Test
+ fun javaCodeInParam() {
+ verifyJavaMarkdownNodes("javaCodeInParam", defaultModelConfig) {
+ selectNodes(it) {
+ subgraphOf(RefKind.Member)
+ withKind(NodeKind.Function)
+ }
+ }
+ }
+
+ @Test
+ fun annotationParams() {
+ verifyMarkdownNode("annotationParams", ModelConfig(analysisPlatform = analysisPlatform, withKotlinRuntime = true))
+ }
+
+ @Test fun inheritedLink() {
+ val filePath = "testdata/format/inheritedLink"
+ verifyOutput(
+ filePath,
+ ".md",
+ ModelConfig(
+ roots = arrayOf(
+ contentRootFromPath("$filePath.kt"),
+ contentRootFromPath("$filePath.1.kt")
+ ),
+ withJdk = true,
+ withKotlinRuntime = true,
+ includeNonPublic = false,
+ analysisPlatform = analysisPlatform
+
+ )
+ ) { model, output ->
+ buildPagesAndReadInto(model.members.single { it.name == "p2" }.members.single().members, output)
+ }
+ }
+
+ @Test
+ fun javadocOrderedList() {
+ verifyJavaMarkdownNodes("javadocOrderedList", defaultModelConfig) { model ->
+ model.members.single().members.filter { it.name == "Bar" }
+ }
+ }
+
+ @Test
+ fun jdkLinks() {
+ verifyMarkdownNode("jdkLinks", ModelConfig(withKotlinRuntime = true, analysisPlatform = analysisPlatform))
+ }
+
+ @Test
+ fun javadocHtml() {
+ verifyJavaMarkdownNode("javadocHtml", defaultModelConfig)
}
}
+
+class CommonMarkdownFormatTest: BaseMarkdownFormatTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/issues/IssuesTest.kt b/core/src/test/kotlin/issues/IssuesTest.kt
index 625d7e46..da5acd6e 100644
--- a/core/src/test/kotlin/issues/IssuesTest.kt
+++ b/core/src/test/kotlin/issues/IssuesTest.kt
@@ -2,17 +2,19 @@ package issues
import org.jetbrains.dokka.DocumentationNode
import org.jetbrains.dokka.NodeKind
-import org.jetbrains.dokka.tests.toTestString
-import org.jetbrains.dokka.tests.verifyModel
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.tests.ModelConfig
+import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel
import org.junit.Test
import kotlin.test.assertEquals
-
-class IssuesTest {
+abstract class BaseIssuesTest(val analysisPlatform: Platform) {
+ val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test
fun errorClasses() {
- verifyModel("testdata/issues/errorClasses.kt", withJdk = true, withKotlinRuntime = true) { model ->
+ checkSourceExistsAndVerifyModel("testdata/issues/errorClasses.kt",
+ modelConfig = ModelConfig(analysisPlatform = analysisPlatform, withJdk = true, withKotlinRuntime = true)) { model ->
val cls = model.members.single().members.single()
fun DocumentationNode.returnType() = this.details.find { it.kind == NodeKind.Type }?.name
@@ -26,3 +28,7 @@ class IssuesTest {
}
}
}
+
+class JSIssuesTest: BaseIssuesTest(Platform.js)
+class JVMIssuesTest: BaseIssuesTest(Platform.jvm)
+class CommonIssuesTest: BaseIssuesTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt
index 6adbe7a0..1c4dd258 100644
--- a/core/src/test/kotlin/javadoc/JavadocTest.kt
+++ b/core/src/test/kotlin/javadoc/JavadocTest.kt
@@ -3,15 +3,19 @@ package org.jetbrains.dokka.javadoc
import com.sun.javadoc.Tag
import com.sun.javadoc.Type
import org.jetbrains.dokka.DokkaConsoleLogger
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.tests.ModelConfig
import org.jetbrains.dokka.tests.assertEqualsIgnoringSeparators
-import org.jetbrains.dokka.tests.verifyModel
+import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel
import org.junit.Assert.*
import org.junit.Test
import java.lang.reflect.Modifier.*
class JavadocTest {
+ val defaultModelConfig = ModelConfig(analysisPlatform = Platform.jvm)
+
@Test fun testTypes() {
- verifyJavadoc("testdata/javadoc/types.kt", withJdk = true) { doc ->
+ verifyJavadoc("testdata/javadoc/types.kt", ModelConfig(analysisPlatform = Platform.jvm, withJdk = true)) { doc ->
val classDoc = doc.classNamed("foo.TypesKt")!!
val method = classDoc.methods().find { it.name() == "foo" }!!
@@ -27,7 +31,7 @@ class JavadocTest {
}
@Test fun testObject() {
- verifyJavadoc("testdata/javadoc/obj.kt") { doc ->
+ verifyJavadoc("testdata/javadoc/obj.kt", defaultModelConfig) { doc ->
val classDoc = doc.classNamed("foo.O")
assertNotNull(classDoc)
@@ -40,7 +44,10 @@ class JavadocTest {
}
@Test fun testException() {
- verifyJavadoc("testdata/javadoc/exception.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/exception.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val classDoc = doc.classNamed("foo.MyException")!!
val member = classDoc.methods().find { it.name() == "foo" }
assertEquals(classDoc, member!!.containingClass())
@@ -48,7 +55,10 @@ class JavadocTest {
}
@Test fun testByteArray() {
- verifyJavadoc("testdata/javadoc/bytearr.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/bytearr.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val classDoc = doc.classNamed("foo.ByteArray")!!
assertNotNull(classDoc.asClassDoc())
@@ -58,7 +68,10 @@ class JavadocTest {
}
@Test fun testStringArray() {
- verifyJavadoc("testdata/javadoc/stringarr.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/stringarr.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val classDoc = doc.classNamed("foo.Foo")!!
assertNotNull(classDoc.asClassDoc())
@@ -71,7 +84,10 @@ class JavadocTest {
}
@Test fun testJvmName() {
- verifyJavadoc("testdata/javadoc/jvmname.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/jvmname.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val classDoc = doc.classNamed("foo.Apple")!!
assertNotNull(classDoc.asClassDoc())
@@ -81,7 +97,10 @@ class JavadocTest {
}
@Test fun testLinkWithParam() {
- verifyJavadoc("testdata/javadoc/paramlink.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/paramlink.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val classDoc = doc.classNamed("demo.Apple")!!
assertNotNull(classDoc.asClassDoc())
val tags = classDoc.inlineTags().filterIsInstance<SeeTagAdapter>()
@@ -92,7 +111,10 @@ class JavadocTest {
}
@Test fun testInternalVisibility() {
- verifyJavadoc("testdata/javadoc/internal.kt", withKotlinRuntime = true, includeNonPublic = false) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/internal.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true, includeNonPublic = false)
+ ) { doc ->
val classDoc = doc.classNamed("foo.Person")!!
val constructors = classDoc.constructors()
assertEquals(1, constructors.size)
@@ -101,7 +123,10 @@ class JavadocTest {
}
@Test fun testSuppress() {
- verifyJavadoc("testdata/javadoc/suppress.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/suppress.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
assertNull(doc.classNamed("Some"))
assertNull(doc.classNamed("SomeAgain"))
assertNull(doc.classNamed("Interface"))
@@ -112,7 +137,10 @@ class JavadocTest {
}
@Test fun testTypeAliases() {
- verifyJavadoc("testdata/javadoc/typealiases.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/typealiases.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
assertNull(doc.classNamed("B"))
assertNull(doc.classNamed("D"))
@@ -121,13 +149,17 @@ class JavadocTest {
.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())
+ assertEquals("? super A, C",
+ methodParamType.asParameterizedType().typeArguments().joinToString(transform = Type::qualifiedTypeName)
+ )
}
}
@Test fun testKDocKeywordsOnMethod() {
- verifyJavadoc("testdata/javadoc/kdocKeywordsOnMethod.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/kdocKeywordsOnMethod.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val method = doc.classNamed("KdocKeywordsOnMethodKt")!!.methods()[0]
assertEquals("@return [ContentText(text=value of a)]", method.tags("return").first().text())
assertEquals("@param a [ContentText(text=Some string)]", method.paramTags().first().text())
@@ -137,7 +169,10 @@ class JavadocTest {
@Test
fun testBlankLineInsideCodeBlock() {
- verifyJavadoc("testdata/javadoc/blankLineInsideCodeBlock.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc(
+ "testdata/javadoc/blankLineInsideCodeBlock.kt",
+ ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)
+ ) { doc ->
val method = doc.classNamed("BlankLineInsideCodeBlockKt")!!.methods()[0]
val text = method.inlineTags().joinToString(separator = "", transform = Tag::text)
assertEqualsIgnoringSeparators("""
@@ -154,7 +189,7 @@ class JavadocTest {
@Test
fun testCompanionMethodReference() {
- verifyJavadoc("testdata/javadoc/companionMethodReference.kt") { doc ->
+ verifyJavadoc("testdata/javadoc/companionMethodReference.kt", defaultModelConfig) { doc ->
val classDoc = doc.classNamed("foo.TestClass")!!
val tag = classDoc.inlineTags().filterIsInstance<SeeMethodTagAdapter>().first()
assertEquals("TestClass.Companion", tag.referencedClassName())
@@ -180,7 +215,7 @@ class JavadocTest {
@Test
fun shouldHaveValidVisibilityModifiers() {
- verifyJavadoc("testdata/javadoc/visibilityModifiers.kt", withKotlinRuntime = true) { doc ->
+ verifyJavadoc("testdata/javadoc/visibilityModifiers.kt", ModelConfig(analysisPlatform = Platform.jvm, withKotlinRuntime = true)) { doc ->
val classDoc = doc.classNamed("foo.Apple")!!
val methods = classDoc.methods()
@@ -270,14 +305,27 @@ class JavadocTest {
}
}
+ @Test
+ fun functionParameters() {
+ verifyJavadoc("testdata/javadoc/functionParameters.java") { doc ->
+ val tags = doc.classNamed("bar.Foo")!!.methods().first().paramTags()
+ assertEquals((tags.first() as ParamTagAdapter).content.size, 1)
+ assertEquals((tags[1] as ParamTagAdapter).content.size, 1)
+ }
+ }
private fun verifyJavadoc(name: String,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
- includeNonPublic: Boolean = true,
+ modelConfig: ModelConfig = ModelConfig(),
callback: (ModuleNodeAdapter) -> Unit) {
- verifyModel(name, format = "javadoc", withJdk = withJdk, withKotlinRuntime = withKotlinRuntime, includeNonPublic = includeNonPublic) { model ->
+ checkSourceExistsAndVerifyModel(name,
+ ModelConfig(
+ analysisPlatform = Platform.jvm,
+ format = "javadoc",
+ withJdk = modelConfig.withJdk,
+ withKotlinRuntime = modelConfig.withKotlinRuntime,
+ includeNonPublic = modelConfig.includeNonPublic
+ )) { model ->
val doc = ModuleNodeAdapter(model, StandardReporter(DokkaConsoleLogger), "")
callback(doc)
}
diff --git a/core/src/test/kotlin/model/ClassTest.kt b/core/src/test/kotlin/model/ClassTest.kt
index ea586041..35ec1d09 100644
--- a/core/src/test/kotlin/model/ClassTest.kt
+++ b/core/src/test/kotlin/model/ClassTest.kt
@@ -2,14 +2,17 @@ package org.jetbrains.dokka.tests
import org.jetbrains.dokka.Content
import org.jetbrains.dokka.NodeKind
+import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.RefKind
+import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
-class ClassTest {
+abstract class BaseClassTest(val analysisPlatform: Platform) {
+ protected val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test fun emptyClass() {
- verifyModel("testdata/classes/emptyClass.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/emptyClass.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(NodeKind.Class, kind)
assertEquals("Klass", name)
@@ -21,7 +24,7 @@ class ClassTest {
}
@Test fun emptyObject() {
- verifyModel("testdata/classes/emptyObject.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/emptyObject.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(NodeKind.Object, kind)
assertEquals("Obj", name)
@@ -33,7 +36,7 @@ class ClassTest {
}
@Test fun classWithConstructor() {
- verifyModel("testdata/classes/classWithConstructor.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/classWithConstructor.kt", defaultModelConfig) { model ->
with (model.members.single().members.single()) {
assertEquals(NodeKind.Class, kind)
assertEquals("Klass", name)
@@ -63,7 +66,7 @@ class ClassTest {
}
@Test fun classWithFunction() {
- verifyModel("testdata/classes/classWithFunction.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/classWithFunction.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(NodeKind.Class, kind)
assertEquals("Klass", name)
@@ -93,7 +96,7 @@ class ClassTest {
}
@Test fun classWithProperty() {
- verifyModel("testdata/classes/classWithProperty.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/classWithProperty.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(NodeKind.Class, kind)
assertEquals("Klass", name)
@@ -123,7 +126,7 @@ class ClassTest {
}
@Test fun classWithCompanionObject() {
- verifyModel("testdata/classes/classWithCompanionObject.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/classWithCompanionObject.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(NodeKind.Class, kind)
assertEquals("Klass", name)
@@ -151,33 +154,25 @@ class ClassTest {
}
}
- @Test fun annotatedClass() {
- verifyPackageMember("testdata/classes/annotatedClass.kt", withKotlinRuntime = true) { cls ->
- assertEquals(1, cls.annotations.count())
- with(cls.annotations[0]) {
- assertEquals("Strictfp", name)
- assertEquals(Content.Empty, content)
- assertEquals(NodeKind.Annotation, kind)
- }
- }
- }
-
@Test fun dataClass() {
- verifyPackageMember("testdata/classes/dataClass.kt") { cls ->
+ verifyPackageMember("testdata/classes/dataClass.kt", defaultModelConfig) { cls ->
val modifiers = cls.details(NodeKind.Modifier).map { it.name }
assertTrue("data" in modifiers)
}
}
@Test fun sealedClass() {
- verifyPackageMember("testdata/classes/sealedClass.kt") { cls ->
+ verifyPackageMember("testdata/classes/sealedClass.kt", defaultModelConfig) { cls ->
val modifiers = cls.details(NodeKind.Modifier).map { it.name }
assertEquals(1, modifiers.count { it == "sealed" })
}
}
@Test fun annotatedClassWithAnnotationParameters() {
- verifyModel("testdata/classes/annotatedClassWithAnnotationParameters.kt") { model ->
+ checkSourceExistsAndVerifyModel(
+ "testdata/classes/annotatedClassWithAnnotationParameters.kt",
+ defaultModelConfig
+ ) { model ->
with(model.members.single().members.single()) {
with(deprecation!!) {
assertEquals("Deprecated", name)
@@ -197,29 +192,8 @@ class ClassTest {
}
}
- @Test fun javaAnnotationClass() {
- verifyModel("testdata/classes/javaAnnotationClass.kt", withJdk = true) { model ->
- with(model.members.single().members.single()) {
- assertEquals(1, annotations.count())
- with(annotations[0]) {
- assertEquals("Retention", name)
- assertEquals(Content.Empty, content)
- assertEquals(NodeKind.Annotation, kind)
- with(details[0]) {
- assertEquals(NodeKind.Parameter, kind)
- assertEquals(1, details.count())
- with(details[0]) {
- assertEquals(NodeKind.Value, kind)
- assertEquals("RetentionPolicy.SOURCE", name)
- }
- }
- }
- }
- }
- }
-
@Test fun notOpenClass() {
- verifyModel("testdata/classes/notOpenClass.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/notOpenClass.kt", defaultModelConfig) { model ->
with(model.members.single().members.first { it.name == "D"}.members.first { it.name == "f" }) {
val modifiers = details(NodeKind.Modifier)
assertEquals(2, modifiers.size)
@@ -232,7 +206,7 @@ class ClassTest {
}
@Test fun indirectOverride() {
- verifyModel("testdata/classes/indirectOverride.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/indirectOverride.kt", defaultModelConfig) { model ->
with(model.members.single().members.first { it.name == "E"}.members.first { it.name == "foo" }) {
val modifiers = details(NodeKind.Modifier)
assertEquals(2, modifiers.size)
@@ -245,7 +219,7 @@ class ClassTest {
}
@Test fun innerClass() {
- verifyPackageMember("testdata/classes/innerClass.kt") { cls ->
+ verifyPackageMember("testdata/classes/innerClass.kt", defaultModelConfig) { cls ->
val innerClass = cls.members.single { it.name == "D" }
val modifiers = innerClass.details(NodeKind.Modifier)
assertEquals(3, modifiers.size)
@@ -254,7 +228,7 @@ class ClassTest {
}
@Test fun companionObjectExtension() {
- verifyModel("testdata/classes/companionObjectExtension.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/companionObjectExtension.kt", defaultModelConfig) { model ->
val pkg = model.members.single()
val cls = pkg.members.single { it.name == "Foo" }
val extensions = cls.extensions.filter { it.kind == NodeKind.CompanionObjectProperty }
@@ -263,7 +237,7 @@ class ClassTest {
}
@Test fun secondaryConstructor() {
- verifyPackageMember("testdata/classes/secondaryConstructor.kt") { cls ->
+ verifyPackageMember("testdata/classes/secondaryConstructor.kt", defaultModelConfig) { cls ->
val constructors = cls.members(NodeKind.Constructor)
assertEquals(2, constructors.size)
with (constructors.first { it.details(NodeKind.Parameter).size == 1}) {
@@ -274,15 +248,18 @@ class ClassTest {
}
@Test fun sinceKotlin() {
- verifyModel("testdata/classes/sinceKotlin.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/classes/sinceKotlin.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
- assertEquals(listOf("Kotlin 1.1"), platforms)
+ assertEquals("1.1", sinceKotlin)
}
}
}
@Test fun privateCompanionObject() {
- verifyModel("testdata/classes/privateCompanionObject.kt", includeNonPublic = false) { model ->
+ checkSourceExistsAndVerifyModel(
+ "testdata/classes/privateCompanionObject.kt",
+ modelConfig = ModelConfig(analysisPlatform = analysisPlatform, includeNonPublic = false)
+ ) { model ->
with(model.members.single().members.single()) {
assertEquals(0, members(NodeKind.CompanionObjectFunction).size)
assertEquals(0, members(NodeKind.CompanionObjectProperty).size)
@@ -291,3 +268,51 @@ class ClassTest {
}
}
+
+class JSClassTest: BaseClassTest(Platform.js) {}
+
+class JVMClassTest: BaseClassTest(Platform.jvm) {
+ @Test
+ fun annotatedClass() {
+ verifyPackageMember("testdata/classes/annotatedClass.kt", ModelConfig(
+ analysisPlatform = analysisPlatform,
+ withKotlinRuntime = true
+ )
+ ) { cls ->
+ Assert.assertEquals(1, cls.annotations.count())
+ with(cls.annotations[0]) {
+ Assert.assertEquals("Strictfp", name)
+ Assert.assertEquals(Content.Empty, content)
+ Assert.assertEquals(NodeKind.Annotation, kind)
+ }
+ }
+ }
+
+
+ @Test fun javaAnnotationClass() {
+ checkSourceExistsAndVerifyModel(
+ "testdata/classes/javaAnnotationClass.kt",
+ modelConfig = ModelConfig(analysisPlatform = analysisPlatform, withJdk = true)
+ ) { model ->
+ with(model.members.single().members.single()) {
+ Assert.assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ Assert.assertEquals("Retention", name)
+ Assert.assertEquals(Content.Empty, content)
+ Assert.assertEquals(NodeKind.Annotation, kind)
+ with(details[0]) {
+ Assert.assertEquals(NodeKind.Parameter, kind)
+ Assert.assertEquals(1, details.count())
+ with(details[0]) {
+ Assert.assertEquals(NodeKind.Value, kind)
+ Assert.assertEquals("RetentionPolicy.SOURCE", name)
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
+
+class CommonClassTest: BaseClassTest(Platform.common) {} \ No newline at end of file
diff --git a/core/src/test/kotlin/model/CommentTest.kt b/core/src/test/kotlin/model/CommentTest.kt
index 3752bb8c..08aa3572 100644
--- a/core/src/test/kotlin/model/CommentTest.kt
+++ b/core/src/test/kotlin/model/CommentTest.kt
@@ -4,10 +4,10 @@ import org.junit.Test
import org.junit.Assert.*
import org.jetbrains.dokka.*
-public class CommentTest {
-
+abstract class BaseCommentTest(val analysisPlatform: Platform) {
+ val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test fun codeBlockComment() {
- verifyModel("testdata/comments/codeBlockComment.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/codeBlockComment.kt", defaultModelConfig) { model ->
with(model.members.single().members.first()) {
assertEqualsIgnoringSeparators("""[code lang=brainfuck]
|
@@ -30,7 +30,7 @@ public class CommentTest {
}
@Test fun emptyDoc() {
- verifyModel("testdata/comments/emptyDoc.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/emptyDoc.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(Content.Empty, content)
}
@@ -38,7 +38,7 @@ public class CommentTest {
}
@Test fun emptyDocButComment() {
- verifyModel("testdata/comments/emptyDocButComment.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/emptyDocButComment.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals(Content.Empty, content)
}
@@ -46,7 +46,7 @@ public class CommentTest {
}
@Test fun multilineDoc() {
- verifyModel("testdata/comments/multilineDoc.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/multilineDoc.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("doc1", content.summary.toTestString())
assertEquals("doc2\ndoc3", content.description.toTestString())
@@ -55,7 +55,7 @@ public class CommentTest {
}
@Test fun multilineDocWithComment() {
- verifyModel("testdata/comments/multilineDocWithComment.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/multilineDocWithComment.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("doc1", content.summary.toTestString())
assertEquals("doc2\ndoc3", content.description.toTestString())
@@ -64,7 +64,7 @@ public class CommentTest {
}
@Test fun oneLineDoc() {
- verifyModel("testdata/comments/oneLineDoc.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/oneLineDoc.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("doc", content.summary.toTestString())
}
@@ -72,7 +72,7 @@ public class CommentTest {
}
@Test fun oneLineDocWithComment() {
- verifyModel("testdata/comments/oneLineDocWithComment.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/oneLineDocWithComment.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("doc", content.summary.toTestString())
}
@@ -80,7 +80,7 @@ public class CommentTest {
}
@Test fun oneLineDocWithEmptyLine() {
- verifyModel("testdata/comments/oneLineDocWithEmptyLine.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/oneLineDocWithEmptyLine.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("doc", content.summary.toTestString())
}
@@ -88,7 +88,7 @@ public class CommentTest {
}
@Test fun emptySection() {
- verifyModel("testdata/comments/emptySection.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/emptySection.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Summary", content.summary.toTestString())
assertEquals(1, content.sections.count())
@@ -101,7 +101,7 @@ public class CommentTest {
}
@Test fun quotes() {
- verifyModel("testdata/comments/quotes.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/quotes.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("it's \"useful\"", content.summary.toTestString())
}
@@ -109,7 +109,7 @@ public class CommentTest {
}
@Test fun section1() {
- verifyModel("testdata/comments/section1.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/section1.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Summary", content.summary.toTestString())
assertEquals(1, content.sections.count())
@@ -122,7 +122,7 @@ public class CommentTest {
}
@Test fun section2() {
- verifyModel("testdata/comments/section2.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/section2.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Summary", content.summary.toTestString())
assertEquals(2, content.sections.count())
@@ -139,7 +139,7 @@ public class CommentTest {
}
@Test fun multilineSection() {
- verifyModel("testdata/comments/multilineSection.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/multilineSection.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Summary", content.summary.toTestString())
assertEquals(1, content.sections.count())
@@ -153,7 +153,7 @@ line two""", toTestString())
}
@Test fun directive() {
- verifyModel("testdata/comments/directive.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/comments/directive.kt", defaultModelConfig) { model ->
with(model.members.single().members.first()) {
assertEquals("Summary", content.summary.toTestString())
with (content.description) {
@@ -184,3 +184,7 @@ line two""", toTestString())
}
}
}
+
+class JSCommentTest: BaseCommentTest(Platform.js)
+class JVMCommentTest: BaseCommentTest(Platform.jvm)
+class CommonCommentTest: BaseCommentTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/model/FunctionTest.kt b/core/src/test/kotlin/model/FunctionTest.kt
index fd7a16a4..4c6bfb74 100644
--- a/core/src/test/kotlin/model/FunctionTest.kt
+++ b/core/src/test/kotlin/model/FunctionTest.kt
@@ -2,14 +2,17 @@ package org.jetbrains.dokka.tests
import org.jetbrains.dokka.Content
import org.jetbrains.dokka.NodeKind
+import org.jetbrains.dokka.Platform
+import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters
+import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
-import kotlin.test.assertNotNull
-class FunctionTest {
+abstract class BaseFunctionTest(val analysisPlatform: Platform) {
+ protected val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test fun function() {
- verifyModel("testdata/functions/function.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/function.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("fn", name)
assertEquals(NodeKind.Function, kind)
@@ -22,7 +25,7 @@ class FunctionTest {
}
@Test fun functionWithReceiver() {
- verifyModel("testdata/functions/functionWithReceiver.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/functionWithReceiver.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("kotlin.String", name)
assertEquals(NodeKind.ExternalClass, kind)
@@ -54,7 +57,7 @@ class FunctionTest {
}
@Test fun genericFunction() {
- verifyModel("testdata/functions/genericFunction.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/genericFunction.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("generic", name)
assertEquals(NodeKind.Function, kind)
@@ -78,7 +81,7 @@ class FunctionTest {
}
}
@Test fun genericFunctionWithConstraints() {
- verifyModel("testdata/functions/genericFunctionWithConstraints.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/genericFunctionWithConstraints.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("generic", name)
assertEquals(NodeKind.Function, kind)
@@ -118,7 +121,7 @@ class FunctionTest {
}
@Test fun functionWithParams() {
- verifyModel("testdata/functions/functionWithParams.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/functionWithParams.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("function", name)
assertEquals(NodeKind.Function, kind)
@@ -143,25 +146,14 @@ Documentation""", content.description.toTestString())
}
}
- @Test fun annotatedFunction() {
- verifyPackageMember("testdata/functions/annotatedFunction.kt", withKotlinRuntime = true) { func ->
- assertEquals(1, func.annotations.count())
- with(func.annotations[0]) {
- assertEquals("Strictfp", name)
- assertEquals(Content.Empty, content)
- assertEquals(NodeKind.Annotation, kind)
- }
- }
- }
-
@Test fun functionWithNotDocumentedAnnotation() {
- verifyPackageMember("testdata/functions/functionWithNotDocumentedAnnotation.kt") { func ->
+ verifyPackageMember("testdata/functions/functionWithNotDocumentedAnnotation.kt", defaultModelConfig) { func ->
assertEquals(0, func.annotations.count())
}
}
@Test fun inlineFunction() {
- verifyPackageMember("testdata/functions/inlineFunction.kt") { func ->
+ verifyPackageMember("testdata/functions/inlineFunction.kt", defaultModelConfig) { func ->
val modifiers = func.details(NodeKind.Modifier).map { it.name }
assertTrue("inline" in modifiers)
}
@@ -195,7 +187,7 @@ Documentation""", content.description.toTestString())
}
@Test fun functionWithAnnotatedParam() {
- verifyModel("testdata/functions/functionWithAnnotatedParam.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/functionWithAnnotatedParam.kt", defaultModelConfig) { model ->
with(model.members.single().members.single { it.name == "function" }) {
with(details(NodeKind.Parameter).first()) {
assertEquals(1, annotations.count())
@@ -210,7 +202,7 @@ Documentation""", content.description.toTestString())
}
@Test fun functionWithNoinlineParam() {
- verifyPackageMember("testdata/functions/functionWithNoinlineParam.kt") { func ->
+ verifyPackageMember("testdata/functions/functionWithNoinlineParam.kt", defaultModelConfig) { func ->
with(func.details(NodeKind.Parameter).first()) {
val modifiers = details(NodeKind.Modifier).map { it.name }
assertTrue("noinline" in modifiers)
@@ -219,7 +211,10 @@ Documentation""", content.description.toTestString())
}
@Test fun annotatedFunctionWithAnnotationParameters() {
- verifyModel("testdata/functions/annotatedFunctionWithAnnotationParameters.kt") { model ->
+ checkSourceExistsAndVerifyModel(
+ "testdata/functions/annotatedFunctionWithAnnotationParameters.kt",
+ defaultModelConfig
+ ) { model ->
with(model.members.single().members.single { it.name == "f" }) {
assertEquals(1, annotations.count())
with(annotations[0]) {
@@ -241,7 +236,7 @@ Documentation""", content.description.toTestString())
}
@Test fun functionWithDefaultParameter() {
- verifyModel("testdata/functions/functionWithDefaultParameter.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/functionWithDefaultParameter.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
with(details.elementAt(3)) {
val value = details(NodeKind.Value)
@@ -255,10 +250,32 @@ Documentation""", content.description.toTestString())
}
@Test fun sinceKotlin() {
- verifyModel("testdata/functions/sinceKotlin.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/functions/sinceKotlin.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
- assertEquals(listOf("Kotlin 1.1"), platforms)
+ assertEquals("1.1", sinceKotlin)
+ }
+ }
+ }
+}
+
+class JSFunctionTest: BaseFunctionTest(Platform.js)
+
+class JVMFunctionTest: BaseFunctionTest(Platform.jvm) {
+ @Test
+ fun annotatedFunction() {
+ verifyPackageMember("testdata/functions/annotatedFunction.kt", ModelConfig(
+ analysisPlatform = Platform.jvm,
+ withKotlinRuntime = true
+ )) { func ->
+ Assert.assertEquals(1, func.annotations.count())
+ with(func.annotations[0]) {
+ Assert.assertEquals("Strictfp", name)
+ Assert.assertEquals(Content.Empty, content)
+ Assert.assertEquals(NodeKind.Annotation, kind)
}
}
}
+
}
+
+class CommonFunctionTest: BaseFunctionTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt
index 0bec6d01..da9da624 100644
--- a/core/src/test/kotlin/model/JavaTest.kt
+++ b/core/src/test/kotlin/model/JavaTest.kt
@@ -1,14 +1,16 @@
package org.jetbrains.dokka.tests
import org.jetbrains.dokka.NodeKind
+import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.RefKind
import org.junit.Assert.*
import org.junit.Ignore
import org.junit.Test
public class JavaTest {
+ private val defaultModelConfig = ModelConfig(analysisPlatform = Platform.jvm)
@Test fun function() {
- verifyJavaPackageMember("testdata/java/member.java") { cls ->
+ verifyJavaPackageMember("testdata/java/member.java", defaultModelConfig) { cls ->
assertEquals("Test", cls.name)
assertEquals(NodeKind.Class, cls.kind)
with(cls.members(NodeKind.Function).single()) {
@@ -45,7 +47,7 @@ public class JavaTest {
}
@Test fun memberWithModifiers() {
- verifyJavaPackageMember("testdata/java/memberWithModifiers.java") { cls ->
+ verifyJavaPackageMember("testdata/java/memberWithModifiers.java", defaultModelConfig) { cls ->
val modifiers = cls.details(NodeKind.Modifier).map { it.name }
assertTrue("abstract" in modifiers)
with(cls.members.single { it.name == "fn" }) {
@@ -58,7 +60,7 @@ public class JavaTest {
}
@Test fun superClass() {
- verifyJavaPackageMember("testdata/java/superClass.java") { cls ->
+ verifyJavaPackageMember("testdata/java/superClass.java", defaultModelConfig) { cls ->
val superTypes = cls.details(NodeKind.Supertype)
assertEquals(2, superTypes.size)
assertEquals("Exception", superTypes[0].name)
@@ -67,7 +69,7 @@ public class JavaTest {
}
@Test fun arrayType() {
- verifyJavaPackageMember("testdata/java/arrayType.java") { cls ->
+ verifyJavaPackageMember("testdata/java/arrayType.java", defaultModelConfig) { cls ->
with(cls.members(NodeKind.Function).single()) {
val type = detail(NodeKind.Type)
assertEquals("Array", type.name)
@@ -81,7 +83,7 @@ public class JavaTest {
}
@Test fun typeParameter() {
- verifyJavaPackageMember("testdata/java/typeParameter.java") { cls ->
+ verifyJavaPackageMember("testdata/java/typeParameter.java", defaultModelConfig) { cls ->
val typeParameters = cls.details(NodeKind.TypeParameter)
with(typeParameters.single()) {
assertEquals("T", name)
@@ -100,7 +102,7 @@ public class JavaTest {
}
@Test fun constructors() {
- verifyJavaPackageMember("testdata/java/constructors.java") { cls ->
+ verifyJavaPackageMember("testdata/java/constructors.java", defaultModelConfig) { cls ->
val constructors = cls.members(NodeKind.Constructor)
assertEquals(2, constructors.size)
with(constructors[0]) {
@@ -110,14 +112,14 @@ public class JavaTest {
}
@Test fun innerClass() {
- verifyJavaPackageMember("testdata/java/InnerClass.java") { cls ->
+ verifyJavaPackageMember("testdata/java/InnerClass.java", defaultModelConfig) { cls ->
val innerClass = cls.members(NodeKind.Class).single()
assertEquals("D", innerClass.name)
}
}
@Test fun varargs() {
- verifyJavaPackageMember("testdata/java/varargs.java") { cls ->
+ verifyJavaPackageMember("testdata/java/varargs.java", defaultModelConfig) { cls ->
val fn = cls.members(NodeKind.Function).single()
val param = fn.detail(NodeKind.Parameter)
assertEquals("vararg", param.details(NodeKind.Modifier).first().name)
@@ -128,7 +130,7 @@ public class JavaTest {
}
@Test fun fields() {
- verifyJavaPackageMember("testdata/java/field.java") { cls ->
+ verifyJavaPackageMember("testdata/java/field.java", defaultModelConfig) { cls ->
val i = cls.members(NodeKind.Property).single { it.name == "i" }
assertEquals("Int", i.detail(NodeKind.Type).name)
assertTrue("var" in i.details(NodeKind.Modifier).map { it.name })
@@ -141,7 +143,7 @@ public class JavaTest {
}
@Test fun staticMethod() {
- verifyJavaPackageMember("testdata/java/staticMethod.java") { cls ->
+ verifyJavaPackageMember("testdata/java/staticMethod.java", defaultModelConfig) { cls ->
val m = cls.members(NodeKind.Function).single { it.name == "foo" }
assertTrue("static" in m.details(NodeKind.Modifier).map { it.name })
}
@@ -154,13 +156,13 @@ public class JavaTest {
* Proposed tag `@exclude` for it, but not supported yet
*/
@Ignore("@suppress not supported in Java!") @Test fun suppressTag() {
- verifyJavaPackageMember("testdata/java/suppressTag.java") { cls ->
+ verifyJavaPackageMember("testdata/java/suppressTag.java", defaultModelConfig) { cls ->
assertEquals(1, cls.members(NodeKind.Function).size)
}
}
@Test fun annotatedAnnotation() {
- verifyJavaPackageMember("testdata/java/annotatedAnnotation.java") { cls ->
+ verifyJavaPackageMember("testdata/java/annotatedAnnotation.java", defaultModelConfig) { cls ->
assertEquals(1, cls.annotations.size)
with(cls.annotations[0]) {
assertEquals(1, details.count())
@@ -177,21 +179,21 @@ public class JavaTest {
}
@Test fun deprecation() {
- verifyJavaPackageMember("testdata/java/deprecation.java") { cls ->
+ verifyJavaPackageMember("testdata/java/deprecation.java", defaultModelConfig) { cls ->
val fn = cls.members(NodeKind.Function).single()
assertEquals("This should no longer be used", fn.deprecation!!.content.toTestString())
}
}
@Test fun javaLangObject() {
- verifyJavaPackageMember("testdata/java/javaLangObject.java") { cls ->
+ verifyJavaPackageMember("testdata/java/javaLangObject.java", defaultModelConfig) { cls ->
val fn = cls.members(NodeKind.Function).single()
assertEquals("Any", fn.detail(NodeKind.Type).name)
}
}
@Test fun enumValues() {
- verifyJavaPackageMember("testdata/java/enumValues.java") { cls ->
+ verifyJavaPackageMember("testdata/java/enumValues.java", defaultModelConfig) { cls ->
val superTypes = cls.details(NodeKind.Supertype)
assertEquals(1, superTypes.size)
assertEquals(1, cls.members(NodeKind.EnumItem).size)
@@ -199,7 +201,7 @@ public class JavaTest {
}
@Test fun inheritorLinks() {
- verifyJavaPackageMember("testdata/java/InheritorLinks.java") { cls ->
+ verifyJavaPackageMember("testdata/java/InheritorLinks.java", defaultModelConfig) { cls ->
val fooClass = cls.members.single { it.name == "Foo" }
val inheritors = fooClass.references(RefKind.Inheritor)
assertEquals(1, inheritors.size)
diff --git a/core/src/test/kotlin/model/KotlinAsJavaTest.kt b/core/src/test/kotlin/model/KotlinAsJavaTest.kt
index 22818038..8249dd0f 100644
--- a/core/src/test/kotlin/model/KotlinAsJavaTest.kt
+++ b/core/src/test/kotlin/model/KotlinAsJavaTest.kt
@@ -2,10 +2,11 @@ package org.jetbrains.dokka.tests
import org.jetbrains.dokka.DocumentationModule
import org.jetbrains.dokka.NodeKind
+import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.RefKind
import org.junit.Assert
-import org.junit.Test
import org.junit.Assert.assertEquals
+import org.junit.Test
class KotlinAsJavaTest {
@Test fun function() {
@@ -50,11 +51,15 @@ class KotlinAsJavaTest {
}
fun verifyModelAsJava(source: String,
- withJdk: Boolean = false,
- withKotlinRuntime: Boolean = false,
+ modelConfig: ModelConfig = ModelConfig(),
verifier: (DocumentationModule) -> Unit) {
- verifyModel(source,
- withJdk = withJdk, withKotlinRuntime = withKotlinRuntime,
+ checkSourceExistsAndVerifyModel(
+ source,
+ modelConfig = ModelConfig(
+ withJdk = modelConfig.withJdk,
+ withKotlinRuntime = modelConfig.withKotlinRuntime,
format = "html-as-java",
- verifier = verifier)
+ analysisPlatform = Platform.jvm),
+ verifier = verifier
+ )
}
diff --git a/core/src/test/kotlin/model/LinkTest.kt b/core/src/test/kotlin/model/LinkTest.kt
index 6b72525f..6526a4db 100644
--- a/core/src/test/kotlin/model/LinkTest.kt
+++ b/core/src/test/kotlin/model/LinkTest.kt
@@ -3,12 +3,14 @@ package org.jetbrains.dokka.tests
import org.jetbrains.dokka.ContentBlock
import org.jetbrains.dokka.ContentNodeLazyLink
import org.jetbrains.dokka.NodeKind
+import org.jetbrains.dokka.Platform
import org.junit.Assert.assertEquals
import org.junit.Test
-class LinkTest {
+abstract class BaseLinkTest(val analysisPlatform: Platform) {
+ private val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test fun linkToSelf() {
- verifyModel("testdata/links/linkToSelf.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/links/linkToSelf.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Foo", name)
assertEquals(NodeKind.Class, kind)
@@ -17,8 +19,18 @@ class LinkTest {
}
}
+ @Test fun linkToExternalSite() {
+ checkSourceExistsAndVerifyModel("testdata/links/linkToExternalSite.kt", defaultModelConfig) { model ->
+ with(model.members.single().members.single()) {
+ assertEquals("Foo", name)
+ assertEquals(NodeKind.Class, kind)
+ assertEquals("This is link to http://example.com/#example", content.summary.toTestString())
+ }
+ }
+ }
+
@Test fun linkToMember() {
- verifyModel("testdata/links/linkToMember.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/links/linkToMember.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Foo", name)
assertEquals(NodeKind.Class, kind)
@@ -28,7 +40,7 @@ class LinkTest {
}
@Test fun linkToConstantWithUnderscores() {
- verifyModel("testdata/links/linkToConstantWithUnderscores.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/links/linkToConstantWithUnderscores.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Foo", name)
assertEquals(NodeKind.Class, kind)
@@ -38,7 +50,7 @@ class LinkTest {
}
@Test fun linkToQualifiedMember() {
- verifyModel("testdata/links/linkToQualifiedMember.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/links/linkToQualifiedMember.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Foo", name)
assertEquals(NodeKind.Class, kind)
@@ -48,7 +60,7 @@ class LinkTest {
}
@Test fun linkToParam() {
- verifyModel("testdata/links/linkToParam.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/links/linkToParam.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("Foo", name)
assertEquals(NodeKind.Function, kind)
@@ -58,7 +70,7 @@ class LinkTest {
}
@Test fun linkToPackage() {
- verifyModel("testdata/links/linkToPackage.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/links/linkToPackage.kt", defaultModelConfig) { model ->
val packageNode = model.members.single()
with(packageNode) {
assertEquals(this.name, "test.magic")
@@ -72,4 +84,8 @@ class LinkTest {
}
}
-} \ No newline at end of file
+}
+
+class JSLinkTest: BaseLinkTest(Platform.js)
+class JVMLinkTest: BaseLinkTest(Platform.jvm)
+class CommonLinkTest: BaseLinkTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/model/PackageTest.kt b/core/src/test/kotlin/model/PackageTest.kt
index 7a8f0d06..e20e6afa 100644
--- a/core/src/test/kotlin/model/PackageTest.kt
+++ b/core/src/test/kotlin/model/PackageTest.kt
@@ -1,15 +1,14 @@
package org.jetbrains.dokka.tests
-import org.jetbrains.dokka.Content
-import org.jetbrains.dokka.NodeKind
-import org.jetbrains.dokka.PackageOptionsImpl
+import org.jetbrains.dokka.*
import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot
import org.junit.Assert.*
import org.junit.Test
-public class PackageTest {
+abstract class BasePackageTest(val analysisPlatform: Platform) {
+ val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test fun rootPackage() {
- verifyModel("testdata/packages/rootPackage.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/packages/rootPackage.kt", defaultModelConfig) { model ->
with(model.members.single()) {
assertEquals(NodeKind.Package, kind)
assertEquals("", name)
@@ -22,7 +21,7 @@ public class PackageTest {
}
@Test fun simpleNamePackage() {
- verifyModel("testdata/packages/simpleNamePackage.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/packages/simpleNamePackage.kt", defaultModelConfig) { model ->
with(model.members.single()) {
assertEquals(NodeKind.Package, kind)
assertEquals("simple", name)
@@ -35,7 +34,7 @@ public class PackageTest {
}
@Test fun dottedNamePackage() {
- verifyModel("testdata/packages/dottedNamePackage.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/packages/dottedNamePackage.kt", defaultModelConfig) { model ->
with(model.members.single()) {
assertEquals(NodeKind.Package, kind)
assertEquals("dot.name", name)
@@ -48,8 +47,15 @@ public class PackageTest {
}
@Test fun multipleFiles() {
- verifyModel(KotlinSourceRoot("testdata/packages/dottedNamePackage.kt", false),
- KotlinSourceRoot("testdata/packages/simpleNamePackage.kt", false)) { model ->
+ verifyModel(
+ ModelConfig(
+ roots = arrayOf(
+ KotlinSourceRoot("testdata/packages/dottedNamePackage.kt", false),
+ KotlinSourceRoot("testdata/packages/simpleNamePackage.kt", false)
+ ),
+ analysisPlatform = analysisPlatform
+ )
+ ) { model ->
assertEquals(2, model.members.count())
with(model.members.single { it.name == "simple" }) {
assertEquals(NodeKind.Package, kind)
@@ -70,8 +76,15 @@ public class PackageTest {
}
@Test fun multipleFilesSamePackage() {
- verifyModel(KotlinSourceRoot("testdata/packages/simpleNamePackage.kt", false),
- KotlinSourceRoot("testdata/packages/simpleNamePackage2.kt", false)) { model ->
+ verifyModel(
+ ModelConfig(
+ roots = arrayOf(
+ KotlinSourceRoot("testdata/packages/simpleNamePackage.kt", false),
+ KotlinSourceRoot("testdata/packages/simpleNamePackage2.kt", false)
+ ),
+ analysisPlatform = analysisPlatform
+ )
+ ) { model ->
assertEquals(1, model.members.count())
with(model.members.elementAt(0)) {
assertEquals(NodeKind.Package, kind)
@@ -85,7 +98,12 @@ public class PackageTest {
}
@Test fun classAtPackageLevel() {
- verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt", false)) { model ->
+ verifyModel(
+ ModelConfig(
+ roots = arrayOf(KotlinSourceRoot("testdata/packages/classInPackage.kt", false)),
+ analysisPlatform = analysisPlatform
+ )
+ ) { model ->
assertEquals(1, model.members.count())
with(model.members.elementAt(0)) {
assertEquals(NodeKind.Package, kind)
@@ -99,8 +117,15 @@ public class PackageTest {
}
@Test fun suppressAtPackageLevel() {
- verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt", false),
- perPackageOptions = listOf(PackageOptionsImpl(prefix = "simple.name", suppress = true))) { model ->
+ verifyModel(
+ ModelConfig(
+ roots = arrayOf(KotlinSourceRoot("testdata/packages/classInPackage.kt", false)),
+ perPackageOptions = listOf(
+ PackageOptionsImpl(prefix = "simple.name", suppress = true)
+ ),
+ analysisPlatform = analysisPlatform
+ )
+ ) { model ->
assertEquals(1, model.members.count())
with(model.members.elementAt(0)) {
assertEquals(NodeKind.Package, kind)
@@ -113,3 +138,7 @@ public class PackageTest {
}
}
}
+
+class JSPackageTest : BasePackageTest(Platform.js)
+class JVMPackageTest : BasePackageTest(Platform.jvm)
+class CommonPackageTest : BasePackageTest(Platform.common) \ No newline at end of file
diff --git a/core/src/test/kotlin/model/PropertyTest.kt b/core/src/test/kotlin/model/PropertyTest.kt
index 296eaa4c..9f070862 100644
--- a/core/src/test/kotlin/model/PropertyTest.kt
+++ b/core/src/test/kotlin/model/PropertyTest.kt
@@ -1,15 +1,16 @@
package org.jetbrains.dokka.tests
-import org.jetbrains.dokka.Content
-import org.jetbrains.dokka.NodeKind
-import org.jetbrains.dokka.RefKind
+import org.jetbrains.dokka.*
+import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
-class PropertyTest {
+abstract class BasePropertyTest(val analysisPlatform: Platform) {
+
+ protected val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform)
@Test fun valueProperty() {
- verifyModel("testdata/properties/valueProperty.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/properties/valueProperty.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("property", name)
assertEquals(NodeKind.Property, kind)
@@ -22,7 +23,7 @@ class PropertyTest {
}
@Test fun variableProperty() {
- verifyModel("testdata/properties/variableProperty.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/properties/variableProperty.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("property", name)
assertEquals(NodeKind.Property, kind)
@@ -35,7 +36,7 @@ class PropertyTest {
}
@Test fun valuePropertyWithGetter() {
- verifyModel("testdata/properties/valuePropertyWithGetter.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/properties/valuePropertyWithGetter.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("property", name)
assertEquals(NodeKind.Property, kind)
@@ -48,7 +49,7 @@ class PropertyTest {
}
@Test fun variablePropertyWithAccessors() {
- verifyModel("testdata/properties/variablePropertyWithAccessors.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/properties/variablePropertyWithAccessors.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
assertEquals("property", name)
assertEquals(NodeKind.Property, kind)
@@ -64,21 +65,11 @@ class PropertyTest {
}
}
- @Test fun annotatedProperty() {
- verifyModel("testdata/properties/annotatedProperty.kt", withKotlinRuntime = true) { model ->
- with(model.members.single().members.single()) {
- assertEquals(1, annotations.count())
- with(annotations[0]) {
- assertEquals("Strictfp", name)
- assertEquals(Content.Empty, content)
- assertEquals(NodeKind.Annotation, kind)
- }
- }
- }
- }
-
@Test fun propertyWithReceiver() {
- verifyModel("testdata/properties/propertyWithReceiver.kt") { model ->
+ checkSourceExistsAndVerifyModel(
+ "testdata/properties/propertyWithReceiver.kt",
+ defaultModelConfig
+ ) { model ->
with(model.members.single().members.single()) {
assertEquals("kotlin.String", name)
assertEquals(NodeKind.ExternalClass, kind)
@@ -91,7 +82,7 @@ class PropertyTest {
}
@Test fun propertyOverride() {
- verifyModel("testdata/properties/propertyOverride.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/properties/propertyOverride.kt", defaultModelConfig) { model ->
with(model.members.single().members.single { it.name == "Bar" }.members.single { it.name == "xyzzy"}) {
assertEquals("xyzzy", name)
val override = references(RefKind.Override).single().to
@@ -102,10 +93,37 @@ class PropertyTest {
}
@Test fun sinceKotlin() {
- verifyModel("testdata/properties/sinceKotlin.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/properties/sinceKotlin.kt", defaultModelConfig) { model ->
with(model.members.single().members.single()) {
- assertEquals(listOf("Kotlin 1.1"), platforms)
+ assertEquals("1.1", sinceKotlin)
}
}
}
}
+
+class JSPropertyTest: BasePropertyTest(Platform.js) {}
+
+class JVMPropertyTest : BasePropertyTest(Platform.jvm) {
+ @Test
+ fun annotatedProperty() {
+ checkSourceExistsAndVerifyModel(
+ "testdata/properties/annotatedProperty.kt",
+ modelConfig = ModelConfig(
+ analysisPlatform = analysisPlatform,
+ withKotlinRuntime = true
+ )
+ ) { model ->
+ with(model.members.single().members.single()) {
+ Assert.assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ Assert.assertEquals("Strictfp", name)
+ Assert.assertEquals(Content.Empty, content)
+ Assert.assertEquals(NodeKind.Annotation, kind)
+ }
+ }
+ }
+ }
+
+}
+
+class CommonPropertyTest: BasePropertyTest(Platform.common) {} \ No newline at end of file
diff --git a/core/src/test/kotlin/model/SourceLinksErrorTest.kt b/core/src/test/kotlin/model/SourceLinksErrorTest.kt
index a72bd62a..9812569d 100644
--- a/core/src/test/kotlin/model/SourceLinksErrorTest.kt
+++ b/core/src/test/kotlin/model/SourceLinksErrorTest.kt
@@ -2,7 +2,8 @@ package org.jetbrains.dokka.tests.model
import org.jetbrains.dokka.NodeKind
import org.jetbrains.dokka.SourceLinkDefinitionImpl
-import org.jetbrains.dokka.tests.verifyModel
+import org.jetbrains.dokka.tests.ModelConfig
+import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel
import org.junit.Assert
import org.junit.Test
import java.io.File
@@ -22,7 +23,7 @@ class SourceLinksErrorTest {
}
private fun verifyNoSourceUrl(sourceLink: SourceLinkDefinitionImpl) {
- verifyModel("testdata/sourceLinks/dummy.kt", sourceLinks = listOf(sourceLink)) { model ->
+ checkSourceExistsAndVerifyModel("testdata/sourceLinks/dummy.kt", ModelConfig(sourceLinks = listOf(sourceLink))) { model ->
with(model.members.single().members.single()) {
Assert.assertEquals("foo", name)
Assert.assertEquals(NodeKind.Function, kind)
diff --git a/core/src/test/kotlin/model/SourceLinksTest.kt b/core/src/test/kotlin/model/SourceLinksTest.kt
index 0e9b666c..a4ba870c 100644
--- a/core/src/test/kotlin/model/SourceLinksTest.kt
+++ b/core/src/test/kotlin/model/SourceLinksTest.kt
@@ -2,7 +2,8 @@ package org.jetbrains.dokka.tests.model
import org.jetbrains.dokka.NodeKind
import org.jetbrains.dokka.SourceLinkDefinitionImpl
-import org.jetbrains.dokka.tests.verifyModel
+import org.jetbrains.dokka.tests.ModelConfig
+import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
@@ -26,7 +27,7 @@ class SourceLinksTest(
}
val sourceLink = SourceLinkDefinitionImpl(link, url, lineSuffix)
- verifyModel(filePath, sourceLinks = listOf(sourceLink)) { model ->
+ checkSourceExistsAndVerifyModel(filePath, ModelConfig(sourceLinks = listOf(sourceLink))) { model ->
with(model.members.single().members.single()) {
Assert.assertEquals("foo", name)
Assert.assertEquals(NodeKind.Function, kind)
diff --git a/core/src/test/kotlin/model/TypeAliasTest.kt b/core/src/test/kotlin/model/TypeAliasTest.kt
index c653ac83..71976dc3 100644
--- a/core/src/test/kotlin/model/TypeAliasTest.kt
+++ b/core/src/test/kotlin/model/TypeAliasTest.kt
@@ -8,7 +8,7 @@ import org.junit.Test
class TypeAliasTest {
@Test
fun testSimple() {
- verifyModel("testdata/typealias/simple.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/simple.kt") {
val pkg = it.members.single()
with(pkg.member(NodeKind.TypeAlias)) {
assertEquals(Content.Empty, content)
@@ -20,7 +20,7 @@ class TypeAliasTest {
@Test
fun testInheritanceFromTypeAlias() {
- verifyModel("testdata/typealias/inheritanceFromTypeAlias.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/inheritanceFromTypeAlias.kt") {
val pkg = it.members.single()
with(pkg.member(NodeKind.TypeAlias)) {
assertEquals(Content.Empty, content)
@@ -36,7 +36,7 @@ class TypeAliasTest {
@Test
fun testChain() {
- verifyModel("testdata/typealias/chain.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/chain.kt") {
val pkg = it.members.single()
with(pkg.members(NodeKind.TypeAlias).find { it.name == "B" }!!) {
assertEquals(Content.Empty, content)
@@ -51,7 +51,7 @@ class TypeAliasTest {
@Test
fun testDocumented() {
- verifyModel("testdata/typealias/documented.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/documented.kt") {
val pkg = it.members.single()
with(pkg.member(NodeKind.TypeAlias)) {
assertEquals("Just typealias", content.summary.toTestString())
@@ -61,7 +61,7 @@ class TypeAliasTest {
@Test
fun testDeprecated() {
- verifyModel("testdata/typealias/deprecated.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/deprecated.kt") {
val pkg = it.members.single()
with(pkg.member(NodeKind.TypeAlias)) {
assertEquals(Content.Empty, content)
@@ -73,7 +73,7 @@ class TypeAliasTest {
@Test
fun testGeneric() {
- verifyModel("testdata/typealias/generic.kt") {
+ checkSourceExistsAndVerifyModel("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)
@@ -88,7 +88,7 @@ class TypeAliasTest {
@Test
fun testFunctional() {
- verifyModel("testdata/typealias/functional.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/functional.kt") {
val pkg = it.members.single()
with(pkg.member(NodeKind.TypeAlias)) {
assertEquals("Function1", detail(NodeKind.TypeAliasUnderlyingType).name)
@@ -105,7 +105,7 @@ class TypeAliasTest {
@Test
fun testAsTypeBoundWithVariance() {
- verifyModel("testdata/typealias/asTypeBoundWithVariance.kt") {
+ checkSourceExistsAndVerifyModel("testdata/typealias/asTypeBoundWithVariance.kt") {
val pkg = it.members.single()
with(pkg.members(NodeKind.Class).find { it.name == "C" }!!) {
val tParam = detail(NodeKind.TypeParameter)
@@ -123,9 +123,9 @@ class TypeAliasTest {
@Test
fun sinceKotlin() {
- verifyModel("testdata/typealias/sinceKotlin.kt") { model ->
+ checkSourceExistsAndVerifyModel("testdata/typealias/sinceKotlin.kt") { model ->
with(model.members.single().members.single()) {
- assertEquals(listOf("Kotlin 1.1"), platforms)
+ assertEquals("1.1", sinceKotlin)
}
}
}
diff --git a/core/testdata/format/JavaSupertype.html b/core/testdata/format/JavaSupertype.html
index 892ef63a..85fb6d84 100644
--- a/core/testdata/format/JavaSupertype.html
+++ b/core/testdata/format/JavaSupertype.html
@@ -4,7 +4,7 @@
<title>JavaSupertype.Bar - test</title>
</HEAD>
<BODY>
-<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="../index.html">JavaSupertype</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
+<a href="../../../index.html">test</a>&nbsp;/&nbsp;<a href="../index.html">JavaSupertype</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
<br/>
<h1>Bar</h1>
<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Bar</span>&nbsp;<span class="symbol">:</span>&nbsp;<a href="../-foo/index.html"><span class="identifier">JavaSupertype.Foo</span></a></code>
@@ -13,7 +13,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -25,7 +25,7 @@
<tbody>
<tr>
<td>
-<p><a href="return-foo.html">returnFoo</a></p>
+<h4><a href="return-foo.html">returnFoo</a></h4>
</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" id="JavaSupertype.Bar$returnFoo(JavaSupertype.Foo)/foo">foo</span><span class="symbol">:</span>&nbsp;<a href="../-foo/index.html"><span class="identifier">JavaSupertype.Foo</span></a><span class="symbol">!</span><span class="symbol">)</span><span class="symbol">: </span><a href="../-foo/index.html"><span class="identifier">JavaSupertype.Foo</span></a><span class="symbol">!</span></code></td>
diff --git a/core/testdata/format/accessor.md b/core/testdata/format/accessor.md
index 190e8538..9bb2c4ed 100644
--- a/core/testdata/format/accessor.md
+++ b/core/testdata/format/accessor.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](index.md) / [x](./x.md)
+[test](../../index.md) / [C](index.md) / [x](./x.md)
# x
diff --git a/core/testdata/format/annotatedTypeParameter.md b/core/testdata/format/annotatedTypeParameter.md
index aa622eac..36d8aba9 100644
--- a/core/testdata/format/annotatedTypeParameter.md
+++ b/core/testdata/format/annotatedTypeParameter.md
@@ -1,4 +1,4 @@
-[test](index.md) / [containsAll](./contains-all.md)
+[test](../index.md) / [containsAll](./contains-all.md)
# containsAll
diff --git a/core/testdata/format/annotationClass.md b/core/testdata/format/annotationClass.md
index 55fda40c..9ce4aea9 100644
--- a/core/testdata/format/annotationClass.md
+++ b/core/testdata/format/annotationClass.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [fancy](./index.md)
+[test](../../index.md) / [fancy](./index.md)
# fancy
diff --git a/core/testdata/format/annotationClass.package.md b/core/testdata/format/annotationClass.package.md
index c8aff7a3..25e0d77c 100644
--- a/core/testdata/format/annotationClass.package.md
+++ b/core/testdata/format/annotationClass.package.md
@@ -1,4 +1,4 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
diff --git a/core/testdata/format/annotationParams.md b/core/testdata/format/annotationParams.md
index cfa3b822..7388c83a 100644
--- a/core/testdata/format/annotationParams.md
+++ b/core/testdata/format/annotationParams.md
@@ -1,4 +1,4 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/annotations.md b/core/testdata/format/annotations.md
index 2e1604d0..07c22103 100644
--- a/core/testdata/format/annotations.md
+++ b/core/testdata/format/annotations.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
diff --git a/core/testdata/format/arrayAverage.md b/core/testdata/format/arrayAverage.md
index 2c6927d6..5867c1be 100644
--- a/core/testdata/format/arrayAverage.md
+++ b/core/testdata/format/arrayAverage.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [XArray](./index.md)
+[test](../../index.md) / [XArray](./index.md)
# XArray
diff --git a/core/testdata/format/backtickInCodeBlock.md b/core/testdata/format/backtickInCodeBlock.md
index 830539ac..d2267204 100644
--- a/core/testdata/format/backtickInCodeBlock.md
+++ b/core/testdata/format/backtickInCodeBlock.md
@@ -1,4 +1,4 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
diff --git a/core/testdata/format/blankLineInsideCodeBlock.html b/core/testdata/format/blankLineInsideCodeBlock.html
index f0351d72..9db7d4f0 100644
--- a/core/testdata/format/blankLineInsideCodeBlock.html
+++ b/core/testdata/format/blankLineInsideCodeBlock.html
@@ -4,7 +4,7 @@
<title>u - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./u.html">u</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./u.html">u</a><br/>
<br/>
<h1>u</h1>
<a name="$u()"></a>
diff --git a/core/testdata/format/blankLineInsideCodeBlock.md b/core/testdata/format/blankLineInsideCodeBlock.md
index 956f8954..1a3ef10e 100644
--- a/core/testdata/format/blankLineInsideCodeBlock.md
+++ b/core/testdata/format/blankLineInsideCodeBlock.md
@@ -1,4 +1,4 @@
-[test](index.md) / [u](./u.md)
+[test](../index.md) / [u](./u.md)
# u
diff --git a/core/testdata/format/bracket.html b/core/testdata/format/bracket.html
index 01aaaf04..5ba19b73 100644
--- a/core/testdata/format/bracket.html
+++ b/core/testdata/format/bracket.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
diff --git a/core/testdata/format/brokenLink.html b/core/testdata/format/brokenLink.html
index c598a73e..db47c05a 100644
--- a/core/testdata/format/brokenLink.html
+++ b/core/testdata/format/brokenLink.html
@@ -4,7 +4,7 @@
<title>f - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
<br/>
<h1>f</h1>
<a name="$f()"></a>
diff --git a/core/testdata/format/classWithCompanionObject.html b/core/testdata/format/classWithCompanionObject.html
index 88feea5e..e477b53b 100644
--- a/core/testdata/format/classWithCompanionObject.html
+++ b/core/testdata/format/classWithCompanionObject.html
@@ -4,7 +4,7 @@
<title>Klass - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Klass</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Klass</a><br/>
<br/>
<h1>Klass</h1>
<code><span class="keyword">class </span><span class="identifier">Klass</span></code>
@@ -13,7 +13,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">Klass</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -25,7 +25,7 @@
<tbody>
<tr>
<td>
-<p><a href="x.html">x</a></p>
+<h4><a href="x.html">x</a></h4>
</td>
<td>
<code><span class="keyword">val </span><span class="identifier">x</span><span class="symbol">: </span><span class="identifier">Int</span></code></td>
@@ -37,7 +37,7 @@
<tbody>
<tr>
<td>
-<p><a href="foo.html">foo</a></p>
+<h4><a href="foo.html">foo</a></h4>
</td>
<td>
<code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
diff --git a/core/testdata/format/classWithCompanionObject.md b/core/testdata/format/classWithCompanionObject.md
index 40f605be..850e51ec 100644
--- a/core/testdata/format/classWithCompanionObject.md
+++ b/core/testdata/format/classWithCompanionObject.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Klass](./index.md)
+[test](../../index.md) / [Klass](./index.md)
# Klass
diff --git a/core/testdata/format/codeBlock.html b/core/testdata/format/codeBlock.html
index 1e07ff09..ead4dbc0 100644
--- a/core/testdata/format/codeBlock.html
+++ b/core/testdata/format/codeBlock.html
@@ -1,11 +1,11 @@
-<!-- File: test/-throws/index.html -->
+<!-- File: test/--root--/-throws/index.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>Throws - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Throws</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Throws</a><br/>
<br/>
<h1>Throws</h1>
<code><span class="keyword">class </span><span class="identifier">Throws</span></code>
@@ -19,25 +19,24 @@ fun readFile(name: String): String {...}
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Throws</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>This annotation indicates what exceptions should be declared by a function when compiled to a JVM method.</p>
-</td>
+<code><span class="identifier">Throws</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
</BODY>
</HTML>
-<!-- File: test/-it-does-some-obfuscated-thing/index.html -->
+<!-- File: test/--root--/-it-does-some-obfuscated-thing/index.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>ItDoesSomeObfuscatedThing - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">ItDoesSomeObfuscatedThing</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">ItDoesSomeObfuscatedThing</a><br/>
<br/>
<h1>ItDoesSomeObfuscatedThing</h1>
<code><span class="keyword">class </span><span class="identifier">ItDoesSomeObfuscatedThing</span></code>
@@ -49,12 +48,11 @@ fun readFile(name: String): String {...}
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">ItDoesSomeObfuscatedThing</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Check output of</p>
-</td>
+<code><span class="identifier">ItDoesSomeObfuscatedThing</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
diff --git a/core/testdata/format/codeBlock.md b/core/testdata/format/codeBlock.md
index d183a8ba..c14fc7bd 100644
--- a/core/testdata/format/codeBlock.md
+++ b/core/testdata/format/codeBlock.md
@@ -1,5 +1,5 @@
-<!-- File: test/-throws/index.md -->
-[test](../index.md) / [Throws](./index.md)
+<!-- File: test/--root--/-throws/index.md -->
+[test](../../index.md) / [Throws](./index.md)
# Throws
@@ -16,10 +16,10 @@ fun readFile(name: String): String {...}
### Constructors
-| [&lt;init&gt;](-init-.md) | `Throws()`<br>This annotation indicates what exceptions should be declared by a function when compiled to a JVM method. |
+| [&lt;init&gt;](-init-.md) | This annotation indicates what exceptions should be declared by a function when compiled to a JVM method.`Throws()` |
-<!-- File: test/-it-does-some-obfuscated-thing/index.md -->
-[test](../index.md) / [ItDoesSomeObfuscatedThing](./index.md)
+<!-- File: test/--root--/-it-does-some-obfuscated-thing/index.md -->
+[test](../../index.md) / [ItDoesSomeObfuscatedThing](./index.md)
# ItDoesSomeObfuscatedThing
@@ -33,5 +33,5 @@ Check output of
### Constructors
-| [&lt;init&gt;](-init-.md) | `ItDoesSomeObfuscatedThing()`<br>Check output of |
+| [&lt;init&gt;](-init-.md) | Check output of`ItDoesSomeObfuscatedThing()` |
diff --git a/core/testdata/format/codeBlockNoHtmlEscape.md b/core/testdata/format/codeBlockNoHtmlEscape.md
index 548dac4f..a54fc25d 100644
--- a/core/testdata/format/codeBlockNoHtmlEscape.md
+++ b/core/testdata/format/codeBlockNoHtmlEscape.md
@@ -1,4 +1,4 @@
-[test](index.md) / [hackTheArithmetic](./hack-the-arithmetic.md)
+[test](../index.md) / [hackTheArithmetic](./hack-the-arithmetic.md)
# hackTheArithmetic
diff --git a/core/testdata/format/codeSpan.html b/core/testdata/format/codeSpan.html
index bfe93f36..28631dbf 100644
--- a/core/testdata/format/codeSpan.html
+++ b/core/testdata/format/codeSpan.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
diff --git a/core/testdata/format/companionImplements.md b/core/testdata/format/companionImplements.md
index aac7b3e6..2734e1fe 100644
--- a/core/testdata/format/companionImplements.md
+++ b/core/testdata/format/companionImplements.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
@@ -12,5 +12,5 @@ Correct ref [Foo.Companion](-companion.md)
### Constructors
-| [&lt;init&gt;](-init-.md) | `Foo()`<br>Correct ref [Foo.Companion](-companion.md) |
+| [&lt;init&gt;](-init-.md) | Correct ref [Foo.Companion](-companion.md)`Foo()` |
diff --git a/core/testdata/format/companionObjectExtension.md b/core/testdata/format/companionObjectExtension.md
index c0e268e6..43dff899 100644
--- a/core/testdata/format/companionObjectExtension.md
+++ b/core/testdata/format/companionObjectExtension.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
@@ -10,5 +10,5 @@
### Companion Object Extension Properties
-| [x](../x.md) | `val Foo.Default.x: Int`<br>The default object property. |
+| [x](../x.md) | The default object property.`val Foo.Default.x: Int` |
diff --git a/core/testdata/format/crossLanguage/kotlinExtendsJava/Bar.html b/core/testdata/format/crossLanguage/kotlinExtendsJava/Bar.html
index 8842969e..4d08043c 100644
--- a/core/testdata/format/crossLanguage/kotlinExtendsJava/Bar.html
+++ b/core/testdata/format/crossLanguage/kotlinExtendsJava/Bar.html
@@ -14,12 +14,11 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>See <a href="../-foo/xyzzy.html">xyzzy</a></p>
-</td>
+<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
@@ -28,7 +27,7 @@
<tbody>
<tr>
<td>
-<p><a href="../-foo/xyzzy.html">xyzzy</a></p>
+<h4><a href="../-foo/xyzzy.html">xyzzy</a></h4>
</td>
<td>
<code><span class="keyword">open</span> <span class="keyword">fun </span><span class="identifier">xyzzy</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
diff --git a/core/testdata/format/deprecated.class.html b/core/testdata/format/deprecated.class.html
index 540060d1..11d2e944 100644
--- a/core/testdata/format/deprecated.class.html
+++ b/core/testdata/format/deprecated.class.html
@@ -1,11 +1,11 @@
-<!-- File: test/-c/index.html -->
+<!-- File: test/--root--/-c/index.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>C - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">C</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">C</a><br/>
<br/>
<h1>C</h1>
<code><span class="keyword">class </span><s><span class="identifier">C</span></s></code><br/>
@@ -16,7 +16,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">C</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -25,14 +25,14 @@
</table>
</BODY>
</HTML>
-<!-- File: test/f.html -->
+<!-- File: test/--root--/f.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>f - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
<br/>
<h1>f</h1>
<a name="$f()"></a>
@@ -41,14 +41,14 @@
<br/>
</BODY>
</HTML>
-<!-- File: test/p.html -->
+<!-- File: test/--root--/p.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>p - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./p.html">p</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./p.html">p</a><br/>
<br/>
<h1>p</h1>
<a name="$p"></a>
diff --git a/core/testdata/format/deprecated.package.html b/core/testdata/format/deprecated.package.html
index 3506de61..5b218f74 100644
--- a/core/testdata/format/deprecated.package.html
+++ b/core/testdata/format/deprecated.package.html
@@ -4,7 +4,7 @@
<title>root package - test</title>
</HEAD>
<BODY>
-<a href="./index.html">test</a><br/>
+<a href="../index.html">test</a><br/>
<br/>
<h2>Package &lt;root&gt;</h2>
<h3>Types</h3>
@@ -12,7 +12,7 @@
<tbody>
<tr>
<td>
-<p><a href="-c/index.html">C</a></p>
+<h4><a href="-c/index.html">C</a></h4>
</td>
<td>
<code><span class="keyword">class </span><s><span class="identifier">C</span></s></code></td>
@@ -24,7 +24,7 @@
<tbody>
<tr>
<td>
-<p><a href="p.html">p</a></p>
+<h4><a href="p.html">p</a></h4>
</td>
<td>
<code><span class="keyword">val </span><s><span class="identifier">p</span></s><span class="symbol">: </span><span class="identifier">Int</span></code></td>
@@ -36,7 +36,7 @@
<tbody>
<tr>
<td>
-<p><a href="f.html">f</a></p>
+<h4><a href="f.html">f</a></h4>
</td>
<td>
<code><span class="keyword">fun </span><s><span class="identifier">f</span></s><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
diff --git a/core/testdata/format/dynamicExtension.md b/core/testdata/format/dynamicExtension.md
index 382cf973..ed81d66c 100644
--- a/core/testdata/format/dynamicExtension.md
+++ b/core/testdata/format/dynamicExtension.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
diff --git a/core/testdata/format/dynamicType.md b/core/testdata/format/dynamicType.md
index 07a1d103..cfb8fd25 100644
--- a/core/testdata/format/dynamicType.md
+++ b/core/testdata/format/dynamicType.md
@@ -1,4 +1,4 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
diff --git a/core/testdata/format/emptyDescription.md b/core/testdata/format/emptyDescription.md
index 5d56d968..3c14ab75 100644
--- a/core/testdata/format/emptyDescription.md
+++ b/core/testdata/format/emptyDescription.md
@@ -1,4 +1,4 @@
-[test](index.md) / [fn](./fn.md)
+[test](../index.md) / [fn](./fn.md)
# fn
diff --git a/core/testdata/format/entity.html b/core/testdata/format/entity.html
index 639f2903..bfeb34ea 100644
--- a/core/testdata/format/entity.html
+++ b/core/testdata/format/entity.html
@@ -4,7 +4,7 @@
<title>Bar - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
<br/>
<h1>Bar</h1>
<code><span class="keyword">class </span><span class="identifier">Bar</span></code>
@@ -14,12 +14,11 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Copyright &copy; JetBrains 2015 &#x22;</p>
-</td>
+<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
diff --git a/core/testdata/format/enumClass.md b/core/testdata/format/enumClass.md
index 50cccfbb..15070049 100644
--- a/core/testdata/format/enumClass.md
+++ b/core/testdata/format/enumClass.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [InlineOption](./index.md)
+[test](../../index.md) / [InlineOption](./index.md)
# InlineOption
diff --git a/core/testdata/format/enumClass.value.md b/core/testdata/format/enumClass.value.md
index 150016cc..9000a1c4 100644
--- a/core/testdata/format/enumClass.value.md
+++ b/core/testdata/format/enumClass.value.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [InlineOption](index.md) / [LOCAL_CONTINUE_AND_BREAK](./-l-o-c-a-l_-c-o-n-t-i-n-u-e_-a-n-d_-b-r-e-a-k.md)
+[test](../../index.md) / [InlineOption](index.md) / [LOCAL_CONTINUE_AND_BREAK](./-l-o-c-a-l_-c-o-n-t-i-n-u-e_-a-n-d_-b-r-e-a-k.md)
# LOCAL_CONTINUE_AND_BREAK
diff --git a/core/testdata/format/enumRef.md b/core/testdata/format/enumRef.md
index f5f5a3e0..5f6b2f64 100644
--- a/core/testdata/format/enumRef.md
+++ b/core/testdata/format/enumRef.md
@@ -1,4 +1,4 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/exceptionClass.md b/core/testdata/format/exceptionClass.md
index 1e928bb6..44ad6705 100644
--- a/core/testdata/format/exceptionClass.md
+++ b/core/testdata/format/exceptionClass.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [MyException](./index.md)
+[test](../../index.md) / [MyException](./index.md)
# MyException
diff --git a/core/testdata/format/exceptionClass.package.md b/core/testdata/format/exceptionClass.package.md
index 8716df0a..13b1c7db 100644
--- a/core/testdata/format/exceptionClass.package.md
+++ b/core/testdata/format/exceptionClass.package.md
@@ -1,4 +1,4 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
diff --git a/core/testdata/format/exclInCodeBlock.md b/core/testdata/format/exclInCodeBlock.md
index d665c415..0302570e 100644
--- a/core/testdata/format/exclInCodeBlock.md
+++ b/core/testdata/format/exclInCodeBlock.md
@@ -1,4 +1,4 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
diff --git a/core/testdata/format/extensionFunctionParameter.md b/core/testdata/format/extensionFunctionParameter.md
index e1e85824..465fe358 100644
--- a/core/testdata/format/extensionFunctionParameter.md
+++ b/core/testdata/format/extensionFunctionParameter.md
@@ -1,4 +1,4 @@
-[test](index.md) / [apply](./apply.md)
+[test](../index.md) / [apply](./apply.md)
# apply
diff --git a/core/testdata/format/extensionScope.md b/core/testdata/format/extensionScope.md
index ea765bd5..2921346a 100644
--- a/core/testdata/format/extensionScope.md
+++ b/core/testdata/format/extensionScope.md
@@ -1,4 +1,4 @@
-[test](index.md) / [test](./test.md)
+[test](../index.md) / [test](./test.md)
# test
diff --git a/core/testdata/format/extensionWithDocumentedReceiver.md b/core/testdata/format/extensionWithDocumentedReceiver.md
index 0679ac8f..4cee0a04 100644
--- a/core/testdata/format/extensionWithDocumentedReceiver.md
+++ b/core/testdata/format/extensionWithDocumentedReceiver.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [kotlin.String](index.md) / [fn](./fn.md)
+[test](../../index.md) / [kotlin.String](index.md) / [fn](./fn.md)
# fn
diff --git a/core/testdata/format/extensions.class.md b/core/testdata/format/extensions.class.md
index b8fa200a..cd1bb70e 100644
--- a/core/testdata/format/extensions.class.md
+++ b/core/testdata/format/extensions.class.md
@@ -2,6 +2,6 @@
### Extensions for kotlin.String
-| [fn](fn.md) | `fun String.fn(): Unit`<br>`fun String.fn(x: Int): Unit`<br>Function with receiver |
-| [foobar](foobar.md) | `val String.foobar: Int`<br>Property with receiver. |
+| [fn](fn.md) | Function with receiver`fun String.fn(): Unit`<br>`fun String.fn(x: Int): Unit` |
+| [foobar](foobar.md) | Property with receiver.`val String.foobar: Int` |
diff --git a/core/testdata/format/externalReferenceLink.md b/core/testdata/format/externalReferenceLink.md
index 3565d9aa..73840e76 100644
--- a/core/testdata/format/externalReferenceLink.md
+++ b/core/testdata/format/externalReferenceLink.md
@@ -1,4 +1,4 @@
-[test](index.md) / [a](./a.md)
+[test](../index.md) / [a](./a.md)
# a
diff --git a/core/testdata/format/functionWithDefaultParameter.md b/core/testdata/format/functionWithDefaultParameter.md
index 05f7fbe6..535ea18d 100644
--- a/core/testdata/format/functionWithDefaultParameter.md
+++ b/core/testdata/format/functionWithDefaultParameter.md
@@ -1,4 +1,4 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/functionalTypeWithNamedParameters.html b/core/testdata/format/functionalTypeWithNamedParameters.html
index 83d03d8f..af97eb4e 100644
--- a/core/testdata/format/functionalTypeWithNamedParameters.html
+++ b/core/testdata/format/functionalTypeWithNamedParameters.html
@@ -1,11 +1,11 @@
-<!-- File: test/-a/index.html -->
+<!-- File: test/--root--/-a/index.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>A - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">A</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">A</a><br/>
<br/>
<h1>A</h1>
<code><span class="keyword">class </span><span class="identifier">A</span></code>
@@ -14,7 +14,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">A</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -23,14 +23,14 @@
</table>
</BODY>
</HTML>
-<!-- File: test/-b/index.html -->
+<!-- File: test/--root--/-b/index.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>B - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">B</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">B</a><br/>
<br/>
<h1>B</h1>
<code><span class="keyword">class </span><span class="identifier">B</span></code>
@@ -39,7 +39,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">B</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -48,14 +48,14 @@
</table>
</BODY>
</HTML>
-<!-- File: test/-c/index.html -->
+<!-- File: test/--root--/-c/index.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>C - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">C</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">C</a><br/>
<br/>
<h1>C</h1>
<code><span class="keyword">class </span><span class="identifier">C</span></code>
@@ -64,7 +64,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">C</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -73,28 +73,28 @@
</table>
</BODY>
</HTML>
-<!-- File: test/f.html -->
+<!-- File: test/--root--/f.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>f - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
<br/>
<h1>f</h1>
<a name="$f"></a>
<code><span class="keyword">val </span><span class="identifier">f</span><span class="symbol">: </span><span class="symbol">(</span><span class="identifier">a</span><span class="symbol">:</span>&nbsp;<a href="-a/index.html"><span class="identifier">A</span></a><span class="symbol">,</span>&nbsp;<span class="identifier">b</span><span class="symbol">:</span>&nbsp;<a href="-b/index.html"><span class="identifier">B</span></a><span class="symbol">)</span>&nbsp;<span class="symbol">-&gt;</span>&nbsp;<a href="-c/index.html"><span class="identifier">C</span></a></code>
</BODY>
</HTML>
-<!-- File: test/accept-function-type-with-named-arguments.html -->
+<!-- File: test/--root--/accept-function-type-with-named-arguments.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>acceptFunctionTypeWithNamedArguments - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./accept-function-type-with-named-arguments.html">acceptFunctionTypeWithNamedArguments</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./accept-function-type-with-named-arguments.html">acceptFunctionTypeWithNamedArguments</a><br/>
<br/>
<h1>acceptFunctionTypeWithNamedArguments</h1>
<a name="$acceptFunctionTypeWithNamedArguments(kotlin.Function2((B, A, C)))"></a>
diff --git a/core/testdata/format/functionalTypeWithNamedParameters.md b/core/testdata/format/functionalTypeWithNamedParameters.md
index 4e78694c..e1c9681a 100644
--- a/core/testdata/format/functionalTypeWithNamedParameters.md
+++ b/core/testdata/format/functionalTypeWithNamedParameters.md
@@ -1,5 +1,5 @@
-<!-- File: test/-a/index.md -->
-[test](../index.md) / [A](./index.md)
+<!-- File: test/--root--/-a/index.md -->
+[test](../../index.md) / [A](./index.md)
# A
@@ -9,8 +9,8 @@
| [&lt;init&gt;](-init-.md) | `A()` |
-<!-- File: test/-b/index.md -->
-[test](../index.md) / [B](./index.md)
+<!-- File: test/--root--/-b/index.md -->
+[test](../../index.md) / [B](./index.md)
# B
@@ -20,8 +20,8 @@
| [&lt;init&gt;](-init-.md) | `B()` |
-<!-- File: test/-c/index.md -->
-[test](../index.md) / [C](./index.md)
+<!-- File: test/--root--/-c/index.md -->
+[test](../../index.md) / [C](./index.md)
# C
@@ -31,14 +31,14 @@
| [&lt;init&gt;](-init-.md) | `C()` |
-<!-- File: test/f.md -->
-[test](index.md) / [f](./f.md)
+<!-- File: test/--root--/f.md -->
+[test](../index.md) / [f](./f.md)
# f
`val f: (a: `[`A`](-a/index.md)`, b: `[`B`](-b/index.md)`) -> `[`C`](-c/index.md)
-<!-- File: test/accept-function-type-with-named-arguments.md -->
-[test](index.md) / [acceptFunctionTypeWithNamedArguments](./accept-function-type-with-named-arguments.md)
+<!-- File: test/--root--/accept-function-type-with-named-arguments.md -->
+[test](../index.md) / [acceptFunctionTypeWithNamedArguments](./accept-function-type-with-named-arguments.md)
# acceptFunctionTypeWithNamedArguments
diff --git a/core/testdata/format/genericInheritedExtensions.md b/core/testdata/format/genericInheritedExtensions.md
index 8d0e316f..90397676 100644
--- a/core/testdata/format/genericInheritedExtensions.md
+++ b/core/testdata/format/genericInheritedExtensions.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
diff --git a/core/testdata/format/gfm/listInTableCell.md b/core/testdata/format/gfm/listInTableCell.md
index 359ad916..1cafb61a 100644
--- a/core/testdata/format/gfm/listInTableCell.md
+++ b/core/testdata/format/gfm/listInTableCell.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
@@ -14,4 +14,4 @@
| Name | Summary |
|---|---|
-| [foo](foo.md) | `fun foo(): Unit`<ol><li>Foo</li><li>Bar</li></ol> |
+| [foo](foo.md) | <ol><li>Foo</li><li>Bar</li></ol>`fun foo(): Unit` |
diff --git a/core/testdata/format/gfm/sample.md b/core/testdata/format/gfm/sample.md
index 2b082296..a9464ea3 100644
--- a/core/testdata/format/gfm/sample.md
+++ b/core/testdata/format/gfm/sample.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
@@ -10,11 +10,11 @@ The class Foo.
| Name | Summary |
|---|---|
-| [&lt;init&gt;](-init-.md) | `Foo()`<br>The class Foo. |
+| [&lt;init&gt;](-init-.md) | The class Foo.`Foo()` |
### Functions
| Name | Summary |
|---|---|
-| [bar](bar.md) | `fun bar(): Unit`<br>The method bar. |
-| [baz](baz.md) | `fun baz(): Unit`<br>The method baz. |
+| [bar](bar.md) | The method bar.`fun bar(): Unit` |
+| [baz](baz.md) | The method baz.`fun baz(): Unit` |
diff --git a/core/testdata/format/htmlEscaping.html b/core/testdata/format/htmlEscaping.html
index bd64454d..435c3149 100644
--- a/core/testdata/format/htmlEscaping.html
+++ b/core/testdata/format/htmlEscaping.html
@@ -4,7 +4,7 @@
<title>x - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./x.html">x</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./x.html">x</a><br/>
<br/>
<h1>x</h1>
<a name="$x()"></a>
diff --git a/core/testdata/format/inapplicableExtensionFunctions.md b/core/testdata/format/inapplicableExtensionFunctions.md
index 08fc2739..35124b3d 100644
--- a/core/testdata/format/inapplicableExtensionFunctions.md
+++ b/core/testdata/format/inapplicableExtensionFunctions.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
diff --git a/core/testdata/format/indentedCodeBlock.html b/core/testdata/format/indentedCodeBlock.html
index 86c129fb..5b4677d1 100644
--- a/core/testdata/format/indentedCodeBlock.html
+++ b/core/testdata/format/indentedCodeBlock.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
diff --git a/core/testdata/format/indentedCodeBlock.md b/core/testdata/format/indentedCodeBlock.md
index 77b0630a..7542ddb9 100644
--- a/core/testdata/format/indentedCodeBlock.md
+++ b/core/testdata/format/indentedCodeBlock.md
@@ -1,4 +1,4 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
diff --git a/core/testdata/format/inheritedCompanionObjectProperties.md b/core/testdata/format/inheritedCompanionObjectProperties.md
index ab8f0aa5..700570cc 100644
--- a/core/testdata/format/inheritedCompanionObjectProperties.md
+++ b/core/testdata/format/inheritedCompanionObjectProperties.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](./index.md)
+[test](../../index.md) / [C](./index.md)
# C
diff --git a/core/testdata/format/inheritedExtensions.md b/core/testdata/format/inheritedExtensions.md
index 97a73666..3b105e28 100644
--- a/core/testdata/format/inheritedExtensions.md
+++ b/core/testdata/format/inheritedExtensions.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
diff --git a/core/testdata/format/inheritedMembers.md b/core/testdata/format/inheritedMembers.md
index 334df360..0bf1a5f6 100644
--- a/core/testdata/format/inheritedMembers.md
+++ b/core/testdata/format/inheritedMembers.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
diff --git a/core/testdata/format/inlineSuspendFunction.kt b/core/testdata/format/inlineSuspendFunction.kt
index f2009eff..02b3094b 100644
--- a/core/testdata/format/inlineSuspendFunction.kt
+++ b/core/testdata/format/inlineSuspendFunction.kt
@@ -1,6 +1,6 @@
/**
* returns 1
*/
-inline suspend fun foo(): Int {
+inline suspend fun foo(a: () -> String): Int {
1
}
diff --git a/core/testdata/format/inlineSuspendFunction.md b/core/testdata/format/inlineSuspendFunction.md
index 946463f7..e109039c 100644
--- a/core/testdata/format/inlineSuspendFunction.md
+++ b/core/testdata/format/inlineSuspendFunction.md
@@ -1,8 +1,8 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
-`suspend inline fun foo(): Int`
+`suspend inline fun foo(a: () -> String): Int`
returns 1
diff --git a/core/testdata/format/javaCodeInParam.md b/core/testdata/format/javaCodeInParam.md
index 566b176d..7bdf4f62 100644
--- a/core/testdata/format/javaCodeInParam.md
+++ b/core/testdata/format/javaCodeInParam.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](index.md) / [withParam](./with-param.md)
+[test](../../index.md) / [C](index.md) / [withParam](./with-param.md)
# withParam
diff --git a/core/testdata/format/javaCodeLiteralTags.md b/core/testdata/format/javaCodeLiteralTags.md
index c2c58047..88472b87 100644
--- a/core/testdata/format/javaCodeLiteralTags.md
+++ b/core/testdata/format/javaCodeLiteralTags.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](./index.md)
+[test](../../index.md) / [C](./index.md)
# C
@@ -12,5 +12,5 @@ A&lt;B&gt;C
### Constructors
-| [&lt;init&gt;](-init-.md) | `C()`<br>`A<B>C` |
+| [&lt;init&gt;](-init-.md) | `A<B>C``C()` |
diff --git a/core/testdata/format/javaDeprecated.html b/core/testdata/format/javaDeprecated.html
index d938fb9d..66e3adef 100644
--- a/core/testdata/format/javaDeprecated.html
+++ b/core/testdata/format/javaDeprecated.html
@@ -4,7 +4,7 @@
<title>Foo.foo - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="index.html">Foo</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="index.html">Foo</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="Foo$foo()"></a>
diff --git a/core/testdata/format/javaLinkTag.html b/core/testdata/format/javaLinkTag.html
index f90a58df..f61673d5 100644
--- a/core/testdata/format/javaLinkTag.html
+++ b/core/testdata/format/javaLinkTag.html
@@ -4,7 +4,7 @@
<title>Foo - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Foo</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Foo</a><br/>
<br/>
<h1>Foo</h1>
<code><span class="keyword">protected</span> <span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code>
@@ -14,12 +14,11 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Call <code><a href="bar.html">#bar()</a></code> to do the job.</p>
-</td>
+<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
@@ -28,7 +27,7 @@
<tbody>
<tr>
<td>
-<p><a href="bar.html">bar</a></p>
+<h4><a href="bar.html">bar</a></h4>
</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>
diff --git a/core/testdata/format/javaLinkTagWithLabel.html b/core/testdata/format/javaLinkTagWithLabel.html
index 51917f7a..92c67795 100644
--- a/core/testdata/format/javaLinkTagWithLabel.html
+++ b/core/testdata/format/javaLinkTagWithLabel.html
@@ -4,7 +4,7 @@
<title>Foo - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Foo</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Foo</a><br/>
<br/>
<h1>Foo</h1>
<code><span class="keyword">protected</span> <span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code>
@@ -14,12 +14,11 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Call <code><a href="bar.html">this wonderful method</a></code> to do the job.</p>
-</td>
+<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
@@ -28,7 +27,7 @@
<tbody>
<tr>
<td>
-<p><a href="bar.html">bar</a></p>
+<h4><a href="bar.html">bar</a></h4>
</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>
diff --git a/core/testdata/format/javaSeeTag.html b/core/testdata/format/javaSeeTag.html
index f8866dc2..dd19c56c 100644
--- a/core/testdata/format/javaSeeTag.html
+++ b/core/testdata/format/javaSeeTag.html
@@ -4,7 +4,7 @@
<title>Foo - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Foo</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Foo</a><br/>
<br/>
<h1>Foo</h1>
<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Foo</span></code>
@@ -15,7 +15,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">Foo</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
@@ -27,7 +27,7 @@
<tbody>
<tr>
<td>
-<p><a href="bar.html">bar</a></p>
+<h4><a href="bar.html">bar</a></h4>
</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>
diff --git a/core/testdata/format/javaSpaceInAuthor.md b/core/testdata/format/javaSpaceInAuthor.md
index 1d2251d0..fc6c53f8 100644
--- a/core/testdata/format/javaSpaceInAuthor.md
+++ b/core/testdata/format/javaSpaceInAuthor.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](./index.md)
+[test](../../index.md) / [C](./index.md)
# C
diff --git a/core/testdata/format/javadocHtml.md b/core/testdata/format/javadocHtml.md
index 77f6c829..b6a03cd6 100644
--- a/core/testdata/format/javadocHtml.md
+++ b/core/testdata/format/javadocHtml.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](./index.md)
+[test](../../index.md) / [C](./index.md)
# C
@@ -34,5 +34,5 @@ with (some) { <code> }
### Constructors
-| [&lt;init&gt;](-init-.md) | `C()`<br>**Bold** **Strong** *Italic* *Emphasized* |
+| [&lt;init&gt;](-init-.md) | **Bold** **Strong** *Italic* *Emphasized* `C()` |
diff --git a/core/testdata/format/javadocOrderedList.md b/core/testdata/format/javadocOrderedList.md
index 88d5f5b6..1d94ad5b 100644
--- a/core/testdata/format/javadocOrderedList.md
+++ b/core/testdata/format/javadocOrderedList.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -10,8 +10,8 @@
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>
+| [&lt;init&gt;](-init-.md) |
1. Rinse
2. Repeat
- <br> |
+ <br>`Bar()` |
diff --git a/core/testdata/format/jdkLinks.md b/core/testdata/format/jdkLinks.md
index c3a5fbf4..eddee485 100644
--- a/core/testdata/format/jdkLinks.md
+++ b/core/testdata/format/jdkLinks.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](./index.md)
+[test](../../index.md) / [C](./index.md)
# C
@@ -10,5 +10,5 @@ You can print something to [java.lang.System.out](https://docs.oracle.com/javase
### Constructors
-| [&lt;init&gt;](-init-.md) | `C()`<br>This is a [ClassLoader](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) and I can get its [ClassLoader.getResource](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)) |
+| [&lt;init&gt;](-init-.md) | This is a [ClassLoader](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) and I can get its [ClassLoader.getResource](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String))`C()` |
diff --git a/core/testdata/format/linkWithLabel.html b/core/testdata/format/linkWithLabel.html
index 59bc6ddf..52dfa4a3 100644
--- a/core/testdata/format/linkWithLabel.html
+++ b/core/testdata/format/linkWithLabel.html
@@ -4,7 +4,7 @@
<title>Bar - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
<br/>
<h1>Bar</h1>
<code><span class="keyword">class </span><span class="identifier">Bar</span></code>
@@ -14,12 +14,11 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Use <a href="foo.html">this method</a> for best results.</p>
-</td>
+<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
@@ -28,7 +27,7 @@
<tbody>
<tr>
<td>
-<p><a href="foo.html">foo</a></p>
+<h4><a href="foo.html">foo</a></h4>
</td>
<td>
<code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
diff --git a/core/testdata/format/linkWithStarProjection.html b/core/testdata/format/linkWithStarProjection.html
index e1b6e098..ce9b82c6 100644
--- a/core/testdata/format/linkWithStarProjection.html
+++ b/core/testdata/format/linkWithStarProjection.html
@@ -4,7 +4,7 @@
<title>KClassLoader - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">KClassLoader</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">KClassLoader</a><br/>
<br/>
<h1>KClassLoader</h1>
<code><span class="keyword">object </span><span class="identifier">KClassLoader</span></code>
@@ -13,7 +13,7 @@
<tbody>
<tr>
<td>
-<p><a href="foo.html">foo</a></p>
+<h4><a href="foo.html">foo</a></h4>
</td>
<td>
<code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="identifier" id="KClassLoader$foo(kotlin.Enum(()))/c">c</span><span class="symbol">:</span>&nbsp;<span class="identifier">Enum</span><span class="symbol">&lt;</span><span class="identifier">*</span><span class="symbol">&gt;</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
diff --git a/core/testdata/format/linksInEmphasis.md b/core/testdata/format/linksInEmphasis.md
index d0ae70c8..984941fa 100644
--- a/core/testdata/format/linksInEmphasis.md
+++ b/core/testdata/format/linksInEmphasis.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -14,7 +14,7 @@ An emphasised class.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>An emphasised class. |
+| [&lt;init&gt;](-init-.md) | An emphasised class.`Bar()` |
### Functions
diff --git a/core/testdata/format/linksInHeaders.md b/core/testdata/format/linksInHeaders.md
index 1dc7d18b..2f18d442 100644
--- a/core/testdata/format/linksInHeaders.md
+++ b/core/testdata/format/linksInHeaders.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -20,7 +20,7 @@ Some class with really useless documentation.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>Some class with really useless documentation. |
+| [&lt;init&gt;](-init-.md) | Some class with really useless documentation.`Bar()` |
### Functions
diff --git a/core/testdata/format/linksInStrong.md b/core/testdata/format/linksInStrong.md
index 5b44112d..d234937b 100644
--- a/core/testdata/format/linksInStrong.md
+++ b/core/testdata/format/linksInStrong.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -14,7 +14,7 @@ A strong class.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>A strong class. |
+| [&lt;init&gt;](-init-.md) | A strong class.`Bar()` |
### Functions
diff --git a/core/testdata/format/markdownInLinks.html b/core/testdata/format/markdownInLinks.html
index f0bb475e..f1146ea0 100644
--- a/core/testdata/format/markdownInLinks.html
+++ b/core/testdata/format/markdownInLinks.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
diff --git a/core/testdata/format/memberExtension.md b/core/testdata/format/memberExtension.md
index 0ec1fda3..f52b46f2 100644
--- a/core/testdata/format/memberExtension.md
+++ b/core/testdata/format/memberExtension.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
diff --git a/core/testdata/format/multiplatform/breadcrumbsInMemberOfMemberOfGroupNode/multiplatform.md b/core/testdata/format/multiplatform/breadcrumbsInMemberOfMemberOfGroupNode/multiplatform.md
index 37e943ad..d70f9d8b 100644
--- a/core/testdata/format/multiplatform/breadcrumbsInMemberOfMemberOfGroupNode/multiplatform.md
+++ b/core/testdata/format/multiplatform/breadcrumbsInMemberOfMemberOfGroupNode/multiplatform.md
@@ -1,8 +1,5 @@
-[test](../../../index.md) / [pack](../../index.md) / [Some](../index.md) / [magic](./magic.md)
+[test](../../index.md) / [pack](../index.md) / [Some](index.md) / [magic](./magic.md)
# magic
-`fun magic(): Unit`
-
-**Platform and version requirements:** JS
-
+(JS) `fun magic(): Unit` \ No newline at end of file
diff --git a/core/testdata/format/multiplatform/groupNode/multiplatform.md b/core/testdata/format/multiplatform/groupNode/multiplatform.md
index 74d464c9..d8b577ca 100644
--- a/core/testdata/format/multiplatform/groupNode/multiplatform.md
+++ b/core/testdata/format/multiplatform/groupNode/multiplatform.md
@@ -2,19 +2,13 @@
# Some
-`typealias Some = SomeCoolJvmClass`
-
-**Platform and version requirements:** JVM
-
-`class Some`
-
-**Platform and version requirements:** JS
+(JVM) `typealias Some = SomeCoolJvmClass`(JS) `class Some`
### Constructors
-| [&lt;init&gt;](-some/-init-.md) | `Some()` |
+| (JS) [&lt;init&gt;](-init-.md) | `Some()` |
### Functions
-| [magic](-some/magic.md) | `fun magic(): Unit` |
+| (JS) [magic](magic.md) | `fun magic(): Unit` |
diff --git a/core/testdata/format/multiplatform/groupNode/multiplatform.package.md b/core/testdata/format/multiplatform/groupNode/multiplatform.package.md
index 5708795e..cf1f70f0 100644
--- a/core/testdata/format/multiplatform/groupNode/multiplatform.package.md
+++ b/core/testdata/format/multiplatform/groupNode/multiplatform.package.md
@@ -4,10 +4,6 @@
### Types
-| [Some](-some/index.md)<br>(JS) | `class Some` |
-| [SomeCoolJvmClass](-some-cool-jvm-class/index.md)<br>(JVM) | `class SomeCoolJvmClass` |
-
-### Type Aliases
-
-| [Some](-some/index.md)<br>(JVM) | `typealias Some = SomeCoolJvmClass` |
+| [Some](-some/index.md) | (JVM) `typealias Some = SomeCoolJvmClass`<br>(JS) `class Some` |
+| (JVM) [SomeCoolJvmClass](-some-cool-jvm-class/index.md) | `class SomeCoolJvmClass` |
diff --git a/core/testdata/format/multiplatform/implied/foo.md b/core/testdata/format/multiplatform/implied/foo.md
index fca2aff4..c261df36 100644
--- a/core/testdata/format/multiplatform/implied/foo.md
+++ b/core/testdata/format/multiplatform/implied/foo.md
@@ -2,23 +2,23 @@
# Foo
-`class Foo`
+(JVM, JS) `class Foo`
This is a foo.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Foo()`<br>This is a foo. |
+| (JVM, JS) [&lt;init&gt;](-init-.md) | This is a foo.`<init>()` |
### Properties
-| [propJs](prop-js.md)<br>(JS) | `val propJs: String` |
-| [propJvm](prop-jvm.md)<br>(JVM) | `val propJvm: String` |
-| [propJvmAndJs](prop-jvm-and-js.md) | `val propJvmAndJs: Int` |
+| (JS) [propJs](prop-js.md) | `val propJs: String` |
+| (JVM) [propJvm](prop-jvm.md) | `val propJvm: String` |
+| (JVM, JS) [propJvmAndJs](prop-jvm-and-js.md) | `val propJvmAndJs: Int` |
### Functions
-| [bothJvmAndJs](both-jvm-and-js.md) | `fun bothJvmAndJs(): Unit` |
-| [js](js.md)<br>(JS) | `fun js(): Unit` |
-| [jvm](jvm.md)<br>(JVM) | `fun jvm(): Unit` |
+| (JVM, JS) [bothJvmAndJs](both-jvm-and-js.md) | `fun bothJvmAndJs(): Unit` |
+| (JS) [js](js.md) | `fun js(): Unit` |
+| (JVM) [jvm](jvm.md) | `fun jvm(): Unit` |
diff --git a/core/testdata/format/multiplatform/merge/multiplatform.package.md b/core/testdata/format/multiplatform/merge/multiplatform.package.md
index ea78b5a3..60ed85c4 100644
--- a/core/testdata/format/multiplatform/merge/multiplatform.package.md
+++ b/core/testdata/format/multiplatform/merge/multiplatform.package.md
@@ -2,9 +2,7 @@
## Package foo
-**Platform and version requirements:** JVM, JS
-
### Types
-| [Foo](-foo/index.md)<br>(JVM, JS) | `class Foo`<br>This is a foo. |
+| (JVM, JS) [Foo](-foo/index.md) | This is a foo.`class Foo` |
diff --git a/core/testdata/format/multiplatform/mergeMembers/foo.md b/core/testdata/format/multiplatform/mergeMembers/foo.md
index 7f41b7d1..c261df36 100644
--- a/core/testdata/format/multiplatform/mergeMembers/foo.md
+++ b/core/testdata/format/multiplatform/mergeMembers/foo.md
@@ -2,25 +2,23 @@
# Foo
-`class Foo`
-
-**Platform and version requirements:** JVM, JS
+(JVM, JS) `class Foo`
This is a foo.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Foo()`<br>This is a foo. |
+| (JVM, JS) [&lt;init&gt;](-init-.md) | This is a foo.`<init>()` |
### Properties
-| [propJs](prop-js.md)<br>(JS) | `val propJs: String` |
-| [propJvm](prop-jvm.md)<br>(JVM) | `val propJvm: String` |
-| [propJvmAndJs](prop-jvm-and-js.md) | `val propJvmAndJs: Int` |
+| (JS) [propJs](prop-js.md) | `val propJs: String` |
+| (JVM) [propJvm](prop-jvm.md) | `val propJvm: String` |
+| (JVM, JS) [propJvmAndJs](prop-jvm-and-js.md) | `val propJvmAndJs: Int` |
### Functions
-| [bothJvmAndJs](both-jvm-and-js.md) | `fun bothJvmAndJs(): Unit` |
-| [js](js.md)<br>(JS) | `fun js(): Unit` |
-| [jvm](jvm.md)<br>(JVM) | `fun jvm(): Unit` |
+| (JVM, JS) [bothJvmAndJs](both-jvm-and-js.md) | `fun bothJvmAndJs(): Unit` |
+| (JS) [js](js.md) | `fun js(): Unit` |
+| (JVM) [jvm](jvm.md) | `fun jvm(): Unit` |
diff --git a/core/testdata/format/multiplatform/omitRedundant/foo.md b/core/testdata/format/multiplatform/omitRedundant/foo.md
index a20b14cf..5ed92d51 100644
--- a/core/testdata/format/multiplatform/omitRedundant/foo.md
+++ b/core/testdata/format/multiplatform/omitRedundant/foo.md
@@ -2,21 +2,19 @@
# Foo
-`class Foo`
-
-**Platform and version requirements:** JVM
+(JVM) `class Foo`
This is a foo.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Foo()`<br>This is a foo. |
+| (JVM) [&lt;init&gt;](-init-.md) | This is a foo.`Foo()` |
### Properties
-| [propJvm](prop-jvm.md) | `val propJvm: String` |
+| (JVM) [propJvm](prop-jvm.md) | `val propJvm: String` |
### Functions
-| [jvm](jvm.md) | `fun jvm(): Unit` |
+| (JVM) [jvm](jvm.md) | `fun jvm(): Unit` |
diff --git a/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.index.md b/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.index.md
index 6f45342b..9b0d6b63 100644
--- a/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.index.md
+++ b/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.index.md
@@ -1,10 +1,8 @@
[test](./index.md)
-**Platform and version requirements:** JVM, JS
-
### Packages
-| [foo.bar](foo.bar/index.md)<br>(JVM, JS) | |
+| (JVM, JS) [foo.bar](foo.bar/index.md) | |
### Index
diff --git a/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.package.md b/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.package.md
index 4ddfe2e3..a7fef864 100644
--- a/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.package.md
+++ b/core/testdata/format/multiplatform/packagePlatformsFromMembers/multiplatform.package.md
@@ -2,9 +2,7 @@
## Package foo.bar
-**Platform and version requirements:** JVM, JS
-
### Functions
-| [buz](buz.md)<br>(JVM, JS) | `fun buz(): Unit` |
+| (JVM, JS) [buz](buz.md) | `fun buz(): Unit` |
diff --git a/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.index.md b/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.index.md
index f4186b6e..b5543c80 100644
--- a/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.index.md
+++ b/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.index.md
@@ -1,10 +1,8 @@
[test](./index.md)
-**Platform and version requirements:** JVM
-
### Packages
-| [some](some/index.md)<br>(JVM) | |
+| (JVM) [some](some/index.md) | |
### Index
diff --git a/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.package.md b/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.package.md
index ff480b5a..6e42d0dc 100644
--- a/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.package.md
+++ b/core/testdata/format/multiplatform/packagePlatformsWithExtExtensions/multiplatform.package.md
@@ -2,9 +2,7 @@
## Package some
-**Platform and version requirements:** JVM
-
### Extensions for External Classes
-| [kotlin.String](kotlin.-string/index.md) | |
+| (JVM) [kotlin.String](kotlin.-string/index.md) | |
diff --git a/core/testdata/format/multiplatform/simple/multiplatform.package.md b/core/testdata/format/multiplatform/simple/multiplatform.package.md
index fad7e90d..73f7d1df 100644
--- a/core/testdata/format/multiplatform/simple/multiplatform.package.md
+++ b/core/testdata/format/multiplatform/simple/multiplatform.package.md
@@ -4,6 +4,6 @@
### Types
-| [Bar](-bar/index.md)<br>(JS) | `class Bar`<br>This is a bar. |
-| [Foo](-foo/index.md)<br>(JVM) | `class Foo`<br>This is a foo. |
+| (JS) [Bar](-bar/index.md) | This is a bar.`class Bar` |
+| (JVM) [Foo](-foo/index.md) | This is a foo.`class Foo` |
diff --git a/core/testdata/format/multipleTypeParameterConstraints.md b/core/testdata/format/multipleTypeParameterConstraints.md
index 78586aca..27581598 100644
--- a/core/testdata/format/multipleTypeParameterConstraints.md
+++ b/core/testdata/format/multipleTypeParameterConstraints.md
@@ -1,17 +1,17 @@
-<!-- File: test/-a.md -->
-[test](index.md) / [A](./-a.md)
+<!-- File: test/--root--/-a.md -->
+[test](../index.md) / [A](./-a.md)
# A
`interface A`
-<!-- File: test/-b.md -->
-[test](index.md) / [B](./-b.md)
+<!-- File: test/--root--/-b.md -->
+[test](../index.md) / [B](./-b.md)
# B
`interface B`
-<!-- File: test/f.md -->
-[test](index.md) / [f](./f.md)
+<!-- File: test/--root--/f.md -->
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/nestedLists.md b/core/testdata/format/nestedLists.md
index fb25bc32..6b8de8dc 100644
--- a/core/testdata/format/nestedLists.md
+++ b/core/testdata/format/nestedLists.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -29,7 +29,7 @@ Usage instructions:
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>Usage instructions: |
+| [&lt;init&gt;](-init-.md) | Usage instructions:`Bar()` |
### Properties
diff --git a/core/testdata/format/newlineInTableCell.package.md b/core/testdata/format/newlineInTableCell.package.md
index 53716db3..6ed783b3 100644
--- a/core/testdata/format/newlineInTableCell.package.md
+++ b/core/testdata/format/newlineInTableCell.package.md
@@ -1,8 +1,8 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
### Types
-| [A](-a/index.md) | `class A`<br>There is `long long int` story full of new lines |
+| [A](-a/index.md) | There is `long long int` story full of new lines`class A` |
diff --git a/core/testdata/format/notPublishedTypeAliasAutoExpansion.md b/core/testdata/format/notPublishedTypeAliasAutoExpansion.md
index ca95093c..75b6db3e 100644
--- a/core/testdata/format/notPublishedTypeAliasAutoExpansion.md
+++ b/core/testdata/format/notPublishedTypeAliasAutoExpansion.md
@@ -1,4 +1,4 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
diff --git a/core/testdata/format/nullability.md b/core/testdata/format/nullability.md
index 7b81c255..2acd6f65 100644
--- a/core/testdata/format/nullability.md
+++ b/core/testdata/format/nullability.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](./index.md)
+[test](../../index.md) / [C](./index.md)
# C
diff --git a/core/testdata/format/nullableTypeParameterFunction.md b/core/testdata/format/nullableTypeParameterFunction.md
index 5764007b..ec968537 100644
--- a/core/testdata/format/nullableTypeParameterFunction.md
+++ b/core/testdata/format/nullableTypeParameterFunction.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
diff --git a/core/testdata/format/operatorOverloading.md b/core/testdata/format/operatorOverloading.md
index 0a4c87b6..df8ea182 100644
--- a/core/testdata/format/operatorOverloading.md
+++ b/core/testdata/format/operatorOverloading.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [C](index.md) / [plus](./plus.md)
+[test](../../index.md) / [C](index.md) / [plus](./plus.md)
# plus
diff --git a/core/testdata/format/orderedList.html b/core/testdata/format/orderedList.html
index 6f735bfd..b84de731 100644
--- a/core/testdata/format/orderedList.html
+++ b/core/testdata/format/orderedList.html
@@ -4,7 +4,7 @@
<title>Bar - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
<br/>
<h1>Bar</h1>
<code><span class="keyword">class </span><span class="identifier">Bar</span></code>
@@ -17,12 +17,11 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
-<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Usage instructions:</p>
-</td>
+<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
diff --git a/core/testdata/format/overloads.html b/core/testdata/format/overloads.html
index feda82e4..8e0693bf 100644
--- a/core/testdata/format/overloads.html
+++ b/core/testdata/format/overloads.html
@@ -4,7 +4,7 @@
<title>root package - test</title>
</HEAD>
<BODY>
-<a href="./index.html">test</a><br/>
+<a href="../index.html">test</a><br/>
<br/>
<h2>Package &lt;root&gt;</h2>
<h3>Functions</h3>
@@ -12,13 +12,12 @@
<tbody>
<tr>
<td>
-<p><a href="f.html">f</a></p>
+<h4><a href="f.html">f</a></h4>
</td>
<td>
-<code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier" id="$f(kotlin.Int)/x">x</span><span class="symbol">:</span>&nbsp;<span class="identifier">Int</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code><br/>
-<code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier" id="$f(kotlin.String)/x">x</span><span class="symbol">:</span>&nbsp;<span class="identifier">String</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code>
<p>Performs an action on x.</p>
-</td>
+<code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier" id="$f(kotlin.Int)/x">x</span><span class="symbol">:</span>&nbsp;<span class="identifier">Int</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code><br/>
+<code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier" id="$f(kotlin.String)/x">x</span><span class="symbol">:</span>&nbsp;<span class="identifier">String</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
</tr>
</tbody>
</table>
diff --git a/core/testdata/format/overloadsWithDescription.html b/core/testdata/format/overloadsWithDescription.html
index 16b03f7e..329393d1 100644
--- a/core/testdata/format/overloadsWithDescription.html
+++ b/core/testdata/format/overloadsWithDescription.html
@@ -4,7 +4,7 @@
<title>f - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
<br/>
<h1>f</h1>
<a name="$f(kotlin.Int)"></a>
diff --git a/core/testdata/format/overloadsWithDifferentDescriptions.html b/core/testdata/format/overloadsWithDifferentDescriptions.html
index 4c4f7f74..c2a348c6 100644
--- a/core/testdata/format/overloadsWithDifferentDescriptions.html
+++ b/core/testdata/format/overloadsWithDifferentDescriptions.html
@@ -4,7 +4,7 @@
<title>f - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
<br/>
<h1>f</h1>
<a name="$f(kotlin.Int)"></a>
diff --git a/core/testdata/format/overridingFunction.md b/core/testdata/format/overridingFunction.md
index d0ec82fa..91c81410 100644
--- a/core/testdata/format/overridingFunction.md
+++ b/core/testdata/format/overridingFunction.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [D](index.md) / [f](./f.md)
+[test](../../index.md) / [D](index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/paramTag.md b/core/testdata/format/paramTag.md
index 7cc33d21..9a368d3a 100644
--- a/core/testdata/format/paramTag.md
+++ b/core/testdata/format/paramTag.md
@@ -1,4 +1,4 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/parameterAnchor.html b/core/testdata/format/parameterAnchor.html
index a4ae0997..e54a066b 100644
--- a/core/testdata/format/parameterAnchor.html
+++ b/core/testdata/format/parameterAnchor.html
@@ -4,7 +4,7 @@
<title>processFiles - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./process-files.html">processFiles</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./process-files.html">processFiles</a><br/>
<br/>
<h1>processFiles</h1>
<a name="$processFiles(kotlin.Function0((processFiles.T)))"></a>
diff --git a/core/testdata/format/parenthesis.html b/core/testdata/format/parenthesis.html
index c63154c1..8f6edbee 100644
--- a/core/testdata/format/parenthesis.html
+++ b/core/testdata/format/parenthesis.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
diff --git a/core/testdata/format/propertyVar.md b/core/testdata/format/propertyVar.md
index 887d25a5..474379d9 100644
--- a/core/testdata/format/propertyVar.md
+++ b/core/testdata/format/propertyVar.md
@@ -1,4 +1,4 @@
-[test](index.md) / [x](./x.md)
+[test](../index.md) / [x](./x.md)
# x
diff --git a/core/testdata/format/qualifiedNameLink.md b/core/testdata/format/qualifiedNameLink.md
index 92fa8f7a..53984037 100644
--- a/core/testdata/format/qualifiedNameLink.md
+++ b/core/testdata/format/qualifiedNameLink.md
@@ -1,4 +1,4 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
diff --git a/core/testdata/format/receiverParameterTypeBound.md b/core/testdata/format/receiverParameterTypeBound.md
index 978dc0f8..95f3beec 100644
--- a/core/testdata/format/receiverParameterTypeBound.md
+++ b/core/testdata/format/receiverParameterTypeBound.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
diff --git a/core/testdata/format/receiverReference.md b/core/testdata/format/receiverReference.md
index bdcce322..96c6ec61 100644
--- a/core/testdata/format/receiverReference.md
+++ b/core/testdata/format/receiverReference.md
@@ -1,6 +1,6 @@
-[test](../index.md) / [kotlin.String](./index.md)
+[test](../../index.md) / [kotlin.String](./index.md)
### Extensions for kotlin.String
-| [some](some.md) | `fun String.some(): Unit`<br>Prints [this](some/-this-.md) |
+| [some](some.md) | Prints [this](some/-this-.md)`fun String.some(): Unit` |
diff --git a/core/testdata/format/reifiedTypeParameter.kt b/core/testdata/format/reifiedTypeParameter.kt
index 00fa1dc9..1b1de359 100644
--- a/core/testdata/format/reifiedTypeParameter.kt
+++ b/core/testdata/format/reifiedTypeParameter.kt
@@ -1,3 +1,3 @@
-inline fun f<reified T>() {
+inline fun f<reified T>(a: () -> String) {
}
diff --git a/core/testdata/format/reifiedTypeParameter.md b/core/testdata/format/reifiedTypeParameter.md
index 40dbed7b..7bb406ee 100644
--- a/core/testdata/format/reifiedTypeParameter.md
+++ b/core/testdata/format/reifiedTypeParameter.md
@@ -1,5 +1,5 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
-`inline fun <reified T> f(): Unit` \ No newline at end of file
+`inline fun <reified T> f(a: () -> String): Unit` \ No newline at end of file
diff --git a/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md b/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md
index 4b5f3a64..6d449fb4 100644
--- a/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md
+++ b/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [kotlin.coroutines.SuspendFunction0](./index.md)
+[test](../../index.md) / [kotlin.coroutines.SuspendFunction0](./index.md)
### Extensions for kotlin.coroutines.SuspendFunction0
diff --git a/core/testdata/format/returnWithLink.html b/core/testdata/format/returnWithLink.html
index fe1d031b..9f36d294 100644
--- a/core/testdata/format/returnWithLink.html
+++ b/core/testdata/format/returnWithLink.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo(kotlin.String)"></a>
diff --git a/core/testdata/format/see.html b/core/testdata/format/see.html
index 74773951..2a8caf6f 100644
--- a/core/testdata/format/see.html
+++ b/core/testdata/format/see.html
@@ -1,11 +1,11 @@
-<!-- File: test/quux.html -->
+<!-- File: test/--root--/quux.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>quux - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./quux.html">quux</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./quux.html">quux</a><br/>
<br/>
<h1>quux</h1>
<a name="$quux()"></a>
@@ -16,28 +16,28 @@
</p>
</BODY>
</HTML>
-<!-- File: test/foo.html -->
+<!-- File: test/--root--/foo.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
<code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code>
</BODY>
</HTML>
-<!-- File: test/bar.html -->
+<!-- File: test/--root--/bar.html -->
<HTML>
<HEAD>
<meta charset="UTF-8">
<title>bar - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./bar.html">bar</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./bar.html">bar</a><br/>
<br/>
<h1>bar</h1>
<a name="$bar()"></a>
diff --git a/core/testdata/format/shadowedExtensionFunctions.md b/core/testdata/format/shadowedExtensionFunctions.md
index f900ecb2..4adfda6a 100644
--- a/core/testdata/format/shadowedExtensionFunctions.md
+++ b/core/testdata/format/shadowedExtensionFunctions.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
diff --git a/core/testdata/format/sinceKotlin.html b/core/testdata/format/sinceKotlin.html
index 32988de2..3ca6889a 100644
--- a/core/testdata/format/sinceKotlin.html
+++ b/core/testdata/format/sinceKotlin.html
@@ -4,23 +4,21 @@
<title>Since1.1 - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Since1.1</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Since1.1</a><br/>
<br/>
<h1>Since1.1</h1>
<code><span class="keyword">class </span><span class="identifier">Since1.1</span></code>
-<p><strong>Platform and version requirements:</strong> Kotlin 1.1</p>
<p>Useful</p>
<h3>Constructors</h3>
<table>
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
-</td>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
+Since: <code>1.1</code></td>
<td>
-<code><span class="identifier">Since1.1</span><span class="symbol">(</span><span class="symbol">)</span></code>
<p>Useful</p>
-</td>
+<code><span class="identifier">Since1.1</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
</tr>
</tbody>
</table>
diff --git a/core/testdata/format/sinceKotlin.md b/core/testdata/format/sinceKotlin.md
index df96db0a..197be48c 100644
--- a/core/testdata/format/sinceKotlin.md
+++ b/core/testdata/format/sinceKotlin.md
@@ -1,14 +1,12 @@
-[test](../index.md) / [Since1.1](./index.md)
+[test](../../index.md) / [Since1.1](./index.md)
# Since1.1
`class Since1.1`
-**Platform and version requirements:** Kotlin 1.1
-
Useful
### Constructors
-| [&lt;init&gt;](-init-.md) | `Since1.1()`<br>Useful |
+| [&lt;init&gt;](-init-.md)Since: `1.1` | Useful`Since1.1()` |
diff --git a/core/testdata/format/sinceKotlin.package.md b/core/testdata/format/sinceKotlin.package.md
index eabf88d5..fa29e019 100644
--- a/core/testdata/format/sinceKotlin.package.md
+++ b/core/testdata/format/sinceKotlin.package.md
@@ -1,10 +1,8 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
-**Platform and version requirements:** Kotlin 1.1
-
### Types
-| [Since1.1](-since1.1/index.md)<br>(Kotlin 1.1) | `class Since1.1`<br>Useful |
+| [Since1.1](-since1.1/index.md) (Since: `1.1`) | Useful`class Since1.1` |
diff --git a/core/testdata/format/sinceKotlinWide.package.md b/core/testdata/format/sinceKotlinWide.package.md
index 58a5045e..d79d593d 100644
--- a/core/testdata/format/sinceKotlinWide.package.md
+++ b/core/testdata/format/sinceKotlinWide.package.md
@@ -1,11 +1,9 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
-**Platform and version requirements:** Kotlin 1.1+
-
### Types
-| [Since1.1](-since1.1/index.md)<br>(Kotlin 1.1) | `class Since1.1`<br>Useful |
-| [Since1.2](-since1.2/index.md)<br>(Kotlin 1.2) | `class Since1.2`<br>Useful also |
+| [Since1.1](-since1.1/index.md) (Since: `1.1`) | Useful`class Since1.1` |
+| [Since1.2](-since1.2/index.md) (Since: `1.2`) | Useful also`class Since1.2` |
diff --git a/core/testdata/format/starProjection.md b/core/testdata/format/starProjection.md
index 5a53e5b9..594a7d72 100644
--- a/core/testdata/format/starProjection.md
+++ b/core/testdata/format/starProjection.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [kotlin.collections.Iterable](./index.md)
+[test](../../index.md) / [kotlin.collections.Iterable](./index.md)
### Extensions for kotlin.collections.Iterable
diff --git a/core/testdata/format/summarizeSignatures.md b/core/testdata/format/summarizeSignatures.md
index 4f494166..a6755328 100644
--- a/core/testdata/format/summarizeSignatures.md
+++ b/core/testdata/format/summarizeSignatures.md
@@ -10,5 +10,5 @@
### Functions
-| [foo](foo.md) | `fun <T> any_array<T>.foo(predicate: (`[`T`](foo.md#T)`) -> Boolean): Boolean`<br>Returns true if foo. |
+| [foo](foo.md) | Returns true if foo.`fun <T> any_array<T>.foo(predicate: (`[`T`](foo.md#T)`) -> Boolean): Boolean` |
diff --git a/core/testdata/format/summarizeSignaturesProperty.md b/core/testdata/format/summarizeSignaturesProperty.md
index 507ad6a5..1070a060 100644
--- a/core/testdata/format/summarizeSignaturesProperty.md
+++ b/core/testdata/format/summarizeSignaturesProperty.md
@@ -10,5 +10,5 @@
### Properties
-| [foo](foo.md) | `val <T> any_array<T>.foo: Int`<br>Returns true if foo. |
+| [foo](foo.md) | Returns true if foo.`val <T> any_array<T>.foo: Int` |
diff --git a/core/testdata/format/suspendInlineFunction.md b/core/testdata/format/suspendInlineFunction.md
index 946463f7..056c8799 100644
--- a/core/testdata/format/suspendInlineFunction.md
+++ b/core/testdata/format/suspendInlineFunction.md
@@ -1,8 +1,8 @@
-[test](index.md) / [foo](./foo.md)
+[test](../index.md) / [foo](./foo.md)
# foo
-`suspend inline fun foo(): Int`
+`suspend fun foo(): Int`
returns 1
diff --git a/core/testdata/format/suspendParam.md b/core/testdata/format/suspendParam.md
index ab116140..7bc656f4 100644
--- a/core/testdata/format/suspendParam.md
+++ b/core/testdata/format/suspendParam.md
@@ -1,4 +1,4 @@
-[test](index.md) / [takesSuspendParam](./takes-suspend-param.md)
+[test](../index.md) / [takesSuspendParam](./takes-suspend-param.md)
# takesSuspendParam
diff --git a/core/testdata/format/suspendParam.package.md b/core/testdata/format/suspendParam.package.md
index 92bd7ee7..3fdb1bc6 100644
--- a/core/testdata/format/suspendParam.package.md
+++ b/core/testdata/format/suspendParam.package.md
@@ -1,4 +1,4 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
diff --git a/core/testdata/format/throwsTag.md b/core/testdata/format/throwsTag.md
index 70fba512..104493a7 100644
--- a/core/testdata/format/throwsTag.md
+++ b/core/testdata/format/throwsTag.md
@@ -1,4 +1,4 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/tokensInEmphasis.md b/core/testdata/format/tokensInEmphasis.md
index a68861de..0dd78dec 100644
--- a/core/testdata/format/tokensInEmphasis.md
+++ b/core/testdata/format/tokensInEmphasis.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -12,7 +12,7 @@ Another emphasised class.
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>Another emphasised class. |
+| [&lt;init&gt;](-init-.md) | Another emphasised class.`Bar()` |
### Functions
diff --git a/core/testdata/format/tokensInHeaders.md b/core/testdata/format/tokensInHeaders.md
index bd25492e..31abd971 100644
--- a/core/testdata/format/tokensInHeaders.md
+++ b/core/testdata/format/tokensInHeaders.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [The](./index.md)
+[test](../../index.md) / [The](./index.md)
# The
@@ -24,7 +24,7 @@ Why did the token cross the road?
### Constructors
-| [&lt;init&gt;](-init-.md) | `The()`<br>Why did the token cross the road? |
+| [&lt;init&gt;](-init-.md) | Why did the token cross the road?`The()` |
### Functions
diff --git a/core/testdata/format/tokensInStrong.md b/core/testdata/format/tokensInStrong.md
index 2781656c..8a444c8d 100644
--- a/core/testdata/format/tokensInStrong.md
+++ b/core/testdata/format/tokensInStrong.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Yasc](./index.md)
+[test](../../index.md) / [Yasc](./index.md)
# Yasc
@@ -12,7 +12,7 @@
### Constructors
-| [&lt;init&gt;](-init-.md) | `Yasc()`<br>**YASC: [Yasc](./index.md) Yet Another Strong Class** |
+| [&lt;init&gt;](-init-.md) | **YASC: [Yasc](./index.md) Yet Another Strong Class**`Yasc()` |
### Functions
diff --git a/core/testdata/format/tripleBackticks.html b/core/testdata/format/tripleBackticks.html
index dacd0567..7dbdf4f2 100644
--- a/core/testdata/format/tripleBackticks.html
+++ b/core/testdata/format/tripleBackticks.html
@@ -4,7 +4,7 @@
<title>f - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./f.html">f</a><br/>
<br/>
<h1>f</h1>
<a name="$f()"></a>
diff --git a/core/testdata/format/typeAliases.md b/core/testdata/format/typeAliases.md
index 218c4848..755bd18d 100644
--- a/core/testdata/format/typeAliases.md
+++ b/core/testdata/format/typeAliases.md
@@ -1,5 +1,5 @@
-<!-- File: test/-a/index.md -->
-[test](../index.md) / [A](./index.md)
+<!-- File: test/--root--/-a/index.md -->
+[test](../../index.md) / [A](./index.md)
# A
@@ -9,8 +9,8 @@
| [&lt;init&gt;](-init-.md) | `A()` |
-<!-- File: test/-b/index.md -->
-[test](../index.md) / [B](./index.md)
+<!-- File: test/--root--/-b/index.md -->
+[test](../../index.md) / [B](./index.md)
# B
@@ -20,8 +20,8 @@
| [&lt;init&gt;](-init-.md) | `B()` |
-<!-- File: test/-c/index.md -->
-[test](../index.md) / [C](./index.md)
+<!-- File: test/--root--/-c/index.md -->
+[test](../../index.md) / [C](./index.md)
# C
@@ -31,62 +31,62 @@
| [&lt;init&gt;](-init-.md) | `C()` |
-<!-- File: test/-d.md -->
-[test](index.md) / [D](./-d.md)
+<!-- File: test/--root--/-d.md -->
+[test](../index.md) / [D](./-d.md)
# D
`typealias D = `[`A`](-a/index.md)
-<!-- File: test/-e.md -->
-[test](index.md) / [E](./-e.md)
+<!-- File: test/--root--/-e.md -->
+[test](../index.md) / [E](./-e.md)
# E
`typealias E = `[`D`](-d.md)
-<!-- File: test/-f.md -->
-[test](index.md) / [F](./-f.md)
+<!-- File: test/--root--/-f.md -->
+[test](../index.md) / [F](./-f.md)
# F
`typealias F = (`[`A`](-a/index.md)`) -> `[`B`](-b/index.md)
-<!-- File: test/-g.md -->
-[test](index.md) / [G](./-g.md)
+<!-- File: test/--root--/-g.md -->
+[test](../index.md) / [G](./-g.md)
# G
`typealias G = `[`C`](-c/index.md)`<`[`A`](-a/index.md)`>`
-<!-- File: test/-h.md -->
-[test](index.md) / [H](./-h.md)
+<!-- File: test/--root--/-h.md -->
+[test](../index.md) / [H](./-h.md)
# H
`typealias H<T> = `[`C`](-c/index.md)`<`[`T`](-h.md#T)`>`
-<!-- File: test/-i.md -->
-[test](index.md) / [I](./-i.md)
+<!-- File: test/--root--/-i.md -->
+[test](../index.md) / [I](./-i.md)
# I
`typealias I<T> = `[`H`](-h.md)`<`[`T`](-i.md#T)`>`
-<!-- File: test/-j.md -->
-[test](index.md) / [J](./-j.md)
+<!-- File: test/--root--/-j.md -->
+[test](../index.md) / [J](./-j.md)
# J
`typealias J = `[`H`](-h.md)`<`[`A`](-a/index.md)`>`
-<!-- File: test/-k.md -->
-[test](index.md) / [K](./-k.md)
+<!-- File: test/--root--/-k.md -->
+[test](../index.md) / [K](./-k.md)
# K
`typealias K = `[`H`](-h.md)`<`[`J`](-j.md)`>`
-<!-- File: test/-l.md -->
-[test](index.md) / [L](./-l.md)
+<!-- File: test/--root--/-l.md -->
+[test](../index.md) / [L](./-l.md)
# L
`typealias L = (`[`K`](-k.md)`, `[`B`](-b/index.md)`) -> `[`J`](-j.md)
-<!-- File: test/-m.md -->
-[test](index.md) / [M](./-m.md)
+<!-- File: test/--root--/-m.md -->
+[test](../index.md) / [M](./-m.md)
# M
@@ -94,8 +94,8 @@
Documented
-<!-- File: test/-n.md -->
-[test](index.md) / [N](./-n.md)
+<!-- File: test/--root--/-n.md -->
+[test](../index.md) / [N](./-n.md)
# N
diff --git a/core/testdata/format/typeAliases.package.md b/core/testdata/format/typeAliases.package.md
index 199e91c2..0c083811 100644
--- a/core/testdata/format/typeAliases.package.md
+++ b/core/testdata/format/typeAliases.package.md
@@ -1,4 +1,4 @@
-[test](./index.md)
+[test](../index.md)
## Package &lt;root&gt;
@@ -7,9 +7,6 @@
| [A](-a/index.md) | `class A` |
| [B](-b/index.md) | `class B` |
| [C](-c/index.md) | `class C<T>` |
-
-### Type Aliases
-
| [D](-d.md) | `typealias D = `[`A`](-a/index.md) |
| [E](-e.md) | `typealias E = `[`D`](-d.md) |
| [F](-f.md) | `typealias F = (`[`A`](-a/index.md)`) -> `[`B`](-b/index.md) |
@@ -19,6 +16,6 @@
| [J](-j.md) | `typealias J = `[`H`](-h.md)`<`[`A`](-a/index.md)`>` |
| [K](-k.md) | `typealias K = `[`H`](-h.md)`<`[`J`](-j.md)`>` |
| [L](-l.md) | `typealias L = (`[`K`](-k.md)`, `[`B`](-b/index.md)`) -> `[`J`](-j.md) |
-| [M](-m.md) | `typealias M = `[`A`](-a/index.md)<br>Documented |
+| [M](-m.md) | Documented`typealias M = `[`A`](-a/index.md) |
| [N](-n.md) | `typealias ~~N~~ = `[`A`](-a/index.md) |
diff --git a/core/testdata/format/typeLink.html b/core/testdata/format/typeLink.html
index 30af8a93..7909be23 100644
--- a/core/testdata/format/typeLink.html
+++ b/core/testdata/format/typeLink.html
@@ -4,7 +4,7 @@
<title>Bar - test</title>
</HEAD>
<BODY>
-<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
+<a href="../../index.html">test</a>&nbsp;/&nbsp;<a href="./index.html">Bar</a><br/>
<br/>
<h1>Bar</h1>
<code><span class="keyword">class </span><span class="identifier">Bar</span>&nbsp;<span class="symbol">:</span>&nbsp;<a href="../-foo/index.html"><span class="identifier">Foo</span></a></code>
@@ -13,7 +13,7 @@
<tbody>
<tr>
<td>
-<p><a href="-init-.html">&lt;init&gt;</a></p>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
</td>
<td>
<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
diff --git a/core/testdata/format/typeParameterBounds.md b/core/testdata/format/typeParameterBounds.md
index cf03b3a7..0e207763 100644
--- a/core/testdata/format/typeParameterBounds.md
+++ b/core/testdata/format/typeParameterBounds.md
@@ -1,4 +1,4 @@
-[test](index.md) / [generic](./generic.md)
+[test](../index.md) / [generic](./generic.md)
# generic
diff --git a/core/testdata/format/typeParameterReference.md b/core/testdata/format/typeParameterReference.md
index 5001d321..0baefba0 100644
--- a/core/testdata/format/typeParameterReference.md
+++ b/core/testdata/format/typeParameterReference.md
@@ -1,4 +1,4 @@
-[test](index.md) / [tt](./tt.md)
+[test](../index.md) / [tt](./tt.md)
# tt
diff --git a/core/testdata/format/typeParameterVariance.md b/core/testdata/format/typeParameterVariance.md
index b0615d43..9ea5feda 100644
--- a/core/testdata/format/typeParameterVariance.md
+++ b/core/testdata/format/typeParameterVariance.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Foo](./index.md)
+[test](../../index.md) / [Foo](./index.md)
# Foo
diff --git a/core/testdata/format/typeProjectionVariance.md b/core/testdata/format/typeProjectionVariance.md
index d3a55c58..082ffdba 100644
--- a/core/testdata/format/typeProjectionVariance.md
+++ b/core/testdata/format/typeProjectionVariance.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [kotlin.Array](./index.md)
+[test](../../index.md) / [kotlin.Array](./index.md)
### Extensions for kotlin.Array
diff --git a/core/testdata/format/uninterpretedEmphasisCharacters.html b/core/testdata/format/uninterpretedEmphasisCharacters.html
index dd338f72..a5b182b8 100644
--- a/core/testdata/format/uninterpretedEmphasisCharacters.html
+++ b/core/testdata/format/uninterpretedEmphasisCharacters.html
@@ -4,7 +4,7 @@
<title>foo - test</title>
</HEAD>
<BODY>
-<a href="index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
+<a href="../index.html">test</a>&nbsp;/&nbsp;<a href="./foo.html">foo</a><br/>
<br/>
<h1>foo</h1>
<a name="$foo()"></a>
diff --git a/core/testdata/format/unorderedLists.md b/core/testdata/format/unorderedLists.md
index 52ad9a71..1beb2c64 100644
--- a/core/testdata/format/unorderedLists.md
+++ b/core/testdata/format/unorderedLists.md
@@ -1,4 +1,4 @@
-[test](../index.md) / [Bar](./index.md)
+[test](../../index.md) / [Bar](./index.md)
# Bar
@@ -32,7 +32,7 @@ Rinse options:
### Constructors
-| [&lt;init&gt;](-init-.md) | `Bar()`<br>Usage summary: |
+| [&lt;init&gt;](-init-.md) | Usage summary:`Bar()` |
### Properties
diff --git a/core/testdata/format/varargsFunction.md b/core/testdata/format/varargsFunction.md
index 550202cc..b23760f0 100644
--- a/core/testdata/format/varargsFunction.md
+++ b/core/testdata/format/varargsFunction.md
@@ -1,4 +1,4 @@
-[test](index.md) / [f](./f.md)
+[test](../index.md) / [f](./f.md)
# f
diff --git a/core/testdata/format/website-html/dataTags/multiplatform.package.html b/core/testdata/format/website-html/dataTags/multiplatform.package.html
index 35453ab1..99f0b7a2 100644
--- a/core/testdata/format/website-html/dataTags/multiplatform.package.html
+++ b/core/testdata/format/website-html/dataTags/multiplatform.package.html
@@ -1,71 +1,74 @@
<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./index.html">foo</a></div>
<h2>Package foo</h2>
<h3>Functions</h3>
-<table class="api-docs-table">
-<tbody>
-<tr data-platform="JVM" data-jre-version="JRE7"><td>
-<p><a href="jre7.html">jre7</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">jre7</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JVM" data-kotlin-version="Kotlin 1.1" data-jre-version="JRE7"><td>
-<p><a href="jre7-new.html">jre7New</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">jre7New</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JS"><td>
-<p><a href="js.html">js</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">js</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JS" data-kotlin-version="Kotlin 1.1"><td>
-<p><a href="js-new.html">jsNew</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">jsNew</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JVM"><td>
-<p><a href="jvm.html">jvm</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">jvm</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JVM" data-kotlin-version="Kotlin 1.1"><td>
-<p><a href="jvm-new.html">jvmNew</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">jvmNew</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JVM, JS" data-jre-version="JRE7"><td>
-<p><a href="shared.html">shared</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">shared</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr><tr data-platform="JVM, JS" data-kotlin-version="Kotlin 1.1" data-jre-version="JRE7"><td>
-<p><a href="shared-new.html">sharedNew</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">sharedNew</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr></tbody>
-</table>
+<div class="api-declarations-list"><div class="declarations" data-platform="JVM, JRE7" data-kotlin-version="1.0, 1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.0">JVM</div>
+<div class="tags__tag platform tag-value-JRE7" data-tag-version="1.0">JRE7</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="jre7.html">jre7</a></h4>
+<div class="summary-group" data-platform="JVM, JRE7" data-kotlin-version="1.0, 1.0"><div data-platform="JVM, JRE7" data-kotlin-version="1.0, 1.0"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">jre7</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JVM, JRE7" data-kotlin-version="1.1, 1.1"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.1">JVM</div>
+<div class="tags__tag platform tag-value-JRE7" data-tag-version="1.1">JRE7</div>
+<div class="tags__tag kotlin-version">1.1</div>
+</div>
+<h4><a href="jre7-new.html">jre7New</a></h4>
+<div class="summary-group" data-platform="JVM, JRE7" data-kotlin-version="1.1, 1.1"><div data-platform="JVM, JRE7" data-kotlin-version="1.1, 1.1"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">jre7New</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JS" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.0">JS</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="js.html">js</a></h4>
+<div class="summary-group" data-platform="JS" data-kotlin-version="1.0"><div data-platform="JS" data-kotlin-version="1.0"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">js</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JS" data-kotlin-version="1.1"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.1">JS</div>
+<div class="tags__tag kotlin-version">1.1</div>
+</div>
+<h4><a href="js-new.html">jsNew</a></h4>
+<div class="summary-group" data-platform="JS" data-kotlin-version="1.1"><div data-platform="JS" data-kotlin-version="1.1"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">jsNew</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JVM" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.0">JVM</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="jvm.html">jvm</a></h4>
+<div class="summary-group" data-platform="JVM" data-kotlin-version="1.0"><div data-platform="JVM" data-kotlin-version="1.0"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">jvm</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JVM" data-kotlin-version="1.1"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.1">JVM</div>
+<div class="tags__tag kotlin-version">1.1</div>
+</div>
+<h4><a href="jvm-new.html">jvmNew</a></h4>
+<div class="summary-group" data-platform="JVM" data-kotlin-version="1.1"><div data-platform="JVM" data-kotlin-version="1.1"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">jvmNew</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JVM, JS, JRE7" data-kotlin-version="1.0, 1.0, 1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.0">JVM</div>
+<div class="tags__tag platform tag-value-JRE7" data-tag-version="1.0">JRE7</div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.0">JS</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="shared.html">shared</a></h4>
+<div class="summary-group" data-platform="JVM, JS, JRE7" data-kotlin-version="1.0, 1.0, 1.0"><div data-platform="JVM, JS, JRE7" data-kotlin-version="1.0, 1.0, 1.0"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">shared</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JVM, JS, JRE7" data-kotlin-version="1.1, 1.1, 1.1"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.1">JVM</div>
+<div class="tags__tag platform tag-value-JRE7" data-tag-version="1.1">JRE7</div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.1">JS</div>
+<div class="tags__tag kotlin-version">1.1</div>
+</div>
+<h4><a href="shared-new.html">sharedNew</a></h4>
+<div class="summary-group" data-platform="JVM, JS, JRE7" data-kotlin-version="1.1, 1.1, 1.1"><div data-platform="JVM, JS, JRE7" data-kotlin-version="1.1, 1.1, 1.1"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">sharedNew</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
+</div>
diff --git a/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.html b/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.html
index 3d34fc7e..eddee862 100644
--- a/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.html
+++ b/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.html
@@ -1,38 +1,35 @@
<div class='api-docs-breadcrumbs'><a href="../../index.html">test</a> / <a href="../index.html">pack</a> / <a href="./index.html">Some</a></div>
<h1>Some</h1>
-<div class="overload-group" data-platform="JVM"><div class="signature"><code><span class="keyword">typealias </span><span class="identifier">Some</span>&nbsp;<span class="symbol">=</span>&nbsp;<span class="identifier">SomeCoolJvmClass</span></code></div>
-<p><strong>Platform and version requirements:</strong> JVM</p>
+<div class="node-page-main" data-platform="JVM, JS" data-kotlin-version="1.0, 1.0"><div data-platform="JVM" data-kotlin-version="1.0"><a name="pack.Some"></a>
+<div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.0">JVM</div>
+<div class="tags__tag kotlin-version">1.0</div>
</div>
-<div class="overload-group" data-platform="JS"><div class="signature"><code><span class="keyword">class </span><span class="identifier">Some</span></code></div>
-<p><strong>Platform and version requirements:</strong> JS</p>
+<div class="signature"><code><span class="keyword">typealias </span><span class="identifier">Some</span>&nbsp;<span class="symbol">=</span>&nbsp;<span class="identifier">SomeCoolJvmClass</span></code></div>
+</div><div data-platform="JS" data-kotlin-version="1.0"><a name="pack.Some"></a>
+<div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.0">JS</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<div class="signature"><code><span class="keyword">class </span><span class="identifier">Some</span></code></div>
+</div></div>
<h3>Constructors</h3>
-<table class="api-docs-table">
-<tbody>
-<tr>
-<td>
-<p><a href="-some/-init-.html">&lt;init&gt;</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="identifier">Some</span><span class="symbol">(</span><span class="symbol">)</span></code></div>
-
-</td>
-</tr>
-</tbody>
-</table>
+<div class="api-declarations-list"><div class="declarations" data-platform="JS" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.0">JS</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="-init-.html">&lt;init&gt;</a></h4>
+<div class="summary-group" data-platform="JS" data-kotlin-version="1.0"><div data-platform="JS" data-kotlin-version="1.0"><div class="signature"><code><span class="identifier">Some</span><span class="symbol">(</span><span class="symbol">)</span></code></div>
+</div></div>
+</div>
+</div>
<h3>Functions</h3>
-<table class="api-docs-table">
-<tbody>
-<tr>
-<td>
-<p><a href="-some/magic.html">magic</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">fun </span><span class="identifier">magic</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-
-</td>
-</tr>
-</tbody>
-</table>
+<div class="api-declarations-list"><div class="declarations" data-platform="JS" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.0">JS</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="magic.html">magic</a></h4>
+<div class="summary-group" data-platform="JS" data-kotlin-version="1.0"><div data-platform="JS" data-kotlin-version="1.0"><div class="signature"><code><span class="keyword">fun </span><span class="identifier">magic</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
+</div></div>
+</div>
</div>
diff --git a/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.package.html b/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.package.html
index c8926a28..99aae350 100644
--- a/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.package.html
+++ b/core/testdata/format/website-html/dataTagsInGroupNode/multiplatform.package.html
@@ -1,36 +1,26 @@
<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./index.html">pack</a></div>
<h2>Package pack</h2>
<h3>Types</h3>
-<table class="api-docs-table">
-<tbody>
-<tr data-platform="JS"><td>
-<p><a href="-some/index.html">Some</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">class </span><span class="identifier">Some</span></code></div>
-
-</td>
-</tr><tr data-platform="JVM"><td>
-<p><a href="-some-cool-jvm-class/index.html">SomeCoolJvmClass</a></p>
-
-</td>
-<td>
-<div class="signature"><code><span class="keyword">class </span><span class="identifier">SomeCoolJvmClass</span></code></div>
-
-</td>
-</tr></tbody>
-</table>
-<h3>Type Aliases</h3>
-<table class="api-docs-table">
-<tbody>
-<tr data-platform="JVM"><td>
-<p><a href="-some/index.html">Some</a></p>
-
-</td>
-<td>
+<div class="api-declarations-list"><div class="declarations" data-platform="JVM, JS" data-kotlin-version="1.0, 1.0">
+<h4><a href="-some/index.html">Some</a></h4>
+<div class="summary-group" data-platform="JVM, JS" data-kotlin-version="1.0, 1.0"><div data-platform="JVM" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.0">JVM</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
<div class="signature"><code><span class="keyword">typealias </span><span class="identifier">Some</span>&nbsp;<span class="symbol">=</span>&nbsp;<span class="identifier">SomeCoolJvmClass</span></code></div>
-
-</td>
-</tr></tbody>
-</table>
+</div><div data-platform="JS" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JS" data-tag-version="1.0">JS</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<div class="signature"><code><span class="keyword">class </span><span class="identifier">Some</span></code></div>
+</div></div>
+</div>
+<div class="declarations" data-platform="JVM" data-kotlin-version="1.0"><div class="tags"><div class="spacer"></div>
+<div class="tags__tag platform tag-value-JVM" data-tag-version="1.0">JVM</div>
+<div class="tags__tag kotlin-version">1.0</div>
+</div>
+<h4><a href="-some-cool-jvm-class/index.html">SomeCoolJvmClass</a></h4>
+<div class="summary-group" data-platform="JVM" data-kotlin-version="1.0"><div data-platform="JVM" data-kotlin-version="1.0"><div class="signature"><code><span class="keyword">class </span><span class="identifier">SomeCoolJvmClass</span></code></div>
+</div></div>
+</div>
+</div>
diff --git a/core/testdata/format/website-html/dropImport.html b/core/testdata/format/website-html/dropImport.html
index e0fcb12b..b6748a5c 100644
--- a/core/testdata/format/website-html/dropImport.html
+++ b/core/testdata/format/website-html/dropImport.html
@@ -1,11 +1,15 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./foo.html">foo</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./foo.html">foo</a></div>
<h1>foo</h1>
+<div class="node-page-main" data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
<a name="$foo()"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-<div class="sample"><pre><code class="lang-kotlin">import some.*
+<div class="sample" data-min-compiler-version="1.3"><pre><code class="lang-kotlin">import some.*
fun main(args: Array&lt;String&gt;) {
//sampleStart
//sampleEnd
}</code></pre></div>
+</div>
diff --git a/core/testdata/format/website-html/newLinesInImportList.html b/core/testdata/format/website-html/newLinesInImportList.html
index b5a07325..712b6a4b 100644
--- a/core/testdata/format/website-html/newLinesInImportList.html
+++ b/core/testdata/format/website-html/newLinesInImportList.html
@@ -1,8 +1,11 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./foo.html">foo</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./foo.html">foo</a></div>
<h1>foo</h1>
+<div class="node-page-main" data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
<a name="$foo()"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-<div class="sample"><pre><code class="lang-kotlin">import same.*
+<div class="sample" data-min-compiler-version="1.3"><pre><code class="lang-kotlin">import same.*
import some.*
fun main(args: Array&lt;String&gt;) {
@@ -10,3 +13,4 @@ fun main(args: Array&lt;String&gt;) {
//sampleEnd
}</code></pre></div>
+</div>
diff --git a/core/testdata/format/website-html/newLinesInSamples.html b/core/testdata/format/website-html/newLinesInSamples.html
index 50f875da..7e379c68 100644
--- a/core/testdata/format/website-html/newLinesInSamples.html
+++ b/core/testdata/format/website-html/newLinesInSamples.html
@@ -1,8 +1,11 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./foo.html">foo</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./foo.html">foo</a></div>
<h1>foo</h1>
+<div class="node-page-main" data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
<a name="$foo()"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></div>
-<div class="sample"><pre><code class="lang-kotlin">
+<div class="sample" data-min-compiler-version="1.3"><pre><code class="lang-kotlin">
fun main(args: Array&lt;String&gt;) {
//sampleStart
@@ -17,3 +20,4 @@ val mutableByLength: MutableMap&lt;Int, MutableList&lt;String&gt;&gt; = words.gr
println("mutableByLength == byLength is ${mutableByLength == byLength}") // true
//sampleEnd
}</code></pre></div>
+</div>
diff --git a/core/testdata/format/website-html/overloadGroup.html b/core/testdata/format/website-html/overloadGroup.html
index aaba9c96..808cd606 100644
--- a/core/testdata/format/website-html/overloadGroup.html
+++ b/core/testdata/format/website-html/overloadGroup.html
@@ -1,13 +1,19 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./magic.html">magic</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./magic.html">magic</a></div>
<h1>magic</h1>
-<div class="overload-group"><a name="$magic(kotlin.String)"></a>
+<div class="overload-group"data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
+<a name="$magic(kotlin.String)"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">magic</span><span class="symbol">(</span><span class="parameterName" id="$magic(kotlin.String)/spell">spell</span><span class="symbol">:</span>&nbsp;<span class="identifier">String</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Int</span></code></div>
<h3>Parameters</h3>
<p><a name="spell"></a>
<code>spell</code> - The text of spell, often distributed on scrolls</p>
<p><strong>Return</strong> Spell ID for future casts</p>
</div>
-<div class="overload-group"><a name="$magic(kotlin.Int)"></a>
+<div class="overload-group"data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
+<a name="$magic(kotlin.Int)"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">magic</span><span class="symbol">(</span><span class="parameterName" id="$magic(kotlin.Int)/spell">spell</span><span class="symbol">:</span>&nbsp;<span class="identifier">Int</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Int</span></code></div>
<h3>Parameters</h3>
<p><a name="spell"></a>
diff --git a/core/testdata/format/website-html/returnTag.html b/core/testdata/format/website-html/returnTag.html
index 7724eaa7..2e761527 100644
--- a/core/testdata/format/website-html/returnTag.html
+++ b/core/testdata/format/website-html/returnTag.html
@@ -1,5 +1,8 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./index-of.html">indexOf</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./index-of.html">indexOf</a></div>
<h1>indexOf</h1>
+<div class="node-page-main" data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
<a name="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)"></a>
<div class="signature"><code><span class="keyword">fun </span><a href="-foo/index.html"><span class="identifier">Foo</span></a><span class="symbol">.</span><span class="identifier">indexOf</span><span class="symbol">(</span><br/>&nbsp;&nbsp;&nbsp;&nbsp;<span class="parameterName" id="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/char">char</span><span class="symbol">:</span>&nbsp;<span class="identifier">Char</span><span class="symbol">, </span><br/>&nbsp;&nbsp;&nbsp;&nbsp;<span class="parameterName" id="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/startIndex">startIndex</span><span class="symbol">:</span>&nbsp;<span class="identifier">Int</span>&nbsp;<span class="symbol">=</span>&nbsp;0<span class="symbol">, </span><br/>&nbsp;&nbsp;&nbsp;&nbsp;<span class="parameterName" id="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/ignoreCase">ignoreCase</span><span class="symbol">:</span>&nbsp;<span class="identifier">Boolean</span>&nbsp;<span class="symbol">=</span>&nbsp;false<br/><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Int</span></code></div>
<p>Returns the index within this string of the first occurrence of the specified character, starting from the specified <a href="index-of.html#$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/startIndex">startIndex</a>.</p>
@@ -7,3 +10,4 @@
<p><a name="ignoreCase"></a>
<code>ignoreCase</code> - <code>true</code> to ignore character case when matching a character. By default <code>false</code>.</p>
<p><strong>Returns</strong> An index of the first occurrence of <a href="index-of.html#$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/char">char</a> or -1 if none is found.</p>
+</div>
diff --git a/core/testdata/format/website-html/sample.html b/core/testdata/format/website-html/sample.html
index 1fb26e41..479af45c 100644
--- a/core/testdata/format/website-html/sample.html
+++ b/core/testdata/format/website-html/sample.html
@@ -1,10 +1,13 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./foo.html">foo</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./foo.html">foo</a></div>
<h1>foo</h1>
-<div class="overload-group"><a name="$foo()"></a>
+<div class="overload-group"data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
+<a name="$foo()"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Int</span></code></div>
<p>Groups elements of the original sequence by the key returned by the given <a href="#">keySelector</a> function
applied to each element and returns a map where each group key is associated with a list of corresponding elements.</p>
-<div class="sample"><pre><code class="lang-kotlin">
+<div class="sample" data-min-compiler-version="1.3"><pre><code class="lang-kotlin">
fun main(args: Array&lt;String&gt;) {
//sampleStart
@@ -14,6 +17,9 @@ if (true) {
//sampleEnd
}</code></pre></div>
</div>
-<div class="overload-group"><a name="$foo(kotlin.Int)"></a>
+<div class="overload-group"data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
+<a name="$foo(kotlin.Int)"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">foo</span><span class="symbol">(</span><span class="parameterName" id="$foo(kotlin.Int)/i">i</span><span class="symbol">:</span>&nbsp;<span class="identifier">Int</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Int</span></code></div>
</div>
diff --git a/core/testdata/format/website-html/sampleWithAsserts.html b/core/testdata/format/website-html/sampleWithAsserts.html
index e91232f5..3febe91e 100644
--- a/core/testdata/format/website-html/sampleWithAsserts.html
+++ b/core/testdata/format/website-html/sampleWithAsserts.html
@@ -1,8 +1,11 @@
-<div class='api-docs-breadcrumbs'><a href="index.html">test</a> / <a href="./a.html">a</a></div>
+<div class='api-docs-breadcrumbs'><a href="../index.html">test</a> / <a href="./a.html">a</a></div>
<h1>a</h1>
+<div class="node-page-main" data-platform="" data-kotlin-version=""><div class="tags"><div class="spacer"></div>
+<div class="tags__tag kotlin-version"></div>
+</div>
<a name="$a()"></a>
<div class="signature"><code><span class="keyword">fun </span><span class="identifier">a</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">String</span></code></div>
-<div class="sample"><pre><code class="lang-kotlin">import java.io.FileNotFoundException
+<div class="sample" data-min-compiler-version="1.3"><pre><code class="lang-kotlin">import java.io.FileNotFoundException
import java.io.File
fun main(args: Array&lt;String&gt;) {
@@ -14,9 +17,12 @@ println("a() == b() is ${a() == b()}") // true
// readSomeFile(File("some.txt")) // reading file now will fail
// readSomeFile(File("some.txt")) // will fail with FileNotFoundException
+// readSomeFile(File("some.txt")) // will fail
+
fun indented() {
// A neq B
println("a() != b() is ${a() != b()}") // false
}
//sampleEnd
}</code></pre></div>
+</div>
diff --git a/core/testdata/format/website-html/sampleWithAsserts.kt b/core/testdata/format/website-html/sampleWithAsserts.kt
index b3bce11d..bb5848e6 100644
--- a/core/testdata/format/website-html/sampleWithAsserts.kt
+++ b/core/testdata/format/website-html/sampleWithAsserts.kt
@@ -26,6 +26,8 @@ fun sample() {
assertFails("reading file now") { readSomeFile(File("some.txt")) }
assertFailsWith<FileNotFoundException> { readSomeFile(File("some.txt")) }
+ assertFails { readSomeFile(File("some.txt")) }
+
fun indented() {
assertFalse(a() != b(), "A neq B")
}
diff --git a/core/testdata/functions/inlineFunction.kt b/core/testdata/functions/inlineFunction.kt
index 11c19672..64a617a4 100644
--- a/core/testdata/functions/inlineFunction.kt
+++ b/core/testdata/functions/inlineFunction.kt
@@ -1,2 +1,2 @@
-inline fun f() {
+inline fun f(a: () -> String) {
}
diff --git a/core/testdata/functions/inlineSuspendFunction.kt b/core/testdata/functions/inlineSuspendFunction.kt
index 54032ccf..5f376267 100644
--- a/core/testdata/functions/inlineSuspendFunction.kt
+++ b/core/testdata/functions/inlineSuspendFunction.kt
@@ -1,2 +1,2 @@
-inline suspend fun f() {
+inline suspend fun f(a: () -> String) {
}
diff --git a/core/testdata/functions/suspendInlineFunction.kt b/core/testdata/functions/suspendInlineFunction.kt
index 15a9018f..54f65658 100644
--- a/core/testdata/functions/suspendInlineFunction.kt
+++ b/core/testdata/functions/suspendInlineFunction.kt
@@ -1,2 +1,2 @@
-suspend inline fun f() {
+suspend inline fun f(a: () -> String) {
}
diff --git a/core/testdata/javadoc/functionParameters.java b/core/testdata/javadoc/functionParameters.java
new file mode 100644
index 00000000..8d5f5143
--- /dev/null
+++ b/core/testdata/javadoc/functionParameters.java
@@ -0,0 +1,17 @@
+package bar;
+
+/**
+ * Foo
+ */
+
+public class Foo {
+
+ /** perfom request
+ *
+ * @param name user name
+ * @param password user password
+ */
+ public void request(String name, String password) {
+
+ }
+} \ No newline at end of file
diff --git a/core/testdata/links/linkToExternalSite.kt b/core/testdata/links/linkToExternalSite.kt
new file mode 100644
index 00000000..a3d8c5ef
--- /dev/null
+++ b/core/testdata/links/linkToExternalSite.kt
@@ -0,0 +1,4 @@
+/**
+ * This is link to [http://example.com/#example]
+ */
+class Foo {} \ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 9436e38b..7741642b 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,16 +1,23 @@
-dokka_version=0.9.18-SNAPSHOT
+dokka_version_base=0.10.0
dokka_publication_channel=dokka
-#Kotlin compiler and plugin
+# Kotlin compiler and plugin
bundled_kotlin_compiler_version=1.3.20-dev-564
-kotlin_version=1.2.21
+kotlin_version=1.3.30
kotlin_for_gradle_runtime_version=1.1.60
+language_version=1.3
ant_version=1.9.6
-#Maven plugin dependencies
+# Maven plugin dependencies
maven_version=3.5.0
maven_archiver_version=2.5
plexus_utils_version=3.0.22
plexus_archiver_version=3.4
maven_plugin_tools_version=3.5.2
+
+# For CI
+mvn=mvn
+
+# For serialization
+gson_version=2.8.5 \ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 736fb7d3..28861d27 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 610ad4c5..f73107db 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip
diff --git a/gradlew.bat b/gradlew.bat
index f9553162..e95643d6 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,84 +1,84 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration/build.gradle b/integration/build.gradle
index 24d59edf..ce25d9bf 100644
--- a/integration/build.gradle
+++ b/integration/build.gradle
@@ -1,4 +1,6 @@
buildscript {
+ repositories { jcenter() }
+
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
@@ -6,13 +8,12 @@ buildscript {
apply plugin: 'kotlin'
-
sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
- languageVersion = "1.2"
- apiVersion = "1.1"
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
@@ -20,7 +21,5 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
dependencies {
compileOnly group: 'org.jetbrains.kotlin', name: 'kotlin-stdlib', version: kotlin_for_gradle_runtime_version
compileOnly group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlin_for_gradle_runtime_version
- compile('com.github.yole:jkid:8fc7f12e1a') {
- transitive = false
- }
+ implementation "com.google.code.gson:gson:$gson_version"
} \ No newline at end of file
diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt
index 69d19944..6eae9701 100644
--- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt
+++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt
@@ -1,52 +1,64 @@
package org.jetbrains.dokka
-import ru.yole.jkid.CustomSerializer
-import ru.yole.jkid.ValueSerializer
-import ru.yole.jkid.deserialization.JKidException
-import java.io.Serializable
import java.net.URL
+enum class Platform(val key: String) {
+ jvm("jvm"),
+ js("js"),
+ native("native"),
+ common("common");
-class UrlSerializer : ValueSerializer<URL?> {
- override fun fromJsonValue(jsonValue: Any?): URL? {
- if (jsonValue !is String?)
- throw JKidException("Expected string representation of URL, got: $jsonValue")
- return jsonValue?.let { URL(jsonValue) }
- }
+ companion object {
+ val DEFAULT = jvm
- override fun toJsonValue(value: URL?): Any? = value?.toExternalForm()
+ fun fromString(key: String): Platform {
+ return when (key.toLowerCase()) {
+ jvm.key -> jvm
+ js.key -> js
+ native.key -> native
+ common.key -> common
+ else -> throw IllegalArgumentException("Unrecognized platform: $key")
+ }
+ }
+ }
}
interface DokkaConfiguration {
- val moduleName: String
- val classpath: List<String>
- val sourceRoots: List<SourceRoot>
- val samples: List<String>
- val includes: List<String>
val outputDir: String
val format: String
- val includeNonPublic: Boolean
- val includeRootPackage: Boolean
- val reportUndocumented: Boolean
- val skipEmptyPackages: Boolean
- val skipDeprecated: Boolean
- val jdkVersion: Int
val generateIndexPages: Boolean
- val sourceLinks: List<SourceLinkDefinition>
- val impliedPlatforms: List<String>
- val perPackageOptions: List<PackageOptions>
- val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>
- val languageVersion: String?
- val apiVersion: String?
- val noStdlibLink: Boolean
- val noJdkLink: Boolean
val cacheRoot: String?
- val suppressedFiles: List<String>
- val collectInheritedExtensionsFromLibraries: Boolean
+ val passesConfigurations: List<PassConfiguration>
+ val impliedPlatforms: List<String>
+
+ interface PassConfiguration {
+ val moduleName: String
+ val classpath: List<String>
+ val sourceRoots: List<SourceRoot>
+ val samples: List<String>
+ val includes: List<String>
+ val includeNonPublic: Boolean
+ val includeRootPackage: Boolean
+ val reportUndocumented: Boolean
+ val skipEmptyPackages: Boolean
+ val skipDeprecated: Boolean
+ val jdkVersion: Int
+ val sourceLinks: List<SourceLinkDefinition>
+ val perPackageOptions: List<PackageOptions>
+ val externalDocumentationLinks: List<ExternalDocumentationLink>
+ val languageVersion: String?
+ val apiVersion: String?
+ val noStdlibLink: Boolean
+ val noJdkLink: Boolean
+ val suppressedFiles: List<String>
+ val collectInheritedExtensionsFromLibraries: Boolean
+ val analysisPlatform: Platform
+ val targets: List<String>
+ val sinceKotlin: String?
+ }
interface SourceRoot {
val path: String
- val platforms: List<String>
}
interface SourceLinkDefinition {
@@ -64,53 +76,21 @@ interface DokkaConfiguration {
}
interface ExternalDocumentationLink {
- @CustomSerializer(UrlSerializer::class) val url: URL
- @CustomSerializer(UrlSerializer::class) val packageListUrl: URL
+ val url: URL
+ val packageListUrl: URL
open class Builder(open var url: URL? = null,
open var packageListUrl: URL? = null) {
constructor(root: String, packageList: String? = null) : this(URL(root), packageList?.let { URL(it) })
- fun build(): DokkaConfiguration.ExternalDocumentationLink =
- if (packageListUrl != null && url != null)
- ExternalDocumentationLinkImpl(url!!, packageListUrl!!)
- else if (url != null)
- ExternalDocumentationLinkImpl(url!!, URL(url!!, "package-list"))
- else
- throw IllegalArgumentException("url or url && packageListUrl must not be null for external documentation link")
+ fun build(): ExternalDocumentationLink =
+ if (packageListUrl != null && url != null)
+ ExternalDocumentationLinkImpl(url!!, packageListUrl!!)
+ else if (url != null)
+ ExternalDocumentationLinkImpl(url!!, URL(url!!, "package-list"))
+ else
+ throw IllegalArgumentException("url or url && packageListUrl must not be null for external documentation link")
}
}
}
-
-data class SerializeOnlyDokkaConfiguration(
- override val moduleName: String,
- override val classpath: List<String>,
- override val sourceRoots: List<DokkaConfiguration.SourceRoot>,
- override val samples: List<String>,
- override val includes: List<String>,
- override val outputDir: String,
- override val format: String,
- override val includeNonPublic: Boolean,
- override val includeRootPackage: Boolean,
- override val reportUndocumented: Boolean,
- override val skipEmptyPackages: Boolean,
- override val skipDeprecated: Boolean,
- override val jdkVersion: Int,
- override val generateIndexPages: Boolean,
- override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>,
- override val impliedPlatforms: List<String>,
- override val perPackageOptions: List<DokkaConfiguration.PackageOptions>,
- override val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>,
- override val noStdlibLink: Boolean,
- override val noJdkLink: Boolean,
- override val cacheRoot: String?,
- override val suppressedFiles: List<String>,
- override val languageVersion: String?,
- override val apiVersion: String?,
- override val collectInheritedExtensionsFromLibraries: Boolean
-) : DokkaConfiguration
-
-
-data class ExternalDocumentationLinkImpl(@CustomSerializer(UrlSerializer::class) override val url: URL,
- @CustomSerializer(UrlSerializer::class) override val packageListUrl: URL) : Serializable, DokkaConfiguration.ExternalDocumentationLink \ No newline at end of file
diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/defaultConfiguration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/defaultConfiguration.kt
new file mode 100644
index 00000000..78112904
--- /dev/null
+++ b/integration/src/main/kotlin/org/jetbrains/dokka/defaultConfiguration.kt
@@ -0,0 +1,73 @@
+package org.jetbrains.dokka
+
+import java.io.File
+import java.net.URL
+
+data class DokkaConfigurationImpl(
+ override val outputDir: String,
+ override val format: String,
+ override val generateIndexPages: Boolean,
+ override val cacheRoot: String?,
+ override val impliedPlatforms: List<String>,
+ override val passesConfigurations: List<PassConfigurationImpl>
+) : DokkaConfiguration
+
+data class PassConfigurationImpl (
+ override val moduleName: String,
+ override val classpath: List<String>,
+ override val sourceRoots: List<SourceRootImpl>,
+ override val samples: List<String>,
+ override val includes: List<String>,
+ override val includeNonPublic: Boolean,
+ override val includeRootPackage: Boolean,
+ override val reportUndocumented: Boolean,
+ override val skipEmptyPackages: Boolean,
+ override val skipDeprecated: Boolean,
+ override val jdkVersion: Int,
+ override val sourceLinks: List<SourceLinkDefinitionImpl>,
+ override val perPackageOptions: List<PackageOptionsImpl>,
+ override var externalDocumentationLinks: List<ExternalDocumentationLinkImpl>,
+ override val languageVersion: String?,
+ override val apiVersion: String?,
+ override val noStdlibLink: Boolean,
+ override val noJdkLink: Boolean,
+ override val suppressedFiles: List<String>,
+ override val collectInheritedExtensionsFromLibraries: Boolean,
+ override val analysisPlatform: Platform,
+ override val targets: List<String>,
+ override val sinceKotlin: String?
+) : DokkaConfiguration.PassConfiguration
+
+
+data class SourceRootImpl(
+ override val path: String
+): DokkaConfiguration.SourceRoot
+
+data class SourceLinkDefinitionImpl(
+ override val path: String,
+ override val url: String,
+ override val lineSuffix: String?
+): DokkaConfiguration.SourceLinkDefinition {
+ companion object {
+ fun parseSourceLinkDefinition(srcLink: String): SourceLinkDefinitionImpl {
+ val (path, urlAndLine) = srcLink.split('=')
+ return SourceLinkDefinitionImpl(
+ File(path).canonicalPath,
+ urlAndLine.substringBefore("#"),
+ urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" })
+ }
+ }
+}
+
+data class PackageOptionsImpl(
+ override val prefix: String,
+ override val includeNonPublic: Boolean,
+ override val reportUndocumented: Boolean,
+ override val skipDeprecated: Boolean,
+ override val suppress: Boolean
+): DokkaConfiguration.PackageOptions
+
+
+data class ExternalDocumentationLinkImpl(override val url: URL,
+ override val packageListUrl: URL
+) : DokkaConfiguration.ExternalDocumentationLink \ No newline at end of file
diff --git a/runners/android-gradle-plugin/build.gradle b/runners/android-gradle-plugin/build.gradle
deleted file mode 100644
index 28b0cbb9..00000000
--- a/runners/android-gradle-plugin/build.gradle
+++ /dev/null
@@ -1,101 +0,0 @@
-import com.gradle.publish.DependenciesBuilder
-import org.jetbrains.CorrectShadowPublishing
-
-apply plugin: 'java'
-apply plugin: 'kotlin'
-
-
-apply plugin: 'com.github.johnrengelman.shadow'
-apply plugin: "com.gradle.plugin-publish"
-
-sourceCompatibility = 1.8
-
-tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
- kotlinOptions {
- freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = "1.1"
- jvmTarget = "1.8"
- }
-}
-
-repositories {
- jcenter()
-}
-
-dependencies {
- testCompile group: 'junit', name: 'junit', version: '4.12'
-
- shadow project(path: ':runners:gradle-plugin', configuration: 'shadow')
- compileOnly project(':integration')
-
- compileOnly gradleApi()
- compileOnly localGroovy()
-}
-
-task sourceJar(type: Jar) {
- from sourceSets.main.allSource
-}
-
-processResources {
- eachFile {
- if (it.name == "org.jetbrains.dokka-android.properties") {
- it.filter { line ->
- line.replace("<version>", dokka_version)
- }
- }
- }
-}
-
-shadowJar {
- baseName = 'dokka-android-gradle-plugin'
- classifier = ''
-}
-
-apply plugin: 'maven-publish'
-
-publishing {
- publications {
- dokkaAndroidGradlePlugin(MavenPublication) { MavenPublication publication ->
- artifactId = 'dokka-android-gradle-plugin'
-
- artifact sourceJar {
- classifier "sources"
- }
-
- CorrectShadowPublishing.configure(publication, project)
- }
- }
-}
-
-bintrayPublication(project, ['dokkaAndroidGradlePlugin'])
-
-configurations.archives.artifacts.clear()
-artifacts {
- archives shadowJar
-}
-
-pluginBundle {
- website = 'https://www.kotlinlang.org/'
- vcsUrl = 'https://github.com/kotlin/dokka.git'
- description = 'Dokka, the Kotlin documentation tool'
- tags = ['dokka', 'kotlin', 'kdoc', 'android']
-
- plugins {
- dokkaAndroidGradlePlugin {
- id = 'org.jetbrains.dokka-android'
- displayName = 'Dokka Android plugin'
- }
- }
-
- withDependencies { List<Dependency> list ->
- list.clear()
- def builder = new DependenciesBuilder()
- builder.addUniqueScopedDependencies(list, configurations.shadow, "compile")
- }
-
- mavenCoordinates {
- groupId = "org.jetbrains.dokka"
- artifactId = "dokka-android-gradle-plugin"
- }
-} \ No newline at end of file
diff --git a/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt b/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt
deleted file mode 100644
index b1996da0..00000000
--- a/runners/android-gradle-plugin/src/main/kotlin/mainAndroid.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.tasks.Input
-import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
-import java.io.File
-
-open class DokkaAndroidPlugin : Plugin<Project> {
- override fun apply(project: Project) {
- DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties"))
- project.tasks.create("dokka", DokkaAndroidTask::class.java).apply {
- dokkaRuntime = project.configurations.create("dokkaRuntime")
- moduleName = project.name
- outputDirectory = File(project.buildDir, "dokka").absolutePath
- }
- }
-}
-
-private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build()
-
-open class DokkaAndroidTask : DokkaTask() {
-
- @Input var noAndroidSdkLink: Boolean = false
-
- override fun collectSuppressedFiles(sourceRoots: List<SourceRoot>): List<String> {
- val generatedRoot = project.buildDir.resolve("generated").absoluteFile
- return sourceRoots
- .map { File(it.path) }
- .filter { it.startsWith(generatedRoot) }
- .flatMap { it.walk().toList() }
- .map { it.absolutePath }
- }
-
- init {
- project.afterEvaluate {
- if (!noAndroidSdkLink) externalDocumentationLinks.add(ANDROID_REFERENCE_URL)
- }
- }
-}
diff --git a/runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties b/runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties
deleted file mode 100644
index b204da7b..00000000
--- a/runners/android-gradle-plugin/src/main/resources/META-INF/gradle-plugins/org.jetbrains.dokka-android.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-implementation-class=org.jetbrains.dokka.gradle.DokkaAndroidPlugin
-dokka-version=<version> \ No newline at end of file
diff --git a/runners/ant/build.gradle b/runners/ant/build.gradle
index e7dcd441..216420c6 100644
--- a/runners/ant/build.gradle
+++ b/runners/ant/build.gradle
@@ -5,8 +5,8 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = languageVersion
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt
index b23328e0..3ecc7b94 100644
--- a/runners/ant/src/main/kotlin/ant/dokka.kt
+++ b/runners/ant/src/main/kotlin/ant/dokka.kt
@@ -17,54 +17,103 @@ class AntLogger(val task: Task): DokkaLogger {
class AntSourceLinkDefinition(var path: String? = null, var url: String? = null, var lineSuffix: String? = null)
-class AntSourceRoot(var path: String? = null, var platforms: String? = null) {
- fun toSourceRoot(): SourceRootImpl? = path?.let {
- path ->
- SourceRootImpl(path, platforms?.split(',').orEmpty())
+class AntSourceRoot(var path: String? = null) {
+ fun toSourceRoot(): SourceRootImpl? = path?.let { path ->
+ SourceRootImpl(path)
}
}
-class AntPackageOptions(
- override var prefix: String = "",
- override var includeNonPublic: Boolean = false,
- override var reportUndocumented: Boolean = true,
- override var skipDeprecated: Boolean = false,
- override var suppress: Boolean = false) : DokkaConfiguration.PackageOptions
-
+class TextProperty(var value: String = "")
+
+class AntPassConfig(task: Task) : DokkaConfiguration.PassConfiguration {
+ override var moduleName: String = ""
+ override val classpath: List<String>
+ get() = buildClassPath.list().toList()
+
+ override val sourceRoots: List<DokkaConfiguration.SourceRoot>
+ get() = sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }
+
+ override val samples: List<String>
+ get() = samplesPath.list().toList()
+ override val includes: List<String>
+ get() = includesPath.list().toList()
+ override var includeNonPublic: Boolean = false
+ override var includeRootPackage: Boolean = true
+ override var reportUndocumented: Boolean = false
+ override var skipEmptyPackages: Boolean = true
+ override var skipDeprecated: Boolean = false
+ override var jdkVersion: Int = 6
+ override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>
+ get() = antSourceLinkDefinition.map {
+ val path = it.path!!
+ val url = it.url!!
+ SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix)
+ }
+ override val perPackageOptions: MutableList<DokkaConfiguration.PackageOptions> = mutableListOf()
+ override val externalDocumentationLinks: List<ExternalDocumentationLink>
+ get() = buildExternalLinksBuilders.map { it.build() } + defaultExternalDocumentationLinks
+
+ override var languageVersion: String? = null
+ override var apiVersion: String? = null
+ override var noStdlibLink: Boolean = false
+ override var noJdkLink: Boolean = false
+ override var suppressedFiles: MutableList<String> = mutableListOf()
+ override var collectInheritedExtensionsFromLibraries: Boolean = false
+ override var analysisPlatform: Platform = Platform.DEFAULT
+ override var targets: List<String> = listOf()
+ get() = buildTargets.filter { it.value != "" }
+ .map { it.value }
+
+ override var sinceKotlin: String? = null
+
+ private val samplesPath: Path by lazy { Path(task.project) }
+ private val includesPath: Path by lazy { Path(task.project) }
+ private val buildClassPath: Path by lazy { Path(task.project) }
+ val sourcePath: Path by lazy { Path(task.project) }
+ val antSourceRoots: MutableList<AntSourceRoot> = mutableListOf()
+
+ private val buildTargets: MutableList<TextProperty> = mutableListOf()
+ private val buildExternalLinksBuilders: MutableList<ExternalDocumentationLink.Builder> = mutableListOf()
+ val antSourceLinkDefinition: MutableList<AntSourceLinkDefinition> = mutableListOf()
+
+ private val defaultExternalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>
+ get() {
+ val links = mutableListOf<DokkaConfiguration.ExternalDocumentationLink>()
+ if (!noJdkLink)
+ links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build()
+
+ if (!noStdlibLink)
+ links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build()
+ return links
+ }
-class DokkaAntTask: Task() {
- var moduleName: String? = null
- var outputDir: String? = null
- var outputFormat: String = "html"
- var impliedPlatforms: String = ""
- var jdkVersion: Int = 6
- var noStdlibLink: Boolean = false
- var noJdkLink: Boolean = false
+ fun setSamples(ref: Path) {
+ samplesPath.append(ref)
+ }
- var skipDeprecated: Boolean = false
+ fun setSamplesRef(ref: Reference) {
+ samplesPath.createPath().refid = ref
+ }
- var cacheRoot: String? = null
+ fun setInclude(ref: Path) {
+ includesPath.append(ref)
+ }
- var languageVersion: String? = null
- var apiVersion: String? = null
+ fun setClasspath(classpath: Path) {
+ buildClassPath.append(classpath)
+ }
- val compileClasspath: Path by lazy { Path(getProject()) }
- val sourcePath: Path by lazy { Path(getProject()) }
- val samplesPath: Path by lazy { Path(getProject()) }
- val includesPath: Path by lazy { Path(getProject()) }
+ fun createPackageOptions(): AntPackageOptions = AntPackageOptions().apply { perPackageOptions.add(this) }
- val antSourceLinks: MutableList<AntSourceLinkDefinition> = arrayListOf()
- val antSourceRoots: MutableList<AntSourceRoot> = arrayListOf()
- val antPackageOptions: MutableList<AntPackageOptions> = arrayListOf()
- val antExternalDocumentationLinks = mutableListOf<ExternalDocumentationLink.Builder>()
+ fun createSourceRoot(): AntSourceRoot = AntSourceRoot().apply { antSourceRoots.add(this) }
- fun setClasspath(classpath: Path) {
- compileClasspath.append(classpath)
+ fun createTarget(): TextProperty = TextProperty().apply {
+ buildTargets.add(this)
}
fun setClasspathRef(ref: Reference) {
- compileClasspath.createPath().refid = ref
+ buildClassPath.createPath().refid = ref
}
fun setSrc(src: Path) {
@@ -75,73 +124,69 @@ class DokkaAntTask: Task() {
sourcePath.createPath().refid = ref
}
- fun setSamples(samples: Path) {
- samplesPath.append(samples)
- }
-
- fun setSamplesRef(ref: Reference) {
- samplesPath.createPath().refid = ref
- }
-
- fun setInclude(include: Path) {
- includesPath.append(include)
- }
-
fun createSourceLink(): AntSourceLinkDefinition {
val def = AntSourceLinkDefinition()
- antSourceLinks.add(def)
+ antSourceLinkDefinition.add(def)
return def
}
- fun createSourceRoot(): AntSourceRoot = AntSourceRoot().apply { antSourceRoots.add(this) }
+ fun createExternalDocumentationLink() =
+ ExternalDocumentationLink.Builder().apply { buildExternalLinksBuilders.add(this) }
+
+}
+
+class AntPackageOptions(
+ override var prefix: String = "",
+ override var includeNonPublic: Boolean = false,
+ override var reportUndocumented: Boolean = true,
+ override var skipDeprecated: Boolean = false,
+ override var suppress: Boolean = false) : DokkaConfiguration.PackageOptions
+
+class DokkaAntTask: Task(), DokkaConfiguration {
- fun createPackageOptions(): AntPackageOptions = AntPackageOptions().apply { antPackageOptions.add(this) }
+ override var format: String = "html"
+ override var generateIndexPages: Boolean = false
+ override var outputDir: String = ""
+ override var impliedPlatforms: List<String> = listOf()
+ get() = buildImpliedPlatforms.map { it.value }.toList()
+ private val buildImpliedPlatforms: MutableList<TextProperty> = mutableListOf()
+
+ override var cacheRoot: String? = null
+ override val passesConfigurations: MutableList<AntPassConfig> = mutableListOf()
+
+ fun createPassConfig() = AntPassConfig(this).apply { passesConfigurations.add(this) }
+ fun createImpliedPlatform(): TextProperty = TextProperty().apply { buildImpliedPlatforms.add(this) }
- fun createExternalDocumentationLink() = ExternalDocumentationLink.Builder().apply { antExternalDocumentationLinks.add(this) }
override fun execute() {
- if (sourcePath.list().isEmpty() && antSourceRoots.isEmpty()) {
- throw BuildException("At least one source path needs to be specified")
- }
- if (moduleName == null) {
- throw BuildException("Module name needs to be specified")
- }
- if (outputDir == null) {
- throw BuildException("Output directory needs to be specified")
- }
- val sourceLinks = antSourceLinks.map {
- val path = it.path ?: throw BuildException("'path' attribute of a <sourceLink> element is required")
- if (path.contains("\\")) {
- throw BuildException("'dir' attribute of a <sourceLink> - incorrect value, only Unix based path allowed.")
+ for (passConfig in passesConfigurations) {
+ if (passConfig.sourcePath.list().isEmpty() && passConfig.antSourceRoots.isEmpty()) {
+ throw BuildException("At least one source path needs to be specified")
}
- val url = it.url ?: throw BuildException("'url' attribute of a <sourceLink> element is required")
- SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix)
+ if (passConfig.moduleName == "") {
+ throw BuildException("Module name needs to be specified and not empty")
+ }
+
+ for (sourceLink in passConfig.antSourceLinkDefinition) {
+ if (sourceLink.path == null) {
+ throw BuildException("'path' attribute of a <sourceLink> element is required")
+ }
+ if (sourceLink.path!!.contains("\\")) {
+ throw BuildException("'dir' attribute of a <sourceLink> - incorrect value, only Unix based path allowed")
+ }
+
+ if (sourceLink.url == null) {
+ throw BuildException("'url' attribute of a <sourceLink> element is required")
+ }
+ }
+ }
+
+ if (outputDir == "") {
+ throw BuildException("Output directory needs to be specified and not empty")
}
- val generator = DokkaGenerator(
- AntLogger(this),
- compileClasspath.list().toList(),
- sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() },
- samplesPath.list().toList(),
- includesPath.list().toList(),
- moduleName!!,
- DocumentationOptions(
- outputDir!!,
- outputFormat,
- skipDeprecated = skipDeprecated,
- sourceLinks = sourceLinks,
- jdkVersion = jdkVersion,
- impliedPlatforms = impliedPlatforms.split(','),
- perPackageOptions = antPackageOptions,
- externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() },
- noStdlibLink = noStdlibLink,
- noJdkLink = noJdkLink,
- cacheRoot = cacheRoot,
- languageVersion = languageVersion,
- apiVersion = apiVersion
- )
- )
+ val generator = DokkaGenerator(this, AntLogger(this))
generator.generate()
}
} \ No newline at end of file
diff --git a/runners/cli/build.gradle b/runners/cli/build.gradle
index 7f733140..24db0b1e 100644
--- a/runners/cli/build.gradle
+++ b/runners/cli/build.gradle
@@ -4,13 +4,13 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
- languageVersion = "1.2"
- apiVersion = languageVersion
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
dependencies {
- compile project(":core")
- compile "com.github.spullara.cli-parser:cli-parser:1.1.1"
+ implementation "org.jetbrains.kotlinx:kotlinx-cli-jvm:0.1.0-dev-3"
+ implementation project(":core")
}
diff --git a/runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt b/runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt
new file mode 100644
index 00000000..5d795da7
--- /dev/null
+++ b/runners/cli/src/main/kotlin/cli/DokkaArgumentsParser.kt
@@ -0,0 +1,185 @@
+package org.jetbrains.dokka
+
+import kotlinx.cli.*
+import kotlin.reflect.KProperty
+
+class ParseContext(val cli: CommandLineInterface = CommandLineInterface("dokka")) {
+ private val transformActions = mutableMapOf<KProperty<*>, (String) -> Unit>()
+ private val flagActions = mutableMapOf<KProperty<*>, () -> Unit>()
+
+ fun registerFlagAction(
+ keys: List<String>,
+ help: String,
+ property: KProperty<*>,
+ invoke: () -> Unit
+ ) {
+ if (property !in flagActions.keys) {
+ cli.flagAction(keys, help) {
+ flagActions[property]!!()
+ }
+ }
+ flagActions[property] = invoke
+
+ }
+
+ fun registerSingleOption(
+ keys: List<String>,
+ help: String,
+ property: KProperty<*>,
+ invoke: (String) -> Unit
+ ) {
+ if (property !in transformActions.keys) {
+ cli.singleAction(keys, help) {
+ transformActions[property]!!(it)
+ }
+ }
+ transformActions[property] = invoke
+ }
+
+ fun registerRepeatableOption(
+ keys: List<String>,
+ help: String,
+ property: KProperty<*>,
+ invoke: (String) -> Unit
+ ) {
+ if (property !in transformActions.keys) {
+ cli.repeatingAction(keys, help) {
+ transformActions[property]!!(it)
+ }
+ }
+ transformActions[property] = invoke
+ }
+
+ fun parse(args: Array<String>) {
+ cli.parseArgs(*args)
+ }
+
+}
+
+fun CommandLineInterface.singleAction(
+ keys: List<String>,
+ help: String,
+ invoke: (String) -> Unit
+) = registerAction(
+ object : FlagActionBase(keys, help) {
+ override fun invoke(arguments: ListIterator<String>) {
+ if (arguments.hasNext()) {
+ val msg = arguments.next()
+ invoke(msg)
+ }
+ }
+
+ override fun invoke() {
+ error("should be never called")
+ }
+ }
+)
+
+fun CommandLineInterface.repeatingAction(
+ keys: List<String>,
+ help: String,
+ invoke: (String) -> Unit
+) = registerAction(
+ object : FlagActionBase(keys, help) {
+ override fun invoke(arguments: ListIterator<String>) {
+ while (arguments.hasNext()) {
+ val message = arguments.next()
+
+ if (this@repeatingAction.getFlagAction(message) != null) {
+ arguments.previous()
+ break
+ }
+ invoke(message)
+ }
+ }
+
+ override fun invoke() {
+ error("should be never called")
+ }
+ }
+
+)
+
+
+class DokkaArgumentsParser(val args: Array<String>, val parseContext: ParseContext) {
+ class OptionDelegate<T>(
+ var value: T,
+ private val action: (delegate: OptionDelegate<T>, property: KProperty<*>) -> Unit
+ ) {
+ operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
+ operator fun provideDelegate(thisRef: Any, property: KProperty<*>): OptionDelegate<T> {
+ action(this, property)
+ return this
+ }
+ }
+
+ fun <T> parseInto(dest: T): T {
+ // TODO: constructor: (DokkaArgumentsParser) -> T
+ parseContext.parse(args)
+ return dest
+ }
+
+ fun <T> repeatableOption(
+ keys: List<String>,
+ help: String,
+ transform: (String) -> T
+ ) = OptionDelegate(mutableListOf<T>()) { delegate, property ->
+ parseContext.registerRepeatableOption(keys, help, property) {
+ delegate.value.add(transform(it))
+ }
+ }
+
+ fun <T : String?> repeatableOption(
+ keys: List<String>,
+ help: String
+ ) = repeatableOption(keys, help) { it as T }
+
+ fun <T> repeatableFlag(
+ keys: List<String>,
+ help: String,
+ initElement: (ParseContext) -> T
+ ) = OptionDelegate(mutableListOf<T>()) { delegate, property ->
+ parseContext.registerFlagAction(keys, help, property) {
+ delegate.value.add(initElement(parseContext))
+ }
+ }
+
+ fun <T> singleFlag(
+ keys: List<String>,
+ help: String,
+ initElement: (ParseContext) -> T,
+ transform: () -> T
+ ) = OptionDelegate(initElement(parseContext)) { delegate, property ->
+ parseContext.registerFlagAction(keys, help, property) {
+ delegate.value = transform()
+ }
+ }
+
+ fun singleFlag(
+ keys: List<String>,
+ help: String
+ ) = singleFlag(keys, help, { false }, { true })
+
+ fun <T : String?> stringOption(
+ keys: List<String>,
+ help: String,
+ defaultValue: T
+ ) = singleOption(keys, help, { it as T }, { defaultValue })
+
+ fun <T> singleOption(
+ keys: List<String>,
+ help: String,
+ transform: (String) -> T,
+ initElement: (ParseContext) -> T
+ ) = OptionDelegate(initElement(parseContext)) { delegate, property ->
+ parseContext.registerSingleOption(keys, help, property) {
+ val toAdd = transform(it)
+ delegate.value = toAdd
+ }
+ }
+}
+
+
+//`(-perPackage fqName [-include-non-public] [...other flags])*` (edited)
+//`(-sourceLink dir url [-urlSuffix value])*`
+//`(-extLink url [packageListUrl])*` \ No newline at end of file
diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt
index f871f406..52815e75 100644
--- a/runners/cli/src/main/kotlin/cli/main.kt
+++ b/runners/cli/src/main/kotlin/cli/main.kt
@@ -1,142 +1,190 @@
package org.jetbrains.dokka
-
-import com.sampullara.cli.Args
-import com.sampullara.cli.Argument
import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
-
import java.io.File
import java.net.MalformedURLException
import java.net.URL
import java.net.URLClassLoader
-class DokkaArguments {
- @set:Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)")
- var src: String = ""
-
- @set:Argument(value = "srcLink", description = "Mapping between a source directory and a Web site for browsing the code")
- var srcLink: String = ""
-
- @set:Argument(value = "include", description = "Markdown files to load (allows many paths separated by the system path separator)")
- var include: String = ""
-
- @set:Argument(value = "samples", description = "Source root for samples")
- var samples: String = ""
-
- @set:Argument(value = "output", description = "Output directory path")
- var outputDir: String = "out/doc/"
-
- @set:Argument(value = "format", description = "Output format (text, html, markdown, jekyll, kotlin-website)")
- var outputFormat: String = "html"
-
- @set:Argument(value = "module", description = "Name of the documentation module")
- var moduleName: String = ""
-
- @set:Argument(value = "classpath", description = "Classpath for symbol resolution")
- var classpath: String = ""
-
- @set:Argument(value = "nodeprecated", description = "Exclude deprecated members from documentation")
- var nodeprecated: Boolean = false
-
- @set:Argument(value = "jdkVersion", description = "Version of JDK to use for linking to JDK JavaDoc")
- var jdkVersion: Int = 6
-
- @set:Argument(value = "impliedPlatforms", description = "List of implied platforms (comma-separated)")
- var impliedPlatforms: String = ""
-
- @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ")
- var packageOptions: String = ""
-
- @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...")
- var links: String = ""
-
- @set:Argument(value = "noStdlibLink", description = "Disable documentation link to stdlib")
- var noStdlibLink: Boolean = false
-
- @set:Argument(value = "noJdkLink", description = "Disable documentation link to jdk")
- var noJdkLink: Boolean = false
-
- @set:Argument(value = "cacheRoot", description = "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled")
- var cacheRoot: String? = null
-
- @set:Argument(value = "languageVersion", description = "Language Version to pass to Kotlin Analysis")
- var languageVersion: String? = null
-
- @set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis")
- var apiVersion: String? = null
-
- @set:Argument(value = "collectInheritedExtensionsFromLibraries", description = "Search for applicable extensions in libraries")
- var collectInheritedExtensionsFromLibraries: Boolean = false
-
+open class GlobalArguments(parser: DokkaArgumentsParser) : DokkaConfiguration {
+ override val outputDir: String by parser.stringOption(
+ listOf("-output"),
+ "Output directory path",
+ "")
+
+ override val format: String by parser.stringOption(
+ listOf("-format"),
+ "Output format (text, html, markdown, jekyll, kotlin-website)",
+ "")
+
+ override val generateIndexPages: Boolean by parser.singleFlag(
+ listOf("-generateIndexPages"),
+ "Generate index page"
+ )
+
+ override val cacheRoot: String? by parser.stringOption(
+ listOf("-cacheRoot"),
+ "Path to cache folder, or 'default' to use ~/.cache/dokka, if not provided caching is disabled",
+ null)
+
+ override val impliedPlatforms: List<String> = emptyList()
+
+ override val passesConfigurations: List<Arguments> by parser.repeatableFlag(
+ listOf("-pass"),
+ "Single dokka pass"
+ ) {
+ Arguments(parser)
+ }
}
+class Arguments(val parser: DokkaArgumentsParser) : DokkaConfiguration.PassConfiguration {
+ override val moduleName: String by parser.stringOption(
+ listOf("-module"),
+ "Name of the documentation module",
+ "")
+
+ override val classpath: List<String> by parser.repeatableOption(
+ listOf("-classpath"),
+ "Classpath for symbol resolution"
+ )
+
+ override val sourceRoots: List<DokkaConfiguration.SourceRoot> by parser.repeatableOption(
+ listOf("-src"),
+ "Source file or directory (allows many paths separated by the system path separator)"
+ ) { SourceRootImpl(it) }
+
+ override val samples: List<String> by parser.repeatableOption(
+ listOf("-sample"),
+ "Source root for samples"
+ )
+
+ override val includes: List<String> by parser.repeatableOption(
+ listOf("-include"),
+ "Markdown files to load (allows many paths separated by the system path separator)"
+ )
+
+ override val includeNonPublic: Boolean by parser.singleFlag(
+ listOf("-includeNonPublic"),
+ "Include non public")
+
+ override val includeRootPackage: Boolean by parser.singleFlag(
+ listOf("-includeRootPackage"),
+ "Include root package")
+
+ override val reportUndocumented: Boolean by parser.singleFlag(
+ listOf("-reportUndocumented"),
+ "Report undocumented members")
+
+ override val skipEmptyPackages: Boolean by parser.singleFlag(
+ listOf("-skipEmptyPackages"),
+ "Do not create index pages for empty packages")
+
+ override val skipDeprecated: Boolean by parser.singleFlag(
+ listOf("-skipDeprecated"),
+ "Do not output deprecated members")
+
+ override val jdkVersion: Int by parser.singleOption(
+ listOf("-jdkVersion"),
+ "Version of JDK to use for linking to JDK JavaDoc",
+ { it.toInt() },
+ { 6 }
+ )
+
+ override val languageVersion: String? by parser.stringOption(
+ listOf("-languageVersion"),
+ "Language Version to pass to Kotlin Analysis",
+ null)
+
+ override val apiVersion: String? by parser.stringOption(
+ listOf("-apiVersion"),
+ "Kotlin Api Version to pass to Kotlin Analysis",
+ null
+ )
+
+ override val noStdlibLink: Boolean by parser.singleFlag(
+ listOf("-noStdlibLink"),
+ "Disable documentation link to stdlib")
+
+ override val noJdkLink: Boolean by parser.singleFlag(
+ listOf("-noJdkLink"),
+ "Disable documentation link to JDK")
+
+ override val suppressedFiles: List<String> by parser.repeatableOption(
+ listOf("-suppressedFile"),
+ ""
+ )
+
+ override val sinceKotlin: String? by parser.stringOption(
+ listOf("-sinceKotlin"),
+ "Kotlin Api version to use as base version, if none specified",
+ null
+ )
+
+ override val collectInheritedExtensionsFromLibraries: Boolean by parser.singleFlag(
+ listOf("-collectInheritedExtensionsFromLibraries"),
+ "Search for applicable extensions in libraries")
+
+ override val analysisPlatform: Platform by parser.singleOption(
+ listOf("-analysisPlatform"),
+ "Platform for analysis",
+ { Platform.fromString(it) },
+ { Platform.DEFAULT }
+ )
+
+ override val targets: List<String> by parser.repeatableOption(
+ listOf("-target"),
+ "Generation targets"
+ )
+
+ override val perPackageOptions: MutableList<DokkaConfiguration.PackageOptions> by parser.singleOption(
+ listOf("-packageOptions"),
+ "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ",
+ { parsePerPackageOptions(it).toMutableList() },
+ { mutableListOf() }
+ )
+
+ override val externalDocumentationLinks: MutableList<DokkaConfiguration.ExternalDocumentationLink> by parser.singleOption(
+ listOf("-links"),
+ "External documentation links in format url^packageListUrl^^url2...",
+ { MainKt.parseLinks(it).toMutableList() },
+ { mutableListOf() }
+ )
+
+ override val sourceLinks: MutableList<DokkaConfiguration.SourceLinkDefinition> by parser.repeatableOption(
+ listOf("-srcLink"),
+ "Mapping between a source directory and a Web site for browsing the code"
+ ) {
+ if (it.isNotEmpty() && it.contains("="))
+ SourceLinkDefinitionImpl.parseSourceLinkDefinition(it)
+ else {
+ throw IllegalArgumentException("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
+ }
+ }
+}
object MainKt {
-
fun parseLinks(links: String): List<ExternalDocumentationLink> {
val (parsedLinks, parsedOfflineLinks) = links.split("^^")
- .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
- .filter { it.isNotEmpty() }
- .partition { it.size == 1 }
+ .map { it.split("^").map { it.trim() }.filter { it.isNotBlank() } }
+ .filter { it.isNotEmpty() }
+ .partition { it.size == 1 }
return parsedLinks.map { (root) -> ExternalDocumentationLink.Builder(root).build() } +
parsedOfflineLinks.map { (root, packageList) ->
val rootUrl = URL(root)
val packageListUrl =
- try {
- URL(packageList)
- } catch (ex: MalformedURLException) {
- File(packageList).toURI().toURL()
- }
+ try {
+ URL(packageList)
+ } catch (ex: MalformedURLException) {
+ File(packageList).toURI().toURL()
+ }
ExternalDocumentationLink.Builder(rootUrl, packageListUrl).build()
}
}
@JvmStatic
- fun entry(args: Array<String>) {
- val arguments = DokkaArguments()
- val freeArgs: List<String> = Args.parse(arguments, args) ?: listOf()
- val sources = if (arguments.src.isNotEmpty()) arguments.src.split(File.pathSeparatorChar).toList() + freeArgs else freeArgs
- val samples = if (arguments.samples.isNotEmpty()) arguments.samples.split(File.pathSeparatorChar).toList() else listOf()
- val includes = if (arguments.include.isNotEmpty()) arguments.include.split(File.pathSeparatorChar).toList() else listOf()
-
- val sourceLinks = if (arguments.srcLink.isNotEmpty() && arguments.srcLink.contains("="))
- listOf(SourceLinkDefinitionImpl.parseSourceLinkDefinition(arguments.srcLink))
- else {
- if (arguments.srcLink.isNotEmpty()) {
- println("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
- }
- listOf()
- }
-
- val classPath = arguments.classpath.split(File.pathSeparatorChar).toList()
-
- val documentationOptions = DocumentationOptions(
- arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' },
- arguments.outputFormat,
- skipDeprecated = arguments.nodeprecated,
- sourceLinks = sourceLinks,
- impliedPlatforms = arguments.impliedPlatforms.split(','),
- perPackageOptions = parsePerPackageOptions(arguments.packageOptions),
- jdkVersion = arguments.jdkVersion,
- externalDocumentationLinks = parseLinks(arguments.links),
- noStdlibLink = arguments.noStdlibLink,
- cacheRoot = arguments.cacheRoot,
- languageVersion = arguments.languageVersion,
- apiVersion = arguments.apiVersion,
- collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries,
- noJdkLink = arguments.noJdkLink
- )
-
- val generator = DokkaGenerator(
- DokkaConsoleLogger,
- classPath,
- sources.map(SourceRootImpl.Companion::parseSourceRoot),
- samples,
- includes,
- arguments.moduleName,
- documentationOptions)
-
+ fun entry(configuration: DokkaConfiguration) {
+ val generator = DokkaGenerator(configuration, DokkaConsoleLogger)
generator.generate()
DokkaConsoleLogger.report()
}
@@ -162,27 +210,65 @@ object MainKt {
return URLClassLoader(urls, ClassLoader.getSystemClassLoader().parent)
}
- fun startWithToolsJar(args: Array<String>) {
+ fun startWithToolsJar(configuration: DokkaConfiguration) {
try {
javaClass.classLoader.loadClass("com.sun.tools.doclets.formats.html.HtmlDoclet")
- entry(args)
+ entry(configuration)
} catch (e: ClassNotFoundException) {
val classLoader = createClassLoaderWithTools()
classLoader.loadClass("org.jetbrains.dokka.MainKt")
- .methods.find { it.name == "entry" }!!
- .invoke(null, args)
+ .methods.find { it.name == "entry" }!!
+ .invoke(null, configuration)
+ }
+ }
+
+ fun createConfiguration(args: Array<String>): GlobalArguments {
+ val parseContext = ParseContext()
+ val parser = DokkaArgumentsParser(args, parseContext)
+ val configuration = GlobalArguments(parser)
+
+ parseContext.cli.singleAction(
+ listOf("-globalPackageOptions"),
+ "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" "
+ ) { link ->
+ configuration.passesConfigurations.all { it.perPackageOptions.addAll(parsePerPackageOptions(link)) }
}
+
+ parseContext.cli.singleAction(
+ listOf("-globalLinks"),
+ "External documentation links in format url^packageListUrl^^url2..."
+ ) { link ->
+ configuration.passesConfigurations.all { it.externalDocumentationLinks.addAll(parseLinks(link)) }
+ }
+
+ parseContext.cli.repeatingAction(
+ listOf("-globalSrcLink"),
+ "Mapping between a source directory and a Web site for browsing the code"
+ ) {
+ val newSourceLinks = if (it.isNotEmpty() && it.contains("="))
+ listOf(SourceLinkDefinitionImpl.parseSourceLinkDefinition(it))
+ else {
+ if (it.isNotEmpty()) {
+ println("Warning: Invalid -srcLink syntax. Expected: <path>=<url>[#lineSuffix]. No source links will be generated.")
+ }
+ listOf()
+ }
+
+ configuration.passesConfigurations.all { it.sourceLinks.addAll(newSourceLinks) }
+ }
+
+ parser.parseInto(configuration)
+ return configuration
}
@JvmStatic
fun main(args: Array<String>) {
- val arguments = DokkaArguments()
- Args.parse(arguments, args)
+ val configuration = createConfiguration(args)
- if (arguments.outputFormat == "javadoc")
- startWithToolsJar(args)
+ if (configuration.format.toLowerCase() == "javadoc")
+ startWithToolsJar(configuration)
else
- entry(args)
+ entry(configuration)
}
}
diff --git a/runners/gradle-integration-tests/build.gradle b/runners/gradle-integration-tests/build.gradle
index 297a175a..2430d46b 100644
--- a/runners/gradle-integration-tests/build.gradle
+++ b/runners/gradle-integration-tests/build.gradle
@@ -1,5 +1,3 @@
-
-
apply plugin: 'kotlin'
sourceCompatibility = 1.8
@@ -7,16 +5,16 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = "1.0"
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
configurations {
dokkaPlugin
- dokkaAndroidPlugin
dokkaFatJar
+ kotlinGradle
}
dependencies {
@@ -26,9 +24,10 @@ dependencies {
testCompile ideaRT()
dokkaPlugin project(path: ':runners:gradle-plugin', configuration: 'shadow')
- dokkaAndroidPlugin project(path: ':runners:android-gradle-plugin', configuration: 'shadow')
dokkaFatJar project(path: ":runners:fatjar", configuration: 'shadow')
+ kotlinGradle "org.jetbrains.kotlin:kotlin-gradle-plugin"
+
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile gradleTestKit()
}
@@ -38,14 +37,14 @@ dependencies {
task createClasspathManifest {
def outputDir = file("$buildDir/$name")
- inputs.files(configurations.dokkaPlugin + configurations.dokkaAndroidPlugin + configurations.dokkaFatJar)
+ inputs.files(configurations.dokkaPlugin + configurations.dokkaFatJar)
outputs.dir outputDir
doLast {
outputDir.mkdirs()
file("$outputDir/dokka-plugin-classpath.txt").text = configurations.dokkaPlugin.join("\n")
- file("$outputDir/android-dokka-plugin-classpath.txt").text = configurations.dokkaAndroidPlugin.join("\n")
file("$outputDir/fatjar.txt").text = configurations.dokkaFatJar.join("\n")
+ file("$outputDir/kotlin-gradle.txt").text = configurations.kotlinGradle.join("\n")
}
}
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt
index 06753342..334fc7c8 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaAndroidGradleTest.kt
@@ -5,7 +5,7 @@ import java.io.File
abstract class AbstractDokkaAndroidGradleTest : AbstractDokkaGradleTest() {
- override val pluginClasspath: List<File> = androidPluginClasspathData.toFile().readLines().map { File(it) }
+ override val pluginClasspath: List<File> = pluginClasspathData.toFile().readLines().map { File(it) }
companion object {
@@ -31,7 +31,7 @@ abstract class AbstractDokkaAndroidGradleTest : AbstractDokkaGradleTest() {
acceptedLicenses.listFiles().forEach { licenseFile ->
val target = sdkLicensesDir.resolve(licenseFile.name)
if(!target.exists() || target.readText() != licenseFile.readText()) {
- val overwrite = System.getProperty("android.licenses.overwrite", "false").toBoolean()
+ val overwrite = System.getProperty("android.licenses.overwrite", "false")!!.toBoolean()
if (!target.exists() || overwrite) {
licenseFile.copyTo(target, true)
println("Accepted ${licenseFile.name}, by copying $licenseFile to $target")
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
index 255138a9..4814e707 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AbstractDokkaGradleTest.kt
@@ -7,15 +7,15 @@ import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.io.File
import java.nio.file.Files
+import java.nio.file.Path
import java.nio.file.Paths
-val testDataFolder = Paths.get("testData")
+val testDataFolder: Path = Paths.get("testData")
-val pluginClasspathData = Paths.get("build", "createClasspathManifest", "dokka-plugin-classpath.txt")
-val androidPluginClasspathData = pluginClasspathData.resolveSibling("android-dokka-plugin-classpath.txt")
+val pluginClasspathData: Path = Paths.get("build", "createClasspathManifest", "dokka-plugin-classpath.txt")
-val dokkaFatJarPathData = pluginClasspathData.resolveSibling("fatjar.txt")
+val dokkaFatJarPathData: Path = pluginClasspathData.resolveSibling("fatjar.txt")
val androidLocalProperties = testDataFolder.resolve("android.local.properties").let { if (Files.exists(it)) it else null }
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt
index 2a4ce712..9bc52273 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/AndroidLibDependsOnJavaLibTest.kt
@@ -2,8 +2,6 @@ package org.jetbrains.dokka.gradle
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Test
-import java.nio.file.Path
-import java.nio.file.Paths
import kotlin.test.assertEquals
class AndroidLibDependsOnJavaLibTest: AbstractDokkaAndroidGradleTest() {
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
index ebaf1653..2e1a0d41 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/BasicTest.kt
@@ -37,10 +37,6 @@ class BasicTest : AbstractDokkaGradleTest() {
"""<a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/index.html"><span class="identifier">String</span></a>""")
}
- @Test fun `test kotlin 1_1_2 and gradle 3_5`() {
- doTest("3.5", "1.1.2")
- }
-
@Test fun `test kotlin 1_0_7 and gradle 2_14_1`() {
doTest("2.14.1", "1.0.7")
}
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt
new file mode 100644
index 00000000..3e61d79e
--- /dev/null
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt
@@ -0,0 +1,54 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.testkit.runner.TaskOutcome
+import org.junit.Test
+import java.io.File
+import kotlin.test.assertEquals
+
+class MultiplatformProjectTest : AbstractDokkaGradleTest() {
+
+ fun prepareTestData(testDataRootPath: String) {
+ val testDataRoot = testDataFolder.resolve(testDataRootPath)
+ val tmpRoot = testProjectDir.root.toPath()
+
+ testDataRoot.apply {
+ resolve("build.gradle").copy(tmpRoot.resolve("build.gradle"))
+ resolve("settings.gradle").copy(tmpRoot.resolve("settings.gradle"))
+ resolve("src").copy(tmpRoot.resolve("src"))
+ }
+ }
+
+ private fun doTest(gradleVersion: String, kotlinVersion: String) {
+ val kotlinGradlePlugin = pluginClasspathData.resolveSibling("kotlin-gradle.txt").toFile().readLines().map { File(it) }
+ prepareTestData("multiplatformProject")
+
+ // Remove withDebug(false) when https://github.com/gradle/gradle/issues/6862 is solved
+ val result = configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace"))
+ .withDebug(false)
+ .withPluginClasspath(pluginClasspath.union(kotlinGradlePlugin))
+ .build()
+
+ println(result.output)
+
+ assertEquals(TaskOutcome.SUCCESS, result.task(":dokka")?.outcome)
+
+ val docsOutput = "build/dokka"
+
+ checkOutputStructure("multiplatformProject/fileTree.txt", docsOutput)
+
+ checkNoErrorClasses(docsOutput)
+ checkNoUnresolvedLinks(docsOutput)
+ }
+
+ @Test fun `test kotlin 1_3_30 and gradle 4_7`() {
+ doTest("4.7", "1.3.30")
+ }
+
+ @Test fun `test kotlin 1_3_40 and gradle 4_10_3`() {
+ doTest("4.10.3", "1.3.40")
+ }
+
+ @Test fun `test kotlin 1_3_40 and gradle 5_6_1`() {
+ doTest("5.6.1", "1.3.50")
+ }
+} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt
index f712998c..8b2db560 100644
--- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt
+++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/RebuildAfterSourceChangeTest.kt
@@ -30,7 +30,7 @@ class RebuildAfterSourceChangeTest : AbstractDokkaGradleTest() {
}
- configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "--stacktrace")).build().let { result ->
+ configure(gradleVersion, kotlinVersion, arguments = arrayOf("dokka", "-i", "--stacktrace")).build().let { result ->
println(result.output)
assertEquals(TaskOutcome.UP_TO_DATE, result.task(":dokka")?.outcome)
@@ -53,13 +53,13 @@ class RebuildAfterSourceChangeTest : AbstractDokkaGradleTest() {
@Test
- fun `test kotlin 1_1_2 and gradle 3_5`() {
- doTest("3.5", "1.1.2")
+ fun `test kotlin 1_0_7 and gradle 2_14_1`() {
+ doTest("2.14.1", "1.0.7")
}
@Test
- fun `test kotlin 1_0_7 and gradle 2_14_1`() {
- doTest("2.14.1", "1.0.7")
+ fun `test kotlin 1_1_2 and gradle 3_5`() {
+ doTest("3.5", "1.1.2")
}
@Test
diff --git a/runners/gradle-integration-tests/testData/androidApp/app/build.gradle b/runners/gradle-integration-tests/testData/androidApp/app/build.gradle
index 1555de9f..2420107c 100644
--- a/runners/gradle-integration-tests/testData/androidApp/app/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidApp/app/build.gradle
@@ -9,14 +9,13 @@ buildscript {
}
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
-apply plugin: 'org.jetbrains.dokka-android'
android {
compileSdkVersion Integer.parseInt(sdk_version)
@@ -42,9 +41,5 @@ android {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version"
-}
-
-
-dokka {
- dokkaFatJar = new File(dokka_fatjar)
+ dokkaRuntime files(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle
index 6a053a5e..66421f52 100644
--- a/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/app/build.gradle
@@ -9,13 +9,12 @@ buildscript {
}
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
-apply plugin: 'org.jetbrains.dokka-android'
android {
compileSdkVersion Integer.parseInt(sdk_version)
@@ -41,10 +40,10 @@ android {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version"
+ dokkaRuntime files(dokka_fatjar)
}
dokka {
outputFormat = "javadoc"
- dokkaFatJar = new File(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle b/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle
index 0f27d365..b1ee52ab 100644
--- a/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidLibDependsOnJavaLib/lib/build.gradle
@@ -7,13 +7,12 @@ buildscript {
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
-apply plugin: 'org.jetbrains.dokka-android'
android {
@@ -27,13 +26,14 @@ android {
dependencies {
api(project(":jlib"))
+ dokkaRuntime files(dokka_fatjar)
}
dokka {
- dokkaFatJar = new File(dokka_fatjar)
-
- externalDocumentationLink {
- url = new URL("https://example.com")
- packageListUrl = file("$rootDir/package-list").toURI().toURL()
+ configuration {
+ externalDocumentationLink {
+ url = new URL("https://example.com")
+ packageListUrl = file("$rootDir/package-list").toURI().toURL()
+ }
}
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle b/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle
index ee68ba6d..660257ab 100644
--- a/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle
+++ b/runners/gradle-integration-tests/testData/androidMultiFlavourApp/app/build.gradle
@@ -9,14 +9,13 @@ buildscript {
}
plugins {
- id 'org.jetbrains.dokka-android'
+ id 'org.jetbrains.dokka'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
-apply plugin: 'org.jetbrains.dokka-android'
android {
compileSdkVersion Integer.parseInt(sdk_version)
@@ -57,19 +56,20 @@ android {
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$test_kotlin_version"
+ dokkaRuntime files(dokka_fatjar)
}
dokka {
outputDirectory = "$buildDir/dokka/all"
- dokkaFatJar = new File(dokka_fatjar)
}
-task dokkaFullFlavourOnly(type: org.jetbrains.dokka.gradle.DokkaAndroidTask) {
- kotlinTasks {
- ["compileFullReleaseKotlin"]
- }
- dokkaFatJar = new File(dokka_fatjar)
+task dokkaFullFlavourOnly(type: org.jetbrains.dokka.gradle.DokkaTask) {
outputDirectory = "$buildDir/dokka/fullOnly"
- moduleName = "full"
+ configuration {
+ moduleName = "full"
+ kotlinTasks {
+ ["compileFullReleaseKotlin"]
+ }
+ }
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/basic/build.gradle b/runners/gradle-integration-tests/testData/basic/build.gradle
index a3116751..79645204 100644
--- a/runners/gradle-integration-tests/testData/basic/build.gradle
+++ b/runners/gradle-integration-tests/testData/basic/build.gradle
@@ -29,12 +29,14 @@ repositories {
}
dependencies {
+ dokkaRuntime files(dokka_fatjar)
compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
}
dokka {
- dokkaFatJar = new File(dokka_fatjar)
- classpath += files("$projectDir/classDir")
+ configuration {
+ classpath += "$projectDir/classDir"
+ }
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
index 4f561472..0ea86d4c 100644
--- a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
+++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle
@@ -22,11 +22,16 @@ subprojects {
}
}
+dependencies {
+ dokkaRuntime files(dokka_fatjar)
+}
+
apply plugin: 'org.jetbrains.dokka'
dokka {
- kotlinTasks {
- [":subA:compileKotlin", ":subB:compileKotlin"]
+ configuration {
+ kotlinTasks {
+ [":subA:compileKotlin", ":subB:compileKotlin"]
+ }
}
- dokkaFatJar = new File(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/build.gradle b/runners/gradle-integration-tests/testData/multiplatformProject/build.gradle
new file mode 100644
index 00000000..b5454c55
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/build.gradle
@@ -0,0 +1,60 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" }
+ maven { url "https://dl.bintray.com/kotlin/kotlin-dev" }
+ }
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version"
+ }
+}
+
+plugins {
+ id 'org.jetbrains.dokka'
+}
+
+repositories {
+ jcenter()
+ mavenLocal()
+}
+
+group 'org.test'
+version '1.0-SNAPSHOT'
+
+apply plugin: "org.jetbrains.kotlin.multiplatform"
+
+kotlin {
+ jvm() // Create a JVM target with the default name 'jvm'
+ js()
+ sourceSets {
+ jsMain {
+ dependencies{
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-js"
+ }
+ }
+ jvmMain {
+ dependencies {
+ implementation kotlin('stdlib-jdk8')
+ }
+ }
+ }
+}
+
+dependencies {
+ dokkaRuntime files(dokka_fatjar)
+}
+
+apply plugin: 'org.jetbrains.dokka'
+
+dokka {
+
+ multiplatform {
+ javascript {
+ targets = ["js"]
+ platform = "js"
+ kotlinTasks { [tasks.getByPath(":compileKotlinJs")] }
+ }
+ jvm {}
+ }
+}
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt b/runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt
new file mode 100644
index 00000000..51a5df94
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/fileTree.txt
@@ -0,0 +1,17 @@
+/
+ multiplatform-project-root/
+ alltypes/
+ index.html
+ index-outline.html
+ index.html
+ org.kotlintestmpp/
+ get-current-date.html
+ index.html
+ js.html
+ jvm.html
+ kotlin.-string/
+ index.html
+ main.html
+ shared.html
+ package-list
+ style.css
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle b/runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle
new file mode 100644
index 00000000..0bb1e91b
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = "multiplatformProjectRoot"
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt b/runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt
new file mode 100644
index 00000000..a77b50f9
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/src/jsMain/kotlin/org/kotlintestmpp/main.kt
@@ -0,0 +1,14 @@
+package org.kotlintestmpp
+
+fun main(args : Array<String>) {
+ console.log("Hello, world!")
+}
+
+fun js(){}
+fun shared(){}
+
+fun getCurrentDate(): String {
+ return "test"
+}
+
+fun String.myExtension() = println("test") \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt b/runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt
new file mode 100644
index 00000000..96d725fc
--- /dev/null
+++ b/runners/gradle-integration-tests/testData/multiplatformProject/src/jvmMain/kotlin/org/kotlintestmpp/main.kt
@@ -0,0 +1,20 @@
+package org.kotlintestmpp
+
+
+fun main(args : Array<String>) {
+ println("Hello, world!")
+}
+
+/**
+ * comment for this class
+ */
+fun jvm(){}
+fun shared(){}
+
+fun getCurrentDate(): String {
+ return "test"
+}
+
+fun String.myExtension() = println("test2")
+
+
diff --git a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle
index 4627e8ef..a6270e23 100644
--- a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle
+++ b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle
@@ -29,11 +29,7 @@ repositories {
}
dependencies {
+ dokkaRuntime files(dokka_fatjar)
compile group: 'org.jetbrains.kotlin', name: 'kotlin-runtime', version: test_kotlin_version
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: test_kotlin_version
-}
-
-
-dokka {
- dokkaFatJar = new File(dokka_fatjar)
} \ No newline at end of file
diff --git a/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle b/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle
index 327cead8..8688ae41 100644
--- a/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle
+++ b/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle
@@ -8,6 +8,7 @@ import java.util.concurrent.Callable
buildscript {
repositories {
jcenter()
+ mavenLocal()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$test_kotlin_version"
@@ -23,57 +24,45 @@ apply plugin: 'kotlin'
@CompileStatic
def configureDokkaTypeSafely(DokkaTask dokka) {
dokka.with {
- moduleName = "some String"
outputFormat = "some String"
outputDirectory = "some String"
- classpath = Collections.singleton(file("someClassDir"))
- includes = Collections.emptyList()
- linkMappings = new ArrayList<LinkMapping>()
- samples = Collections.emptyList()
+ cacheRoot = null as String
+ impliedPlatforms = new ArrayList<String>()
+ }
+ dokka.configuration.with {
+ moduleName = "some String"
+ classpath = Arrays.asList("someClassDir")
+ includes = Collections.<String> emptyList()
+ samples = Collections.<String> emptyList()
jdkVersion = 6
- sourceDirs = Collections.<File>emptyList()
- sourceRoots = new ArrayList<SourceRoot>()
- dokkaFatJar = file("some File")
+ sourceRoots = new ArrayList<GradleSourceRootImpl>() as List<DokkaConfiguration.SourceRoot>
+
includeNonPublic = false
skipDeprecated = false
skipEmptyPackages = true
reportUndocumented = true
- perPackageOptions = new ArrayList<PackageOptions>()
- impliedPlatforms = Collections.<String>emptyList()
+ perPackageOptions = new ArrayList<GradlePackageOptionsImpl>() as List<DokkaConfiguration.PackageOptions>
externalDocumentationLinks = new ArrayList<DokkaConfiguration.ExternalDocumentationLink>()
noStdlibLink = false
- cacheRoot = null as String
languageVersion = null as String
apiVersion = null as String
- kotlinTasks(new Callable<List<Object>>() {
- @Override
- List<Object> call() {
- return defaultKotlinTasks()
- }
- })
- linkMapping(new Action<LinkMapping>() {
+ sourceRoot(new Action<GradleSourceRootImpl>() {
@Override
- void execute(LinkMapping mapping) {
- mapping.dir = "some String"
- mapping.url = "some String"
- }
- })
- sourceRoot(new Action<SourceRoot>() {
- @Override
- void execute(SourceRoot sourceRoot) {
+ void execute(GradleSourceRootImpl sourceRoot) {
sourceRoot.path = "some String"
}
})
- packageOptions(new Action<PackageOptions>() {
+ externalDocumentationLink(new Action<GradleExternalDocumentationLinkImpl>() {
@Override
- void execute(PackageOptions packageOptions) {
- packageOptions.prefix = "some String"
+ void execute(GradleExternalDocumentationLinkImpl link) {
+ link.url = uri("some URI").toURL()
+ link.packageListUrl = uri("some URI").toURL()
}
})
- externalDocumentationLink(new Action<DokkaConfiguration.ExternalDocumentationLink.Builder>() {
+ kotlinTasks(new Callable<List<Object>>() {
@Override
- void execute(DokkaConfiguration.ExternalDocumentationLink.Builder builder) {
- builder.url = uri("some URI").toURL()
+ List<Object> call() {
+ return defaultKotlinTasks()
}
})
}
diff --git a/runners/gradle-plugin/build.gradle b/runners/gradle-plugin/build.gradle
index 8e59a7be..ceb03bae 100644
--- a/runners/gradle-plugin/build.gradle
+++ b/runners/gradle-plugin/build.gradle
@@ -12,12 +12,17 @@ sourceCompatibility = 1.8
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
- languageVersion = "1.2"
- apiVersion = "1.1"
+ languageVersion = language_version
+ apiVersion = language_version
jvmTarget = "1.8"
}
}
+repositories {
+ jcenter()
+ google()
+}
+
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
@@ -26,8 +31,13 @@ dependencies {
compile project(":integration")
+ compileOnly "org.jetbrains.kotlin:kotlin-gradle-plugin"
+ compileOnly("com.android.tools.build:gradle:3.0.0")
+ compileOnly("com.android.tools.build:gradle-core:3.0.0")
+ compileOnly("com.android.tools.build:builder-model:3.0.0")
compileOnly gradleApi()
compileOnly localGroovy()
+ implementation "com.google.code.gson:gson:$gson_version"
}
task sourceJar(type: Jar) {
@@ -54,7 +64,6 @@ apply plugin: 'maven-publish'
publishing {
publications {
dokkaGradlePlugin(MavenPublication) { publication ->
-
artifactId = 'dokka-gradle-plugin'
artifact sourceJar {
@@ -77,7 +86,7 @@ pluginBundle {
website = 'https://www.kotlinlang.org/'
vcsUrl = 'https://github.com/kotlin/dokka.git'
description = 'Dokka, the Kotlin documentation tool'
- tags = ['dokka', 'kotlin', 'kdoc']
+ tags = ['dokka', 'kotlin', 'kdoc', 'android']
plugins {
dokkaGradlePlugin {
diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt
deleted file mode 100644
index f4adc1c3..00000000
--- a/runners/gradle-plugin/src/main/kotlin/main.kt
+++ /dev/null
@@ -1,499 +0,0 @@
-package org.jetbrains.dokka.gradle
-
-import groovy.lang.Closure
-import org.gradle.api.Action
-import org.gradle.api.DefaultTask
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.Task
-import org.gradle.api.artifacts.Configuration
-import org.gradle.api.file.FileCollection
-import org.gradle.api.plugins.JavaBasePlugin
-import org.gradle.api.plugins.JavaPluginConvention
-import org.gradle.api.tasks.*
-import org.gradle.api.tasks.Optional
-import org.gradle.api.tasks.compile.AbstractCompile
-import org.jetbrains.dokka.*
-import org.jetbrains.dokka.ReflectDsl.isNotInstance
-import org.jetbrains.dokka.gradle.ClassloaderContainer.fatJarClassLoader
-import org.jetbrains.dokka.gradle.DokkaVersion.version
-import ru.yole.jkid.JsonExclude
-import ru.yole.jkid.serialization.serialize
-import java.io.File
-import java.io.InputStream
-import java.io.Serializable
-import java.net.URLClassLoader
-import java.util.*
-import java.util.concurrent.Callable
-import java.util.function.BiConsumer
-
-open class DokkaPlugin : Plugin<Project> {
-
- override fun apply(project: Project) {
- DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties"))
- project.tasks.create("dokka", DokkaTask::class.java).apply {
- dokkaRuntime = project.configurations.create("dokkaRuntime")
- moduleName = project.name
- outputDirectory = File(project.buildDir, "dokka").absolutePath
- }
- }
-}
-
-object DokkaVersion {
- var version: String? = null
-
- fun loadFrom(stream: InputStream) {
- version = Properties().apply {
- load(stream)
- }.getProperty("dokka-version")
- }
-}
-
-
-object ClassloaderContainer {
- @JvmField
- var fatJarClassLoader: ClassLoader? = null
-}
-
-const val `deprecationMessage reportNotDocumented` = "Will be removed in 0.9.17, see dokka#243"
-
-open class DokkaTask : DefaultTask() {
-
- fun defaultKotlinTasks() = with(ReflectDsl) {
- val abstractKotlinCompileClz = try {
- project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (cnfe: ClassNotFoundException) {
- logger.warn("$ABSTRACT_KOTLIN_COMPILE class not found, default kotlin tasks ignored")
- return@with emptyList<Task>()
- }
-
- return@with project.tasks.filter { it isInstance abstractKotlinCompileClz }.filter { "Test" !in it.name }
- }
-
- init {
- group = JavaBasePlugin.DOCUMENTATION_GROUP
- description = "Generates dokka documentation for Kotlin"
-
- @Suppress("LeakingThis")
- dependsOn(Callable { kotlinTasks.map { it.taskDependencies } })
- }
-
- @Input
- var moduleName: String = ""
- @Input
- var outputFormat: String = "html"
- var outputDirectory: String = ""
- var dokkaRuntime: Configuration? = null
-
- @Deprecated("Going to be removed in 0.9.16, use classpath + sourceDirs instead if kotlinTasks is not suitable for you")
- @Input var processConfigurations: List<Any?> = emptyList()
-
- @InputFiles var classpath: Iterable<File> = arrayListOf()
-
- @Input
- var includes: List<Any?> = arrayListOf()
- @Input
- var linkMappings: ArrayList<LinkMapping> = arrayListOf()
- @Input
- var samples: List<Any?> = arrayListOf()
- @Input
- var jdkVersion: Int = 6
- @Input
- var sourceDirs: Iterable<File> = emptyList()
-
- @Input
- var sourceRoots: MutableList<SourceRoot> = arrayListOf()
-
- @Input
- var dokkaFatJar: Any = "org.jetbrains.dokka:dokka-fatjar:$version"
-
- @Input var includeNonPublic = false
- @Input var skipDeprecated = false
- @Input var skipEmptyPackages = true
-
- @Deprecated(`deprecationMessage reportNotDocumented`, replaceWith = ReplaceWith("reportUndocumented"))
- var reportNotDocumented
- get() = reportUndocumented
- set(value) {
- logger.warn("Dokka: reportNotDocumented is deprecated and " + `deprecationMessage reportNotDocumented`.decapitalize())
- reportUndocumented = value
- }
-
- @Input var reportUndocumented = true
- @Input var perPackageOptions: MutableList<PackageOptions> = arrayListOf()
- @Input var impliedPlatforms: MutableList<String> = arrayListOf()
-
- @Input var externalDocumentationLinks = mutableListOf<DokkaConfiguration.ExternalDocumentationLink>()
-
- @Input var noStdlibLink: Boolean = false
-
- @Input
- var noJdkLink: Boolean = false
-
- @Optional @Input
- var cacheRoot: String? = null
-
-
- @Optional @Input
- var languageVersion: String? = null
-
- @Optional @Input
- var apiVersion: String? = null
-
- @Input
- var collectInheritedExtensionsFromLibraries: Boolean = false
-
- @get:Internal
- internal val kotlinCompileBasedClasspathAndSourceRoots: ClasspathAndSourceRoots by lazy { extractClasspathAndSourceRootsFromKotlinTasks() }
-
-
- private var kotlinTasksConfigurator: () -> List<Any?>? = { defaultKotlinTasks() }
- private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks() }
-
- fun kotlinTasks(taskSupplier: Callable<List<Any>>) {
- kotlinTasksConfigurator = { taskSupplier.call() }
- }
-
- fun kotlinTasks(closure: Closure<Any?>) {
- kotlinTasksConfigurator = { closure.call() as? List<Any?> }
- }
-
- fun linkMapping(action: Action<LinkMapping>) {
- val mapping = LinkMapping()
- action.execute(mapping)
-
- if (mapping.path.isEmpty()) {
- throw IllegalArgumentException("Link mapping should have dir")
- }
- if (mapping.url.isEmpty()) {
- throw IllegalArgumentException("Link mapping should have url")
- }
-
- linkMappings.add(mapping)
- }
-
- fun linkMapping(closure: Closure<Unit>) {
- linkMapping(Action { mapping ->
- closure.delegate = mapping
- closure.call()
- })
- }
-
- fun sourceRoot(action: Action<SourceRoot>) {
- val sourceRoot = SourceRoot()
- action.execute(sourceRoot)
- sourceRoots.add(sourceRoot)
- }
-
- fun sourceRoot(closure: Closure<Unit>) {
- sourceRoot(Action { sourceRoot ->
- closure.delegate = sourceRoot
- closure.call()
- })
- }
-
- fun packageOptions(action: Action<PackageOptions>) {
- val packageOptions = PackageOptions()
- action.execute(packageOptions)
- perPackageOptions.add(packageOptions)
- }
-
- fun packageOptions(closure: Closure<Unit>) {
- packageOptions(Action { packageOptions ->
- closure.delegate = packageOptions
- closure.call()
- })
- }
-
- fun externalDocumentationLink(action: Action<DokkaConfiguration.ExternalDocumentationLink.Builder>) {
- val builder = DokkaConfiguration.ExternalDocumentationLink.Builder()
- action.execute(builder)
- externalDocumentationLinks.add(builder.build())
- }
-
- fun externalDocumentationLink(closure: Closure<Unit>) {
- externalDocumentationLink(Action { builder ->
- closure.delegate = builder
- closure.call()
- })
- }
-
- fun tryResolveFatJar(project: Project): Set<File> {
- return try {
- dokkaRuntime!!.resolve()
- } catch (e: Exception) {
- project.parent?.let { tryResolveFatJar(it) } ?: throw e
- }
- }
-
- fun loadFatJar() {
- if (fatJarClassLoader == null) {
- val jars = if (dokkaFatJar is File)
- setOf(dokkaFatJar as File)
- else
- tryResolveFatJar(project)
- fatJarClassLoader = URLClassLoader(jars.map { it.toURI().toURL() }.toTypedArray(), ClassLoader.getSystemClassLoader().parent)
- }
- }
-
- internal data class ClasspathAndSourceRoots(val classpathFileCollection: FileCollection, val sourceRoots: List<File>) : Serializable
-
- private fun extractKotlinCompileTasks(): List<Task> {
- val inputList = (kotlinTasksConfigurator.invoke() ?: emptyList()).filterNotNull()
- val (paths, other) = inputList.partition { it is String }
-
- val taskContainer = project.tasks
-
- val tasksByPath = paths.map { taskContainer.findByPath(it as String) ?: throw IllegalArgumentException("Task with path '$it' not found") }
-
- other
- .filter { it !is Task || it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal entry in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE or String, but was $it") }
-
- tasksByPath
- .filter { it == null || it isNotInstance getAbstractKotlinCompileFor(it) }
- .forEach { throw IllegalArgumentException("Illegal task path in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE, but was $it") }
-
-
- return (tasksByPath + other) as List<Task>
- }
-
- private fun extractClasspathAndSourceRootsFromKotlinTasks(): ClasspathAndSourceRoots {
-
- val allTasks = kotlinTasks
-
- val allClasspath = mutableSetOf<File>()
- var allClasspathFileCollection: FileCollection = project.files()
- val allSourceRoots = mutableSetOf<File>()
-
- allTasks.forEach {
-
- logger.debug("Dokka found AbstractKotlinCompile task: $it")
- with(ReflectDsl) {
- val taskSourceRoots: List<File> = it["sourceRootsContainer"]["sourceRoots"].v()
-
- val abstractKotlinCompileClz = getAbstractKotlinCompileFor(it)!!
-
- val taskClasspath: Iterable<File> =
- (it["getClasspath", AbstractCompile::class].takeIfIsFunc()?.invoke()
- ?: it["compileClasspath", abstractKotlinCompileClz].takeIfIsProp()?.v()
- ?: it["getClasspath", abstractKotlinCompileClz]())
-
- if (taskClasspath is FileCollection) {
- allClasspathFileCollection += taskClasspath
- } else {
- allClasspath += taskClasspath
- }
- allSourceRoots += taskSourceRoots.filter { it.exists() }
- }
- }
-
- return ClasspathAndSourceRoots(allClasspathFileCollection + project.files(allClasspath), allSourceRoots.toList())
- }
-
- private fun Iterable<File>.toSourceRoots(): List<SourceRoot> = this.filter { it.exists() }.map { SourceRoot().apply { path = it.path } }
-
- protected open fun collectSuppressedFiles(sourceRoots: List<SourceRoot>): List<String> = emptyList()
-
- @TaskAction
- fun generate() {
- if (dokkaRuntime == null){
- dokkaRuntime = project.configurations.getByName("dokkaRuntime")
- }
-
- dokkaRuntime?.defaultDependencies{ dependencies -> dependencies.add(project.dependencies.create(dokkaFatJar)) }
- val kotlinColorsEnabledBefore = System.getProperty(COLORS_ENABLED_PROPERTY) ?: "false"
- System.setProperty(COLORS_ENABLED_PROPERTY, "false")
- try {
- loadFatJar()
-
- val (tasksClasspath, tasksSourceRoots) = kotlinCompileBasedClasspathAndSourceRoots
-
- val project = project
- val sourceRoots = collectSourceRoots() + tasksSourceRoots.toSourceRoots()
-
- if (sourceRoots.isEmpty()) {
- logger.warn("No source directories found: skipping dokka generation")
- return
- }
-
- val fullClasspath = collectClasspathFromOldSources() + tasksClasspath + classpath
-
- val bootstrapClass = fatJarClassLoader!!.loadClass("org.jetbrains.dokka.DokkaBootstrapImpl")
-
- val bootstrapInstance = bootstrapClass.constructors.first().newInstance()
-
- val bootstrapProxy: DokkaBootstrap = automagicTypedProxy(javaClass.classLoader, bootstrapInstance)
-
- val configuration = SerializeOnlyDokkaConfiguration(
- moduleName,
- fullClasspath.map { it.absolutePath },
- sourceRoots,
- samples.filterNotNull().map { project.file(it).absolutePath },
- includes.filterNotNull().map { project.file(it).absolutePath },
- outputDirectory,
- outputFormat,
- includeNonPublic,
- false,
- reportUndocumented,
- skipEmptyPackages,
- skipDeprecated,
- jdkVersion,
- true,
- linkMappings,
- impliedPlatforms,
- perPackageOptions,
- externalDocumentationLinks,
- noStdlibLink,
- noJdkLink,
- cacheRoot,
- collectSuppressedFiles(sourceRoots),
- languageVersion,
- apiVersion,
- collectInheritedExtensionsFromLibraries
- )
-
-
- bootstrapProxy.configure(
- BiConsumer { level, message ->
- when (level) {
- "info" -> logger.info(message)
- "warn" -> logger.warn(message)
- "error" -> logger.error(message)
- }
- },
- serialize(configuration)
- )
-
- bootstrapProxy.generate()
-
- } finally {
- System.setProperty(COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore)
- }
- }
-
- private fun collectClasspathFromOldSources(): List<File> {
-
- val allConfigurations = project.configurations
-
- val fromConfigurations =
- processConfigurations.flatMap { allConfigurations.getByName(it.toString()) }
-
- return fromConfigurations
- }
-
- private fun collectSourceRoots(): List<SourceRoot> {
- val sourceDirs = if (sourceDirs.any()) {
- logger.info("Dokka: Taking source directories provided by the user")
- sourceDirs.toSet()
- } else if (kotlinTasks.isEmpty()) {
- project.convention.findPlugin(JavaPluginConvention::class.java)?.let { javaPluginConvention ->
- logger.info("Dokka: Taking source directories from default java plugin")
- val sourceSets = javaPluginConvention.sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)
- sourceSets?.allSource?.srcDirs
- }
- } else {
- emptySet()
- }
-
- return sourceRoots + (sourceDirs?.toSourceRoots() ?: emptyList())
- }
-
-
- @Classpath
- fun getInputClasspath(): FileCollection {
- val (classpathFileCollection) = extractClasspathAndSourceRootsFromKotlinTasks()
- return project.files(collectClasspathFromOldSources() + classpath) + classpathFileCollection
- }
-
- @InputFiles
- fun getInputFiles(): FileCollection {
- val (_, tasksSourceRoots) = extractClasspathAndSourceRootsFromKotlinTasks()
- return project.files(tasksSourceRoots.map { project.fileTree(it) }) +
- project.files(collectSourceRoots().map { project.fileTree(File(it.path)) }) +
- project.files(includes) +
- project.files(samples.filterNotNull().map { project.fileTree(it) })
- }
-
- @OutputDirectory
- fun getOutputDirectoryAsFile(): File = project.file(outputDirectory)
-
- companion object {
- const val COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled"
- const val ABSTRACT_KOTLIN_COMPILE = "org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile"
-
- private fun getAbstractKotlinCompileFor(task: Task) = try {
- task.project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
- } catch (e: ClassNotFoundException) {
- null
- }
- }
-}
-
-class SourceRoot : DokkaConfiguration.SourceRoot, Serializable {
- override var path: String = ""
- set(value) {
- field = File(value).absolutePath
- }
-
- override var platforms: List<String> = arrayListOf()
-
- override fun toString(): String {
- return "${platforms.joinToString()}::$path"
- }
-}
-
-open class LinkMapping : Serializable, DokkaConfiguration.SourceLinkDefinition {
- @JsonExclude
- var dir: String
- get() = path
- set(value) {
- if (value.contains("\\"))
- throw java.lang.IllegalArgumentException("Incorrect dir property, only Unix based path allowed.")
- else path = value
- }
-
- override var path: String = ""
- override var url: String = ""
-
- @JsonExclude
- var suffix: String?
- get() = lineSuffix
- set(value) {
- lineSuffix = value
- }
-
- override var lineSuffix: String? = null
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other?.javaClass != javaClass) return false
-
- other as LinkMapping
-
- if (path != other.path) return false
- if (url != other.url) return false
- if (lineSuffix != other.lineSuffix) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- var result = path.hashCode()
- result = 31 * result + url.hashCode()
- result = 31 * result + (lineSuffix?.hashCode() ?: 0)
- return result
- }
-
- companion object {
- const val serialVersionUID: Long = -8133501684312445981L
- }
-}
-
-class PackageOptions : Serializable, DokkaConfiguration.PackageOptions {
- override var prefix: String = ""
- override var includeNonPublic: Boolean = false
- override var reportUndocumented: Boolean = true
- override var skipDeprecated: Boolean = false
- override var suppress: Boolean = false
-}
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
new file mode 100644
index 00000000..c66998d9
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt
@@ -0,0 +1,217 @@
+package org.jetbrains.dokka.gradle
+
+import com.android.build.gradle.*
+import com.android.build.gradle.api.BaseVariant
+import com.android.builder.core.BuilderConstants
+import org.gradle.api.NamedDomainObjectCollection
+import org.gradle.api.Project
+import org.gradle.api.Task
+import org.gradle.api.UnknownDomainObjectException
+import org.gradle.api.artifacts.ResolveException
+import org.gradle.api.file.FileCollection
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.compile.AbstractCompile
+import org.jetbrains.dokka.ReflectDsl
+import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
+import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
+import org.jetbrains.kotlin.gradle.dsl.KotlinSingleTargetExtension
+import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
+import java.io.File
+import java.io.Serializable
+
+class ConfigurationExtractor(private val project: Project) {
+
+ fun extractFromSinglePlatform(variantName: String? = null): PlatformData? {
+ val target: KotlinTarget
+ try {
+ target = project.extensions.getByType(KotlinSingleTargetExtension::class.java).target
+ } catch (e: Throwable) {
+ when (e){
+ is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
+ return null
+ else -> throw e
+ }
+ }
+
+ return try {
+ PlatformData(null, getClasspath(target, variantName), getSourceSet(target, variantName), getPlatformName(target.platformType))
+ } catch(e: NoSuchMethodError){
+ null
+ }
+ }
+
+ fun extractFromMultiPlatform(): List<PlatformData>? {
+ val targets: NamedDomainObjectCollection<KotlinTarget>
+ try {
+ targets = project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets
+ } catch (e: Throwable) {
+ when (e){
+ is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
+ return null
+ else -> throw e
+ }
+ }
+
+ val commonTargetPlatformData = targets.find { it.platformType == KotlinPlatformType.common }?.let {
+ PlatformData("common", getClasspath(it), getSourceSet(it), "common")
+ }
+ val config = targets.filter { it.platformType != KotlinPlatformType.common }.map {
+ PlatformData(it.name, getClasspath(it), getSourceSet(it), it.platformType.toString())
+ }
+
+ return (config + commonTargetPlatformData).filterNotNull()
+ }
+
+ fun extractFromJavaPlugin(): PlatformData? =
+ project.convention.findPlugin(JavaPluginConvention::class.java)
+ ?.run { sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)?.allSource?.srcDirs }
+ ?.let { PlatformData(null, emptyList(), it.toList(), "") }
+
+ fun extractFromKotlinTasks(kotlinTasks: List<Task>): PlatformData? =
+ try {
+ kotlinTasks.map { extractFromKotlinTask(it) }.let { platformDataList ->
+ PlatformData(null, platformDataList.flatMap { it.classpath }, platformDataList.flatMap { it.sourceRoots }, "")
+ }
+ } catch (e: Throwable) {
+ when (e){
+ is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
+ extractFromKotlinTasksTheHardWay(kotlinTasks)
+ else -> throw e
+ }
+ }
+
+ private fun extractFromKotlinTask(task: Task): PlatformData =
+ try {
+ project.extensions.getByType(KotlinSingleTargetExtension::class.java).target
+ .compilations
+ .find { it.compileKotlinTask == task }
+ } catch (e: Throwable) {
+ when (e){
+ is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException ->
+ project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets
+ .firstNotNullResult { target -> target.compilations.find { it.compileKotlinTask == task } }
+ else -> throw e
+ }
+ }.let { PlatformData(task.name, getClasspath(it), getSourceSet(it), it?.platformType?.toString() ?: "") }
+
+ private fun extractFromKotlinTasksTheHardWay(kotlinTasks: List<Task>): PlatformData? {
+ val allClasspath = mutableSetOf<File>()
+ var allClasspathFileCollection: FileCollection = project.files()
+ val allSourceRoots = mutableSetOf<File>()
+
+ kotlinTasks.forEach {
+ with(ReflectDsl) {
+ val taskSourceRoots: List<File>
+ val abstractKotlinCompileClz: Class<out Any>
+ try {
+ taskSourceRoots = it["sourceRootsContainer"]["sourceRoots"].v()
+ abstractKotlinCompileClz = DokkaTask.getAbstractKotlinCompileFor(it)!!
+ } catch (e: NullPointerException) {
+ println("Error during extraction of sources from kotlinTasks. This may be a result of outdated Kotlin Gradle Plugin")
+ return null
+ }
+
+ val taskClasspath: Iterable<File> =
+ (it["getClasspath", AbstractCompile::class].takeIfIsFunc()?.invoke()
+ ?: it["compileClasspath", abstractKotlinCompileClz].takeIfIsProp()?.v()
+ ?: it["getClasspath", abstractKotlinCompileClz]())
+
+ if (taskClasspath is FileCollection) {
+ allClasspathFileCollection += taskClasspath
+ } else {
+ allClasspath += taskClasspath
+ }
+ allSourceRoots += taskSourceRoots.filter { it.exists() }
+ }
+ }
+ val classpath: MutableList<File> = try {
+ allClasspathFileCollection.toMutableList()
+ } catch (e: ResolveException) {
+ mutableListOf()
+ }
+ classpath.addAll (project.files(allClasspath).toList())
+
+ return PlatformData(null, classpath, allSourceRoots.toList(), "")
+ }
+
+ private fun getSourceSet(target: KotlinTarget, variantName: String? = null): List<File> =
+ if(variantName != null)
+ getSourceSet(getCompilation(target, variantName))
+ else
+ getSourceSet(getMainCompilation(target))
+
+ private fun getClasspath(target: KotlinTarget, variantName: String? = null): List<File> = if (target.isAndroidTarget()) {
+ if(variantName != null)
+ getClasspathFromAndroidTask(getCompilation(target, variantName))
+ else
+ getClasspathFromAndroidTask(getMainCompilation(target))
+ } else {
+ getClasspath(getMainCompilation(target))
+ }
+
+ private fun getSourceSet(compilation: KotlinCompilation<*>?): List<File> = compilation
+ ?.allKotlinSourceSets
+ ?.flatMap { it.kotlin.sourceDirectories }
+ ?.filter { it.exists() }
+ .orEmpty()
+
+ private fun getClasspath(compilation: KotlinCompilation<*>?): List<File> = compilation
+ ?.compileDependencyFiles
+ ?.files
+ ?.toList()
+ ?.filter { it.exists() }
+ .orEmpty()
+
+ // This is a workaround for KT-33893
+ private fun getClasspathFromAndroidTask(compilation: KotlinCompilation<*>): List<File> = (compilation
+ .compileKotlinTask as? KotlinCompile)
+ ?.classpath?.files?.toList() ?: getClasspath(compilation)
+
+ private fun getMainCompilation(target: KotlinTarget) =
+ getCompilation(target, getMainCompilationName(target))
+
+ private fun getCompilation(target: KotlinTarget, name: String) =
+ target.compilations.getByName(name)
+
+ private fun getMainCompilationName(target: KotlinTarget) = if (target.isAndroidTarget())
+ getVariants(project).filter { it.buildType.name == BuilderConstants.RELEASE }.map { it.name }.first()
+ else
+ KotlinCompilation.MAIN_COMPILATION_NAME
+
+ private fun getVariants(project: Project): Set<BaseVariant> {
+ val androidExtension = project.extensions.getByName("android")
+ val baseVariants = when (androidExtension) {
+ is AppExtension -> androidExtension.applicationVariants.toSet()
+ is LibraryExtension -> {
+ androidExtension.libraryVariants.toSet() +
+ if (androidExtension is FeatureExtension) {
+ androidExtension.featureVariants.toSet()
+ } else {
+ emptySet<BaseVariant>()
+ }
+ }
+ is TestExtension -> androidExtension.applicationVariants.toSet()
+ else -> emptySet()
+ }
+ val testVariants = if (androidExtension is TestedExtension) {
+ androidExtension.testVariants.toSet() + androidExtension.unitTestVariants.toSet()
+ } else {
+ emptySet<BaseVariant>()
+ }
+
+ return baseVariants + testVariants
+ }
+
+ private fun getPlatformName(platform: KotlinPlatformType): String =
+ if (platform == KotlinPlatformType.androidJvm) KotlinPlatformType.jvm.toString() else platform.toString()
+
+ data class PlatformData(val name: String?,
+ val classpath: List<File>,
+ val sourceRoots: List<File>,
+ val platform: String) : Serializable
+} \ No newline at end of file
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
new file mode 100644
index 00000000..5153ae1c
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt
@@ -0,0 +1,353 @@
+package org.jetbrains.dokka.gradle
+
+import com.google.gson.GsonBuilder
+import org.gradle.api.*
+import org.gradle.api.artifacts.Configuration
+import org.gradle.api.file.FileCollection
+import org.gradle.api.internal.plugins.DslObject
+import org.gradle.api.plugins.JavaBasePlugin
+import org.gradle.api.tasks.*
+import org.jetbrains.dokka.DokkaBootstrap
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder
+import org.jetbrains.dokka.DokkaConfiguration.SourceRoot
+import org.jetbrains.dokka.Platform
+import org.jetbrains.dokka.ReflectDsl
+import org.jetbrains.dokka.ReflectDsl.isNotInstance
+import org.jetbrains.dokka.gradle.ConfigurationExtractor.PlatformData
+import java.io.File
+import java.net.URLClassLoader
+import java.util.concurrent.Callable
+import java.util.function.BiConsumer
+
+open class DokkaTask : DefaultTask() {
+ private val ANDROID_REFERENCE_URL = Builder("https://developer.android.com/reference/").build()
+ private val GLOBAL_PLATFORM_NAME = "global" // Used for copying perPackageOptions to other platforms
+
+ @Suppress("MemberVisibilityCanBePrivate")
+ fun defaultKotlinTasks(): List<Task> = with(ReflectDsl) {
+ val abstractKotlinCompileClz = try {
+ project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
+ } catch (cnfe: ClassNotFoundException) {
+ logger.warn("$ABSTRACT_KOTLIN_COMPILE class not found, default kotlin tasks ignored")
+ return@with emptyList<Task>()
+ }
+
+ return@with project.tasks.filter { it isInstance abstractKotlinCompileClz }.filter { "Test" !in it.name }
+ }
+
+ init {
+ group = JavaBasePlugin.DOCUMENTATION_GROUP
+ description = "Generates dokka documentation for Kotlin"
+
+ @Suppress("LeakingThis")
+ dependsOn(Callable { kotlinTasks.map { it.taskDependencies } })
+ }
+
+ @Input
+ var outputFormat: String = "html"
+
+ @Input
+ var outputDirectory: String = ""
+
+ var dokkaRuntime: Configuration? = null
+
+ @Input
+ var impliedPlatforms: MutableList<String> = arrayListOf()
+
+ @Optional
+ @Input
+ var cacheRoot: String? = null
+
+ var multiplatform: NamedDomainObjectContainer<GradlePassConfigurationImpl>
+ @Suppress("UNCHECKED_CAST")
+ @Nested get() = (DslObject(this).extensions.getByName(MULTIPLATFORM_EXTENSION_NAME) as NamedDomainObjectContainer<GradlePassConfigurationImpl>)
+ internal set(value) = DslObject(this).extensions.add(MULTIPLATFORM_EXTENSION_NAME, value)
+
+ var configuration: GradlePassConfigurationImpl
+ @Suppress("UNCHECKED_CAST")
+ @Nested get() = DslObject(this).extensions.getByType(GradlePassConfigurationImpl::class.java)
+ internal set(value) = DslObject(this).extensions.add(CONFIGURATION_EXTENSION_NAME, value)
+
+ // Configure Dokka with closure in Gradle Kotlin DSL
+ fun configuration(action: Action<in GradlePassConfigurationImpl>) = action.execute(configuration)
+
+ private var externalDocumentationLinks: MutableList<DokkaConfiguration.ExternalDocumentationLink> = mutableListOf()
+
+ private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks(configuration.collectKotlinTasks ?: { defaultKotlinTasks() }) }
+
+ private val configExtractor = ConfigurationExtractor(project)
+
+ @Input
+ var subProjects: List<String> = emptyList()
+
+ @Input
+ var disableAutoconfiguration: Boolean = false
+
+ private var outputDiagnosticInfo: Boolean = false // Workaround for Gradle, which fires some methods (like collectConfigurations()) multiple times in its lifecycle
+
+ private fun tryResolveFatJar(configuration: Configuration?): Set<File> {
+ return try {
+ configuration!!.resolve()
+ } catch (e: Exception) {
+ project.parent?.let { tryResolveFatJar(configuration) } ?: throw e
+ }
+ }
+
+ private fun loadFatJar() {
+ if (ClassloaderContainer.fatJarClassLoader == null) {
+ val jars = tryResolveFatJar(dokkaRuntime).toList()
+ ClassloaderContainer.fatJarClassLoader = URLClassLoader(jars.map { it.toURI().toURL() }.toTypedArray(), ClassLoader.getSystemClassLoader().parent)
+ }
+ }
+
+ private fun extractKotlinCompileTasks(collectTasks: () -> List<Any?>?): List<Task> {
+ val inputList = (collectTasks.invoke() ?: emptyList()).filterNotNull()
+ val (paths, other) = inputList.partition { it is String }
+
+ val taskContainer = project.tasks
+
+ val tasksByPath = paths.map { taskContainer.findByPath(it as String) ?: throw IllegalArgumentException("Task with path '$it' not found") }
+
+ other
+ .filter { it !is Task || it isNotInstance getAbstractKotlinCompileFor(it) }
+ .forEach { throw IllegalArgumentException("Illegal entry in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE or String, but was $it") }
+
+ tasksByPath
+ .filter { it isNotInstance getAbstractKotlinCompileFor(it) }
+ .forEach { throw IllegalArgumentException("Illegal task path in kotlinTasks, must be subtype of $ABSTRACT_KOTLIN_COMPILE, but was $it") }
+
+ @Suppress("UNCHECKED_CAST")
+ return (tasksByPath + other) as List<Task>
+ }
+
+ private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootImpl> = this.filter { it.exists() }.map { GradleSourceRootImpl().apply { path = it.path } }
+ private fun Iterable<String>.toProjects(): List<Project> = project.subprojects.toList().filter { this.contains(it.name) }
+
+ private fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) =
+ if(project.isAndroidProject()) {
+ val generatedRoot = project.buildDir.resolve("generated").absoluteFile
+ sourceRoots
+ .map { File(it.path) }
+ .filter { it.startsWith(generatedRoot) }
+ .flatMap { it.walk().toList() }
+ .map { it.absolutePath }
+ } else {
+ emptyList()
+ }
+
+ @TaskAction
+ fun generate() {
+ outputDiagnosticInfo = true
+ val kotlinColorsEnabledBefore = System.getProperty(COLORS_ENABLED_PROPERTY) ?: "false"
+ System.setProperty(COLORS_ENABLED_PROPERTY, "false")
+ try {
+ loadFatJar()
+
+ val bootstrapClass = ClassloaderContainer.fatJarClassLoader!!.loadClass("org.jetbrains.dokka.DokkaBootstrapImpl")
+ val bootstrapInstance = bootstrapClass.constructors.first().newInstance()
+ val bootstrapProxy: DokkaBootstrap =
+ automagicTypedProxy(javaClass.classLoader, bootstrapInstance)
+
+ val gson = GsonBuilder().setPrettyPrinting().create()
+
+ val globalConfig = multiplatform.toList().find { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }
+ val passConfigurationList = collectConfigurations()
+ .map { defaultPassConfiguration(globalConfig, it) }
+
+ val configuration = GradleDokkaConfigurationImpl()
+ configuration.outputDir = outputDirectory
+ configuration.format = outputFormat
+ configuration.generateIndexPages = true
+ configuration.cacheRoot = cacheRoot
+ configuration.impliedPlatforms = impliedPlatforms
+ configuration.passesConfigurations = passConfigurationList
+
+ bootstrapProxy.configure(
+ BiConsumer { level, message ->
+ when (level) {
+ "info" -> logger.info(message)
+ "warn" -> logger.warn(message)
+ "error" -> logger.error(message)
+ }
+ },
+ gson.toJson(configuration)
+ )
+
+ bootstrapProxy.generate()
+
+ } finally {
+ System.setProperty(COLORS_ENABLED_PROPERTY, kotlinColorsEnabledBefore)
+ }
+ }
+
+ private fun collectConfigurations(): List<GradlePassConfigurationImpl> =
+ if (this.isMultiplatformProject()) collectFromMultiPlatform() else collectFromSinglePlatform()
+
+ private fun collectFromMultiPlatform(): List<GradlePassConfigurationImpl> {
+ val userConfig = multiplatform
+ .filterNot { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME }
+ .map {
+ if (it.collectKotlinTasks != null) {
+ configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it.collectKotlinTasks!!))
+ ?.let { platformData -> mergeUserConfigurationAndPlatformData(it, platformData) } ?: it
+ } else {
+ it
+ }
+ }
+
+ if (disableAutoconfiguration) return userConfig
+
+ val baseConfig = mergeUserAndAutoConfigurations(
+ userConfig,
+ configExtractor.extractFromMultiPlatform().orEmpty()
+ )
+
+ return if (subProjects.isNotEmpty())
+ subProjects.toProjects().fold(baseConfig) { list, subProject ->
+ mergeUserAndAutoConfigurations(list, ConfigurationExtractor(subProject).extractFromMultiPlatform().orEmpty())
+ }
+ else
+ baseConfig
+ }
+
+ private fun collectFromSinglePlatform(): List<GradlePassConfigurationImpl> {
+ val userConfig = configuration.let {
+ if (it.collectKotlinTasks != null) {
+ configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it.collectKotlinTasks!!))
+ ?.let { platformData -> mergeUserConfigurationAndPlatformData(it, platformData) } ?: it
+ } else {
+ it
+ }
+ }
+
+ if (disableAutoconfiguration) return listOf(userConfig)
+
+ val extractedConfig = configExtractor.extractFromSinglePlatform(userConfig.androidVariant)
+ val baseConfig = if (extractedConfig != null)
+ listOf(mergeUserConfigurationAndPlatformData(userConfig, extractedConfig))
+ else
+ collectFromSinglePlatformOldPlugin()
+
+ return if (subProjects.isNotEmpty()) {
+ try {
+ subProjects.toProjects().fold(baseConfig) { list, subProject ->
+ listOf(mergeUserConfigurationAndPlatformData(
+ list.first(),
+ ConfigurationExtractor(subProject).extractFromSinglePlatform()!!
+ ))
+ }
+ } catch(e: NullPointerException) {
+ logger.warn("Cannot extract sources from subProjects. Do you have the Kotlin plugin in version 1.3.30+ " +
+ "and the Kotlin plugin applied in the root project?")
+ baseConfig
+ }
+ } else {
+ baseConfig
+ }
+ }
+
+ private fun collectFromSinglePlatformOldPlugin(): List<GradlePassConfigurationImpl> {
+ val kotlinTasks = configExtractor.extractFromKotlinTasks(kotlinTasks)
+ return if (kotlinTasks != null) {
+ listOf(mergeUserConfigurationAndPlatformData(configuration, kotlinTasks))
+ } else {
+ val javaPlugin = configExtractor.extractFromJavaPlugin()
+ if (javaPlugin != null)
+ listOf(mergeUserConfigurationAndPlatformData(configuration, javaPlugin)) else listOf(configuration)
+ }
+ }
+
+ private fun mergeUserAndAutoConfigurations(userConfigurations: List<GradlePassConfigurationImpl>,
+ autoConfigurations: List<PlatformData>): List<GradlePassConfigurationImpl> {
+ val merged: MutableList<GradlePassConfigurationImpl> = mutableListOf()
+ merged.addAll(
+ userConfigurations.map { userConfig ->
+ val autoConfig = autoConfigurations.find { autoConfig -> autoConfig.name == userConfig.name }
+ if (autoConfig != null) {
+ mergeUserConfigurationAndPlatformData(userConfig, autoConfig)
+ } else {
+ if(outputDiagnosticInfo) {
+ logger.warn(
+ "Could not find platform with name: ${userConfig.name} in Kotlin Gradle Plugin, " +
+ "using only user provided configuration for this platform"
+ )
+ }
+ userConfig
+ }
+ }
+ )
+ return merged.toList()
+ }
+
+ private fun mergeUserConfigurationAndPlatformData(userConfig: GradlePassConfigurationImpl,
+ autoConfig: PlatformData): GradlePassConfigurationImpl =
+ userConfig.copy().apply {
+ sourceRoots.addAll(userConfig.sourceRoots.union(autoConfig.sourceRoots.toSourceRoots()).distinct())
+ classpath = userConfig.classpath.union(autoConfig.classpath.map { it.absolutePath }).distinct()
+ if (userConfig.platform == null && autoConfig.platform != "")
+ platform = autoConfig.platform
+ }
+
+ private fun defaultPassConfiguration(globalConfig: GradlePassConfigurationImpl?, config: GradlePassConfigurationImpl): GradlePassConfigurationImpl {
+ if (config.moduleName == "") {
+ config.moduleName = project.name
+ }
+ if (config.targets.isEmpty() && multiplatform.isNotEmpty()){
+ config.targets = listOf(config.name)
+ }
+ config.classpath = (config.classpath as List<Any>).map { it.toString() }.distinct() // Workaround for Groovy's GStringImpl
+ config.sourceRoots = config.sourceRoots.distinct().toMutableList()
+ config.samples = config.samples.map { project.file(it).absolutePath }
+ config.includes = config.includes.map { project.file(it).absolutePath }
+ config.suppressedFiles += collectSuppressedFiles(config.sourceRoots)
+ if (project.isAndroidProject() && !config.noAndroidSdkLink) { // TODO: introduce Android as a separate Dokka platform?
+ config.externalDocumentationLinks.add(ANDROID_REFERENCE_URL)
+ }
+ config.externalDocumentationLinks.addAll(externalDocumentationLinks)
+ if (config.platform != null && config.platform.toString().isNotEmpty()) {
+ config.analysisPlatform = dokkaPlatformFromString(config.platform.toString())
+ }
+ if (globalConfig != null) {
+ config.perPackageOptions.addAll(globalConfig.perPackageOptions)
+ config.externalDocumentationLinks.addAll(globalConfig.externalDocumentationLinks)
+ config.sourceLinks.addAll(globalConfig.sourceLinks)
+ config.samples += globalConfig.samples.map { project.file(it).absolutePath }
+ config.includes += globalConfig.includes.map { project.file(it).absolutePath }
+ }
+ return config
+ }
+
+ private fun dokkaPlatformFromString(platform: String) = when (platform.toLowerCase()) {
+ "androidjvm", "android" -> Platform.jvm
+ else -> Platform.fromString(platform)
+ }
+
+ // Needed for Gradle incremental build
+ @OutputDirectory
+ fun getOutputDirectoryAsFile(): File = project.file(outputDirectory)
+
+ // Needed for Gradle incremental build
+ @InputFiles
+ fun getInputFiles(): FileCollection {
+ val config = collectConfigurations()
+ return project.files(config.flatMap { it.sourceRoots }.map { project.fileTree(File(it.path)) }) +
+ project.files(config.flatMap { it.includes }) +
+ project.files(config.flatMap { it.samples }.map { project.fileTree(File(it)) })
+ }
+
+ @Classpath
+ fun getInputClasspath(): FileCollection =
+ project.files((collectConfigurations().flatMap { it.classpath } as List<Any>).map { project.fileTree(File(it.toString())) })
+
+ companion object {
+ const val COLORS_ENABLED_PROPERTY = "kotlin.colors.enabled"
+ const val ABSTRACT_KOTLIN_COMPILE = "org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile"
+
+ internal fun getAbstractKotlinCompileFor(task: Task) = try {
+ task.project.buildscript.classLoader.loadClass(ABSTRACT_KOTLIN_COMPILE)
+ } catch (e: ClassNotFoundException) {
+ null
+ }
+ }
+}
diff --git a/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt
index 7bdf2f9d..f8965993 100644
--- a/runners/gradle-plugin/src/main/kotlin/ProxyUtils.kt
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ProxyUtils.kt
@@ -1,4 +1,4 @@
-package org.jetbrains.dokka
+package org.jetbrains.dokka.gradle
import java.lang.reflect.InvocationHandler
import java.lang.reflect.InvocationTargetException
@@ -26,9 +26,9 @@ inline fun <reified T : Any> automagicTypedProxy(targetClassLoader: ClassLoader,
*/
fun automagicProxy(targetClassLoader: ClassLoader, targetType: Class<*>, delegate: Any): Any =
Proxy.newProxyInstance(
- targetClassLoader,
- arrayOf(targetType),
- DelegatedInvocationHandler(delegate)
+ targetClassLoader,
+ arrayOf(targetType),
+ DelegatedInvocationHandler(delegate)
)
class DelegatedInvocationHandler(private val delegate: Any) : InvocationHandler {
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
new file mode 100644
index 00000000..767bf4f4
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt
@@ -0,0 +1,150 @@
+package org.jetbrains.dokka.gradle
+
+import groovy.lang.Closure
+import org.gradle.api.Action
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
+import org.gradle.util.ConfigureUtil
+import org.jetbrains.dokka.DokkaConfiguration
+import org.jetbrains.dokka.DokkaConfiguration.*
+import org.jetbrains.dokka.Platform
+import java.io.File
+import java.io.Serializable
+import java.net.URL
+import java.util.concurrent.Callable
+import kotlin.reflect.KMutableProperty
+import kotlin.reflect.full.memberProperties
+
+class GradleSourceRootImpl: SourceRoot, Serializable {
+ override var path: String = ""
+ set(value) {
+ field = File(value).absolutePath
+ }
+
+ override fun toString(): String = path
+}
+
+open class GradlePassConfigurationImpl(@Transient val name: String = ""): PassConfiguration {
+ @Input @Optional override var classpath: List<String> = emptyList()
+ @Input override var moduleName: String = ""
+ @Input override var sourceRoots: MutableList<SourceRoot> = mutableListOf()
+ @Input override var samples: List<String> = emptyList()
+ @Input override var includes: List<String> = emptyList()
+ @Input override var includeNonPublic: Boolean = false
+ @Input override var includeRootPackage: Boolean = false
+ @Input override var reportUndocumented: Boolean = false
+ @Input override var skipEmptyPackages: Boolean = false
+ @Input override var skipDeprecated: Boolean = false
+ @Input override var jdkVersion: Int = 6
+ @Input override var sourceLinks: MutableList<SourceLinkDefinition> = mutableListOf()
+ @Input override var perPackageOptions: MutableList<PackageOptions> = mutableListOf()
+ @Input override var externalDocumentationLinks: MutableList<ExternalDocumentationLink> = mutableListOf()
+ @Input @Optional override var languageVersion: String? = null
+ @Input @Optional override var apiVersion: String? = null
+ @Input override var noStdlibLink: Boolean = false
+ @Input override var noJdkLink: Boolean = false
+ @Input var noAndroidSdkLink: Boolean = false
+ @Input override var suppressedFiles: List<String> = emptyList()
+ @Input override var collectInheritedExtensionsFromLibraries: Boolean = false
+ @Input override var analysisPlatform: Platform = Platform.DEFAULT
+ @Input @Optional var platform: String? = null
+ @Input override var targets: List<String> = emptyList()
+ @Input @Optional override var sinceKotlin: String? = null
+ @Transient var collectKotlinTasks: (() -> List<Any?>?)? = null
+ @Input @Optional @Transient var androidVariant: String? = null
+
+ fun kotlinTasks(taskSupplier: Callable<List<Any>>) {
+ collectKotlinTasks = { taskSupplier.call() }
+ }
+
+ fun kotlinTasks(closure: Closure<Any?>) {
+ collectKotlinTasks = { closure.call() as? List<Any?> }
+ }
+
+ fun sourceRoot(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradleSourceRootImpl())
+ sourceRoots.add(configured)
+ }
+
+ fun sourceRoot(action: Action<in GradleSourceRootImpl>) {
+ val sourceRoot = GradleSourceRootImpl()
+ action.execute(sourceRoot)
+ sourceRoots.add(sourceRoot)
+ }
+
+ fun sourceLink(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradleSourceLinkDefinitionImpl())
+ sourceLinks.add(configured)
+ }
+
+ fun sourceLink(action: Action<in GradleSourceLinkDefinitionImpl>) {
+ val sourceLink = GradleSourceLinkDefinitionImpl()
+ action.execute(sourceLink)
+ sourceLinks.add(sourceLink)
+ }
+
+ fun perPackageOption(c: Closure<Unit>) {
+ val configured = ConfigureUtil.configure(c, GradlePackageOptionsImpl())
+ perPackageOptions.add(configured)
+ }
+
+ fun perPackageOption(action: Action<in GradlePackageOptionsImpl>) {
+ val option = GradlePackageOptionsImpl()
+ action.execute(option)
+ perPackageOptions.add(option)
+ }
+
+ fun externalDocumentationLink(c: Closure<Unit>) {
+ val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkImpl())
+ externalDocumentationLinks.add(link)
+ }
+
+ fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkImpl>) {
+ val link = GradleExternalDocumentationLinkImpl()
+ action.execute(link)
+ externalDocumentationLinks.add(link)
+ }
+}
+
+class GradleSourceLinkDefinitionImpl : SourceLinkDefinition, Serializable {
+ override var path: String = ""
+ override var url: String = ""
+ override var lineSuffix: String? = null
+}
+
+class GradleExternalDocumentationLinkImpl : ExternalDocumentationLink, Serializable {
+ override var url: URL = URL("http://")
+ override var packageListUrl: URL = URL("http://")
+}
+
+class GradleDokkaConfigurationImpl: DokkaConfiguration {
+ override var outputDir: String = ""
+ override var format: String = "html"
+ override var generateIndexPages: Boolean = false
+ override var cacheRoot: String? = null
+ override var impliedPlatforms: List<String> = emptyList()
+ override var passesConfigurations: List<GradlePassConfigurationImpl> = emptyList()
+}
+
+class GradlePackageOptionsImpl: PackageOptions, Serializable {
+ override var prefix: String = ""
+ override var includeNonPublic: Boolean = false
+ override var reportUndocumented: Boolean = true
+ override var skipDeprecated: Boolean = true
+ override var suppress: Boolean = false
+}
+
+fun GradlePassConfigurationImpl.copy(): GradlePassConfigurationImpl {
+ val newObj = GradlePassConfigurationImpl(this.name)
+ this::class.memberProperties.forEach { field ->
+ if (field is KMutableProperty<*>) {
+ val value = field.getter.call(this)
+ if (value is Collection<*>) {
+ field.setter.call(newObj, value.toMutableList())
+ } else {
+ field.setter.call(newObj, field.getter.call(this))
+ }
+ }
+ }
+ return newObj
+} \ No newline at end of file
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
new file mode 100644
index 00000000..6f8d55e4
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt
@@ -0,0 +1,58 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.artifacts.Configuration
+import org.gradle.util.GradleVersion
+import java.io.File
+import java.io.InputStream
+import java.util.*
+
+internal const val CONFIGURATION_EXTENSION_NAME = "configuration"
+internal const val MULTIPLATFORM_EXTENSION_NAME = "multiplatform"
+
+open class DokkaPlugin : Plugin<Project> {
+ private val taskName = "dokka"
+
+ override fun apply(project: Project) {
+ loadDokkaVersion()
+ val dokkaRuntimeConfiguration = addConfiguration(project)
+ addTasks(project, dokkaRuntimeConfiguration, DokkaTask::class.java)
+ }
+
+ private fun loadDokkaVersion() = DokkaVersion.loadFrom(javaClass.getResourceAsStream("/META-INF/gradle-plugins/org.jetbrains.dokka.properties"))
+
+ private fun addConfiguration(project: Project) =
+ project.configurations.create("dokkaRuntime").apply {
+ defaultDependencies{ dependencies -> dependencies.add(project.dependencies.create("org.jetbrains.dokka:dokka-fatjar:${DokkaVersion.version}")) }
+ }
+
+ private fun addTasks(project: Project, runtimeConfiguration: Configuration, taskClass: Class<out DokkaTask>) {
+ if(GradleVersion.current() >= GradleVersion.version("4.10")) {
+ project.tasks.register(taskName, taskClass)
+ } else {
+ project.tasks.create(taskName, taskClass)
+ }
+ project.tasks.withType(taskClass) { task ->
+ task.multiplatform = project.container(GradlePassConfigurationImpl::class.java)
+ task.configuration = GradlePassConfigurationImpl()
+ task.dokkaRuntime = runtimeConfiguration
+ task.outputDirectory = File(project.buildDir, taskName).absolutePath
+ }
+ }
+}
+
+object DokkaVersion {
+ var version: String? = null
+
+ fun loadFrom(stream: InputStream) {
+ version = Properties().apply {
+ load(stream)
+ }.getProperty("dokka-version")
+ }
+}
+
+object ClassloaderContainer {
+ @JvmField
+ var fatJarClassLoader: ClassLoader? = null
+} \ No newline at end of file
diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
new file mode 100644
index 00000000..d70b0499
--- /dev/null
+++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt
@@ -0,0 +1,19 @@
+package org.jetbrains.dokka.gradle
+
+import org.gradle.api.Project
+import org.gradle.api.UnknownDomainObjectException
+import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
+import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+
+
+fun Project.isAndroidProject() = try {
+ project.extensions.getByName("android")
+ true
+} catch(e: UnknownDomainObjectException) {
+ false
+} catch(e: ClassNotFoundException) {
+ false
+}
+
+fun KotlinTarget.isAndroidTarget() = this.platformType == KotlinPlatformType.androidJvm
+fun DokkaTask.isMultiplatformProject() = this.multiplatform.isNotEmpty() \ No newline at end of file
diff --git a/runners/maven-plugin/build.gradle b/runners/maven-plugin/build.gradle
index 2e9d0b1b..76fab68d 100644
--- a/runners/maven-plugin/build.gradle
+++ b/runners/maven-plugin/build.gradle
@@ -52,8 +52,8 @@ task setupMaven(type: Sync) {
def mavenBuildDir = "$buildDir/maven"
-sourceSets.main.resources {
- srcDirs += "$mavenBuildDir/classes/java/main"
+sourceSets.main.resources {
+ srcDirs += "$mavenBuildDir/classes/java/main"
exclude "**/*.class"
}
diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
index 324703a0..fb11ecac 100644
--- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
+++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt
@@ -15,14 +15,14 @@ import java.io.File
import java.net.URL
class SourceLinkMapItem {
- @Parameter(name = "dir", required = true)
- var dir: String = ""
+ @Parameter(name = "path", required = true)
+ var path: String = ""
@Parameter(name = "url", required = true)
var url: String = ""
- @Parameter(name = "urlSuffix")
- var urlSuffix: String? = null
+ @Parameter(name = "lineSuffix")
+ var lineSuffix: String? = null
}
class ExternalDocumentationLinkBuilder : DokkaConfiguration.ExternalDocumentationLink.Builder() {
@@ -37,9 +37,6 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
class SourceRoot : DokkaConfiguration.SourceRoot {
@Parameter(required = true)
override var path: String = ""
-
- @Parameter
- override var platforms: List<String> = emptyList()
}
class PackageOptions : DokkaConfiguration.PackageOptions {
@@ -62,11 +59,7 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
var sourceRoots: List<SourceRoot> = emptyList()
@Parameter
- var samplesDirs: List<String> = emptyList()
-
- @Parameter
- @Deprecated("Use <includes> instead")
- var includeDirs: List<String> = emptyList()
+ var samples: List<String> = emptyList()
@Parameter
var includes: List<String> = emptyList()
@@ -75,7 +68,7 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
var classpath: List<String> = emptyList()
@Parameter
- var sourceLinks: Array<SourceLinkMapItem> = emptyArray()
+ var sourceLinks: List<SourceLinkMapItem> = emptyList()
@Parameter(required = true, defaultValue = "\${project.artifactId}")
var moduleName: String = ""
@@ -87,11 +80,11 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
var jdkVersion: Int = 6
@Parameter
- var skipDeprecated = false
+ var skipDeprecated: Boolean = false
@Parameter
- var skipEmptyPackages = true
+ var skipEmptyPackages: Boolean = true
@Parameter
- var reportNotDocumented = true
+ var reportUndocumented: Boolean = true
@Parameter
var impliedPlatforms: List<String> = emptyList()
@@ -117,7 +110,32 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
@Parameter
var apiVersion: String? = null
+ @Parameter
+ var includeRootPackage: Boolean = false
+
+ @Parameter
+ var suppressedFiles: List<String> = emptyList()
+
+ @Parameter
+ var collectInheritedExtensionsFromLibraries: Boolean = false
+
+ @Parameter
+ var platform: String = ""
+
+ @Parameter
+ var targets: List<String> = emptyList()
+
+ @Parameter
+ var sinceKotlin: String? = null
+
+ @Parameter
+ var includeNonPublic: Boolean = false
+
+ @Parameter
+ var generateIndexPages: Boolean = false
+
protected abstract fun getOutDir(): String
+
protected abstract fun getOutFormat(): String
override fun execute() {
@@ -127,35 +145,55 @@ abstract class AbstractDokkaMojo : AbstractMojo() {
}
sourceLinks.forEach {
- if (it.dir.contains("\\")) {
- throw MojoExecutionException("Incorrect dir property, only Unix based path allowed.")
+ if (it.path.contains("\\")) {
+ throw MojoExecutionException("Incorrect path property, only Unix based path allowed.")
}
}
- val gen = DokkaGenerator(
- MavenDokkaLogger(log),
- classpath,
- sourceDirectories.map { SourceRootImpl(it) } + sourceRoots,
- samplesDirs,
- includeDirs + includes,
- moduleName,
- DocumentationOptions(getOutDir(), getOutFormat(),
- sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) },
- jdkVersion = jdkVersion,
- skipDeprecated = skipDeprecated,
- skipEmptyPackages = skipEmptyPackages,
- reportUndocumented = reportNotDocumented,
- impliedPlatforms = impliedPlatforms,
- perPackageOptions = perPackageOptions,
- externalDocumentationLinks = externalDocumentationLinks.map { it.build() },
- noStdlibLink = noStdlibLink,
- noJdkLink = noJdkLink,
- cacheRoot = cacheRoot,
- languageVersion = languageVersion,
- apiVersion = apiVersion
- )
+ val passConfiguration = PassConfigurationImpl(
+ classpath = classpath,
+ sourceRoots = sourceDirectories.map { SourceRootImpl(it) } + sourceRoots.map { SourceRootImpl(path = it.path) },
+ samples = samples,
+ includes = includes,
+ collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries, // TODO: Should we implement this?
+ sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.path, it.url, it.lineSuffix) },
+ jdkVersion = jdkVersion,
+ skipDeprecated = skipDeprecated,
+ skipEmptyPackages = skipEmptyPackages,
+ reportUndocumented = reportUndocumented,
+ perPackageOptions = perPackageOptions.map {
+ PackageOptionsImpl(
+ prefix = it.prefix,
+ includeNonPublic = it.includeNonPublic,
+ reportUndocumented = it.reportUndocumented,
+ skipDeprecated = it.skipDeprecated,
+ suppress = it.suppress
+ )},
+ externalDocumentationLinks = externalDocumentationLinks.map { it.build() as ExternalDocumentationLinkImpl },
+ noStdlibLink = noStdlibLink,
+ noJdkLink = noJdkLink,
+ languageVersion = languageVersion,
+ apiVersion = apiVersion,
+ moduleName = moduleName,
+ suppressedFiles = suppressedFiles,
+ sinceKotlin = sinceKotlin,
+ analysisPlatform = if (platform.isNotEmpty()) Platform.fromString(platform) else Platform.DEFAULT,
+ targets = targets,
+ includeNonPublic = includeNonPublic,
+ includeRootPackage = includeRootPackage
)
+ val configuration = DokkaConfigurationImpl(
+ outputDir = getOutDir(),
+ format = getOutFormat(),
+ impliedPlatforms = impliedPlatforms,
+ cacheRoot = cacheRoot,
+ passesConfigurations = listOf(passConfiguration),
+ generateIndexPages = generateIndexPages
+ )
+
+ val gen = DokkaGenerator(configuration, MavenDokkaLogger(log))
+
gen.generate()
}
}
@@ -246,11 +284,11 @@ class DokkaJavadocJarMojo : AbstractDokkaMojo() {
val javadocJar = File(jarOutputDirectory, jarFileName)
val archiver = MavenArchiver()
- archiver.setArchiver(jarArchiver)
+ archiver.archiver = jarArchiver
archiver.setOutputFile(javadocJar)
archiver.archiver.addDirectory(File(outputDir), arrayOf("**/**"), arrayOf())
- archive.setAddMavenDescriptor(false)
+ archive.isAddMavenDescriptor = false
archiver.createArchive(session, project, archive)
return javadocJar
diff --git a/settings.gradle b/settings.gradle
index ef5f9869..8a89d827 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -7,5 +7,4 @@ include 'core',
'runners:cli',
'runners:maven-plugin',
'runners:gradle-plugin',
- 'runners:android-gradle-plugin',
'runners:gradle-integration-tests'