diff options
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 @@ -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 "$KOTLIN_BUNDLED$/lib/kotlin-compiler.jar:$KOTLIN_BUNDLED$/lib/kotlin-runtime.jar"" /> - <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 @@ -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(" ") } - 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/> ") - } - } - - 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> / <a href="../index.html">JavaSupertype</a> / <a href="./index.html">Bar</a><br/> +<a href="../../../index.html">test</a> / <a href="../index.html">JavaSupertype</a> / <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> <span class="symbol">:</span> <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"><init></a></p> +<h4><a href="-init-.html"><init></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> <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 <root> 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> / <a href="./u.html">u</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./f.html">f</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./index.html">Klass</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">Throws</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">ItDoesSomeObfuscatedThing</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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 -| [<init>](-init-.md) | `Throws()`<br>This annotation indicates what exceptions should be declared by a function when compiled to a JVM method. | +| [<init>](-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 -| [<init>](-init-.md) | `ItDoesSomeObfuscatedThing()`<br>Check output of | +| [<init>](-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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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 -| [<init>](-init-.md) | `Foo()`<br>Correct ref [Foo.Companion](-companion.md) | +| [<init>](-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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">C</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./f.html">f</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./p.html">p</a><br/> +<a href="../index.html">test</a> / <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 <root></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> / <a href="./index.html">Bar</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></a></h4> </td> <td> -<code><span class="identifier">Bar</span><span class="symbol">(</span><span class="symbol">)</span></code> <p>Copyright © JetBrains 2015 "</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 <root> 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> / <a href="./index.html">A</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">B</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">C</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./f.html">f</a><br/> +<a href="../index.html">test</a> / <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> <a href="-a/index.html"><span class="identifier">A</span></a><span class="symbol">,</span> <span class="identifier">b</span><span class="symbol">:</span> <a href="-b/index.html"><span class="identifier">B</span></a><span class="symbol">)</span> <span class="symbol">-></span> <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> / <a href="./accept-function-type-with-named-arguments.html">acceptFunctionTypeWithNamedArguments</a><br/> +<a href="../index.html">test</a> / <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 @@ | [<init>](-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 @@ | [<init>](-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 @@ | [<init>](-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 | |---|---| -| [<init>](-init-.md) | `Foo()`<br>The class Foo. | +| [<init>](-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> / <a href="./x.html">x</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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<B>C ### Constructors -| [<init>](-init-.md) | `C()`<br>`A<B>C` | +| [<init>](-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> / <a href="index.html">Foo</a> / <a href="./foo.html">foo</a><br/> +<a href="../../index.html">test</a> / <a href="index.html">Foo</a> / <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> / <a href="./index.html">Foo</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">Foo</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">Foo</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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 -| [<init>](-init-.md) | `C()`<br>**Bold** **Strong** *Italic* *Emphasized* | +| [<init>](-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 -| [<init>](-init-.md) | `Bar()`<br> +| [<init>](-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 -| [<init>](-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)) | +| [<init>](-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> / <a href="./index.html">Bar</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./index.html">KClassLoader</a><br/> +<a href="../../index.html">test</a> / <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> <span class="identifier">Enum</span><span class="symbol"><</span><span class="identifier">*</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/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 -| [<init>](-init-.md) | `Bar()`<br>An emphasised class. | +| [<init>](-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 -| [<init>](-init-.md) | `Bar()`<br>Some class with really useless documentation. | +| [<init>](-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 -| [<init>](-init-.md) | `Bar()`<br>A strong class. | +| [<init>](-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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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 -| [<init>](-some/-init-.md) | `Some()` | +| (JS) [<init>](-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 -| [<init>](-init-.md) | `Foo()`<br>This is a foo. | +| (JVM, JS) [<init>](-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 -| [<init>](-init-.md) | `Foo()`<br>This is a foo. | +| (JVM, JS) [<init>](-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 -| [<init>](-init-.md) | `Foo()`<br>This is a foo. | +| (JVM) [<init>](-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 -| [<init>](-init-.md) | `Bar()`<br>Usage instructions: | +| [<init>](-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 <root> ### 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> / <a href="./index.html">Bar</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> +<h4><a href="-init-.html"><init></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 <root></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> <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> <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> <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> <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> / <a href="./f.html">f</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./f.html">f</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./process-files.html">processFiles</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./quux.html">quux</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./bar.html">bar</a><br/> +<a href="../index.html">test</a> / <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> / <a href="./index.html">Since1.1</a><br/> +<a href="../../index.html">test</a> / <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"><init></a></p> -</td> +<h4><a href="-init-.html"><init></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 -| [<init>](-init-.md) | `Since1.1()`<br>Useful | +| [<init>](-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 <root> -**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 <root> -**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 <root> 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 -| [<init>](-init-.md) | `Bar()`<br>Another emphasised class. | +| [<init>](-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 -| [<init>](-init-.md) | `The()`<br>Why did the token cross the road? | +| [<init>](-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 -| [<init>](-init-.md) | `Yasc()`<br>**YASC: [Yasc](./index.md) Yet Another Strong Class** | +| [<init>](-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> / <a href="./f.html">f</a><br/> +<a href="../index.html">test</a> / <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 @@ | [<init>](-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 @@ | [<init>](-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 @@ | [<init>](-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 <root> @@ -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> / <a href="./index.html">Bar</a><br/> +<a href="../../index.html">test</a> / <a href="./index.html">Bar</a><br/> <br/> <h1>Bar</h1> <code><span class="keyword">class </span><span class="identifier">Bar</span> <span class="symbol">:</span> <a href="../-foo/index.html"><span class="identifier">Foo</span></a></code> @@ -13,7 +13,7 @@ <tbody> <tr> <td> -<p><a href="-init-.html"><init></a></p> +<h4><a href="-init-.html"><init></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> / <a href="./foo.html">foo</a><br/> +<a href="../index.html">test</a> / <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 -| [<init>](-init-.md) | `Bar()`<br>Usage summary: | +| [<init>](-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> <span class="symbol">=</span> <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> <span class="symbol">=</span> <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"><init></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"><init></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> <span class="symbol">=</span> <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<String>) { //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<String>) { @@ -10,3 +13,4 @@ fun main(args: Array<String>) { //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<String>) { //sampleStart @@ -17,3 +20,4 @@ val mutableByLength: MutableMap<Int, MutableList<String>> = 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> <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> <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/> <span class="parameterName" id="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/char">char</span><span class="symbol">:</span> <span class="identifier">Char</span><span class="symbol">, </span><br/> <span class="parameterName" id="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/startIndex">startIndex</span><span class="symbol">:</span> <span class="identifier">Int</span> <span class="symbol">=</span> 0<span class="symbol">, </span><br/> <span class="parameterName" id="$indexOf(Foo, kotlin.Char, kotlin.Int, kotlin.Boolean)/ignoreCase">ignoreCase</span><span class="symbol">:</span> <span class="identifier">Boolean</span> <span class="symbol">=</span> 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<String>) { //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> <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<String>) { @@ -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 Binary files differindex 736fb7d3..28861d27 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar 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' |