diff options
123 files changed, 1959 insertions, 930 deletions
diff --git a/.idea/encodings.xml b/.idea/encodings.xml index e206d70d..f7589596 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" /> -</project> - + <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false"> + <file url="PROJECT" charset="UTF-8" /> + </component> +</project>
\ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 00b45e99..acfc0bba 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,6 +12,11 @@ </set> </option> <option name="useAutoImport" value="true" /> + <option name="myModules"> + <set> + <option value="$PROJECT_DIR$/dokka-fatjar" /> + </set> + </option> </GradleProjectSettings> <GradleProjectSettings> <option name="distributionType" value="DEFAULT_WRAPPED" /> @@ -22,6 +27,27 @@ </set> </option> <option name="useAutoImport" value="true" /> + <option name="myModules"> + <set> + <option value="$PROJECT_DIR$/gradle-plugin" /> + </set> + </option> + </GradleProjectSettings> + <GradleProjectSettings> + <option name="distributionType" value="DEFAULT_WRAPPED" /> + <option name="externalProjectPath" value="$PROJECT_DIR$/javadoc" /> + <option name="gradleJvm" value="1.8" /> + <option name="modules"> + <set> + <option value="$PROJECT_DIR$/javadoc" /> + </set> + </option> + <option name="useAutoImport" value="true" /> + <option name="myModules"> + <set> + <option value="$PROJECT_DIR$/javadoc" /> + </set> + </option> </GradleProjectSettings> <GradleProjectSettings> <option name="distributionType" value="DEFAULT_WRAPPED" /> diff --git a/.idea/libraries/Gradle__org_fusesource_jansi_jansi_1_11.xml b/.idea/libraries/Gradle__org_fusesource_jansi_jansi_1_11.xml deleted file mode 100644 index 8c78e1dc..00000000 --- a/.idea/libraries/Gradle__org_fusesource_jansi_jansi_1_11.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<component name="libraryTable"> - <library name="Gradle: org.fusesource.jansi:jansi:1.11"> - <CLASSES> - <root url="jar://$MAVEN_REPOSITORY$/org/fusesource/jansi/jansi/1.11/jansi-1.11.jar!/" /> - </CLASSES> - <JAVADOC /> - <SOURCES /> - </library> -</component>
\ No newline at end of file diff --git a/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_0_0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_1_0_0_beta_1038.xml index 1328f8e8..eee2b80d 100644 --- a/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_0_0_1_SNAPSHOT.xml +++ b/.idea/libraries/Gradle__org_jetbrains_dokka_dokka_fatjar_1_0_0_beta_1038.xml @@ -1,12 +1,11 @@ -<?xml version="1.0" encoding="UTF-8"?> <component name="libraryTable"> - <library name="Gradle: org.jetbrains.dokka:dokka-fatjar:0.0.1-SNAPSHOT"> + <library name="Gradle: org.jetbrains.dokka:dokka-fatjar:1.0.0-beta-1038"> <CLASSES> - <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/0.0.1-SNAPSHOT/dokka-fatjar-0.0.1-SNAPSHOT.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/1.0.0-beta-1038/dokka-fatjar-1.0.0-beta-1038.jar!/" /> </CLASSES> <JAVADOC /> <SOURCES> - <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/0.0.1-SNAPSHOT/dokka-fatjar-0.0.1-SNAPSHOT-sources.jar!/" /> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/dokka/dokka-fatjar/1.0.0-beta-1038/dokka-fatjar-1.0.0-beta-1038-sources.jar!/" /> </SOURCES> </library> </component>
\ No newline at end of file diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml new file mode 100644 index 00000000..7269fee8 --- /dev/null +++ b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component name="libraryTable"> + <library name="Gradle: org.jetbrains.kotlin:kotlin-runtime:0.1-SNAPSHOT"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/0.1-SNAPSHOT/kotlin-runtime-0.1-SNAPSHOT.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-runtime/0.1-SNAPSHOT/kotlin-runtime-0.1-SNAPSHOT-sources.jar!/" /> + </SOURCES> + </library> +</component>
\ No newline at end of file diff --git a/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml new file mode 100644 index 00000000..7ee2d16e --- /dev/null +++ b/.idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component name="libraryTable"> + <library name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:0.1-SNAPSHOT"> + <CLASSES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/0.1-SNAPSHOT/kotlin-stdlib-0.1-SNAPSHOT.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/0.1-SNAPSHOT/kotlin-stdlib-0.1-SNAPSHOT-sources.jar!/" /> + </SOURCES> + </library> +</component>
\ No newline at end of file diff --git a/.idea/libraries/jansi.xml b/.idea/libraries/jansi.xml new file mode 100644 index 00000000..f191460f --- /dev/null +++ b/.idea/libraries/jansi.xml @@ -0,0 +1,9 @@ +<component name="libraryTable"> + <library name="jansi"> + <CLASSES> + <root url="jar://$PROJECT_DIR$/lib/jansi.jar!/" /> + </CLASSES> + <JAVADOC /> + <SOURCES /> + </library> +</component>
\ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 4b4cbc1b..99b0072e 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -7,6 +7,7 @@ <module fileurl="file://$PROJECT_DIR$/dokka-fatjar/dokka-fatjar.iml" filepath="$PROJECT_DIR$/dokka-fatjar/dokka-fatjar.iml" /> <module fileurl="file://$PROJECT_DIR$/gradle-plugin/dokka-gradle-plugin.iml" filepath="$PROJECT_DIR$/gradle-plugin/dokka-gradle-plugin.iml" /> <module fileurl="file://$PROJECT_DIR$/maven-plugin/dokka-maven-plugin.iml" filepath="$PROJECT_DIR$/maven-plugin/dokka-maven-plugin.iml" /> + <module fileurl="file://$PROJECT_DIR$/javadoc/javadoc.iml" filepath="$PROJECT_DIR$/javadoc/javadoc.iml" /> </modules> </component> </project>
\ No newline at end of file diff --git a/.idea/runConfigurations/All_tests.xml b/.idea/runConfigurations/All_tests.xml index 4e7c9c09..5976ed25 100644 --- a/.idea/runConfigurations/All_tests.xml +++ b/.idea/runConfigurations/All_tests.xml @@ -1,20 +1,20 @@ <component name="ProjectRunConfigurationManager"> <configuration default="false" name="All tests" type="JUnit" factoryName="JUnit" singleton="true"> <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> - <module name="" /> + <module name="dokka" /> <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> <option name="ALTERNATIVE_JRE_PATH" value="" /> <option name="PACKAGE_NAME" value="org.jetbrains.dokka.tests" /> <option name="MAIN_CLASS_NAME" value="" /> <option name="METHOD_NAME" value="" /> <option name="TEST_OBJECT" value="package" /> - <option name="VM_PARAMETERS" value="" /> + <option name="VM_PARAMETERS" value="-ea -Xmx256m" /> <option name="PARAMETERS" value="" /> <option name="WORKING_DIRECTORY" value="" /> <option name="ENV_VARIABLES" /> <option name="PASS_PARENT_ENVS" value="true" /> <option name="TEST_SEARCH_SCOPE"> - <value defaultName="wholeProject" /> + <value defaultName="moduleWithDependencies" /> </option> <envs /> <patterns /> diff --git a/.idea/runConfigurations/Dokka.xml b/.idea/runConfigurations/Dokka.xml index b752422e..e2388ba2 100644 --- a/.idea/runConfigurations/Dokka.xml +++ b/.idea/runConfigurations/Dokka.xml @@ -1,13 +1,12 @@ -<?xml version="1.0" encoding="UTF-8"?> <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.DokkaPackage" /> + <option name="MAIN_CLASS_NAME" value="org.jetbrains.dokka.MainKt" /> <option name="VM_PARAMETERS" value="" /> <option name="PROGRAM_PARAMETERS" value="src/ -output doc -module dokka -format kotlin-website -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="ALTERNATIVE_JRE_PATH" value="" /> <option name="PASS_PARENT_ENVS" value="true" /> <module name="dokka" /> <envs /> diff --git a/.idea/runConfigurations/Stdlib.xml b/.idea/runConfigurations/Stdlib.xml index 7750c5df..d29fc0bd 100644 --- a/.idea/runConfigurations/Stdlib.xml +++ b/.idea/runConfigurations/Stdlib.xml @@ -1,13 +1,12 @@ -<?xml version="1.0" encoding="UTF-8"?> <component name="ProjectRunConfigurationManager"> <configuration default="false" name="Stdlib" type="JetRunConfigurationType" factoryName="Kotlin"> <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" /> - <option name="MAIN_CLASS_NAME" value="org.jetbrains.dokka.DokkaPackage" /> + <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/builtins ../kotlin/core/reflection -samples ../kotlin/libraries/stdlib/test -output doc -module stdlib -include ../kotlin/libraries/stdlib/src/Module.md -format kotlin-website -srcLink ../kotlin=http://github.com/JetBrains/kotlin/blob/master#L" /> + <option name="PROGRAM_PARAMETERS" value="../kotlin/libraries/stdlib/src ../kotlin/core/builtins ../kotlin/core/reflection.jvm -samples ../kotlin/libraries/stdlib/test -output doc -module stdlib -include ../kotlin/libraries/stdlib/src/Module.md -format kotlin-website -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="ALTERNATIVE_JRE_PATH" value="" /> <option name="PASS_PARENT_ENVS" value="true" /> <module name="dokka" /> <envs /> diff --git a/ant/src/dokka.kt b/ant/src/dokka.kt index 882dbdb7..d78980f8 100644 --- a/ant/src/dokka.kt +++ b/ant/src/dokka.kt @@ -37,7 +37,7 @@ class DokkaAntTask(): Task() { } public fun setClasspathRef(ref: Reference) { - compileClasspath.createPath().setRefid(ref) + compileClasspath.createPath().refid = ref } public fun setSrc(src: Path) { @@ -45,7 +45,7 @@ class DokkaAntTask(): Task() { } public fun setSrcRef(ref: Reference) { - sourcePath.createPath().setRefid(ref) + sourcePath.createPath().refid = ref } public fun setSamples(samples: Path) { @@ -53,7 +53,7 @@ class DokkaAntTask(): Task() { } public fun setSamplesRef(ref: Reference) { - samplesPath.createPath().setRefid(ref) + samplesPath.createPath().refid = ref } public fun setInclude(include: Path) { @@ -67,7 +67,7 @@ class DokkaAntTask(): Task() { } override fun execute() { - if (sourcePath.list().size() == 0) { + if (sourcePath.list().size == 0) { throw BuildException("At least one source path needs to be specified") } if (moduleName == null) { @@ -85,11 +85,11 @@ class DokkaAntTask(): Task() { if (url == null) { throw BuildException("Path attribute of a <sourceLink> element is required") } - SourceLinkDefinition(File(path).getCanonicalFile().getAbsolutePath(), url, it.lineSuffix) + SourceLinkDefinition(File(path).canonicalFile.absolutePath, url, it.lineSuffix) } - val url = javaClass<DokkaAntTask>().getResource("/org/jetbrains/dokka/ant/DokkaAntTask.class") - val jarRoot = url.getPath().substringBefore("!/").removePrefix("file:") + val url = DokkaAntTask::class.java.getResource("/org/jetbrains/dokka/ant/DokkaAntTask.class") + val jarRoot = url.path.substringBefore("!/").removePrefix("file:") val generator = DokkaGenerator( AntLogger(this), @@ -34,10 +34,47 @@ </kotlinc> <jar jarfile="out/dokka-ant.jar" update="true" > - <zipfileset dir="ant/src" includes="*.xml" prefix="org/jetbrains/dokka/ant" /> + <zipfileset dir="ant/src" includes="*.xml"/> </jar> </target> + <target name="zip" depends="build"> + <zip zipfile="out/dokka.zip"> + <zipfileset dir="lib" prefix="lib"> + <include name="*.jar"/> + <exclude name="junit*.jar"/> + <exclude name="hamcrest*.jar"/> + <exclude name="maven-ant-tasks*.jar"/> + </zipfileset> + <zipfileset dir="out" prefix="lib"> + <include name="dokka.jar"/> + <include name="dokka-ant.jar"/> + </zipfileset> + </zip> + </target> + + <target name="test" depends="build"> + <mkdir dir="out/test"/> + + <kotlinc src="test/src" output="out/test"> + <classpath> + <fileset dir="lib" includes="*.jar"/> + <fileset dir="out" includes="dokka.jar" /> + </classpath> + </kotlinc> + + <junit fork="true"> + <classpath> + <fileset dir="lib" includes="*.jar"/> + <fileset dir="out" includes="dokka.jar" /> + <pathelement path="out/test"/> + </classpath> + <batchtest> + <fileset dir="out/test" includes="**/*Test.class"/> + </batchtest> + </junit> + </target> + <target name="fatjar" depends="build"> <exec executable="${basedir}/dokka-fatjar/gradlew" dir="dokka-fatjar" osfamily="unix" failonerror="true"> <arg value="assemble" /> diff --git a/dokka-fatjar/build.gradle b/dokka-fatjar/build.gradle index ffec3b82..467385e1 100644 --- a/dokka-fatjar/build.gradle +++ b/dokka-fatjar/build.gradle @@ -1,13 +1,19 @@ group 'org.jetbrains.dokka' -version '0.0.1-SNAPSHOT' +version '1.0.0-beta-1038' +import proguard.gradle.ProGuardTask + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'net.sf.proguard:proguard-gradle:5.2.1' + } +} apply plugin: 'java' apply plugin: 'maven-publish' -dependencies { - compile 'org.fusesource.jansi:jansi:[1.11,2.0)' -} - task wrapper(type: Wrapper) { gradleVersion = '2.5' distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" @@ -17,20 +23,34 @@ task sourceJar(type: Jar) { from fileTree('../src') } +task proguard(type: ProGuardTask) { + configuration 'dokka.pro' + + injars 'build/libs/dokka-fatjar-1.0.0-beta-1038.jar' + outjars 'build/libs/dokka-fatjar-1.0.0-beta-1038.out.jar' +} + jar { manifest { attributes "Implementation-Title": "Dokka Kotlin Documentation tool" attributes "Implementation-Version": version - attributes "Main-Class" : "org.jetbrains.dokka.DokkaPackage" + attributes "Main-Class" : "org.jetbrains.dokka.MainKt" } + duplicatesStrategy = DuplicatesStrategy.EXCLUDE - fileTree(project.file('../lib')).filter { it.name.endsWith('.jar') && !it.name.contains("-sources") }.each { + fileTree(project.file('../lib')).filter { + it.name.endsWith('.jar') && + !it.name.contains("-sources") && + !it.name.contains("-javadoc") + }.each { from (zipTree(it)) { exclude 'META-INF/MANIFEST.MF' exclude 'META-INF/*.SF' exclude 'META-INF/*.DSA' exclude 'META-INF/*.RSA' exclude '**/*.kt' + exclude '**/*.java' + exclude '**/*.md' } } from (zipTree(project.file('../out/dokka.jar'))) { @@ -39,6 +59,8 @@ jar { exclude 'META-INF/*.DSA' exclude 'META-INF/*.RSA' exclude '**/*.kt' + exclude '**/*.java' + exclude '**/*.md' } } diff --git a/dokka-fatjar/dokka-fatjar.iml b/dokka-fatjar/dokka-fatjar.iml index dcf9d922..e8948bfb 100644 --- a/dokka-fatjar/dokka-fatjar.iml +++ b/dokka-fatjar/dokka-fatjar.iml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.id="dokka-fatjar" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="0.0.1-SNAPSHOT" type="JAVA_MODULE" version="4"> +<module external.linked.project.id="dokka-fatjar" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="1.0.0-beta-1038" type="JAVA_MODULE" version="4"> <component name="NewModuleRootManager" inherit-compiler-output="false"> <output url="file://$MODULE_DIR$/build/classes/main" /> <output-test url="file://$MODULE_DIR$/build/classes/test" /> diff --git a/dokka-fatjar/dokka.pro b/dokka-fatjar/dokka.pro new file mode 100644 index 00000000..97eae693 --- /dev/null +++ b/dokka-fatjar/dokka.pro @@ -0,0 +1,100 @@ +# Include java runtime classes +-libraryjars <java.home>/lib/rt.jar + +# Keep filenames and line numbers +-keepattributes SourceFile, LineNumberTable + +-target 1.6 +-dontoptimize +-dontobfuscate + +-ignorewarnings +# -keepdirectories + +-dontwarn org.jetbrains.annotations.** +-dontwarn org.apache.commons.httpclient.** +-dontwarn org.apache.tools.ant.** +-dontwarn org.codehaus.plexus.** +-dontwarn hidden.org.codehaus.plexus.** +-dontwarn org.fusesource.** +-dontwarn org.jaxen.jdom.** + +-keep class org.jetbrains.dokka.** { *; } +-keep class org.fusesource.** { *; } +-keep class org.jdom.input.JAXPParserFactory { *; } + +-keep class org.jetbrains.annotations.** { + public protected *; +} + +-keep class javax.inject.** { + public protected *; +} + +-keep class org.jetbrains.kotlin.** { + public protected *; +} + +-keep class org.jetbrains.kotlin.compiler.plugin.** { + public protected *; +} + +-keep class org.jetbrains.kotlin.extensions.** { + public protected *; +} + +-keep class org.jetbrains.org.objectweb.asm.Opcodes { *; } + +-keep class org.jetbrains.kotlin.codegen.extensions.** { + public protected *; +} + +-keepclassmembers class com.intellij.openapi.vfs.VirtualFile { + public InputStream getInputStream(); +} + +-keep class jet.** { + public protected *; +} + +-keep class com.intellij.psi.** { + public protected *; +} + +# for kdoc & dokka +-keep class com.intellij.openapi.util.TextRange { *; } +-keep class com.intellij.lang.impl.PsiBuilderImpl* { + public protected *; +} +-keep class com.intellij.openapi.util.text.StringHash { *; } + +# for gradle plugin and other server tools +-keep class com.intellij.openapi.util.io.ZipFileCache { public *; } + +# for j2k +-keep class com.intellij.codeInsight.NullableNotNullManager { public protected *; } + +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +-keepclassmembers class * { + ** toString(); + ** hashCode(); + void start(); + void stop(); + void dispose(); +} + +-keepclassmembers class org.jetbrains.org.objectweb.asm.Opcodes { + *** ASM5; +} + +-keepclassmembers class org.jetbrains.org.objectweb.asm.ClassReader { + *** SKIP_CODE; + *** SKIP_DEBUG; + *** SKIP_FRAMES; +} + + @@ -7,6 +7,7 @@ <sourceFolder url="file://$MODULE_DIR$/test/src" isTestSource="true" packagePrefix="org.jetbrains.dokka.tests" /> <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" /> <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" /> + <excludeFolder url="file://$MODULE_DIR$/doc" /> </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> @@ -24,5 +25,6 @@ <orderEntry type="library" name="asm" level="project" /> <orderEntry type="library" name="jps-model" level="project" /> <orderEntry type="library" name="com.google.inject:guice:4.0" level="project" /> + <orderEntry type="library" name="jansi" level="project" /> </component> </module>
\ No newline at end of file diff --git a/gradle-plugin/build.gradle b/gradle-plugin/build.gradle index 52fa045e..2c963a81 100644 --- a/gradle-plugin/build.gradle +++ b/gradle-plugin/build.gradle @@ -1,8 +1,8 @@ group 'org.jetbrains.dokka' -version '0.1-SNAPSHOT' +version '1.0.0-beta-1038' buildscript { - ext.kotlin_version = '0.1-SNAPSHOT' + ext.kotlin_version = '1.0.0-beta-1038' repositories { mavenCentral() maven { @@ -30,7 +30,7 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' - compile "org.jetbrains.dokka:dokka-fatjar:(,0.2)" + compile "org.jetbrains.dokka:dokka-fatjar:1.0.0-beta-1038" compile gradleApi() compile localGroovy() diff --git a/gradle-plugin/dokka-gradle-plugin.iml b/gradle-plugin/dokka-gradle-plugin.iml index dfbcc3eb..03f8028f 100644 --- a/gradle-plugin/dokka-gradle-plugin.iml +++ b/gradle-plugin/dokka-gradle-plugin.iml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<module external.linked.project.id="dokka-gradle-plugin" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="0.1-SNAPSHOT" type="JAVA_MODULE" version="4"> +<module external.linked.project.id="dokka-gradle-plugin" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="org.jetbrains.dokka" external.system.module.version="1.0.0-beta-1038" type="JAVA_MODULE" version="4"> <component name="NewModuleRootManager" inherit-compiler-output="false"> <output url="file://$MODULE_DIR$/build/classes/main" /> <output-test url="file://$MODULE_DIR$/build/classes/test" /> @@ -16,6 +16,8 @@ </content> <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" /> + <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" /> <orderEntry type="module-library"> <library name="Gradle: gradle-core-2.5"> <CLASSES> @@ -1464,9 +1466,6 @@ </SOURCES> </library> </orderEntry> - <orderEntry type="library" name="Gradle: org.fusesource.jansi:jansi:1.11" level="project" /> - <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" /> - <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" /> - <orderEntry type="library" name="Gradle: org.jetbrains.dokka:dokka-fatjar:0.0.1-SNAPSHOT" level="project" /> + <orderEntry type="library" name="Gradle: org.jetbrains.dokka:dokka-fatjar:1.0.0-beta-1038" level="project" /> </component> </module>
\ No newline at end of file diff --git a/gradle-plugin/src/main/kotlin/main.kt b/gradle-plugin/src/main/kotlin/main.kt index 418af00f..e56b2371 100644 --- a/gradle-plugin/src/main/kotlin/main.kt +++ b/gradle-plugin/src/main/kotlin/main.kt @@ -15,29 +15,29 @@ import java.util.ArrayList public open class DokkaPlugin : Plugin<Project> { override fun apply(project: Project) { - val ext = project.getExtensions().create("dokka", javaClass<DokkaExtension>()) - project.getTasks().create("dokka", javaClass<DokkaTask>()) + val ext = project.extensions.create("dokka", DokkaExtension::class.java) + project.tasks.create("dokka", DokkaTask::class.java) - ext.moduleName = project.getName() - ext.outputDirectory = File(project.getBuildDir(), "dokka").getAbsolutePath() + ext.moduleName = project.name + ext.outputDirectory = File(project.buildDir, "dokka").absolutePath } } public open class DokkaTask : DefaultTask() { init { - setGroup(JavaBasePlugin.DOCUMENTATION_GROUP) - setDescription("Generates dokka documentation for Kotlin") + group = JavaBasePlugin.DOCUMENTATION_GROUP + description = "Generates dokka documentation for Kotlin" } - TaskAction + @TaskAction fun generate() { - val project = getProject() - val conf = getProject().getExtensions().getByType(javaClass<DokkaExtension>()) - val javaPluginConvention = getProject().getConvention().getPlugin(javaClass<JavaPluginConvention>()) + val project = project + val conf = project.extensions.getByType(DokkaExtension::class.java) + val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java) - val sourceSets = javaPluginConvention.getSourceSets()?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) - val sourceDirectories = sourceSets?.getAllSource()?.getSrcDirs()?.filter { it.exists() } ?: emptyList() - val allConfigurations = getProject().getConfigurations() + val sourceSets = javaPluginConvention.sourceSets?.findByName(SourceSet.MAIN_SOURCE_SET_NAME) + val sourceDirectories = sourceSets?.allSource?.srcDirs?.filter { it.exists() } ?: emptyList() + val allConfigurations = project.configurations val classpath = conf.processConfigurations @@ -45,20 +45,20 @@ public open class DokkaTask : DefaultTask() { .flatMap { it } if (sourceDirectories.isEmpty()) { - getLogger().warn("No source directories found: skipping dokka generation") + logger.warn("No source directories found: skipping dokka generation") return } DokkaGenerator( - DokkaGradleLogger(getLogger()), - classpath.map { it.getAbsolutePath() }, - sourceDirectories.map { it.getAbsolutePath() }, + DokkaGradleLogger(logger), + classpath.map { it.absolutePath }, + sourceDirectories.map { it.absolutePath }, conf.samples, conf.includes, conf.moduleName, conf.outputDirectory, conf.outputFormat, - conf.linkMappings.map { SourceLinkDefinition(project.file(it.dir).getAbsolutePath(), it.url, it.suffix) }, + conf.linkMappings.map { SourceLinkDefinition(project.file(it.dir).absolutePath, it.url, it.suffix) }, false ).generate() } @@ -76,7 +76,7 @@ public open class DokkaExtension { fun linkMapping(closure: Closure<Any?>) { val mapping = LinkMapping() - closure.setDelegate(mapping) + closure.delegate = mapping closure.call() if (mapping.dir.isEmpty()) { diff --git a/javadoc/build.gradle b/javadoc/build.gradle new file mode 100644 index 00000000..ac079b99 --- /dev/null +++ b/javadoc/build.gradle @@ -0,0 +1,55 @@ +group 'org.jetbrains.dokka' +version '0.0.1-SNAPSHOT' + +buildscript { + ext.kotlin_version = '0.1-SNAPSHOT' + repositories { + mavenCentral() + maven { + url 'http://oss.sonatype.org/content/repositories/snapshots' + } + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'java' +apply plugin: 'kotlin' +apply plugin: 'maven-publish' + + +sourceCompatibility = 1.5 + + +repositories { + mavenLocal() + mavenCentral() + maven { + url 'http://oss.sonatype.org/content/repositories/snapshots' + } +} + +dependencies { + testCompile group: 'junit', name: 'junit', version: '4.12' + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "org.jetbrains.dokka:dokka-fatjar:(1.0,1.1)" + compile files("${System.properties['java.home']}/../lib/tools.jar") + + compile gradleApi() + compile localGroovy() +} + +sourceSets { + main.java.srcDirs += 'src/main/kotlin' +} + +task sourceJar(type: Jar) { + from sourceSets.main.allSource +} + + +task wrapper(type: Wrapper) { + gradleVersion = '2.5' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" +} diff --git a/javadoc/gradle/wrapper/gradle-wrapper.jar b/javadoc/gradle/wrapper/gradle-wrapper.jar Binary files differnew file mode 100644 index 00000000..30d399d8 --- /dev/null +++ b/javadoc/gradle/wrapper/gradle-wrapper.jar diff --git a/javadoc/gradle/wrapper/gradle-wrapper.properties b/javadoc/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..a9e95352 --- /dev/null +++ b/javadoc/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jul 24 15:47:38 MSK 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip diff --git a/javadoc/gradlew b/javadoc/gradlew new file mode 100755 index 00000000..91a7e269 --- /dev/null +++ b/javadoc/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/javadoc/gradlew.bat b/javadoc/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/javadoc/gradlew.bat @@ -0,0 +1,90 @@ +@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 + +@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= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@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 Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_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=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +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/javadoc/settings.gradle b/javadoc/settings.gradle new file mode 100644 index 00000000..30b72384 --- /dev/null +++ b/javadoc/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'javadoc' + diff --git a/javadoc/src/main/resources/format/javadoc.properties b/javadoc/src/main/resources/format/javadoc.properties new file mode 100644 index 00000000..a58317fc --- /dev/null +++ b/javadoc/src/main/resources/format/javadoc.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.javadoc.JavadocFormatDescriptor
\ No newline at end of file diff --git a/lib/intellij-core-analysis.jar b/lib/intellij-core-analysis.jar Binary files differindex 2ceaf0d1..2703162f 100644 --- a/lib/intellij-core-analysis.jar +++ b/lib/intellij-core-analysis.jar diff --git a/lib/jansi.jar b/lib/jansi.jar Binary files differnew file mode 100644 index 00000000..63284fd7 --- /dev/null +++ b/lib/jansi.jar diff --git a/lib/kotlin-for-upsource.jar b/lib/kotlin-for-upsource.jar Binary files differindex e48549d3..e860f853 100644 --- a/lib/kotlin-for-upsource.jar +++ b/lib/kotlin-for-upsource.jar diff --git a/lib/markdown.jar b/lib/markdown.jar Binary files differindex 9765d80a..9636893a 100644 --- a/lib/markdown.jar +++ b/lib/markdown.jar diff --git a/maven-plugin/pom.xml b/maven-plugin/pom.xml index 71cc856d..fb7a6423 100644 --- a/maven-plugin/pom.xml +++ b/maven-plugin/pom.xml @@ -6,14 +6,14 @@ <groupId>org.jetbrains.dokka</groupId> <artifactId>dokka-maven-plugin</artifactId> - <version>0.0.1-SNAPSHOT</version> + <version>1.0.0-beta-1038</version> <packaging>maven-plugin</packaging> <properties> <maven-plugin-anno.version>1.4.1</maven-plugin-anno.version> <maven.version>3.0.5</maven.version> <plexus.version>3.0.22</plexus.version> - <kotlin.version>0.1-SNAPSHOT</kotlin.version> + <kotlin.version>1.0.0-beta-1038</kotlin.version> </properties> <dependencies> @@ -46,7 +46,7 @@ <dependency> <groupId>org.jetbrains.dokka</groupId> <artifactId>dokka-fatjar</artifactId> - <version>(,0.2)</version> + <version>1.0.0-beta-1038</version> <type>jar</type> <scope>compile</scope> </dependency> diff --git a/maven-plugin/src/main/kotlin/DokkaMojo.kt b/maven-plugin/src/main/kotlin/DokkaMojo.kt index 80f00c42..fae9d856 100644 --- a/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -9,53 +9,53 @@ import org.jetbrains.dokka.DokkaGenerator import org.jetbrains.dokka.SourceLinkDefinition public class SourceLinkMapItem { - Parameter(name = "dir", required = true) + @Parameter(name = "dir", required = true) var dir: String = "" - Parameter(name = "url", required = true) + @Parameter(name = "url", required = true) var url: String = "" - Parameter(name = "urlSuffix") + @Parameter(name = "urlSuffix") var urlSuffix: String? = null } -Mojo(name = "dokka", defaultPhase = LifecyclePhase.PRE_SITE, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true) +@Mojo(name = "dokka", defaultPhase = LifecyclePhase.PRE_SITE, threadSafe = true, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true) public class DokkaMojo : AbstractMojo() { - Parameter(required = true, defaultValue = "\${project.compileSourceRoots}") + @Parameter(required = true, defaultValue = "\${project.compileSourceRoots}") var sourceDirectories: List<String> = emptyList() - Parameter + @Parameter var samplesDirs: List<String> = emptyList() - Parameter + @Parameter var includeDirs: List<String> = emptyList() - Parameter(required = true, defaultValue = "\${project.compileClasspathElements}") + @Parameter(required = true, defaultValue = "\${project.compileClasspathElements}") var classpath: List<String> = emptyList() - Parameter(required = true, defaultValue = "\${project.basedir}/target/dokka") + @Parameter(required = true, defaultValue = "\${project.basedir}/target/dokka") var outputDir: String = "" - Parameter(required = true, defaultValue = "html") + @Parameter(required = true, defaultValue = "html") var outputFormat: String = "html" - Parameter + @Parameter var sourceLinks: Array<SourceLinkMapItem> = emptyArray() - Parameter(required = true, defaultValue = "\${project.artifactId}") + @Parameter(required = true, defaultValue = "\${project.artifactId}") var moduleName: String = "" - Parameter(required = false, defaultValue = "false") + @Parameter(required = false, defaultValue = "false") var skip: Boolean = false override fun execute() { if (skip) { - getLog().info("Dokka skip parameter is true so no dokka output will be produced") + log.info("Dokka skip parameter is true so no dokka output will be produced") return } val gen = DokkaGenerator( - MavenDokkaLogger(getLog()), + MavenDokkaLogger(log), classpath, sourceDirectories, samplesDirs, diff --git a/src/Analysis/AnalysisEnvironment.kt b/src/Analysis/AnalysisEnvironment.kt index a2836592..561ac2f0 100644 --- a/src/Analysis/AnalysisEnvironment.kt +++ b/src/Analysis/AnalysisEnvironment.kt @@ -4,24 +4,45 @@ import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreModuleManager import com.intellij.mock.MockComponentManager import com.intellij.openapi.Disposable -import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.roots.ContentIterator -import com.intellij.openapi.roots.OrderEntry +import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ProjectFileIndex import com.intellij.openapi.util.Disposer -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.jps.model.module.JpsModuleSourceRootType +import com.intellij.psi.PsiElement +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.analyzer.ModuleContent +import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.analyzer.ResolverForModule import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.config.* -import org.jetbrains.kotlin.config.* +import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot +import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot +import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots +import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.ContentRoot +import org.jetbrains.kotlin.config.KotlinSourceRoot +import org.jetbrains.kotlin.container.get +import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.context.ProjectContext +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.idea.caches.resolve.KotlinOutOfBlockCompletionModificationTracker import org.jetbrains.kotlin.idea.caches.resolve.LibraryModificationTracker -import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade +import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession import java.io.File @@ -45,27 +66,42 @@ public class AnalysisEnvironment(val messageCollector: MessageCollector, body: A * Executes [processor] when analysis is complete. * $processor: function to receive compiler environment, module and context for symbol resolution */ - public fun withContext<T>(processor: (KotlinCoreEnvironment, ResolutionFacade, ResolveSession) -> T): T { + public fun <T> withContext(processor: (KotlinCoreEnvironment, ResolutionFacade, ResolveSession) -> T): T { val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) val projectComponentManager = environment.project as MockComponentManager val moduleManager = CoreModuleManager(environment.project, this) CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.picoContainer, - javaClass<ModuleManager>(), moduleManager) + ModuleManager::class.java, moduleManager) - projectComponentManager.registerService(javaClass<ProjectFileIndex>(), + projectComponentManager.registerService(ProjectFileIndex::class.java, CoreProjectFileIndex()) - projectComponentManager.registerService(javaClass<LibraryModificationTracker>(), + projectComponentManager.registerService(LibraryModificationTracker::class.java, LibraryModificationTracker(environment.project)) - projectComponentManager.registerService(javaClass<KotlinCacheService>(), + projectComponentManager.registerService(KotlinCacheService::class.java, KotlinCacheService(environment.project)) - projectComponentManager.registerService(javaClass<KotlinOutOfBlockCompletionModificationTracker>(), + projectComponentManager.registerService(KotlinOutOfBlockCompletionModificationTracker::class.java, KotlinOutOfBlockCompletionModificationTracker()) + val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() - val facade = KotlinCacheService.getInstance(environment.project).getResolutionFacade(sourceFiles) - // TODO get rid of resolveSession once we have all necessary APIs in ResolutionFacade - val resolveSession = environment.analyze() + + val module = object : ModuleInfo { + override val name: Name = Name.special("<module>") + override fun dependencies(): List<ModuleInfo> = listOf(this) + } + val resolverForProject = JvmAnalyzerFacade.setupResolverForProject( + "Dokka", + projectContext, + listOf(module), + { ModuleContent(sourceFiles, GlobalSearchScope.allScope(environment.project)) }, + JvmPlatformParameters { module }, + CompilerEnvironment + ) + + val resolverForModule = resolverForProject.resolverForModule(module) + val resolveSession = resolverForModule.componentProvider.get<ResolveSession>() + val facade = DokkaResolutionFacade(environment.project, resolverForProject.descriptorForModule(module), resolverForModule) return processor(environment, facade, resolveSession) } @@ -125,3 +161,37 @@ public fun contentRootFromPath(path: String): ContentRoot { val file = File(path) return if (file.extension == "java") JavaSourceRoot(file) else KotlinSourceRoot(path) } + + +class DokkaResolutionFacade(override val project: Project, + override val moduleDescriptor: ModuleDescriptor, + val resolverForModule: ResolverForModule) : ResolutionFacade { + + override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext { + throw UnsupportedOperationException() + } + + override fun analyzeFullyAndGetResult(elements: Collection<KtElement>): AnalysisResult { + throw UnsupportedOperationException() + } + + override fun <T : Any> getFrontendService(element: PsiElement, serviceClass: Class<T>): T { + throw UnsupportedOperationException() + } + + override fun <T : Any> getFrontendService(serviceClass: Class<T>): T { + return resolverForModule.componentProvider.getService(serviceClass) + } + + override fun <T : Any> getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class<T>): T { + throw UnsupportedOperationException() + } + + override fun <T : Any> getIdeService(serviceClass: Class<T>): T { + throw UnsupportedOperationException() + } + + override fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor { + throw UnsupportedOperationException() + } +} diff --git a/src/Analysis/CompilerAPI.kt b/src/Analysis/CompilerAPI.kt deleted file mode 100644 index 5ab2037b..00000000 --- a/src/Analysis/CompilerAPI.kt +++ /dev/null @@ -1,28 +0,0 @@ -package org.jetbrains.dokka - -import com.intellij.psi.search.GlobalSearchScope -import org.jetbrains.kotlin.analyzer.ModuleContent -import org.jetbrains.kotlin.analyzer.ModuleInfo -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.context.ProjectContext -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade -import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters -import org.jetbrains.kotlin.resolve.lazy.ResolveSession - -fun KotlinCoreEnvironment.analyze(): ResolveSession { - val projectContext = ProjectContext(project) - val sourceFiles = getSourceFiles() - - val module = object : ModuleInfo { - override val name: Name = Name.special("<module>") - override fun dependencies(): List<ModuleInfo> = listOf(this) - } - val resolverForProject = JvmAnalyzerFacade.setupResolverForProject( - projectContext, - listOf(module), - { ModuleContent(sourceFiles, GlobalSearchScope.allScope(project)) }, - JvmPlatformParameters { module } - ) - return resolverForProject.resolverForModule(module).lazyResolveSession -} diff --git a/src/Formats/FormatService.kt b/src/Formats/FormatService.kt index 93470a4c..7e66a6b7 100644 --- a/src/Formats/FormatService.kt +++ b/src/Formats/FormatService.kt @@ -17,4 +17,4 @@ public interface FormatService { } /** Format content to [String] using specified [location] */ -fun FormatService.format(location: Location, nodes: Iterable<DocumentationNode>): String = StringBuilder { appendNodes(location, this, nodes) }.toString() +fun FormatService.format(location: Location, nodes: Iterable<DocumentationNode>): String = StringBuilder().apply { appendNodes(location, this, nodes) }.toString() diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt index 5dcd432b..e810ef7f 100644 --- a/src/Formats/HtmlFormatService.kt +++ b/src/Formats/HtmlFormatService.kt @@ -114,13 +114,13 @@ public open class HtmlFormatService @Inject constructor(@Named("folders") locati override fun appendNodes(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) { templateService.appendHeader(to, getPageTitle(nodes)) - super<StructuredFormatService>.appendNodes(location, to, nodes) + super.appendNodes(location, to, nodes) templateService.appendFooter(to) } override fun appendOutline(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) { templateService.appendHeader(to, "Module Contents") - super<OutlineFormatService>.appendOutline(location, to, nodes) + super.appendOutline(location, to, nodes) templateService.appendFooter(to) } @@ -146,16 +146,16 @@ public open class HtmlFormatService @Inject constructor(@Named("folders") locati fun getPageTitle(nodes: Iterable<DocumentationNode>): String? { val breakdownByLocation = nodes.groupBy { node -> formatPageTitle(node) } - return breakdownByLocation.keySet().singleOrNull() + return breakdownByLocation.keys.singleOrNull() } fun formatPageTitle(node: DocumentationNode): String { val path = node.path - if (path.size() == 1) { + if (path.size == 1) { return path.first().name } - val qualifiedName = path.drop(1).map { it.name }.filter { it.length() > 0 }.join(".") - if (qualifiedName.length() == 0 && path.size() == 2) { + val qualifiedName = node.qualifiedName() + if (qualifiedName.length == 0 && path.size == 2) { return path.first().name + " / root package" } return path.first().name + " / " + qualifiedName diff --git a/src/Formats/JekyllFormatService.kt b/src/Formats/JekyllFormatService.kt index 113f229f..75684ac2 100644 --- a/src/Formats/JekyllFormatService.kt +++ b/src/Formats/JekyllFormatService.kt @@ -11,7 +11,7 @@ public open class JekyllFormatService @Inject constructor(locationService: Locat appendFrontMatter(nodes, to) to.appendln("---") to.appendln("") - super<MarkdownFormatService>.appendNodes(location, to, nodes) + super.appendNodes(location, to, nodes) } protected open fun appendFrontMatter(nodes: Iterable<DocumentationNode>, to: StringBuilder) { diff --git a/src/Formats/KotlinWebsiteFormatService.kt b/src/Formats/KotlinWebsiteFormatService.kt index 8fbebaae..25491cb3 100644 --- a/src/Formats/KotlinWebsiteFormatService.kt +++ b/src/Formats/KotlinWebsiteFormatService.kt @@ -5,6 +5,7 @@ import com.google.inject.Inject public class KotlinWebsiteFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : JekyllFormatService(locationService, signatureGenerator) { + private var needHardLineBreaks = false override fun appendFrontMatter(nodes: Iterable<DocumentationNode>, to: StringBuilder) { super.appendFrontMatter(nodes, to) @@ -23,16 +24,27 @@ public class KotlinWebsiteFormatService @Inject constructor(locationService: Loc return "" } - override public fun formatCode(code: String): String = if (code.length() > 0) "<code>$code</code>" else "" + override public fun formatCode(code: String): String = if (code.length > 0) "<code>$code</code>" else "" override fun formatStrikethrough(text: String): String = "<s>$text</s>" - override fun appendAsSignature(to: StringBuilder, block: () -> Unit) { - val oldLength = to.length() - block() - if (to.length() > oldLength) { - to.append("<br/>") // since we've used HTML to format the signature, add an HTML line break following it + override fun appendAsSignature(to: StringBuilder, node: ContentNode, block: () -> Unit) { + val contentLength = node.textLength + if (contentLength == 0) return + to.append("<div class=\"signature\">") + needHardLineBreaks = contentLength >= 62 + try { + block() + } finally { + needHardLineBreaks = false } + to.append("</div>") + } + + override fun appendAsOverloadGroup(to: StringBuilder, block: () -> Unit) { + to.append("<div class=\"overload-group\">\n") + block() + to.append("</div>\n") } override fun formatLink(text: String, href: String): String { @@ -91,8 +103,19 @@ public class KotlinWebsiteFormatService @Inject constructor(locationService: Loc return "<span class=\"${identifierClassName(kind)}\">${formatText(text)}</span>" } + override fun formatSoftLineBreak(): String = if (needHardLineBreaks) + "<br/>" + else + "" + + override fun formatIndentedSoftLineBreak(): String = if (needHardLineBreaks) + "<br/> " + else + "" + private fun identifierClassName(kind: IdentifierKind) = when(kind) { IdentifierKind.ParameterName -> "parameterName" + IdentifierKind.SummarizedTypeName -> "summarizedTypeName" else -> "identifier" } } diff --git a/src/Formats/OutlineService.kt b/src/Formats/OutlineService.kt index 6c7e882e..6626cf51 100644 --- a/src/Formats/OutlineService.kt +++ b/src/Formats/OutlineService.kt @@ -16,7 +16,7 @@ public interface OutlineFormatService { for (node in nodes) { appendOutlineHeader(location, node, to) if (node.members.any()) { - val sortedMembers = node.members.sortBy { it.name } + val sortedMembers = node.members.sortedBy { it.name } appendOutlineLevel(to) { appendOutline(location, to, sortedMembers) } @@ -25,5 +25,5 @@ public interface OutlineFormatService { } fun formatOutline(location: Location, nodes: Iterable<DocumentationNode>): String = - StringBuilder { appendOutline(location, this, nodes) }.toString() + StringBuilder().apply { appendOutline(location, this, nodes) }.toString() } diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt index 1c2e5338..41ffc61d 100644 --- a/src/Formats/StructuredFormatService.kt +++ b/src/Formats/StructuredFormatService.kt @@ -1,62 +1,66 @@ package org.jetbrains.dokka -import java.util.LinkedHashMap import org.jetbrains.dokka.LanguageService.RenderMode +import java.util.* -public data class FormatLink(val text: String, val href: String) +data class FormatLink(val text: String, val href: String) enum class ListKind { Ordered, Unordered } -public abstract class StructuredFormatService(locationService: LocationService, +abstract class StructuredFormatService(locationService: LocationService, val languageService: LanguageService, override val extension: String) : FormatService { val locationService: LocationService = locationService.withExtension(extension) - abstract public fun appendBlockCode(to: StringBuilder, line: String, language: String) - abstract public fun appendHeader(to: StringBuilder, text: String, level: Int = 1) - abstract public fun appendParagraph(to: StringBuilder, text: String) - abstract public fun appendLine(to: StringBuilder, text: String) - public abstract fun appendLine(to: StringBuilder) - public abstract fun appendAnchor(to: StringBuilder, anchor: String) - - public abstract fun appendTable(to: StringBuilder, body: () -> Unit) - public abstract fun appendTableHeader(to: StringBuilder, body: () -> Unit) - public abstract fun appendTableBody(to: StringBuilder, body: () -> Unit) - public abstract fun appendTableRow(to: StringBuilder, body: () -> Unit) - public abstract fun appendTableCell(to: StringBuilder, body: () -> Unit) - - public abstract fun formatText(text: String): String - public abstract fun formatSymbol(text: String): String - public abstract fun formatKeyword(text: String): String - public abstract fun formatIdentifier(text: String, kind: IdentifierKind): String - public fun formatEntity(text: String): String = text - public abstract fun formatLink(text: String, href: String): String - public open fun formatLink(link: FormatLink): String = formatLink(formatText(link.text), link.href) - public abstract fun formatStrong(text: String): String - public abstract fun formatStrikethrough(text: String): String - public abstract fun formatEmphasis(text: String): String - public abstract fun formatCode(code: String): String - public abstract fun formatUnorderedList(text: String): String - public abstract fun formatOrderedList(text: String): String - public abstract fun formatListItem(text: String, kind: ListKind): String - public abstract fun formatBreadcrumbs(items: Iterable<FormatLink>): String - public abstract fun formatNonBreakingSpace(): String + abstract fun appendBlockCode(to: StringBuilder, line: String, language: String) + abstract fun appendHeader(to: StringBuilder, text: String, level: Int = 1) + abstract fun appendParagraph(to: StringBuilder, text: String) + abstract fun appendLine(to: StringBuilder, text: String) + abstract fun appendLine(to: StringBuilder) + abstract fun appendAnchor(to: StringBuilder, anchor: String) + + abstract fun appendTable(to: StringBuilder, body: () -> Unit) + abstract fun appendTableHeader(to: StringBuilder, body: () -> Unit) + abstract fun appendTableBody(to: StringBuilder, body: () -> Unit) + abstract fun appendTableRow(to: StringBuilder, body: () -> Unit) + abstract fun appendTableCell(to: StringBuilder, body: () -> Unit) + + abstract fun formatText(text: String): String + abstract fun formatSymbol(text: String): String + abstract fun formatKeyword(text: String): String + abstract fun formatIdentifier(text: String, kind: IdentifierKind): String + fun formatEntity(text: String): String = text + abstract fun formatLink(text: String, href: String): String + open fun formatLink(link: FormatLink): String = formatLink(formatText(link.text), link.href) + abstract fun formatStrong(text: String): String + abstract fun formatStrikethrough(text: String): String + abstract fun formatEmphasis(text: String): String + abstract fun formatCode(code: String): String + abstract fun formatUnorderedList(text: String): String + abstract fun formatOrderedList(text: String): String + abstract fun formatListItem(text: String, kind: ListKind): String + abstract fun formatBreadcrumbs(items: Iterable<FormatLink>): String + abstract fun formatNonBreakingSpace(): String + open fun formatSoftLineBreak(): String = "" + open fun formatIndentedSoftLineBreak(): String = "" open fun formatText(location: Location, nodes: Iterable<ContentNode>, listKind: ListKind = ListKind.Unordered): String { - return nodes.map { formatText(location, it, listKind) }.join("") + return nodes.map { formatText(location, it, listKind) }.joinToString("") } open fun formatText(location: Location, content: ContentNode, listKind: ListKind = ListKind.Unordered): String { - return StringBuilder { + return StringBuilder().apply { when (content) { is ContentText -> append(formatText(content.text)) is ContentSymbol -> append(formatSymbol(content.text)) is ContentKeyword -> append(formatKeyword(content.text)) is ContentIdentifier -> append(formatIdentifier(content.text, content.kind)) is ContentNonBreakingSpace -> append(formatNonBreakingSpace()) + is ContentSoftLineBreak -> append(formatSoftLineBreak()) + is ContentIndentedSoftLineBreak -> append(formatIndentedSoftLineBreak()) is ContentEntity -> append(formatEntity(content.text)) is ContentStrong -> append(formatStrong(formatText(location, content.children))) is ContentStrikethrough -> append(formatStrikethrough(formatText(location, content.children))) @@ -92,9 +96,9 @@ public abstract class StructuredFormatService(locationService: LocationService, }.toString() } - open public fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension) + open fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension) - open public fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink { + open fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink { return FormatLink(to.name, locationService.relativePathToLocation(from, to)) } @@ -110,41 +114,47 @@ public abstract class StructuredFormatService(locationService: LocationService, val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content } for ((summary, items) in breakdownBySummary) { - items.forEach { - appendAsSignature(to) { - to.append(formatCode(formatText(location, languageService.render(it)))) - it.appendSourceLink(to) + appendAsOverloadGroup(to) { + items.forEach { + val rendered = languageService.render(it) + appendAsSignature(to, rendered) { + to.append(formatCode(formatText(location, rendered))) + it.appendSourceLink(to) + } + it.appendOverrides(to) + it.appendDeprecation(location, to) } - it.appendOverrides(to) - it.appendDeprecation(location, to) - } - // All items have exactly the same documentation, so we can use any item to render it - val item = items.first() - item.details(DocumentationNode.Kind.OverloadGroupNote).forEach { - to.append(formatText(location, it.content)) + // All items have exactly the same documentation, so we can use any item to render it + val item = items.first() + item.details(DocumentationNode.Kind.OverloadGroupNote).forEach { + to.append(formatText(location, it.content)) + } + to.append(formatText(location, item.content.summary)) + appendDescription(location, to, item) + appendLine(to) + appendLine(to) } - to.append(formatText(location, item.content.summary)) - appendDescription(location, to, item) - appendLine(to) - appendLine(to) } } private fun DocumentationNode.isModuleOrPackage(): Boolean = kind == DocumentationNode.Kind.Module || kind == DocumentationNode.Kind.Package - protected open fun appendAsSignature(to: StringBuilder, block: () -> Unit) { + protected open fun appendAsSignature(to: StringBuilder, node: ContentNode, block: () -> Unit) { + block() + } + + protected open fun appendAsOverloadGroup(to: StringBuilder, block: () -> Unit) { block() } fun appendDescription(location: Location, to: StringBuilder, node: DocumentationNode) { if (node.content.description != ContentEmpty) { - appendHeader(to, ContentTags.Description, 3) appendLine(to, formatText(location, node.content.description)) appendLine(to) } node.content.getSectionsWithSubjects().forEach { - appendSectionWithSubject(it.getKey(), location, it.getValue(), to) + appendSectionWithSubject(it.key, location, it.value, to) } for (section in node.content.sections.filter { it.subjectName == null }) { @@ -221,11 +231,11 @@ public abstract class StructuredFormatService(locationService: LocationService, } } - private fun StructuredFormatService.appendSection(location: Location, caption: String, nodes: List<DocumentationNode>, node: DocumentationNode, to: StringBuilder) { + private fun appendSection(location: Location, caption: String, nodes: List<DocumentationNode>, node: DocumentationNode, to: StringBuilder) { if (nodes.any()) { appendHeader(to, caption, 3) - val children = nodes.sortBy { it.name } + val children = nodes.sortedBy { it.name } val membersMap = children.groupBy { link(node, it) } appendTable(to) { @@ -238,24 +248,7 @@ public abstract class StructuredFormatService(locationService: LocationService, appendTableCell(to) { val breakdownBySummary = members.groupBy { formatText(location, it.summary) } for ((summary, items) in breakdownBySummary) { - val signatureTexts = items map { signature -> - val signatureText = languageService.render(signature, RenderMode.SUMMARY) - if (signatureText is ContentBlock && signatureText.isEmpty()) { - "" - } else { - val signatureAsCode = ContentCode() - signatureAsCode.append(signatureText) - formatText(location, signatureAsCode) - } - } - signatureTexts.subList(0, signatureTexts.size()-1).forEach { - appendAsSignature(to) { - appendLine(to, it) - } - } - appendAsSignature(to) { - to.append(signatureTexts.last()) - } + appendSummarySignatures(items, location, to) if (!summary.isEmpty()) { to.append(summary) } @@ -268,6 +261,35 @@ public abstract class StructuredFormatService(locationService: LocationService, } } + private fun appendSummarySignatures(items: List<DocumentationNode>, location: Location, to: StringBuilder) { + val summarySignature = languageService.summarizeSignatures(items) + if (summarySignature != null) { + appendAsSignature(to, summarySignature) { + appendLine(to, summarySignature.signatureToText(location)) + } + return + } + val renderedSignatures = items.map { languageService.render(it, RenderMode.SUMMARY) } + renderedSignatures.subList(0, renderedSignatures.size - 1).forEach { + appendAsSignature(to, it) { + appendLine(to, it.signatureToText(location)) + } + } + appendAsSignature(to, renderedSignatures.last()) { + to.append(renderedSignatures.last().signatureToText(location)) + } + } + + private fun ContentNode.signatureToText(location: Location): String { + return if (this is ContentBlock && this.isEmpty()) { + "" + } else { + val signatureAsCode = ContentCode() + signatureAsCode.append(this) + formatText(location, signatureAsCode) + } + } + override fun appendNodes(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) { val breakdownByLocation = nodes.groupBy { node -> formatBreadcrumbs(node.path.filterNot { it.name.isEmpty() }.map { link(node, it) }) @@ -295,12 +317,14 @@ public abstract class StructuredFormatService(locationService: LocationService, DocumentationNode.Kind.AnnotationClass) }, node, to) appendSection(location, "Extensions for External Classes", node.members(DocumentationNode.Kind.ExternalClass), node, to) + appendSection(location, "Enum Values", node.members(DocumentationNode.Kind.EnumItem), node, to) appendSection(location, "Constructors", node.members(DocumentationNode.Kind.Constructor), node, to) appendSection(location, "Properties", node.members(DocumentationNode.Kind.Property), node, to) + appendSection(location, "Inherited Properties", node.inheritedMembers(DocumentationNode.Kind.Property), node, to) appendSection(location, "Functions", node.members(DocumentationNode.Kind.Function), node, to) + appendSection(location, "Inherited Functions", node.inheritedMembers(DocumentationNode.Kind.Function), node, to) appendSection(location, "Companion Object Properties", node.members(DocumentationNode.Kind.CompanionObjectProperty), node, to) appendSection(location, "Companion Object Functions", node.members(DocumentationNode.Kind.CompanionObjectFunction), node, to) - appendSection(location, "Enum Values", node.members(DocumentationNode.Kind.EnumItem), node, to) appendSection(location, "Other members", node.members.filter { it.kind !in setOf( DocumentationNode.Kind.Class, @@ -318,14 +342,32 @@ public abstract class StructuredFormatService(locationService: LocationService, DocumentationNode.Kind.EnumItem ) }, node, to) - appendSection(location, "Extension Properties", node.extensions.filter { it.kind == DocumentationNode.Kind.Property }, node, to) - appendSection(location, "Extension Functions", node.extensions.filter { it.kind == DocumentationNode.Kind.Function }, node, to) - appendSection(location, "Companion Object Extension Properties", node.extensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectProperty }, node, to) - appendSection(location, "Companion Object Extension Functions", node.extensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectFunction }, node, to) + + val allExtensions = collectAllExtensions(node) + appendSection(location, "Extension Properties", allExtensions.filter { it.kind == DocumentationNode.Kind.Property }, node, to) + appendSection(location, "Extension Functions", allExtensions.filter { it.kind == DocumentationNode.Kind.Function }, node, to) + appendSection(location, "Companion Object Extension Properties", allExtensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectProperty }, node, to) + appendSection(location, "Companion Object Extension Functions", allExtensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectFunction }, node, to) appendSection(location, "Inheritors", node.inheritors.filter { it.kind != DocumentationNode.Kind.EnumItem }, node, to) appendSection(location, "Links", node.links, node, to) } } + + private fun collectAllExtensions(node: DocumentationNode): Collection<DocumentationNode> { + val result = LinkedHashSet<DocumentationNode>() + val visited = hashSetOf<DocumentationNode>() + + fun collect(node: DocumentationNode) { + if (!visited.add(node)) return + result.addAll(node.extensions) + node.references(DocumentationReference.Kind.Superclass).forEach { collect(it.to) } + } + + collect(node) + + return result + + } }
\ No newline at end of file diff --git a/src/Generation/ConsoleGenerator.kt b/src/Generation/ConsoleGenerator.kt index 2f2daa55..803a16e4 100644 --- a/src/Generation/ConsoleGenerator.kt +++ b/src/Generation/ConsoleGenerator.kt @@ -20,7 +20,7 @@ public class ConsoleGenerator(val signatureGenerator: LanguageService, val locat } public fun generateMembers(node: DocumentationNode, indent: String = "") { - val items = node.members.sortBy { it.name } + val items = node.members.sortedBy { it.name } for (child in items) generate(child, indent + IndentStep) } diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaDocumentationBuilder.kt index 9717c1a6..88c13d38 100644 --- a/src/Java/JavaDocumentationBuilder.kt +++ b/src/Java/JavaDocumentationBuilder.kt @@ -229,9 +229,9 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, else -> false } - fun DocumentationNode.appendChildren<T>(elements: Array<T>, - kind: DocumentationReference.Kind = DocumentationReference.Kind.Member, - buildFn: T.() -> DocumentationNode) { + fun <T : Any> DocumentationNode.appendChildren(elements: Array<T>, + kind: DocumentationReference.Kind = DocumentationReference.Kind.Member, + buildFn: T.() -> DocumentationNode) { elements.forEach { if (!skipElement(it)) { append(it.buildFn(), kind) @@ -248,10 +248,10 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, private fun hasSuppressTag(element: Any) = element is PsiDocCommentOwner && element.docComment?.let { it.findTagByName("suppress") != null } ?: false - fun DocumentationNode.appendMembers<T>(elements: Array<T>, buildFn: T.() -> DocumentationNode) = + fun <T : Any> DocumentationNode.appendMembers(elements: Array<T>, buildFn: T.() -> DocumentationNode) = appendChildren(elements, DocumentationReference.Kind.Member, buildFn) - fun DocumentationNode.appendDetails<T>(elements: Array<T>, buildFn: T.() -> DocumentationNode) = + fun <T : Any> DocumentationNode.appendDetails(elements: Array<T>, buildFn: T.() -> DocumentationNode) = appendChildren(elements, DocumentationReference.Kind.Detail, buildFn) fun PsiClass.build(): DocumentationNode { diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt index 9ce81cee..c981eb42 100644 --- a/src/Kotlin/ContentBuilder.kt +++ b/src/Kotlin/ContentBuilder.kt @@ -1,14 +1,19 @@ package org.jetbrains.dokka -import java.util.ArrayDeque -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.scopes.* -import org.jetbrains.kotlin.name.* +import org.intellij.markdown.MarkdownElementTypes +import org.intellij.markdown.MarkdownTokenTypes +import org.intellij.markdown.html.entities.EntityConverter +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.kdoc.getResolutionScope -import org.intellij.markdown.* -import org.jetbrains.kotlin.psi.JetDeclarationWithBody -import org.jetbrains.kotlin.psi.JetBlockExpression +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtBlockExpression +import org.jetbrains.kotlin.psi.KtDeclarationWithBody +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.scopes.KtScope +import org.jetbrains.kotlin.resolve.scopes.utils.asJetScope +import java.util.* public fun buildContent(tree: MarkdownNode, linkResolver: (String) -> ContentBlock): MutableContent { val result = MutableContent() @@ -43,7 +48,8 @@ public fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver MarkdownElementTypes.EMPH -> appendNodeWithChildren(ContentEmphasis()) MarkdownElementTypes.STRONG -> appendNodeWithChildren(ContentStrong()) MarkdownElementTypes.CODE_SPAN -> appendNodeWithChildren(ContentCode()) - MarkdownElementTypes.CODE_BLOCK -> appendNodeWithChildren(ContentBlockCode()) + MarkdownElementTypes.CODE_BLOCK, + MarkdownElementTypes.CODE_FENCE -> appendNodeWithChildren(ContentBlockCode()) MarkdownElementTypes.PARAGRAPH -> appendNodeWithChildren(ContentParagraph()) MarkdownElementTypes.INLINE_LINK -> { @@ -84,11 +90,24 @@ public fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver parent.append(block) } - MarkdownTokenTypes.HTML_ENTITY -> { - parent.append(ContentEntity(node.text)) + MarkdownTokenTypes.TEXT -> { + fun createEntityOrText(text: String): ContentNode { + if (text == "&" || text == """ || text == "<" || text == ">") { + return ContentEntity(text) + } + if (text == "&") { + return ContentEntity("&") + } + val decodedText = EntityConverter.replaceEntities(text, true, true) + if (decodedText != text) { + return ContentEntity(text) + } + return ContentText(text) + } + + parent.append(createEntityOrText(node.text)) } - MarkdownTokenTypes.TEXT, MarkdownTokenTypes.COLON, MarkdownTokenTypes.DOUBLE_QUOTE, MarkdownTokenTypes.LT, @@ -96,7 +115,8 @@ public fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver MarkdownTokenTypes.LPAREN, MarkdownTokenTypes.RPAREN, MarkdownTokenTypes.LBRACKET, - MarkdownTokenTypes.RBRACKET -> { + MarkdownTokenTypes.RBRACKET, + MarkdownTokenTypes.CODE_FENCE_CONTENT -> { parent.append(ContentText(node.text)) } else -> { @@ -120,8 +140,8 @@ fun DocumentationBuilder.functionBody(descriptor: DeclarationDescriptor, functio logger.warn("Missing function name in @sample in ${descriptor.signature()}") return ContentBlockCode().let() { it.append(ContentText("Missing function name in @sample")); it } } - val scope = getResolutionScope(resolutionFacade, descriptor) - val rootPackage = session.getModuleDescriptor().getPackage(FqName.ROOT) + val scope = getResolutionScope(resolutionFacade, descriptor).asJetScope() + val rootPackage = resolutionFacade.moduleDescriptor.getPackage(FqName.ROOT) val rootScope = rootPackage.memberScope val symbol = resolveInScope(functionName, scope) ?: resolveInScope(functionName, rootScope) if (symbol == null) { @@ -135,23 +155,23 @@ fun DocumentationBuilder.functionBody(descriptor: DeclarationDescriptor, functio } val text = when (psiElement) { - is JetDeclarationWithBody -> ContentBlockCode().let() { + is KtDeclarationWithBody -> ContentBlockCode().let() { val bodyExpression = psiElement.bodyExpression when (bodyExpression) { - is JetBlockExpression -> bodyExpression.text.removeSurrounding("{", "}") + is KtBlockExpression -> bodyExpression.text.removeSurrounding("{", "}") else -> bodyExpression!!.text } } else -> psiElement.text } - val lines = text.trimEnd().split("\n".toRegex()).toTypedArray().filterNot { it.length() == 0 } + val lines = text.trimEnd().split("\n".toRegex()).toTypedArray().filterNot { it.length == 0 } val indent = lines.map { it.takeWhile { it.isWhitespace() }.count() }.min() ?: 0 - val finalText = lines.map { it.drop(indent) }.join("\n") + val finalText = lines.map { it.drop(indent) }.joinToString("\n") return ContentBlockCode("kotlin").let() { it.append(ContentText(finalText)); it } } -private fun DocumentationBuilder.resolveInScope(functionName: String, scope: JetScope): DeclarationDescriptor? { +private fun DocumentationBuilder.resolveInScope(functionName: String, scope: KtScope): DeclarationDescriptor? { var currentScope = scope val parts = functionName.split('.') @@ -169,7 +189,7 @@ private fun DocumentationBuilder.resolveInScope(functionName: String, scope: Jet currentScope = if (partSymbol is ClassDescriptor) partSymbol.defaultType.memberScope else - getResolutionScope(resolutionFacade, partSymbol) + getResolutionScope(resolutionFacade, partSymbol).asJetScope() symbol = partSymbol } diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index 6bfeb360..2d3105ac 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -8,23 +8,28 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.kdoc.KDocFinder import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag -import org.jetbrains.kotlin.lexer.JetSingleValueToken +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.JetParameter +import org.jetbrains.kotlin.psi.KtModifierListOwner +import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.ConstantValue +import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.isDocumentedAnnotation import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.JetType +import org.jetbrains.kotlin.types.KtType import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.expressions.OperatorConventions public data class DocumentationOptions(val includeNonPublic: Boolean = false, val reportUndocumented: Boolean = true, @@ -33,8 +38,8 @@ public data class DocumentationOptions(val includeNonPublic: Boolean = false, val sourceLinks: List<SourceLinkDefinition>) private fun isSamePackage(descriptor1: DeclarationDescriptor, descriptor2: DeclarationDescriptor): Boolean { - val package1 = DescriptorUtils.getParentOfType(descriptor1, javaClass<PackageFragmentDescriptor>()) - val package2 = DescriptorUtils.getParentOfType(descriptor2, javaClass<PackageFragmentDescriptor>()) + val package1 = DescriptorUtils.getParentOfType(descriptor1, PackageFragmentDescriptor::class.java) + val package2 = DescriptorUtils.getParentOfType(descriptor2, PackageFragmentDescriptor::class.java) return package1 != null && package2 != null && package1.fqName == package2.fqName } @@ -47,6 +52,10 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, val boringBuiltinClasses = setOf( "kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean", "kotlin.Float", "kotlin.Double", "kotlin.String", "kotlin.Array", "kotlin.Any") + 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) fun parseDocumentation(descriptor: DeclarationDescriptor): Content { val kdoc = KDocFinder.findKDoc(descriptor) ?: findStdlibKDoc(descriptor) @@ -101,9 +110,10 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, deepestDescriptor = deepestDescriptor.overriddenDescriptors.first() } if (DescriptorUtils.getFqName(deepestDescriptor.containingDeclaration).asString() == "kotlin.Any") { - val anyClassDescriptors = session.getTopLevelClassDescriptors(FqName.fromSegments(listOf("kotlin", "Any"))) + val anyClassDescriptors = session.getTopLevelClassDescriptors(FqName.fromSegments(listOf("kotlin", "Any")), + NoLookupLocation.UNSORTED) anyClassDescriptors.forEach { - val anyMethod = it.getMemberScope(listOf()).getFunctions(descriptor.name).single() + val anyMethod = it.getMemberScope(listOf()).getFunctions(descriptor.name, NoLookupLocation.UNSORTED).single() val kdoc = KDocFinder.findKDoc(anyMethod) if (kdoc != null) { return kdoc @@ -115,7 +125,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any { - DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.deprecated" + DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated" } || (this is ConstructorDescriptor && containingDeclaration.isDeprecated()) fun DeclarationDescriptor.signature(): String = when(this) { @@ -142,13 +152,13 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, if (extensionReceiver != null) { params.add(0, extensionReceiver.type) } - return "(" + params.map { it.signature() }.join() + ")" + return "(" + params.map { it.signature() }.joinToString() + ")" } - fun JetType.signature(): String { + fun KtType.signature(): String { val declarationDescriptor = constructor.declarationDescriptor ?: return "<null>" val typeName = DescriptorUtils.getFqName(declarationDescriptor).asString() - if (typeName == "Array" && arguments.size() == 1) { + if (typeName == "Array" && arguments.size == 1) { return "Array<" + arguments.first().type.signature() + ">" } return typeName @@ -203,12 +213,12 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return symbol } - fun KDocSection.getTags(): Array<KDocTag> = PsiTreeUtil.getChildrenOfType(this, javaClass<KDocTag>()) ?: arrayOf() + fun KDocSection.getTags(): Array<KDocTag> = PsiTreeUtil.getChildrenOfType(this, KDocTag::class.java) ?: arrayOf() private fun MutableContent.addTagToSeeAlso(descriptor: DeclarationDescriptor, seeTag: KDocTag) { val subjectName = seeTag.getSubjectName() if (subjectName != null) { - val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) + val seeSection = findSectionByTag("See Also") ?: addSection("See Also", null) val link = resolveContentLink(descriptor, subjectName) link.append(ContentText(subjectName)) val para = ContentParagraph() @@ -217,8 +227,8 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } - fun link(node: DocumentationNode, descriptor: DeclarationDescriptor) { - refGraph.link(node, descriptor.signature(), DocumentationReference.Kind.Link) + fun link(node: DocumentationNode, descriptor: DeclarationDescriptor, kind: DocumentationReference.Kind) { + refGraph.link(node, descriptor.signature(), kind) } fun link(fromDescriptor: DeclarationDescriptor?, toDescriptor: DeclarationDescriptor?, kind: DocumentationReference.Kind) { @@ -231,7 +241,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, refGraph.register(descriptor.signature(), node) } - fun DocumentationNode<T>(descriptor: T, kind: Kind): DocumentationNode where T : DeclarationDescriptor, T : Named { + fun <T> DocumentationNode(descriptor: T, kind: Kind): DocumentationNode where T : DeclarationDescriptor, T : Named { val doc = parseDocumentation(descriptor) val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor) return node @@ -255,7 +265,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, modality = Modality.FINAL } } - val modifier = modality.name().toLowerCase() + val modifier = modality.name.toLowerCase() appendTextNode(modifier, DocumentationNode.Kind.Modifier) } @@ -269,12 +279,14 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, for (superType in superTypes) { if (!ignoreSupertype(superType)) { appendType(superType, DocumentationNode.Kind.Supertype) - link(superType?.constructor?.declarationDescriptor, descriptor, DocumentationReference.Kind.Inheritor) + val superclass = superType?.constructor?.declarationDescriptor + link(superclass, descriptor, DocumentationReference.Kind.Inheritor) + link(descriptor, superclass, DocumentationReference.Kind.Superclass) } } } - private fun ignoreSupertype(superType: JetType): Boolean { + private fun ignoreSupertype(superType: KtType): Boolean { val superClass = superType.constructor.declarationDescriptor as? ClassDescriptor if (superClass != null) { val fqName = DescriptorUtils.getFqNameSafe(superClass).asString() @@ -284,10 +296,15 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun DocumentationNode.appendProjection(projection: TypeProjection, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type) { - appendType(projection.type, kind, projection.projectionKind.label) + if (projection.isStarProjection) { + appendTextNode("*", Kind.Type) + } + else { + appendType(projection.type, kind, projection.projectionKind.label) + } } - fun DocumentationNode.appendType(jetType: JetType?, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type, prefix: String = "") { + fun DocumentationNode.appendType(jetType: KtType?, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type, prefix: String = "") { if (jetType == null) return val classifierDescriptor = jetType.constructor.declarationDescriptor @@ -311,28 +328,53 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, if (jetType.isMarkedNullable) { node.appendTextNode("?", Kind.NullabilityModifier) } - if (classifierDescriptor != null && !classifierDescriptor.isBoringBuiltinClass()) { - link(node, classifierDescriptor) + if (classifierDescriptor != null) { + link(node, classifierDescriptor, + if (classifierDescriptor.isBoringBuiltinClass()) DocumentationReference.Kind.HiddenLink else DocumentationReference.Kind.Link) } append(node, DocumentationReference.Kind.Detail) - for (typeArgument in jetType.arguments) + node.appendAnnotations(jetType) + for (typeArgument in jetType.arguments) { node.appendProjection(typeArgument) + } } fun ClassifierDescriptor.isBoringBuiltinClass(): Boolean = DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses fun DocumentationNode.appendAnnotations(annotated: Annotated) { - annotated.annotations.forEach { + annotated.annotations.filter { it.isDocumented() }.forEach { val annotationNode = it.build() if (annotationNode != null) { append(annotationNode, - if (annotationNode.name == "deprecated") DocumentationReference.Kind.Deprecation else DocumentationReference.Kind.Annotation) + if (annotationNode.isDeprecation()) DocumentationReference.Kind.Deprecation else DocumentationReference.Kind.Annotation) + } + } + } + + private fun AnnotationDescriptor.isDocumented(): Boolean { + if (source.getPsi() != null && mustBeDocumented()) return true + val annotationClassName = type.constructor.declarationDescriptor?.fqNameSafe?.asString() + return annotationClassName == "kotlin.Extension" + } + + fun AnnotationDescriptor.mustBeDocumented(): Boolean { + val annotationClass = type.constructor.declarationDescriptor as? Annotated ?: return false + return annotationClass.isDocumentedAnnotation() + } + + fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { + val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return + KtTokens.MODIFIER_KEYWORDS_ARRAY.filter { it !in knownModifiers }.forEach { + if (psi.hasModifier(it)) { + appendTextNode(it.value, Kind.Modifier) } } } + fun DocumentationNode.isDeprecation() = name == "Deprecated" || name == "deprecated" + fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) { appendSourceLink(sourceElement.getPsi(), options.sourceLinks) } @@ -364,8 +406,18 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } - fun DocumentationNode.appendChildren(descriptors: Iterable<DeclarationDescriptor>, kind: DocumentationReference.Kind) { - descriptors.forEach { descriptor -> appendChild(descriptor, kind) } + fun DocumentationNode.appendMembers(descriptors: Iterable<DeclarationDescriptor>) { + descriptors.forEach { descriptor -> + if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + val baseDescriptor = descriptor.overriddenDescriptors.firstOrNull() + if (baseDescriptor != null) { + link(this, baseDescriptor, DocumentationReference.Kind.InheritedMember) + } + } + else { + appendChild(descriptor, DocumentationReference.Kind.Member) + } + } } fun DocumentationNode.appendInPageChildren(descriptors: Iterable<DeclarationDescriptor>, kind: DocumentationReference.Kind) { @@ -381,7 +433,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, val extensionClassDescriptor = descriptor.getExtensionClassDescriptor() if (extensionClassDescriptor != null && !isSamePackage(descriptor, extensionClassDescriptor) && !ErrorUtils.isError(extensionClassDescriptor)) { - val fqName = DescriptorUtils.getFqNameFromTopLevelClass(extensionClassDescriptor) + val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor) return externalClassNodes.getOrPut(fqName, { val newNode = DocumentationNode(fqName.asString(), Content.Empty, Kind.ExternalClass) append(newNode, DocumentationReference.Kind.Member) @@ -436,26 +488,23 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, else -> Kind.Class } val node = DocumentationNode(this, kind) - if (isInner) { - node.appendTextNode("inner", Kind.Modifier) - } node.appendSupertypes(this) if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, DocumentationReference.Kind.Detail) val constructorsToDocument = if (getKind() == ClassKind.ENUM_CLASS) - constructors.filter { it.valueParameters.size() > 0 } + constructors.filter { it.valueParameters.size > 0 } else constructors - node.appendChildren(constructorsToDocument, DocumentationReference.Kind.Member) + node.appendMembers(constructorsToDocument) } val members = defaultType.memberScope.getAllDescriptors().filter { it != companionObjectDescriptor } - node.appendChildren(members, DocumentationReference.Kind.Member) + node.appendMembers(members) val companionObjectDescriptor = companionObjectDescriptor if (companionObjectDescriptor != null) { - node.appendChildren(companionObjectDescriptor.defaultType.memberScope.getAllDescriptors(), - DocumentationReference.Kind.Member) + node.appendMembers(companionObjectDescriptor.defaultType.memberScope.getAllDescriptors()) } node.appendAnnotations(this) + node.appendModifiers(this) node.appendSourceLink(source) register(this, node) return node @@ -498,8 +547,8 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, node.appendInPageChildren(valueParameters, DocumentationReference.Kind.Detail) node.appendType(returnType) node.appendAnnotations(this) + node.appendModifiers(this) node.appendSourceLink(source) - node.appendOperatorOverloadNote(this) overriddenDescriptors.forEach { addOverrideLink(it, this) @@ -520,64 +569,13 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } - fun DocumentationNode.appendOperatorOverloadNote(descriptor: FunctionDescriptor) { - val operatorName = descriptor.getImplementedOperator() - if (operatorName != null) { - val content = Content() - content.append(ContentText("Implements ")) - content.strong { - text("operator ") - code { - text(operatorName) - } - } - val noteNode = DocumentationNode("", content, DocumentationNode.Kind.OverloadGroupNote) - append(noteNode, DocumentationReference.Kind.Detail) - } - } - - fun FunctionDescriptor.getImplementedOperator(): String? { - var arity = valueParameters.size() - if (containingDeclaration is ClassDescriptor) { - arity++ - } - if (extensionReceiverParameter != null) { - arity++ - } - - val token = if (arity == 2) { - OperatorConventions.BINARY_OPERATION_NAMES.inverse()[name] ?: - OperatorConventions.ASSIGNMENT_OPERATIONS.inverse()[name] ?: - OperatorConventions.BOOLEAN_OPERATIONS.inverse()[name] - } else if (arity == 1) { - OperatorConventions.UNARY_OPERATION_NAMES.inverse()[name] - } - else null - - if (token is JetSingleValueToken) { - return token.value - } - - val name = name.asString() - if (arity == 2 && name == "contains") { - return "in" - } - if (arity >= 2 && (name == "get" || name == "set")) { - return "[]" - } - if (arity == 2 && name == "equals" && valueParameters.size() == 1 && - KotlinBuiltIns.isNullableAny(valueParameters.first().type)) { - return "==" - } - return null - } - fun PropertyDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, if (inCompanionObject()) Kind.CompanionObjectProperty else Kind.Property) node.appendInPageChildren(typeParameters, DocumentationReference.Kind.Detail) extensionReceiverParameter?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } node.appendType(returnType) node.appendAnnotations(this) + node.appendModifiers(this) node.appendSourceLink(source) if (isVar) { node.appendTextNode("var", DocumentationNode.Kind.Modifier) @@ -617,15 +615,9 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun ValueParameterDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, Kind.Parameter) - val varargType = varargElementType - if (varargType != null) { - node.appendTextNode("vararg", Kind.Annotation, DocumentationReference.Kind.Annotation) - node.appendType(varargType) - } else { - node.appendType(type) - } - if (hasDefaultValue()) { - val psi = source.getPsi() as? JetParameter + node.appendType(varargElementType ?: type) + if (declaresDefaultValue()) { + val psi = source.getPsi() as? KtParameter if (psi != null) { val defaultValueText = psi.defaultValue?.text if (defaultValueText != null) { @@ -634,6 +626,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } node.appendAnnotations(this) + node.appendModifiers(this) register(this, node) return node } @@ -647,11 +640,14 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, if (prefix != "") { node.appendTextNode(prefix, Kind.Modifier) } + if (isReified) { + node.appendTextNode("reified", Kind.Modifier) + } - val builtIns = KotlinBuiltIns.getInstance() for (constraint in upperBounds) { - if (constraint == builtIns.defaultBound) + if (KotlinBuiltIns.isDefaultBound(constraint)) { continue + } node.appendType(constraint, Kind.UpperBound) } @@ -683,7 +679,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return null } val node = DocumentationNode(annotationClass.name.asString(), Content.Empty, DocumentationNode.Kind.Annotation) - val arguments = allValueArguments.toList().sortBy { it.first.index } + val arguments = allValueArguments.toList().sortedBy { it.first.index } arguments.forEach { val valueNode = it.second.toDocumentationNode() if (valueNode != null) { @@ -695,6 +691,11 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return node } + fun CompileTimeConstant<Any?>.build(): DocumentationNode? = when (this) { + is TypedCompileTimeConstant -> constantValue.toDocumentationNode() + else -> null + } + fun ConstantValue<*>.toDocumentationNode(): DocumentationNode? = value?.let { value -> when (value) { is String -> diff --git a/src/Kotlin/KotlinLanguageService.kt b/src/Kotlin/KotlinLanguageService.kt index 75675c6f..3c4b974f 100644 --- a/src/Kotlin/KotlinLanguageService.kt +++ b/src/Kotlin/KotlinLanguageService.kt @@ -6,7 +6,7 @@ import org.jetbrains.dokka.LanguageService.RenderMode * Implements [LanguageService] and provides rendering of symbols in Kotlin language */ class KotlinLanguageService : LanguageService { - private val visibilityModifiers = setOf("public", "protected", "private") + private val fullOnlyModifiers = setOf("public", "protected", "private", "inline", "noinline", "crossinline", "reified") override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode { return content { @@ -21,9 +21,9 @@ class KotlinLanguageService : LanguageService { DocumentationNode.Kind.EnumItem, DocumentationNode.Kind.ExternalClass -> if (renderMode == RenderMode.FULL) identifier(node.name) - DocumentationNode.Kind.TypeParameter -> renderTypeParameter(node) + DocumentationNode.Kind.TypeParameter -> renderTypeParameter(node, renderMode) DocumentationNode.Kind.Type, - DocumentationNode.Kind.UpperBound -> renderType(node) + DocumentationNode.Kind.UpperBound -> renderType(node, renderMode) DocumentationNode.Kind.Modifier -> renderModifier(node) DocumentationNode.Kind.Constructor, @@ -43,6 +43,77 @@ class KotlinLanguageService : LanguageService { } } + override fun summarizeSignatures(nodes: List<DocumentationNode>): ContentNode? { + if (nodes.size < 2) return null + val receiverKind = nodes.getReceiverKind() ?: return null + val functionWithTypeParameter = nodes.firstOrNull { it.details(DocumentationNode.Kind.TypeParameter).any() } ?: return null + return content { + val typeParameter = functionWithTypeParameter.details(DocumentationNode.Kind.TypeParameter).first() + if (functionWithTypeParameter.kind == DocumentationNode.Kind.Function) { + renderFunction(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) + } + else { + renderProperty(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) + } + } + } + + private fun List<DocumentationNode>.getReceiverKind(): ReceiverKind? { + val qNames = map { it.getReceiverQName() }.filterNotNull() + if (qNames.size != size) + return null + + return ReceiverKind.values.firstOrNull { kind -> qNames.all { it in kind.classes } } + } + + private fun DocumentationNode.getReceiverQName(): String? { + if (kind != DocumentationNode.Kind.Function && kind != DocumentationNode.Kind.Property) return null + val receiver = details(DocumentationNode.Kind.Receiver).singleOrNull() ?: return null + val receiverType = receiver.detail(DocumentationNode.Kind.Type) + return (receiverType.links.firstOrNull() ?: receiverType.hiddenLinks.firstOrNull())?.qualifiedName() + } + + companion object { + private val arrayClasses = setOf( + "kotlin.Array", + "kotlin.BooleanArray", + "kotlin.ByteArray", + "kotlin.CharArray", + "kotlin.ShortArray", + "kotlin.IntArray", + "kotlin.LongArray", + "kotlin.FloatArray", + "kotlin.DoubleArray" + ) + + private val arrayOrListClasses = setOf("kotlin.List") + arrayClasses + + private val iterableClasses = setOf( + "kotlin.Collection", + "kotlin.Sequence", + "kotlin.Iterable", + "kotlin.Map", + "kotlin.String", + "kotlin.CharSequence") + arrayOrListClasses + } + + private enum class ReceiverKind(val receiverName: String, val classes: Collection<String>) { + ARRAY("any_array", arrayClasses), + ARRAY_OR_LIST("any_array_or_list", arrayOrListClasses), + ITERABLE("any_iterable", iterableClasses), + } + + interface SignatureMapper { + fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) + } + + private class SummarizingMapper(val kind: ReceiverKind, val typeParameterName: String): SignatureMapper { + override fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) { + to.append(ContentIdentifier(kind.receiverName, IdentifierKind.SummarizedTypeName)) + to.text("<$typeParameterName>") + } + } + private fun ContentBlock.renderPackage(node: DocumentationNode) { keyword("package") text(" ") @@ -75,42 +146,36 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderType(node: DocumentationNode) { - val typeArguments = node.details(DocumentationNode.Kind.Type) + private fun ContentBlock.renderType(node: DocumentationNode, renderMode: RenderMode) { + var typeArguments = node.details(DocumentationNode.Kind.Type) if (node.name == "Function${typeArguments.count() - 1}") { // lambda - symbol("(") - renderList(typeArguments.take(typeArguments.size() - 1), noWrap = true) { - renderType(it) + val isExtension = node.annotations.any { it.name == "Extension" } + if (isExtension) { + renderType(typeArguments.first(), renderMode) + symbol(".") + typeArguments = typeArguments.drop(1) } - symbol(")") - nbsp() - symbol("->") - nbsp() - renderType(typeArguments.last()) - return - } - if (node.name == "ExtensionFunction${typeArguments.count() - 2}") { - // extension lambda - renderType(typeArguments.first()) - symbol(".") symbol("(") - renderList(typeArguments.drop(1).take(typeArguments.size() - 2), noWrap = true) { - renderType(it) + renderList(typeArguments.take(typeArguments.size - 1), noWrap = true) { + renderType(it, renderMode) } symbol(")") nbsp() symbol("->") nbsp() - renderType(typeArguments.last()) + renderType(typeArguments.last(), renderMode) return } - renderSingleModifier(node) + if (renderMode == RenderMode.FULL) { + renderAnnotationsForNode(node) + } + renderModifiersForNode(node, renderMode, true) renderLinked(node) { identifier(it.name, IdentifierKind.TypeName) } if (typeArguments.any()) { symbol("<") renderList(typeArguments, noWrap = true) { - renderType(it) + renderType(it, renderMode) } symbol(">") } @@ -120,18 +185,23 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderModifier(node: DocumentationNode) { + private fun ContentBlock.renderModifier(node: DocumentationNode, nowrap: Boolean = false) { when (node.name) { - "final", "internal", "var" -> {} + "final", "public", "var" -> {} else -> { keyword(node.name) - text(" ") + if (nowrap) { + nbsp() + } + else { + text(" ") + } } } } - private fun ContentBlock.renderTypeParameter(node: DocumentationNode) { - renderSingleModifier(node) + private fun ContentBlock.renderTypeParameter(node: DocumentationNode, renderMode: RenderMode) { + renderModifiersForNode(node, renderMode, true) identifier(node.name) @@ -141,26 +211,20 @@ class KotlinLanguageService : LanguageService { symbol(":") nbsp() renderList(constraints, noWrap=true) { - renderType(it) + renderType(it, renderMode) } } } - - private fun ContentBlock.renderSingleModifier(node: DocumentationNode) { - val modifier = node.details(DocumentationNode.Kind.Modifier).singleOrNull() - if (modifier != null) { - keyword(modifier.name) - nbsp() + private fun ContentBlock.renderParameter(node: DocumentationNode, renderMode: RenderMode) { + if (renderMode == RenderMode.FULL) { + renderAnnotationsForNode(node) } - } - - private fun ContentBlock.renderParameter(node: DocumentationNode) { - renderAnnotationsForNode(node) + renderModifiersForNode(node, renderMode) identifier(node.name, IdentifierKind.ParameterName) symbol(":") nbsp() val parameterType = node.detail(DocumentationNode.Kind.Type) - renderType(parameterType) + renderType(parameterType, renderMode) val valueNode = node.details(DocumentationNode.Kind.Value).firstOrNull() if (valueNode != null) { nbsp() @@ -170,38 +234,41 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderTypeParametersForNode(node: DocumentationNode) { + private fun ContentBlock.renderTypeParametersForNode(node: DocumentationNode, renderMode: RenderMode) { val typeParameters = node.details(DocumentationNode.Kind.TypeParameter) if (typeParameters.any()) { symbol("<") renderList(typeParameters) { - renderTypeParameter(it) + renderTypeParameter(it, renderMode) } symbol(">") } } - private fun ContentBlock.renderSupertypesForNode(node: DocumentationNode) { + private fun ContentBlock.renderSupertypesForNode(node: DocumentationNode, renderMode: RenderMode) { val supertypes = node.details(DocumentationNode.Kind.Supertype) if (supertypes.any()) { nbsp() symbol(":") nbsp() renderList(supertypes) { - renderType(it) + indentedSoftLineBreak() + renderType(it, renderMode) } } } - private fun ContentBlock.renderModifiersForNode(node: DocumentationNode, renderMode: RenderMode) { + private fun ContentBlock.renderModifiersForNode(node: DocumentationNode, + renderMode: RenderMode, + nowrap: Boolean = false) { val modifiers = node.details(DocumentationNode.Kind.Modifier) for (it in modifiers) { if (node.kind == org.jetbrains.dokka.DocumentationNode.Kind.Interface && it.name == "abstract") continue - if (renderMode == RenderMode.SUMMARY && it.name in visibilityModifiers) { + if (renderMode == RenderMode.SUMMARY && it.name in fullOnlyModifiers) { continue } - renderModifier(it) + renderModifier(it, nowrap) } } @@ -212,7 +279,7 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderAnnotation(node: DocumentationNode) { - identifier(node.name, IdentifierKind.AnnotationName) + identifier("@" + node.name, IdentifierKind.AnnotationName) val parameters = node.details(DocumentationNode.Kind.Parameter) if (!parameters.isEmpty()) { symbol("(") @@ -225,82 +292,109 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderClass(node: DocumentationNode, renderMode: RenderMode) { + if (renderMode == RenderMode.FULL) { + renderAnnotationsForNode(node) + } renderModifiersForNode(node, renderMode) - renderAnnotationsForNode(node) when (node.kind) { - DocumentationNode.Kind.Class -> keyword("class ") + DocumentationNode.Kind.Class, + DocumentationNode.Kind.AnnotationClass, + DocumentationNode.Kind.Enum -> keyword("class ") DocumentationNode.Kind.Interface -> keyword("interface ") - DocumentationNode.Kind.Enum -> keyword("enum class ") - DocumentationNode.Kind.AnnotationClass -> keyword("annotation class ") DocumentationNode.Kind.EnumItem -> keyword("enum val ") DocumentationNode.Kind.Object -> keyword("object ") else -> throw IllegalArgumentException("Node $node is not a class-like object") } identifierOrDeprecated(node) - renderTypeParametersForNode(node) - renderSupertypesForNode(node) + renderTypeParametersForNode(node, renderMode) + renderSupertypesForNode(node, renderMode) } - private fun ContentBlock.renderFunction(node: DocumentationNode, renderMode: RenderMode) { + private fun ContentBlock.renderFunction(node: DocumentationNode, + renderMode: RenderMode, + signatureMapper: SignatureMapper? = null) { + if (renderMode == RenderMode.FULL) { + renderAnnotationsForNode(node) + } renderModifiersForNode(node, renderMode) - renderAnnotationsForNode(node) when (node.kind) { DocumentationNode.Kind.Constructor -> identifier(node.owner!!.name) DocumentationNode.Kind.Function, DocumentationNode.Kind.CompanionObjectFunction -> keyword("fun ") else -> throw IllegalArgumentException("Node $node is not a function-like object") } - renderTypeParametersForNode(node) + renderTypeParametersForNode(node, renderMode) if (node.details(DocumentationNode.Kind.TypeParameter).any()) { text(" ") } - val receiver = node.details(DocumentationNode.Kind.Receiver).singleOrNull() - if (receiver != null) { - renderType(receiver.detail(DocumentationNode.Kind.Type)) - symbol(".") - } + + renderReceiver(node, renderMode, signatureMapper) if (node.kind != org.jetbrains.dokka.DocumentationNode.Kind.Constructor) identifierOrDeprecated(node) symbol("(") - renderList(node.details(DocumentationNode.Kind.Parameter)) { - renderParameter(it) + val parameters = node.details(DocumentationNode.Kind.Parameter) + renderList(parameters) { + indentedSoftLineBreak() + renderParameter(it, renderMode) } - symbol(")") if (needReturnType(node)) { + if (parameters.isNotEmpty()) { + softLineBreak() + } + symbol(")") symbol(": ") - renderType(node.detail(DocumentationNode.Kind.Type)) + renderType(node.detail(DocumentationNode.Kind.Type), renderMode) + } + else { + symbol(")") + } + } + + private fun ContentBlock.renderReceiver(node: DocumentationNode, renderMode: RenderMode, signatureMapper: SignatureMapper?) { + val receiver = node.details(DocumentationNode.Kind.Receiver).singleOrNull() + if (receiver != null) { + if (signatureMapper != null) { + signatureMapper.renderReceiver(receiver, this) + } else { + renderType(receiver.detail(DocumentationNode.Kind.Type), renderMode) + } + symbol(".") } } private fun needReturnType(node: DocumentationNode) = when(node.kind) { DocumentationNode.Kind.Constructor -> false - else -> true + else -> !node.isUnitReturnType() } - private fun ContentBlock.renderProperty(node: DocumentationNode, renderMode: RenderMode) { + fun DocumentationNode.isUnitReturnType(): Boolean = + detail(DocumentationNode.Kind.Type).hiddenLinks.firstOrNull()?.qualifiedName() == "kotlin.Unit" + + private fun ContentBlock.renderProperty(node: DocumentationNode, + renderMode: RenderMode, + signatureMapper: SignatureMapper? = null) { + if (renderMode == RenderMode.FULL) { + renderAnnotationsForNode(node) + } renderModifiersForNode(node, renderMode) - renderAnnotationsForNode(node) when (node.kind) { DocumentationNode.Kind.Property, DocumentationNode.Kind.CompanionObjectProperty -> keyword("${node.getPropertyKeyword()} ") else -> throw IllegalArgumentException("Node $node is not a property") } - renderTypeParametersForNode(node) + renderTypeParametersForNode(node, renderMode) if (node.details(DocumentationNode.Kind.TypeParameter).any()) { text(" ") } - val receiver = node.details(DocumentationNode.Kind.Receiver).singleOrNull() - if (receiver != null) { - renderType(receiver.detail(DocumentationNode.Kind.Type)) - symbol(".") - } + + renderReceiver(node, renderMode, signatureMapper) identifierOrDeprecated(node) symbol(": ") - renderType(node.detail(DocumentationNode.Kind.Type)) + renderType(node.detail(DocumentationNode.Kind.Type), renderMode) } fun DocumentationNode.getPropertyKeyword() = diff --git a/src/Languages/JavaLanguageService.kt b/src/Languages/JavaLanguageService.kt index 488a2dc4..5750588e 100644 --- a/src/Languages/JavaLanguageService.kt +++ b/src/Languages/JavaLanguageService.kt @@ -1,6 +1,6 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.DocumentationNode.* +import org.jetbrains.dokka.DocumentationNode.Kind import org.jetbrains.dokka.LanguageService.RenderMode /** @@ -34,6 +34,8 @@ public class JavaLanguageService : LanguageService { } } + override fun summarizeSignatures(nodes: List<DocumentationNode>): ContentNode? = null + private fun renderPackage(node: DocumentationNode): String { return "package ${node.name}" } @@ -77,7 +79,7 @@ public class JavaLanguageService : LanguageService { return if (constraints.none()) node.name else { - node.name + " extends " + constraints.map { renderType(node) }.join() + node.name + " extends " + constraints.map { renderType(node) }.joinToString() } } @@ -86,11 +88,11 @@ public class JavaLanguageService : LanguageService { } private fun renderTypeParametersForNode(node: DocumentationNode): String { - return StringBuilder { + return StringBuilder().apply { val typeParameters = node.details(Kind.TypeParameter) if (typeParameters.any()) { append("<") - append(typeParameters.map { renderTypeParameter(it) }.join()) + append(typeParameters.map { renderTypeParameter(it) }.joinToString()) append("> ") } }.toString() @@ -100,11 +102,11 @@ public class JavaLanguageService : LanguageService { val modifiers = node.details(Kind.Modifier).map { renderModifier(it) }.filter { it != "" } if (modifiers.none()) return "" - return modifiers.join(" ", postfix = " ") + return modifiers.joinToString(" ", postfix = " ") } private fun renderClass(node: DocumentationNode): String { - return StringBuilder { + return StringBuilder().apply { when (node.kind) { Kind.Class -> append("class ") Kind.Interface -> append("interface ") @@ -120,7 +122,7 @@ public class JavaLanguageService : LanguageService { } private fun renderFunction(node: DocumentationNode): String { - return StringBuilder { + return StringBuilder().apply { when (node.kind) { Kind.Constructor -> append(node.owner?.name) Kind.Function -> { @@ -144,7 +146,7 @@ public class JavaLanguageService : LanguageService { } private fun renderProperty(node: DocumentationNode): String { - return StringBuilder { + return StringBuilder().apply { when (node.kind) { Kind.Property -> append("val ") else -> throw IllegalArgumentException("Node $node is not a property") diff --git a/src/Languages/LanguageService.kt b/src/Languages/LanguageService.kt index c587335a..b0f4bbc9 100644 --- a/src/Languages/LanguageService.kt +++ b/src/Languages/LanguageService.kt @@ -12,13 +12,19 @@ interface LanguageService { } /** - * Renders a [node](DocumentationNode) as a class, function, property or other signature in a target language. - * $node: A [DocumentationNode] to render - * $returns: [ContentNode] which is a root for a rich content tree suitable for formatting with [FormatService] + * Renders a [node] as a class, function, property or other signature in a target language. + * @param node A [DocumentationNode] to render + * @return [ContentNode] which is a root for a rich content tree suitable for formatting with [FormatService] */ fun render(node: DocumentationNode, renderMode: RenderMode = RenderMode.FULL): ContentNode /** + * Tries to summarize the signatures of the specified documentation nodes in a compact representation. + * Returns the representation if successful, or null if the signatures could not be summarized. + */ + fun summarizeSignatures(nodes: List<DocumentationNode>): ContentNode? + + /** * Renders [node] as a named representation in the target language * * For example: diff --git a/src/Markdown/MarkdownProcessor.kt b/src/Markdown/MarkdownProcessor.kt index 13023a2c..99caddc4 100644 --- a/src/Markdown/MarkdownProcessor.kt +++ b/src/Markdown/MarkdownProcessor.kt @@ -1,9 +1,11 @@ package org.jetbrains.dokka -import org.intellij.markdown.* -import org.intellij.markdown.ast.* -import org.intellij.markdown.parser.* -import org.intellij.markdown.parser.dialects.commonmark.CommonMarkMarkerProcessor +import org.intellij.markdown.IElementType +import org.intellij.markdown.MarkdownElementTypes +import org.intellij.markdown.ast.ASTNode +import org.intellij.markdown.ast.LeafASTNode +import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor +import org.intellij.markdown.parser.MarkdownParser class MarkdownNode(val node: ASTNode, val parent: MarkdownNode?, val markdown: String) { val children: List<MarkdownNode> = node.children.map { MarkdownNode(it, this, markdown) } @@ -11,7 +13,7 @@ class MarkdownNode(val node: ASTNode, val parent: MarkdownNode?, val markdown: S val text: String get() = markdown.substring(node.startOffset, node.endOffset) fun child(type: IElementType): MarkdownNode? = children.firstOrNull { it.type == type } - override fun toString(): String = StringBuilder { presentTo(this) }.toString() + override fun toString(): String = StringBuilder().apply { presentTo(this) }.toString() } fun MarkdownNode.visit(action: (MarkdownNode, () -> Unit) -> Unit) { @@ -44,5 +46,5 @@ private fun MarkdownNode.presentTo(sb: StringBuilder) { fun parseMarkdown(markdown: String): MarkdownNode { if (markdown.isEmpty()) return MarkdownNode(LeafASTNode(MarkdownElementTypes.MARKDOWN_FILE, 0, 0), null, markdown) - return MarkdownNode(MarkdownParser(CommonMarkMarkerProcessor.Factory).buildMarkdownTreeFromString(markdown), null, markdown) + return MarkdownNode(MarkdownParser(CommonMarkFlavourDescriptor()).buildMarkdownTreeFromString(markdown), null, markdown) } diff --git a/src/Model/Content.kt b/src/Model/Content.kt index 0bb78454..45d42a2d 100644 --- a/src/Model/Content.kt +++ b/src/Model/Content.kt @@ -1,10 +1,14 @@ package org.jetbrains.dokka -public abstract class ContentNode +public interface ContentNode { + val textLength: Int +} -public object ContentEmpty : ContentNode() +public object ContentEmpty : ContentNode { + override val textLength: Int get() = 0 +} -public open class ContentBlock() : ContentNode() { +public open class ContentBlock() : ContentNode { val children = arrayListOf<ContentNode>() fun append(node : ContentNode) { @@ -18,21 +22,58 @@ public open class ContentBlock() : ContentNode() { override fun hashCode(): Int = children.hashCode() + + override val textLength: Int + get() = children.sumBy { it.textLength } } enum class IdentifierKind { TypeName, ParameterName, AnnotationName, + SummarizedTypeName, Other } -public data class ContentText(val text: String) : ContentNode() -public data class ContentKeyword(val text: String) : ContentNode() -public data class ContentIdentifier(val text: String, val kind: IdentifierKind = IdentifierKind.Other) : ContentNode() -public data class ContentSymbol(val text: String) : ContentNode() -public data class ContentEntity(val text: String) : ContentNode() -public object ContentNonBreakingSpace: ContentNode() +public data class ContentText(val text: String) : ContentNode { + override val textLength: Int + get() = text.length +} + +public data class ContentKeyword(val text: String) : ContentNode { + override val textLength: Int + get() = text.length +} + +public data class ContentIdentifier(val text: String, val kind: IdentifierKind = IdentifierKind.Other) : ContentNode { + override val textLength: Int + get() = text.length +} + +public data class ContentSymbol(val text: String) : ContentNode { + override val textLength: Int + get() = text.length +} + +public data class ContentEntity(val text: String) : ContentNode { + override val textLength: Int + get() = text.length +} + +public object ContentNonBreakingSpace: ContentNode { + override val textLength: Int + get() = 1 +} + +public object ContentSoftLineBreak: ContentNode { + override val textLength: Int + get() = 0 +} + +public object ContentIndentedSoftLineBreak: ContentNode { + override val textLength: Int + get() = 0 +} public class ContentParagraph() : ContentBlock() public class ContentEmphasis() : ContentBlock() @@ -101,6 +142,9 @@ fun ContentBlock.keyword(value: String) = append(ContentKeyword(value)) fun ContentBlock.symbol(value: String) = append(ContentSymbol(value)) fun ContentBlock.identifier(value: String, kind: IdentifierKind = IdentifierKind.Other) = append(ContentIdentifier(value, kind)) fun ContentBlock.nbsp() = append(ContentNonBreakingSpace) +fun ContentBlock.softLineBreak() = append(ContentSoftLineBreak) +fun ContentBlock.indentedSoftLineBreak() = append(ContentIndentedSoftLineBreak) + fun ContentBlock.strong(body: ContentBlock.() -> Unit) { val strong = ContentStrong() strong.body() @@ -171,9 +215,6 @@ public open class MutableContent() : Content() { return "<empty>" return (listOf(summary, description) + sections).joinToString() } - - val isEmpty: Boolean - get() = sections.none() } fun javadocSectionDisplayName(sectionName: String?): String? = diff --git a/src/Model/DocumentationModule.kt b/src/Model/DocumentationModule.kt deleted file mode 100644 index e74c544b..00000000 --- a/src/Model/DocumentationModule.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.jetbrains.dokka - -public class DocumentationModule(name: String, content: Content = Content.Empty) : DocumentationNode(name, content, DocumentationNode.Kind.Module) { - fun merge(other: DocumentationModule): DocumentationModule { - val model = DocumentationModule(name) - model.addAllReferencesFrom(other) - model.addAllReferencesFrom(this) - return model - } -} - diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt index c3b9942d..4a77f761 100644 --- a/src/Model/DocumentationNode.kt +++ b/src/Model/DocumentationNode.kt @@ -1,6 +1,6 @@ package org.jetbrains.dokka -import java.util.LinkedHashSet +import java.util.* public open class DocumentationNode(val name: String, content: Content, @@ -19,6 +19,8 @@ public open class DocumentationNode(val name: String, get() = references(DocumentationReference.Kind.Detail).map { it.to } public val members: List<DocumentationNode> get() = references(DocumentationReference.Kind.Member).map { it.to } + public val inheritedMembers: List<DocumentationNode> + get() = references(DocumentationReference.Kind.InheritedMember).map { it.to } public val extensions: List<DocumentationNode> get() = references(DocumentationReference.Kind.Extension).map { it.to } public val inheritors: List<DocumentationNode> @@ -27,6 +29,8 @@ public open class DocumentationNode(val name: String, get() = references(DocumentationReference.Kind.Override).map { it.to } public val links: List<DocumentationNode> get() = references(DocumentationReference.Kind.Link).map { it.to } + public val hiddenLinks: List<DocumentationNode> + get() = references(DocumentationReference.Kind.HiddenLink).map { it.to } public val annotations: List<DocumentationNode> get() = references(DocumentationReference.Kind.Annotation).map { it.to } public val deprecation: DocumentationNode? @@ -50,6 +54,7 @@ public open class DocumentationNode(val name: String, public fun details(kind: DocumentationNode.Kind): List<DocumentationNode> = details.filter { it.kind == kind } public fun members(kind: DocumentationNode.Kind): List<DocumentationNode> = members.filter { it.kind == kind } + public fun inheritedMembers(kind: DocumentationNode.Kind): List<DocumentationNode> = inheritedMembers.filter { it.kind == kind } public fun links(kind: DocumentationNode.Kind): List<DocumentationNode> = links.filter { it.kind == kind } public fun detail(kind: DocumentationNode.Kind): DocumentationNode = details.filter { it.kind == kind }.single() @@ -112,6 +117,10 @@ public open class DocumentationNode(val name: String, } +public class DocumentationModule(name: String, content: Content = Content.Empty) + : DocumentationNode(name, content, DocumentationNode.Kind.Module) { +} + val DocumentationNode.path: List<DocumentationNode> get() { val parent = owner ?: return listOf(this) @@ -137,6 +146,7 @@ fun DocumentationNode.append(child: DocumentationNode, kind: DocumentationRefere DocumentationReference.Kind.Detail -> child.addReferenceTo(this, DocumentationReference.Kind.Owner) DocumentationReference.Kind.Member -> child.addReferenceTo(this, DocumentationReference.Kind.Owner) DocumentationReference.Kind.Owner -> child.addReferenceTo(this, DocumentationReference.Kind.Member) + else -> { /* Do not add any links back for other types */ } } } @@ -145,3 +155,5 @@ fun DocumentationNode.appendTextNode(text: String, refKind: DocumentationReference.Kind = DocumentationReference.Kind.Detail) { append(DocumentationNode(text, Content.Empty, kind), refKind) } + +fun DocumentationNode.qualifiedName() = path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".") diff --git a/src/Model/DocumentationReference.kt b/src/Model/DocumentationReference.kt index a61ac65f..79cec2f3 100644 --- a/src/Model/DocumentationReference.kt +++ b/src/Model/DocumentationReference.kt @@ -4,10 +4,13 @@ public data class DocumentationReference(val from: DocumentationNode, val to: Do public enum class Kind { Owner, Member, + InheritedMember, Detail, Link, + HiddenLink, Extension, Inheritor, + Superclass, Override, Annotation, Deprecation, diff --git a/src/Model/PackageDocs.kt b/src/Model/PackageDocs.kt index b5b34942..99da327b 100644 --- a/src/Model/PackageDocs.kt +++ b/src/Model/PackageDocs.kt @@ -5,7 +5,7 @@ import org.intellij.markdown.MarkdownTokenTypes import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import java.io.File -public class PackageDocs(val documentationBuilder: DocumentationBuilder, +public class PackageDocs(val documentationBuilder: DocumentationBuilder?, val linkResolveContext: DeclarationDescriptor?, val logger: DokkaLogger) { public val moduleContent: MutableContent = MutableContent() @@ -13,17 +13,17 @@ public class PackageDocs(val documentationBuilder: DocumentationBuilder, public val packageContent: Map<String, Content> get() = _packageContent - fun parse(path: String) { - val file = File(path) + fun parse(fileName: String) { + val file = File(fileName) if (file.exists()) { val text = file.readText() val tree = parseMarkdown(text) var targetContent: MutableContent = moduleContent tree.children.forEach { if (it.type == MarkdownElementTypes.ATX_1) { - val headingText = it.child(MarkdownTokenTypes.TEXT)?.text + val headingText = it.child(MarkdownTokenTypes.ATX_CONTENT)?.text if (headingText != null) { - targetContent = findTargetContent(headingText) + targetContent = findTargetContent(headingText.trimStart()) } } else { buildContentTo(it, targetContent, { resolveContentLink(it) }) @@ -39,7 +39,7 @@ public class PackageDocs(val documentationBuilder: DocumentationBuilder, return moduleContent } if (heading.startsWith("Package") || heading.startsWith("package")) { - return findOrCreatePackageContent(heading.substring("package".length()).trim()) + return findOrCreatePackageContent(heading.substring("package".length).trim()) } return findOrCreatePackageContent(heading) } @@ -48,7 +48,7 @@ public class PackageDocs(val documentationBuilder: DocumentationBuilder, _packageContent.getOrPut(packageName) { -> MutableContent() } private fun resolveContentLink(href: String): ContentBlock { - if (linkResolveContext != null) { + if (linkResolveContext != null && documentationBuilder != null) { return documentationBuilder.resolveContentLink(linkResolveContext, href) } return ContentExternalLink("#") diff --git a/src/Model/SourceLinks.kt b/src/Model/SourceLinks.kt index 4530518f..956bfe4b 100644 --- a/src/Model/SourceLinks.kt +++ b/src/Model/SourceLinks.kt @@ -15,7 +15,7 @@ fun DocumentationNode.appendSourceLink(psi: PsiElement?, sourceLinks: List<Sourc val absPath = File(path).absolutePath val linkDef = sourceLinks.firstOrNull { absPath.startsWith(it.path) } if (linkDef != null) { - var url = linkDef.url + path.substring(linkDef.path.length()) + var url = linkDef.url + path.substring(linkDef.path.length) if (linkDef.lineSuffix != null) { val line = target?.lineNumber() if (line != null) { @@ -50,8 +50,7 @@ fun PsiElement.lineNumber(): Int? { } fun PsiElement.columnNumber(): Int? { - val doc = PsiDocumentManager.getInstance(project).getDocument(containingFile) - // IJ uses 0-based line-numbers; external source browsers use 1-based - val lineNumber = doc?.getLineNumber(textRange.startOffset)?.plus(1) ?: return null - return startOffset - doc!!.getLineStartOffset(lineNumber) + val doc = PsiDocumentManager.getInstance(project).getDocument(containingFile) ?: return null + val lineNumber = doc.getLineNumber(textRange.startOffset) + return startOffset - doc.getLineStartOffset(lineNumber) }
\ No newline at end of file diff --git a/src/Utilities/GuiceModule.kt b/src/Utilities/GuiceModule.kt index 4ce4863d..57bad468 100644 --- a/src/Utilities/GuiceModule.kt +++ b/src/Utilities/GuiceModule.kt @@ -45,14 +45,14 @@ class GuiceModule(val config: DokkaGenerator) : Module { } -private inline fun <reified T> Binder.registerCategory(category: String) { +private inline fun <reified T: Any> Binder.registerCategory(category: String) { ServiceLocator.allServices(category).forEach { - @suppress("UNCHECKED_CAST") + @Suppress("UNCHECKED_CAST") bind(javaClass<T>()).annotatedWith(Names.named(it.name)).to(javaClass<T>().classLoader.loadClass(it.className) as Class<T>) } } -private inline fun <reified Base, reified T : Base> Binder.bindNameAnnotated(name: String) { +private inline fun <reified Base : Any, reified T : Base> Binder.bindNameAnnotated(name: String) { bind(javaClass<Base>()).annotatedWith(Names.named(name)).to(javaClass<T>()) } diff --git a/src/Utilities/Path.kt b/src/Utilities/Path.kt index fea22250..36277d9f 100644 --- a/src/Utilities/Path.kt +++ b/src/Utilities/Path.kt @@ -1,18 +1,19 @@ package org.jetbrains.dokka -import java.io.* +import java.io.File +import java.io.IOException fun File.getRelativePath(name: File): File { val parent = parentFile ?: throw IOException("No common directory") - val basePath = getCanonicalPath() + File.separator; - val targetPath = name.getCanonicalPath(); + val basePath = canonicalPath + File.separator; + val targetPath = name.canonicalPath; if (targetPath.startsWith(basePath)) { - return File(targetPath.substring(basePath.length())) + return File(targetPath.substring(basePath.length)) } else { return File(".." + File.separator + parent.getRelativePath(name)) } } -fun File.appendExtension(extension: String) = if (extension.isEmpty()) this else File(getPath() + "." + extension) +fun File.appendExtension(extension: String) = if (extension.isEmpty()) this else File(path + "." + extension) diff --git a/src/Utilities/ServiceLocator.kt b/src/Utilities/ServiceLocator.kt index b3610a53..bc04238f 100644 --- a/src/Utilities/ServiceLocator.kt +++ b/src/Utilities/ServiceLocator.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.Utilities import org.jetbrains.dokka.DokkaGenerator import java.io.File -import java.util.Properties +import java.util.* import java.util.jar.JarFile import java.util.zip.ZipEntry @@ -16,7 +16,7 @@ public object ServiceLocator { val loadedClass = javaClass.classLoader.loadClass(descriptor.className) val constructor = loadedClass.constructors .filter { it.parameterTypes.isEmpty() || (it.parameterTypes.size() == 1 && conf.javaClass.isInstance(it.parameterTypes[0])) } - .sortDescendingBy { it.parameterTypes.size() } + .sortedByDescending { it.parameterTypes.size() } .firstOrNull() ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor") val implementationRawType: Any = if (constructor.parameterTypes.isEmpty()) constructor.newInstance() else constructor.newInstance(constructor) @@ -25,7 +25,7 @@ public object ServiceLocator { throw ServiceLookupException("Class ${descriptor.className} is not a subtype of ${clazz.name}") } - @suppress("UNCHECKED_CAST") + @Suppress("UNCHECKED_CAST") return implementationRawType as T } @@ -35,7 +35,7 @@ public object ServiceLocator { throw ServiceLookupException("Class $className is not a subtype of ${clazz.name}") } - @suppress("UNCHECKED_CAST") + @Suppress("UNCHECKED_CAST") val casted = loaded as Class<T> casted @@ -89,6 +89,12 @@ public inline fun <reified T : Any> ServiceLocator.lookupOrNull(category: String null } +fun main(args: Array<String>) { + ServiceLocator.allServices("format").forEach { + println(it) + } +} + private val ZipEntry.fileName: String get() = name.substringAfterLast("/", name) diff --git a/src/main.kt b/src/main.kt index 29a22672..a534ffdd 100644 --- a/src/main.kt +++ b/src/main.kt @@ -22,46 +22,46 @@ import java.io.File import kotlin.util.measureTimeMillis class DokkaArguments { - Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)") - ValueDescription("<path>") + @set:Argument(value = "src", description = "Source file or directory (allows many paths separated by the system path separator)") + @ValueDescription("<path>") public var src: String = "" - Argument(value = "srcLink", description = "Mapping between a source directory and a Web site for browsing the code") - ValueDescription("<path>=<url>[#lineSuffix]") + @set:Argument(value = "srcLink", description = "Mapping between a source directory and a Web site for browsing the code") + @ValueDescription("<path>=<url>[#lineSuffix]") public var srcLink: String = "" - Argument(value = "include", description = "Markdown files to load (allows many paths separated by the system path separator)") - ValueDescription("<path>") + @set:Argument(value = "include", description = "Markdown files to load (allows many paths separated by the system path separator)") + @ValueDescription("<path>") public var include: String = "" - Argument(value = "samples", description = "Source root for samples") - ValueDescription("<path>") + @set:Argument(value = "samples", description = "Source root for samples") + @ValueDescription("<path>") public var samples: String = "" - Argument(value = "output", description = "Output directory path") - ValueDescription("<path>") + @set:Argument(value = "output", description = "Output directory path") + @ValueDescription("<path>") public var outputDir: String = "out/doc/" - Argument(value = "format", description = "Output format (text, html, markdown, jekyll, kotlin-website)") - ValueDescription("<name>") + @set:Argument(value = "format", description = "Output format (text, html, markdown, jekyll, kotlin-website)") + @ValueDescription("<name>") public var outputFormat: String = "html" - Argument(value = "module", description = "Name of the documentation module") - ValueDescription("<name>") + @set:Argument(value = "module", description = "Name of the documentation module") + @ValueDescription("<name>") public var moduleName: String = "" - Argument(value = "classpath", description = "Classpath for symbol resolution") - ValueDescription("<path>") + @set:Argument(value = "classpath", description = "Classpath for symbol resolution") + @ValueDescription("<path>") public var classpath: String = "" - Argument(value = "nodeprecated", description = "Exclude deprecated members from documentation") + @set:Argument(value = "nodeprecated", description = "Exclude deprecated members from documentation") public var nodeprecated: Boolean = false } private fun parseSourceLinkDefinition(srcLink: String): SourceLinkDefinition { val (path, urlAndLine) = srcLink.split('=') - return SourceLinkDefinition(File(path).getAbsolutePath(), + return SourceLinkDefinition(File(path).absolutePath, urlAndLine.substringBefore("#"), urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#" + it }) } @@ -182,7 +182,7 @@ class DokkaGenerator(val logger: DokkaLogger, } fun isSample(file: PsiFile): Boolean { - val sourceFile = File(file.getVirtualFile()!!.getPath()) + val sourceFile = File(file.virtualFile!!.path) return samples.none { sample -> val canonicalSample = File(sample).canonicalPath val canonicalSource = sourceFile.canonicalPath @@ -199,7 +199,7 @@ fun buildDocumentationModule(environment: AnalysisEnvironment, logger: DokkaLogger): DocumentationModule { val documentation = environment.withContext { environment, resolutionFacade, session -> val fragmentFiles = environment.getSourceFiles().filter(filesToDocumentFilter) - val fragments = fragmentFiles.map { session.getPackageFragment(it.getPackageFqName()) }.filterNotNull().distinct() + val fragments = fragmentFiles.map { session.getPackageFragment(it.packageFqName) }.filterNotNull().distinct() val refGraph = NodeReferenceGraph() val documentationBuilder = DocumentationBuilder(resolutionFacade, session, options, refGraph, logger) @@ -235,7 +235,7 @@ fun KotlinCoreEnvironment.getJavaSourceFiles(): List<PsiJavaFile> { val result = arrayListOf<PsiJavaFile>() val localFileSystem = VirtualFileManager.getInstance().getFileSystem("file") sourceRoots.forEach { sourceRoot -> - sourceRoot.getAbsoluteFile().walkTopDown().forEach { + sourceRoot.absoluteFile.walkTopDown().forEach { val vFile = localFileSystem.findFileByPath(it.path) if (vFile != null) { val psiFile = PsiManager.getInstance(project).findFile(vFile) diff --git a/test/data/classes/annotatedClass.kt b/test/data/classes/annotatedClass.kt index 62c6f0ec..1b58f56c 100644 --- a/test/data/classes/annotatedClass.kt +++ b/test/data/classes/annotatedClass.kt @@ -1 +1 @@ -data class Foo() {} +@Strictfp class Foo() {} diff --git a/test/data/classes/annotatedClassWithAnnotationParameters.kt b/test/data/classes/annotatedClassWithAnnotationParameters.kt index 1af97e75..930d6a62 100644 --- a/test/data/classes/annotatedClassWithAnnotationParameters.kt +++ b/test/data/classes/annotatedClassWithAnnotationParameters.kt @@ -1 +1 @@ -deprecated("should no longer be used") class Foo() {} +@Deprecated("should no longer be used") class Foo() {} diff --git a/test/data/classes/dataClass.kt b/test/data/classes/dataClass.kt new file mode 100644 index 00000000..62c6f0ec --- /dev/null +++ b/test/data/classes/dataClass.kt @@ -0,0 +1 @@ +data class Foo() {} diff --git a/test/data/classes/javaAnnotationClass.kt b/test/data/classes/javaAnnotationClass.kt index c5f5cac4..95600147 100644 --- a/test/data/classes/javaAnnotationClass.kt +++ b/test/data/classes/javaAnnotationClass.kt @@ -1,5 +1,5 @@ import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy -Retention(RetentionPolicy.SOURCE) +@Retention(RetentionPolicy.SOURCE) public annotation class throws() diff --git a/test/data/classes/sealedClass.kt b/test/data/classes/sealedClass.kt new file mode 100644 index 00000000..93350393 --- /dev/null +++ b/test/data/classes/sealedClass.kt @@ -0,0 +1 @@ +sealed class Foo() {} diff --git a/test/data/format/annotatedTypeParameter.kt b/test/data/format/annotatedTypeParameter.kt new file mode 100644 index 00000000..cc3bfc1a --- /dev/null +++ b/test/data/format/annotatedTypeParameter.kt @@ -0,0 +1,2 @@ +public fun <E> containsAll(elements: Collection<@UnsafeVariance E>): @UnsafeVariance E { +} diff --git a/test/data/format/annotatedTypeParameter.md b/test/data/format/annotatedTypeParameter.md new file mode 100644 index 00000000..7d26a162 --- /dev/null +++ b/test/data/format/annotatedTypeParameter.md @@ -0,0 +1,8 @@ +[test](test/index) / [containsAll](test/contains-all) + + +# containsAll + +`fun <E> containsAll(elements: Collection<@UnsafeVariance E>): @UnsafeVariance E` + + diff --git a/test/data/format/annotationParams.kt b/test/data/format/annotationParams.kt index ee5b524a..f259a740 100644 --- a/test/data/format/annotationParams.kt +++ b/test/data/format/annotationParams.kt @@ -1 +1 @@ -inlineOptions(InlineOption.LOCAL_CONTINUE_AND_BREAK) fun f() {} +@JvmName("FFF") fun f() {} diff --git a/test/data/format/annotationParams.md b/test/data/format/annotationParams.md index 80fe52cf..8cdd6e96 100644 --- a/test/data/format/annotationParams.md +++ b/test/data/format/annotationParams.md @@ -3,6 +3,6 @@ # f -`inlineOptions([InlineOption.LOCAL_CONTINUE_AND_BREAK]) fun f(): Unit` +`@JvmName("FFF") fun f(): Unit` diff --git a/test/data/format/annotations.md b/test/data/format/annotations.md index caf84084..b898d55c 100644 --- a/test/data/format/annotations.md +++ b/test/data/format/annotations.md @@ -16,11 +16,11 @@ ### Properties -| [x](test/-foo/x) | `inline val x: Int` | +| [x](test/-foo/x) | `val x: Int` | ### Functions -| [bar](test/-foo/bar) | `inline fun bar(noinline notInlined: () -> Unit): Unit` | +| [bar](test/-foo/bar) | `fun bar(notInlined: () -> Unit): Unit` | diff --git a/test/data/format/crossLanguage/kotlinExtendsJava/Bar.html b/test/data/format/crossLanguage/kotlinExtendsJava/Bar.html index 5b93d837..e7b139d8 100644 --- a/test/data/format/crossLanguage/kotlinExtendsJava/Bar.html +++ b/test/data/format/crossLanguage/kotlinExtendsJava/Bar.html @@ -22,5 +22,16 @@ </tr> </tbody> </table> +<h3>Inherited Functions</h3> +<table> +<tbody> +<tr> +<td> +<a href="test/test/-foo/xyzzy">xyzzy</a></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> +</tr> +</tbody> +</table> </BODY> </HTML> diff --git a/test/data/format/deprecated.kt b/test/data/format/deprecated.kt index 9ee2c1d6..4fc568c2 100644 --- a/test/data/format/deprecated.kt +++ b/test/data/format/deprecated.kt @@ -1,5 +1,5 @@ -deprecated("This class sucks") class C() { } +@Deprecated("This class sucks") class C() { } -deprecated("This function sucks") fun f() { } +@Deprecated("This function sucks") fun f() { } -deprecated("This property sucks") val p: Int get() = 0 +@Deprecated("This property sucks") val p: Int get() = 0 diff --git a/test/data/format/enumClass.kt b/test/data/format/enumClass.kt index 5988c644..c1af69d8 100644 --- a/test/data/format/enumClass.kt +++ b/test/data/format/enumClass.kt @@ -1,4 +1,4 @@ public enum class InlineOption { - LOCAL_CONTINUE_AND_BREAK + LOCAL_CONTINUE_AND_BREAK, ONLY_LOCAL_RETURN } diff --git a/test/data/format/enumClass.md b/test/data/format/enumClass.md index da1ef851..7a0e03ff 100644 --- a/test/data/format/enumClass.md +++ b/test/data/format/enumClass.md @@ -3,7 +3,7 @@ # InlineOption -`public enum class InlineOption` +`enum class InlineOption` diff --git a/test/data/format/extensionFunctionParameter.kt b/test/data/format/extensionFunctionParameter.kt new file mode 100644 index 00000000..bfb344b9 --- /dev/null +++ b/test/data/format/extensionFunctionParameter.kt @@ -0,0 +1 @@ +public inline fun <T> T.apply(f: T.() -> Unit): T { f(); return this } diff --git a/test/data/format/extensionFunctionParameter.md b/test/data/format/extensionFunctionParameter.md new file mode 100644 index 00000000..6980912d --- /dev/null +++ b/test/data/format/extensionFunctionParameter.md @@ -0,0 +1,8 @@ +[test](test/index) / [apply](test/apply) + + +# apply + +`inline fun <T> T.apply(f: T.() -> Unit): T` + + diff --git a/test/data/format/extensions.class.md b/test/data/format/extensions.class.md index 33721e67..c66cdb01 100644 --- a/test/data/format/extensions.class.md +++ b/test/data/format/extensions.class.md @@ -1,15 +1,15 @@ -[test](test/index) / [foo](test/foo/index) / [String](test/foo/-string/index) +[test](test/index) / [foo](test/foo/index) / [kotlin.String](test/foo/kotlin.-string/index) -### Extensions for String +### Extensions for kotlin.String -| [fn](test/foo/-string/fn) | `fun String.fn(): Unit` +| [fn](test/foo/kotlin.-string/fn) | `fun String.fn(): Unit` `fun String.fn(x: Int): Unit` Function with receiver | -| [foobar](test/foo/-string/foobar) | `val String.foobar: Int` +| [foobar](test/foo/kotlin.-string/foobar) | `val String.foobar: Int` Property with receiver. | diff --git a/test/data/format/extensions.package.md b/test/data/format/extensions.package.md index 17829ba0..76ff3676 100644 --- a/test/data/format/extensions.package.md +++ b/test/data/format/extensions.package.md @@ -7,5 +7,5 @@ ### Extensions for External Classes -| [String](test/foo/-string/index) | | +| [kotlin.String](test/foo/kotlin.-string/index) | | diff --git a/test/data/format/inheritedExtensions.kt b/test/data/format/inheritedExtensions.kt new file mode 100644 index 00000000..e38fe00d --- /dev/null +++ b/test/data/format/inheritedExtensions.kt @@ -0,0 +1,11 @@ +open class Foo + +class Bar : Foo() + +fun Foo.first() { + +} + +fun Bar.second() { + +} diff --git a/test/data/format/inheritedExtensions.md b/test/data/format/inheritedExtensions.md new file mode 100644 index 00000000..79137eac --- /dev/null +++ b/test/data/format/inheritedExtensions.md @@ -0,0 +1,21 @@ +[test](test/index) / [Bar](test/-bar/index) + + +# Bar + +`class Bar : [Foo](test/-foo/index)` + + + +### Constructors + + +| [<init>](test/-bar/-init-) | `Bar()` | + + +### Extension Functions + + +| [first](test/first) | `fun [Foo](test/-foo/index).first(): Unit` | +| [second](test/second) | `fun [Bar](test/-bar/index).second(): Unit` | + diff --git a/test/data/format/inheritedMembers.kt b/test/data/format/inheritedMembers.kt new file mode 100644 index 00000000..2d0c4ca1 --- /dev/null +++ b/test/data/format/inheritedMembers.kt @@ -0,0 +1,12 @@ +open class Foo { + fun first() { + } + + val firstProp: Int = 0 +} + +class Bar : Foo() { + fun second() + + val secondProp: Int = 1 +} diff --git a/test/data/format/inheritedMembers.md b/test/data/format/inheritedMembers.md new file mode 100644 index 00000000..d58d3974 --- /dev/null +++ b/test/data/format/inheritedMembers.md @@ -0,0 +1,38 @@ +[test](test/index) / [Bar](test/-bar/index) + + +# Bar + +`class Bar : [Foo](test/-foo/index)` + + + +### Constructors + + +| [<init>](test/-bar/-init-) | `Bar()` | + + +### Properties + + +| [secondProp](test/-bar/second-prop) | `val secondProp: Int` | + + +### Inherited Properties + + +| [firstProp](test/-foo/first-prop) | `val firstProp: Int` | + + +### Functions + + +| [second](test/-bar/second) | `fun second(): Unit` | + + +### Inherited Functions + + +| [first](test/-foo/first) | `fun first(): Unit` | + diff --git a/test/data/format/javaDeprecated.html b/test/data/format/javaDeprecated.html index 8410e7ca..9e8958a2 100644 --- a/test/data/format/javaDeprecated.html +++ b/test/data/format/javaDeprecated.html @@ -6,7 +6,7 @@ <a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-foo/index">Foo</a> / <a href="test/test/-foo/foo">foo</a><br/> <br/> <h1>foo</h1> -<code><span class="keyword">public</span> <span class="keyword">open</span> <span class="keyword">fun </span><s><span class="identifier">foo</span></s><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code><br/> +<code><span class="keyword">open</span> <span class="keyword">fun </span><s><span class="identifier">foo</span></s><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code><br/> <strong>Deprecated:</strong> use <code><a href="test/test/-foo/bar">#bar</a></code> instead <p></p> <br/> <br/> diff --git a/test/data/format/javaSupertype.html b/test/data/format/javaSupertype.html index 3a93da0a..2bcc2fce 100644 --- a/test/data/format/javaSupertype.html +++ b/test/data/format/javaSupertype.html @@ -6,7 +6,7 @@ <a href="test/index">test</a> / <a href="test/test/index">test</a> / <a href="test/test/-c/index">C</a> / <a href="test/test/-c/-bar/index">Bar</a><br/> <br/> <h1>Bar</h1> -<code><span class="keyword">public</span> <span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Bar</span> <span class="symbol">:</span> <a href="test/test/-c/-foo"><span class="identifier">Foo</span></a></code><br/> +<code><span class="keyword">open</span> <span class="keyword">class </span><span class="identifier">Bar</span> <span class="symbol">:</span> <a href="test/test/-c/-foo"><span class="identifier">Foo</span></a></code><br/> <br/> <br/> <h3>Functions</h3> diff --git a/test/data/format/javadocHtml.md b/test/data/format/javadocHtml.md index 64b7a5a4..a75ebf35 100644 --- a/test/data/format/javadocHtml.md +++ b/test/data/format/javadocHtml.md @@ -3,7 +3,7 @@ # C -`public open class C` +`open class C` **Bold** **Strong** *Italic* *Emphasized* Paragraph diff --git a/test/data/format/javadocOrderedList.md b/test/data/format/javadocOrderedList.md index ba5935e2..acd3e809 100644 --- a/test/data/format/javadocOrderedList.md +++ b/test/data/format/javadocOrderedList.md @@ -3,7 +3,7 @@ # Bar -`public open class Bar` +`open class Bar` 1. Rinse 1. Repeat diff --git a/test/data/format/operatorOverloading.md b/test/data/format/operatorOverloading.md index fd0fa977..05fe3206 100644 --- a/test/data/format/operatorOverloading.md +++ b/test/data/format/operatorOverloading.md @@ -4,5 +4,5 @@ # plus `fun plus(other: [C](test/-c/index)): [C](test/-c/index)` -Implements **operator `+`** + diff --git a/test/data/format/orderedList.html b/test/data/format/orderedList.html index 223684ff..9917568f 100644 --- a/test/data/format/orderedList.html +++ b/test/data/format/orderedList.html @@ -8,7 +8,6 @@ <h1>Bar</h1> <code><span class="keyword">class </span><span class="identifier">Bar</span></code><br/> <p>Usage instructions:</p> -<h3>Description</h3> <ol><li><p>Rinse</p> </li><li><p>Repeat</p> </li></ol><br/> diff --git a/test/data/format/overloadsWithDescription.html b/test/data/format/overloadsWithDescription.html index a0a27b8c..a0efb472 100644 --- a/test/data/format/overloadsWithDescription.html +++ b/test/data/format/overloadsWithDescription.html @@ -9,7 +9,6 @@ <code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier">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">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><br/> <p>Performs an action on <a href="test/f#x">x</a>.</p> -<h3>Description</h3> <p>This is a long description.</p> <br/> <br/> diff --git a/test/data/format/overloadsWithDifferentDescriptions.html b/test/data/format/overloadsWithDifferentDescriptions.html index a2cc21f4..30a37e75 100644 --- a/test/data/format/overloadsWithDifferentDescriptions.html +++ b/test/data/format/overloadsWithDifferentDescriptions.html @@ -8,7 +8,6 @@ <h1>f</h1> <code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier">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/> <p>Performs an action on x.</p> -<h3>Description</h3> <p>This is a long description.</p> <br/> <br/> @@ -19,7 +18,6 @@ <br/> <code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="identifier">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><br/> <p>Performs an action on x.</p> -<h3>Description</h3> <p>This is a long description.</p> <br/> <br/> diff --git a/test/data/format/parameterAnchor.html b/test/data/format/parameterAnchor.html index 99f0f110..c5920fb7 100644 --- a/test/data/format/parameterAnchor.html +++ b/test/data/format/parameterAnchor.html @@ -6,7 +6,7 @@ <a href="test/index">test</a> / <a href="test/process-files">processFiles</a><br/> <br/> <h1>processFiles</h1> -<code><span class="keyword">public</span> <span class="keyword">fun </span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span> <span class="identifier">processFiles</span><span class="symbol">(</span><span class="identifier">processor</span><span class="symbol">:</span> <span class="symbol">(</span><span class="symbol">)</span> <span class="symbol">-></span> <span class="identifier">T</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">List</span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span></code><br/> +<code><span class="keyword">fun </span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span> <span class="identifier">processFiles</span><span class="symbol">(</span><span class="identifier">processor</span><span class="symbol">:</span> <span class="symbol">(</span><span class="symbol">)</span> <span class="symbol">-></span> <span class="identifier">T</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">List</span><span class="symbol"><</span><span class="identifier">T</span><span class="symbol">></span></code><br/> <p>Runs <a href="test/process-files#processor">processor</a> for each file and collects its results into single list</p> <h3>Parameters</h3> <a name="processor"></a> diff --git a/test/data/format/reifiedTypeParameter.kt b/test/data/format/reifiedTypeParameter.kt new file mode 100644 index 00000000..00fa1dc9 --- /dev/null +++ b/test/data/format/reifiedTypeParameter.kt @@ -0,0 +1,3 @@ +inline fun f<reified T>() { + +} diff --git a/test/data/format/reifiedTypeParameter.md b/test/data/format/reifiedTypeParameter.md new file mode 100644 index 00000000..2e96018e --- /dev/null +++ b/test/data/format/reifiedTypeParameter.md @@ -0,0 +1,8 @@ +[test](test/index) / [f](test/f) + + +# f + +`inline fun <reified T> f(): Unit` + + diff --git a/test/data/format/starProjection.kt b/test/data/format/starProjection.kt new file mode 100644 index 00000000..48d53e47 --- /dev/null +++ b/test/data/format/starProjection.kt @@ -0,0 +1,3 @@ +public fun Iterable<*>.containsFoo(element: Any?): Boolean { + return false +} diff --git a/test/data/format/starProjection.md b/test/data/format/starProjection.md new file mode 100644 index 00000000..c9be2f58 --- /dev/null +++ b/test/data/format/starProjection.md @@ -0,0 +1,8 @@ +[test](test/index) / [kotlin.Iterable](test/kotlin.-iterable/index) + + +### Extensions for kotlin.Iterable + + +| [containsFoo](test/kotlin.-iterable/contains-foo) | `fun Iterable<*>.containsFoo(element: Any?): Boolean` | + diff --git a/test/data/format/summarizeSignatures.kt b/test/data/format/summarizeSignatures.kt new file mode 100644 index 00000000..1d875a50 --- /dev/null +++ b/test/data/format/summarizeSignatures.kt @@ -0,0 +1,20 @@ +package kotlin + +class Array<T> +class IntArray +class CharArray + +/** + * Returns true if foo. + */ +fun IntArray.foo(predicate: (Int) -> Boolean): Boolean = false + +/** + * Returns true if foo. + */ +fun CharArray.foo(predicate: (Char) -> Boolean): Boolean = false + +/** + * Returns true if foo. + */ +fun <T> Array<T>.foo(predicate: (T) -> Boolean): Boolean = false diff --git a/test/data/format/summarizeSignatures.md b/test/data/format/summarizeSignatures.md new file mode 100644 index 00000000..b1707f40 --- /dev/null +++ b/test/data/format/summarizeSignatures.md @@ -0,0 +1,23 @@ +[test](test/index) / [kotlin](test/kotlin/index) + + +## Package kotlin + + +### Types + + +| [Array](test/kotlin/-array/index) | `class Array<T>` | +| [CharArray](test/kotlin/-char-array/index) | `class CharArray` | +| [IntArray](test/kotlin/-int-array/index) | `class IntArray` | + + +### Functions + + +| [foo](test/kotlin/foo) | `fun <T> any_array<T>.foo(predicate: (T) -> Boolean): Boolean` + +Returns true if foo. + + | + diff --git a/test/data/format/summarizeSignaturesProperty.kt b/test/data/format/summarizeSignaturesProperty.kt new file mode 100644 index 00000000..fbbdd328 --- /dev/null +++ b/test/data/format/summarizeSignaturesProperty.kt @@ -0,0 +1,20 @@ +package kotlin + +class Array<T> +class IntArray +class CharArray + +/** + * Returns true if foo. + */ +val IntArray.foo: Int = 0 + +/** + * Returns true if foo. + */ +val CharArray.foo: Int = 0 + +/** + * Returns true if foo. + */ +val <T> Array<T>.foo: Int = 0 diff --git a/test/data/format/summarizeSignaturesProperty.md b/test/data/format/summarizeSignaturesProperty.md new file mode 100644 index 00000000..9646b0f1 --- /dev/null +++ b/test/data/format/summarizeSignaturesProperty.md @@ -0,0 +1,23 @@ +[test](test/index) / [kotlin](test/kotlin/index) + + +## Package kotlin + + +### Types + + +| [Array](test/kotlin/-array/index) | `class Array<T>` | +| [CharArray](test/kotlin/-char-array/index) | `class CharArray` | +| [IntArray](test/kotlin/-int-array/index) | `class IntArray` | + + +### Properties + + +| [foo](test/kotlin/foo) | `val <T> any_array<T>.foo: Int` + +Returns true if foo. + + | + diff --git a/test/data/format/tripleBackticks.html b/test/data/format/tripleBackticks.html index 76b5f9e1..13954985 100644 --- a/test/data/format/tripleBackticks.html +++ b/test/data/format/tripleBackticks.html @@ -8,7 +8,6 @@ <h1>f</h1> <code><span class="keyword">fun </span><span class="identifier">f</span><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code><br/> <p>Description</p> -<h3>Description</h3> <pre><code>code sample</code></pre><br/> <br/> <br/> diff --git a/test/data/format/typeParameterBounds.md b/test/data/format/typeParameterBounds.md index 3962f911..fe597878 100644 --- a/test/data/format/typeParameterBounds.md +++ b/test/data/format/typeParameterBounds.md @@ -3,7 +3,7 @@ # generic -`public fun <T : R, R> generic(): Unit` +`fun <T : R, R> generic(): Unit` generic function diff --git a/test/data/format/typeProjectionVariance.md b/test/data/format/typeProjectionVariance.md index 9812ca3f..7aa34593 100644 --- a/test/data/format/typeProjectionVariance.md +++ b/test/data/format/typeProjectionVariance.md @@ -1,8 +1,8 @@ -[test](test/index) / [Array](test/-array/index) +[test](test/index) / [kotlin.Array](test/kotlin.-array/index) -### Extensions for Array +### Extensions for kotlin.Array -| [foo](test/-array/foo) | `fun <T> Array<out T>.foo(): Unit` | +| [foo](test/kotlin.-array/foo) | `fun <T> Array<out T>.foo(): Unit` | diff --git a/test/data/functions/annotatedFunction.kt b/test/data/functions/annotatedFunction.kt index 11c19672..f7abbf6c 100644 --- a/test/data/functions/annotatedFunction.kt +++ b/test/data/functions/annotatedFunction.kt @@ -1,2 +1,2 @@ -inline fun f() { +@Strictfp fun f() { } diff --git a/test/data/functions/annotatedFunctionWithAnnotationParameters.kt b/test/data/functions/annotatedFunctionWithAnnotationParameters.kt index ee5b524a..e559713a 100644 --- a/test/data/functions/annotatedFunctionWithAnnotationParameters.kt +++ b/test/data/functions/annotatedFunctionWithAnnotationParameters.kt @@ -1 +1,7 @@ -inlineOptions(InlineOption.LOCAL_CONTINUE_AND_BREAK) fun f() {} +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.SOURCE) +@MustBeDocumented +public annotation class Fancy(val size: Int) + + +@Fancy(1) fun f() {} diff --git a/test/data/functions/functionWithAnnotatedParam.kt b/test/data/functions/functionWithAnnotatedParam.kt index 640bec83..f858e671 100644 --- a/test/data/functions/functionWithAnnotatedParam.kt +++ b/test/data/functions/functionWithAnnotatedParam.kt @@ -1,2 +1,7 @@ -fun function(noinline notInlined: () -> Unit) { +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.SOURCE) +@MustBeDocumented +public annotation class Fancy + +fun function(@Fancy notInlined: () -> Unit) { } diff --git a/test/data/functions/functionWithNoinlineParam.kt b/test/data/functions/functionWithNoinlineParam.kt new file mode 100644 index 00000000..640bec83 --- /dev/null +++ b/test/data/functions/functionWithNoinlineParam.kt @@ -0,0 +1,2 @@ +fun function(noinline notInlined: () -> Unit) { +} diff --git a/test/data/functions/functionWithNotDocumentedAnnotation.kt b/test/data/functions/functionWithNotDocumentedAnnotation.kt new file mode 100644 index 00000000..3c7e2ff9 --- /dev/null +++ b/test/data/functions/functionWithNotDocumentedAnnotation.kt @@ -0,0 +1,2 @@ +@Suppress("FOO") fun f() { +} diff --git a/test/data/functions/inlineFunction.kt b/test/data/functions/inlineFunction.kt new file mode 100644 index 00000000..11c19672 --- /dev/null +++ b/test/data/functions/inlineFunction.kt @@ -0,0 +1,2 @@ +inline fun f() { +} diff --git a/test/data/packagedocs/stdlib.md b/test/data/packagedocs/stdlib.md new file mode 100644 index 00000000..5d7432b5 --- /dev/null +++ b/test/data/packagedocs/stdlib.md @@ -0,0 +1,11 @@ +# Module stdlib + +## Kotlin Standard Library + +The Kotlin standard library is a set of functions and types implementing idiomatic patterns when working with collections, +text and files. + +# Package kotlin + +Core functions and types + diff --git a/test/data/properties/annotatedProperty.kt b/test/data/properties/annotatedProperty.kt index f70c28b4..8990af29 100644 --- a/test/data/properties/annotatedProperty.kt +++ b/test/data/properties/annotatedProperty.kt @@ -1 +1 @@ -inline val property = "test"
\ No newline at end of file +@Volatile var property = "test"
\ No newline at end of file diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt index 165278f9..59b6495b 100644 --- a/test/src/TestAPI.kt +++ b/test/src/TestAPI.kt @@ -9,12 +9,14 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.ContentRoot import org.jetbrains.kotlin.config.KotlinSourceRoot -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.junit.Assert import java.io.File import kotlin.test.fail -public fun verifyModel(vararg roots: ContentRoot, verifier: (DocumentationModule) -> Unit) { +public fun verifyModel(vararg roots: ContentRoot, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + verifier: (DocumentationModule) -> Unit) { val messageCollector = object : MessageCollector { override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) { when (severity) { @@ -33,8 +35,14 @@ public fun verifyModel(vararg roots: ContentRoot, verifier: (DocumentationModule } val environment = AnalysisEnvironment(messageCollector) { - val stringRoot = PathManager.getResourceRoot(javaClass<String>(), "/java/lang/String.class") - addClasspath(File(stringRoot)) + if (withJdk || withKotlinRuntime) { + val stringRoot = PathManager.getResourceRoot(String::class.java, "/java/lang/String.class") + addClasspath(File(stringRoot)) + } + if (withKotlinRuntime) { + val kotlinPairRoot = PathManager.getResourceRoot(Pair::class.java, "/kotlin/Pair.class") + addClasspath(File(kotlinPairRoot)) + } addRoots(roots.toList()) } val options = DocumentationOptions(includeNonPublic = true, skipEmptyPackages = false, sourceLinks = listOf<SourceLinkDefinition>()) @@ -43,19 +51,29 @@ public fun verifyModel(vararg roots: ContentRoot, verifier: (DocumentationModule Disposer.dispose(environment) } -public fun verifyModel(source: String, verifier: (DocumentationModule) -> Unit) { - verifyModel(contentRootFromPath(source), verifier = verifier) +public fun verifyModel(source: String, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + verifier: (DocumentationModule) -> Unit) { + verifyModel(contentRootFromPath(source), withJdk = withJdk, withKotlinRuntime = withKotlinRuntime, verifier = verifier) } -public fun verifyPackageMember(kotlinSource: String, verifier: (DocumentationNode) -> Unit) { - verifyModel(kotlinSource) { model -> +public fun verifyPackageMember(kotlinSource: String, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + verifier: (DocumentationNode) -> Unit) { + verifyModel(kotlinSource, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime) { model -> val pkg = model.members.single() verifier(pkg.members.single()) } } -public fun verifyOutput(roots: Array<ContentRoot>, outputExtension: String, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { - verifyModel(*roots) { +public fun verifyOutput(roots: Array<ContentRoot>, + outputExtension: String, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { + verifyModel(*roots, withJdk = withJdk, withKotlinRuntime = withKotlinRuntime) { val output = StringBuilder() outputGenerator(it, output) val ext = outputExtension.removePrefix(".") @@ -65,8 +83,12 @@ public fun verifyOutput(roots: Array<ContentRoot>, outputExtension: String, outp } } -public fun verifyOutput(path: String, outputExtension: String, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { - verifyOutput(arrayOf(contentRootFromPath(path)), outputExtension, outputGenerator) +public fun verifyOutput(path: String, + outputExtension: String, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { + verifyOutput(arrayOf(contentRootFromPath(path)), outputExtension, withJdk, withKotlinRuntime, outputGenerator) } public fun assertEqualsIgnoringSeparators(expectedOutput: String, output: String) { @@ -110,7 +132,7 @@ fun StringBuilder.appendNode(node: ContentNode): StringBuilder { fun ContentNode.toTestString(): String { val node = this - return StringBuilder { + return StringBuilder().apply { appendNode(node) }.toString() } diff --git a/test/src/format/HtmlFormatTest.kt b/test/src/format/HtmlFormatTest.kt index b7fef79f..66fd0fee 100644 --- a/test/src/format/HtmlFormatTest.kt +++ b/test/src/format/HtmlFormatTest.kt @@ -11,37 +11,37 @@ import java.io.File public class HtmlFormatTest { private val htmlService = HtmlFormatService(InMemoryLocationService, KotlinLanguageService(), HtmlTemplateService.default()) - Test fun classWithCompanionObject() { + @Test fun classWithCompanionObject() { verifyOutput("test/data/format/classWithCompanionObject.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun htmlEscaping() { + @Test fun htmlEscaping() { verifyOutput("test/data/format/htmlEscaping.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun overloads() { + @Test fun overloads() { verifyOutput("test/data/format/overloads.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members) } } - Test fun overloadsWithDescription() { + @Test fun overloadsWithDescription() { verifyOutput("test/data/format/overloadsWithDescription.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun overloadsWithDifferentDescriptions() { + @Test fun overloadsWithDifferentDescriptions() { verifyOutput("test/data/format/overloadsWithDifferentDescriptions.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun deprecated() { + @Test fun deprecated() { verifyOutput("test/data/format/deprecated.kt", ".package.html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members) } @@ -50,85 +50,85 @@ public class HtmlFormatTest { } } - Test fun brokenLink() { + @Test fun brokenLink() { verifyOutput("test/data/format/brokenLink.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun codeSpan() { + @Test fun codeSpan() { verifyOutput("test/data/format/codeSpan.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun parenthesis() { + @Test fun parenthesis() { verifyOutput("test/data/format/parenthesis.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun bracket() { + @Test fun bracket() { verifyOutput("test/data/format/bracket.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun see() { + @Test fun see() { verifyOutput("test/data/format/see.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun tripleBackticks() { + @Test fun tripleBackticks() { verifyOutput("test/data/format/tripleBackticks.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun typeLink() { + @Test fun typeLink() { verifyOutput("test/data/format/typeLink.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar"} ) } } - Test fun parameterAnchor() { + @Test fun parameterAnchor() { verifyOutput("test/data/format/parameterAnchor.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaSupertypeLink() { + @Test fun javaSupertypeLink() { verifyOutput("test/data/format/javaSupertype.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.single { it.name == "C"}.members.filter { it.name == "Bar"} ) } } - Test fun javaLinkTag() { - verifyOutput("test/data/format/javaLinkTag.java", ".html") { model, output -> + @Test fun javaLinkTag() { + verifyOutput("test/data/format/javaLinkTag.java", ".html", withJdk = true) { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaLinkTagWithLabel() { - verifyOutput("test/data/format/javaLinkTagWithLabel.java", ".html") { model, output -> + @Test fun javaLinkTagWithLabel() { + verifyOutput("test/data/format/javaLinkTagWithLabel.java", ".html", withJdk = true) { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaSeeTag() { - verifyOutput("test/data/format/javaSeeTag.java", ".html") { model, output -> + @Test fun javaSeeTag() { + verifyOutput("test/data/format/javaSeeTag.java", ".html", withJdk = true) { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaDeprecated() { + @Test fun javaDeprecated() { verifyOutput("test/data/format/javaDeprecated.java", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.single { it.name == "Foo" }.members.filter { it.name == "foo" }) } } - Test fun crossLanguageKotlinExtendsJava() { + @Test fun crossLanguageKotlinExtendsJava() { verifyOutput(arrayOf(KotlinSourceRoot("test/data/format/crossLanguage/kotlinExtendsJava/Bar.kt"), JavaSourceRoot(File("test/data/format/crossLanguage/kotlinExtendsJava"))), ".html") { model, output -> @@ -136,19 +136,19 @@ public class HtmlFormatTest { } } - Test fun orderedList() { + @Test fun orderedList() { verifyOutput("test/data/format/orderedList.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) } } - Test fun linkWithLabel() { + @Test fun linkWithLabel() { verifyOutput("test/data/format/linkWithLabel.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) } } - Test fun entity() { + @Test fun entity() { verifyOutput("test/data/format/entity.kt", ".html") { model, output -> htmlService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) } diff --git a/test/src/format/MarkdownFormatTest.kt b/test/src/format/MarkdownFormatTest.kt index 059b491b..bb61fa1c 100644 --- a/test/src/format/MarkdownFormatTest.kt +++ b/test/src/format/MarkdownFormatTest.kt @@ -1,42 +1,43 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.KotlinLanguageService +import org.jetbrains.dokka.MarkdownFormatService import org.junit.Test -import org.jetbrains.dokka.* public class MarkdownFormatTest { private val markdownService = MarkdownFormatService(InMemoryLocationService, KotlinLanguageService()) - Test fun emptyDescription() { + @Test fun emptyDescription() { verifyOutput("test/data/format/emptyDescription.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun classWithCompanionObject() { + @Test fun classWithCompanionObject() { verifyOutput("test/data/format/classWithCompanionObject.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun annotations() { + @Test fun annotations() { verifyOutput("test/data/format/annotations.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun annotationClass() { + @Test fun annotationClass() { verifyOutput("test/data/format/annotationClass.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun annotationParams() { - verifyOutput("test/data/format/annotationParams.kt", ".md") { model, output -> + @Test fun annotationParams() { + verifyOutput("test/data/format/annotationParams.kt", ".md", withKotlinRuntime = true) { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun extensions() { + @Test fun extensions() { verifyOutput("test/data/format/extensions.kt", ".package.md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members) } @@ -45,7 +46,7 @@ public class MarkdownFormatTest { } } - Test fun enumClass() { + @Test fun enumClass() { verifyOutput("test/data/format/enumClass.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } @@ -56,13 +57,13 @@ public class MarkdownFormatTest { } } - Test fun varargsFunction() { + @Test fun varargsFunction() { verifyOutput("test/data/format/varargsFunction.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun overridingFunction() { + @Test fun overridingFunction() { verifyOutput("test/data/format/overridingFunction.kt", ".md") { model, output -> val classMembers = model.members.single().members.first { it.name == "D" }.members markdownService.appendNodes(tempLocation, output, classMembers.filter { it.name == "f" }) @@ -70,100 +71,148 @@ public class MarkdownFormatTest { } - Test fun propertyVar() { + @Test fun propertyVar() { verifyOutput("test/data/format/propertyVar.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun functionWithDefaultParameter() { + @Test fun functionWithDefaultParameter() { verifyOutput("test/data/format/functionWithDefaultParameter.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun accessor() { + @Test fun accessor() { verifyOutput("test/data/format/accessor.kt", ".md") { model, output -> val propertyNode = model.members.single().members.first { it.name == "C" }.members.filter { it.name == "x" } markdownService.appendNodes(tempLocation, output, propertyNode) } } - Test fun paramTag() { + @Test fun paramTag() { verifyOutput("test/data/format/paramTag.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun throwsTag() { + @Test fun throwsTag() { verifyOutput("test/data/format/throwsTag.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun typeParameterBounds() { + @Test fun typeParameterBounds() { verifyOutput("test/data/format/typeParameterBounds.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun typeParameterVariance() { + @Test fun typeParameterVariance() { verifyOutput("test/data/format/typeParameterVariance.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun typeProjectionVariance() { + @Test fun typeProjectionVariance() { verifyOutput("test/data/format/typeProjectionVariance.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javadocHtml() { - verifyOutput("test/data/format/javadocHtml.java", ".md") { model, output -> + @Test fun javadocHtml() { + verifyOutput("test/data/format/javadocHtml.java", ".md", withJdk = true) { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaCodeLiteralTags() { - verifyOutput("test/data/format/javaCodeLiteralTags.java", ".md") { model, output -> + @Test fun javaCodeLiteralTags() { + verifyOutput("test/data/format/javaCodeLiteralTags.java", ".md", withJdk = true) { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaCodeInParam() { - verifyOutput("test/data/format/javaCodeInParam.java", ".md") { model, output -> + @Test fun javaCodeInParam() { + verifyOutput("test/data/format/javaCodeInParam.java", ".md", withJdk = true) { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun javaSpaceInAuthor() { - verifyOutput("test/data/format/javaSpaceInAuthor.java", ".md") { model, output -> + @Test fun javaSpaceInAuthor() { + verifyOutput("test/data/format/javaSpaceInAuthor.java", ".md", withJdk = true) { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun nullability() { + @Test fun nullability() { verifyOutput("test/data/format/nullability.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members) } } - Test fun operatorOverloading() { + @Test fun operatorOverloading() { verifyOutput("test/data/format/operatorOverloading.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members.single { it.name == "C" }.members.filter { it.name == "plus" }) } } - Test fun javadocOrderedList() { - verifyOutput("test/data/format/javadocOrderedList.java", ".md") { model, output -> + @Test fun javadocOrderedList() { + verifyOutput("test/data/format/javadocOrderedList.java", ".md", withJdk = true) { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) } } - Test fun companionObjectExtension() { + @Test fun companionObjectExtension() { verifyOutput("test/data/format/companionObjectExtension.kt", ".md") { model, output -> markdownService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Foo" }) } } + + @Test fun starProjection() { + verifyOutput("test/data/format/starProjection.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members) + } + } + + @Test fun extensionFunctionParameter() { + verifyOutput("test/data/format/extensionFunctionParameter.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members) + } + } + + @Test fun summarizeSignatures() { + verifyOutput("test/data/format/summarizeSignatures.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members) + } + } + + @Test fun summarizeSignaturesProperty() { + verifyOutput("test/data/format/summarizeSignaturesProperty.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members) + } + } + + @Test fun reifiedTypeParameter() { + verifyOutput("test/data/format/reifiedTypeParameter.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members) + } + } + + @Test fun annotatedTypeParameter() { + verifyOutput("test/data/format/annotatedTypeParameter.kt", ".md", withKotlinRuntime = true) { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members) + } + } + + @Test fun inheritedMembers() { + verifyOutput("test/data/format/inheritedMembers.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) + } + } + + @Test fun inheritedExtensions() { + verifyOutput("test/data/format/inheritedExtensions.kt", ".md") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members.filter { it.name == "Bar" }) + } + } } diff --git a/test/src/format/PackageDocsTest.kt b/test/src/format/PackageDocsTest.kt new file mode 100644 index 00000000..6815de6f --- /dev/null +++ b/test/src/format/PackageDocsTest.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.tests.format + +import org.jetbrains.dokka.ContentBlock +import org.jetbrains.dokka.ContentText +import org.jetbrains.dokka.DokkaConsoleLogger +import org.jetbrains.dokka.PackageDocs +import org.junit.Test +import kotlin.test.assertEquals + +public class PackageDocsTest { + @Test fun verifyParse() { + val docs = PackageDocs(null, null, DokkaConsoleLogger) + docs.parse("test/data/packagedocs/stdlib.md") + val packageContent = docs.packageContent["kotlin"]!! + val block = (packageContent.children.single() as ContentBlock).children.first() as ContentText + assertEquals("Core functions and types", block.text) + } +} diff --git a/test/src/markdown/MarkdownTestRunner.kt b/test/src/markdown/MarkdownTestRunner.kt deleted file mode 100644 index 5ad0224f..00000000 --- a/test/src/markdown/MarkdownTestRunner.kt +++ /dev/null @@ -1,133 +0,0 @@ -package org.jetbrains.kmark.test - -import org.junit.runner.* -import org.junit.runner.notification.* -import java.io.File -import org.junit.runners.ParentRunner -import java.io.Serializable -import kotlin.properties.Delegates -import org.junit.ComparisonFailure - -data class MarkdownTestUniqueId(val id: Int) : Serializable { - companion object { - var id = 0 - fun next() = MarkdownTestUniqueId(id++) - } -} - -public open class MarkdownSpecification(val path: String, val processor: (String) -> String) - - -interface MarkdownTest { - fun description(): Description -} - -public open class MarkdownTestCase(val spec: MarkdownSpecification, val input: String, val expected: String) : MarkdownTest, Runner() { - val _description by lazy { - Description.createSuiteDescription(input, MarkdownTestUniqueId.next())!! - } - - override fun description(): Description = _description - - override fun getDescription(): Description? = description() - override fun run(notifier: RunNotifier?) { - notifier!! - - notifier.fireTestStarted(_description) - val result = spec.processor(input) - when (result) { - expected -> notifier.fireTestFinished(_description) - else -> notifier.fireTestFailure(Failure(_description, ComparisonFailure("Output mismatch", expected, result))) - } - } -} - -public open class MarkdownTestSection(val spec: MarkdownSpecification, val title: String) : MarkdownTest, ParentRunner<MarkdownTest>(spec.javaClass) { - val children = arrayListOf<MarkdownTest>(); - - val _description by lazy { - val desc = Description.createSuiteDescription(title, MarkdownTestUniqueId.next())!! - for (item in getChildren()!!) { - desc.addChild(describeChild(item)) - } - desc - } - - override fun description(): Description = _description - - override fun getChildren(): MutableList<MarkdownTest>? = children - - override fun describeChild(child: MarkdownTest?): Description? = child!!.description() - - override fun runChild(child: MarkdownTest?, notifier: RunNotifier?) { - notifier!! - when (child) { - is MarkdownTestCase -> child.run(notifier) - is MarkdownTestSection -> { - if (child.children.size() == 0) { - notifier.fireTestStarted(child.description()) - notifier.fireTestFinished(child.description()) - } else { - child.run(notifier) - } - } - } - } -} - -public class MarkdownTestRunner(specificationClass: Class<MarkdownSpecification>) : MarkdownTestSection(specificationClass.newInstance(), "Tests") { - init { - val lines = File(spec.path).readLines() - createSections(this, lines, 1) - } - - private fun createTests(parent: MarkdownTestSection, lines: List<String>): Int { - val testMark = lines.takeWhile { it.trim() != "." } - val testHtml = lines.drop(testMark.size()).drop(1).takeWhile { it.trim() != "." } - val markdown = testMark.join("\n", postfix = "\n", prefix = "\n") - val html = testHtml.join("\n", postfix = "\n") - val markdownTestCase = MarkdownTestCase(spec, markdown, html) - parent.children.add(markdownTestCase) - return testMark.size() + testHtml.size() + 3 - } - - private fun createSections(parent: MarkdownTestSection, lines: List<String>, level: Int): Int { - var sectionNumber = 1 - var index = 0 - while (index < lines.size()) { - val line = lines[index] - - if (line.trim() == ".") { - index = createTests(parent, lines.subList(index + 1, lines.lastIndex)) + index + 1 - continue - } - - val head = line.takeWhile { it == '#' }.length() - if (head == 0) { - index++ - continue - } - - if (head < level) { - return index - } - - if (head == level) { - val title = lines[index].dropWhile { it == '#' }.dropWhile { it.isWhitespace() } - sectionNumber++ - val section = MarkdownTestSection(spec, title) - val lastIndex = createSections(section, lines.subList(index + 1, lines.lastIndex), level + 1) + index + 1 - if (section.children.size() > 0) - parent.children.add(section) - val nextHead = lines[lastIndex].takeWhile { it == '#' }.length() - if (nextHead < level) { - return lastIndex - } - index = lastIndex - continue - } - index++ - } - return lines.size() - } -}
\ No newline at end of file diff --git a/test/src/markdown/ParserTest.kt b/test/src/markdown/ParserTest.kt index 50c18f08..5a7adf05 100644 --- a/test/src/markdown/ParserTest.kt +++ b/test/src/markdown/ParserTest.kt @@ -1,12 +1,11 @@ package org.jetbrains.dokka.tests import org.junit.Test -import org.jetbrains.dokka import org.jetbrains.dokka.toTestString import org.jetbrains.dokka.parseMarkdown import org.junit.Ignore -Ignore public class ParserTest { +@Ignore public class ParserTest { fun runTestFor(text : String) { println("MD: ---") println(text) @@ -16,27 +15,27 @@ Ignore public class ParserTest { println() } - Test fun text() { + @Test fun text() { runTestFor("text") } - Test fun textWithSpaces() { + @Test fun textWithSpaces() { runTestFor("text and string") } - Test fun textWithColon() { + @Test fun textWithColon() { runTestFor("text and string: cool!") } - Test fun link() { + @Test fun link() { runTestFor("text [links]") } - Test fun linkWithHref() { + @Test fun linkWithHref() { runTestFor("text [links](http://google.com)") } - Test fun multiline() { + @Test fun multiline() { runTestFor( """ text @@ -45,7 +44,7 @@ string """) } - Test fun para() { + @Test fun para() { runTestFor( """ paragraph number @@ -56,14 +55,14 @@ number two """) } - Test fun bulletList() { + @Test fun bulletList() { runTestFor( """* list item 1 * list item 2 """) } - Test fun bulletListWithLines() { + @Test fun bulletListWithLines() { runTestFor( """ * list item 1 @@ -73,7 +72,7 @@ number two """) } - Test fun bulletListStrong() { + @Test fun bulletListStrong() { runTestFor( """ * list *item* 1 @@ -83,47 +82,47 @@ number two """) } - Test fun emph() { + @Test fun emph() { runTestFor("*text*") } - Test fun directive() { + @Test fun directive() { runTestFor("A text \${code with.another.value} with directive") } - Test fun emphAndEmptySection() { + @Test fun emphAndEmptySection() { runTestFor("*text*\n\$sec:\n") } - Test fun emphAndSection() { + @Test fun emphAndSection() { runTestFor("*text*\n\$sec: some text\n") } - Test fun emphAndBracedSection() { + @Test fun emphAndBracedSection() { runTestFor("Text *bold* text \n\${sec}: some text") } - Test fun section() { + @Test fun section() { runTestFor( "Plain text \n\$one: Summary \n\${two}: Description with *emphasis* \n\${An example of a section}: Example") } - Test fun anonymousSection() { + @Test fun anonymousSection() { runTestFor("Summary\n\nDescription\n") } - Test fun specialSection() { + @Test fun specialSection() { runTestFor( "Plain text \n\$\$summary: Summary \n\${\$description}: Description \n\${\$An example of a section}: Example") } - Test fun emptySection() { + @Test fun emptySection() { runTestFor( "Plain text \n\$summary:") } val b = "$" - Test fun pair() { + @Test fun pair() { runTestFor( """Represents a generic pair of two values. diff --git a/test/src/markdown/Specification.kt b/test/src/markdown/Specification.kt deleted file mode 100644 index 429317c2..00000000 --- a/test/src/markdown/Specification.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.jetbrains.kmark.test - -import org.junit.runner.* -import org.jetbrains.kmark.test.* -import org.jetbrains.dokka.* - -//[RunWith(javaClass<MarkdownTestRunner>())] -class Specification : MarkdownSpecification("test/data/markdown/spec.txt", { -// markdownToHtml(it.replace("→", "\t")) - "" -})
\ No newline at end of file diff --git a/test/src/model/ClassTest.kt b/test/src/model/ClassTest.kt index 6eec91cc..ce4b4683 100644 --- a/test/src/model/ClassTest.kt +++ b/test/src/model/ClassTest.kt @@ -1,43 +1,43 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.Content +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.DocumentationReference import org.junit.Test -import kotlin.test.* -import org.jetbrains.dokka.* +import kotlin.test.assertEquals +import kotlin.test.assertTrue public class ClassTest { - Test fun emptyClass() { + @Test fun emptyClass() { verifyModel("test/data/classes/emptyClass.kt") { model -> with(model.members.single().members.single()) { assertEquals(DocumentationNode.Kind.Class, kind) assertEquals("Klass", name) assertEquals(Content.Empty, content) - assertEquals(2, details.count()) assertEquals("<init>", members.single().name) assertTrue(links.none()) } } } - Test fun emptyObject() { + @Test fun emptyObject() { verifyModel("test/data/classes/emptyObject.kt") { model -> with(model.members.single().members.single()) { assertEquals(DocumentationNode.Kind.Object, kind) assertEquals("Obj", name) assertEquals(Content.Empty, content) - assertEquals(2, details.count()) assertTrue(members.none()) assertTrue(links.none()) } } } - Test fun classWithConstructor() { + @Test fun classWithConstructor() { verifyModel("test/data/classes/classWithConstructor.kt") { model -> with (model.members.single().members.single()) { assertEquals(DocumentationNode.Kind.Class, kind) assertEquals("Klass", name) assertEquals(Content.Empty, content) - assertEquals(2, details.count()) assertTrue(links.none()) assertEquals(1, members.count()) @@ -62,13 +62,12 @@ public class ClassTest { } } - Test fun classWithFunction() { + @Test fun classWithFunction() { verifyModel("test/data/classes/classWithFunction.kt") { model -> with(model.members.single().members.single()) { assertEquals(DocumentationNode.Kind.Class, kind) assertEquals("Klass", name) assertEquals(Content.Empty, content) - assertEquals(2, details.count()) assertTrue(links.none()) assertEquals(2, members.count()) @@ -93,13 +92,12 @@ public class ClassTest { } } - Test fun classWithProperty() { + @Test fun classWithProperty() { verifyModel("test/data/classes/classWithProperty.kt") { model -> with(model.members.single().members.single()) { assertEquals(DocumentationNode.Kind.Class, kind) assertEquals("Klass", name) assertEquals(Content.Empty, content) - assertEquals(2, details.count()) assertTrue(links.none()) assertEquals(2, members.count()) @@ -124,13 +122,12 @@ public class ClassTest { } } - Test fun classWithCompanionObject() { + @Test fun classWithCompanionObject() { verifyModel("test/data/classes/classWithCompanionObject.kt") { model -> with(model.members.single().members.single()) { assertEquals(DocumentationNode.Kind.Class, kind) assertEquals("Klass", name) assertEquals(Content.Empty, content) - assertEquals(2, details.count()) assertTrue(links.none()) assertEquals(3, members.count()) @@ -154,24 +151,36 @@ public class ClassTest { } } - Test fun annotatedClass() { - verifyModel("test/data/classes/annotatedClass.kt") { model -> - with(model.members.single().members.single()) { - assertEquals(1, annotations.count()) - with(annotations[0]) { - assertEquals("data", name) - assertEquals(Content.Empty, content) - assertEquals(DocumentationNode.Kind.Annotation, kind) - } + @Test fun annotatedClass() { + verifyPackageMember("test/data/classes/annotatedClass.kt", withKotlinRuntime = true) { cls -> + assertEquals(1, cls.annotations.count()) + with(cls.annotations[0]) { + assertEquals("Strictfp", name) + assertEquals(Content.Empty, content) + assertEquals(DocumentationNode.Kind.Annotation, kind) } } } - Test fun annotatedClassWithAnnotationParameters() { + @Test fun dataClass() { + verifyPackageMember("test/data/classes/dataClass.kt") { cls -> + val modifiers = cls.details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("data" in modifiers) + } + } + + @Test fun sealedClass() { + verifyPackageMember("test/data/classes/sealedClass.kt") { cls -> + val modifiers = cls.details(DocumentationNode.Kind.Modifier).map { it.name } + assertEquals(1, modifiers.count { it == "sealed" }) + } + } + + @Test fun annotatedClassWithAnnotationParameters() { verifyModel("test/data/classes/annotatedClassWithAnnotationParameters.kt") { model -> with(model.members.single().members.single()) { with(deprecation!!) { - assertEquals("deprecated", name) + assertEquals("Deprecated", name) assertEquals(Content.Empty, content) assertEquals(DocumentationNode.Kind.Annotation, kind) assertEquals(1, details.count()) @@ -188,15 +197,14 @@ public class ClassTest { } } - Test fun javaAnnotationClass() { - verifyModel("test/data/classes/javaAnnotationClass.kt") { model -> + @Test fun javaAnnotationClass() { + verifyModel("test/data/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(DocumentationNode.Kind.Annotation, kind) - assertEquals(1, details.count()) with(details[0]) { assertEquals(DocumentationNode.Kind.Parameter, kind) assertEquals(1, details.count()) @@ -210,55 +218,55 @@ public class ClassTest { } } - Test fun notOpenClass() { + @Test fun notOpenClass() { verifyModel("test/data/classes/notOpenClass.kt") { model -> with(model.members.single().members.first { it.name == "D"}.members.first { it.name == "f" }) { val modifiers = details(DocumentationNode.Kind.Modifier) - assertEquals(2, modifiers.size()) + assertEquals(2, modifiers.size) assertEquals("final", modifiers[1].name) val overrideReferences = references(DocumentationReference.Kind.Override) - assertEquals(1, overrideReferences.size()) + assertEquals(1, overrideReferences.size) } } } - Test fun indirectOverride() { + @Test fun indirectOverride() { verifyModel("test/data/classes/indirectOverride.kt") { model -> with(model.members.single().members.first { it.name == "E"}.members.first { it.name == "foo" }) { val modifiers = details(DocumentationNode.Kind.Modifier) - assertEquals(2, modifiers.size()) + assertEquals(2, modifiers.size) assertEquals("final", modifiers[1].name) val overrideReferences = references(DocumentationReference.Kind.Override) - assertEquals(1, overrideReferences.size()) + assertEquals(1, overrideReferences.size) } } } - Test fun innerClass() { + @Test fun innerClass() { verifyPackageMember("test/data/classes/innerClass.kt") { cls -> val innerClass = cls.members.single { it.name == "D" } val modifiers = innerClass.details(DocumentationNode.Kind.Modifier) - assertEquals(3, modifiers.size()) + assertEquals(3, modifiers.size) assertEquals("inner", modifiers[2].name) } } - Test fun companionObjectExtension() { + @Test fun companionObjectExtension() { verifyModel("test/data/classes/companionObjectExtension.kt") { model -> val pkg = model.members.single() val cls = pkg.members.single { it.name == "Foo" } val extensions = cls.extensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectProperty } - assertEquals(1, extensions.size()) + assertEquals(1, extensions.size) } } - Test fun secondaryConstructor() { + @Test fun secondaryConstructor() { verifyPackageMember("test/data/classes/secondaryConstructor.kt") { cls -> val constructors = cls.members(DocumentationNode.Kind.Constructor) - assertEquals(2, constructors.size()) - with (constructors.first { it.details(DocumentationNode.Kind.Parameter).size()== 1}) { + assertEquals(2, constructors.size) + with (constructors.first { it.details(DocumentationNode.Kind.Parameter).size == 1}) { assertEquals("<init>", name) assertEquals("This is a secondary constructor.", summary.toTestString()) } diff --git a/test/src/model/CommentTest.kt b/test/src/model/CommentTest.kt index 98585b18..c4d867fb 100644 --- a/test/src/model/CommentTest.kt +++ b/test/src/model/CommentTest.kt @@ -5,7 +5,7 @@ import kotlin.test.* import org.jetbrains.dokka.* public class CommentTest { - Test fun emptyDoc() { + @Test fun emptyDoc() { verifyModel("test/data/comments/emptyDoc.kt") { model -> with(model.members.single().members.single()) { assertEquals(Content.Empty, content) @@ -13,7 +13,7 @@ public class CommentTest { } } - Test fun emptyDocButComment() { + @Test fun emptyDocButComment() { verifyModel("test/data/comments/emptyDocButComment.kt") { model -> with(model.members.single().members.single()) { assertEquals(Content.Empty, content) @@ -21,7 +21,7 @@ public class CommentTest { } } - Test fun multilineDoc() { + @Test fun multilineDoc() { verifyModel("test/data/comments/multilineDoc.kt") { model -> with(model.members.single().members.single()) { assertEquals("doc1", content.summary.toTestString()) @@ -30,7 +30,7 @@ public class CommentTest { } } - Test fun multilineDocWithComment() { + @Test fun multilineDocWithComment() { verifyModel("test/data/comments/multilineDocWithComment.kt") { model -> with(model.members.single().members.single()) { assertEquals("doc1", content.summary.toTestString()) @@ -39,7 +39,7 @@ public class CommentTest { } } - Test fun oneLineDoc() { + @Test fun oneLineDoc() { verifyModel("test/data/comments/oneLineDoc.kt") { model -> with(model.members.single().members.single()) { assertEquals("doc", content.summary.toTestString()) @@ -47,7 +47,7 @@ public class CommentTest { } } - Test fun oneLineDocWithComment() { + @Test fun oneLineDocWithComment() { verifyModel("test/data/comments/oneLineDocWithComment.kt") { model -> with(model.members.single().members.single()) { assertEquals("doc", content.summary.toTestString()) @@ -55,7 +55,7 @@ public class CommentTest { } } - Test fun oneLineDocWithEmptyLine() { + @Test fun oneLineDocWithEmptyLine() { verifyModel("test/data/comments/oneLineDocWithEmptyLine.kt") { model -> with(model.members.single().members.single()) { assertEquals("doc", content.summary.toTestString()) @@ -63,7 +63,7 @@ public class CommentTest { } } - Test fun emptySection() { + @Test fun emptySection() { verifyModel("test/data/comments/emptySection.kt") { model -> with(model.members.single().members.single()) { assertEquals("Summary", content.summary.toTestString()) @@ -76,7 +76,7 @@ public class CommentTest { } } - Test fun section1() { + @Test fun section1() { verifyModel("test/data/comments/section1.kt") { model -> with(model.members.single().members.single()) { assertEquals("Summary", content.summary.toTestString()) @@ -89,7 +89,7 @@ public class CommentTest { } } - Test fun section2() { + @Test fun section2() { verifyModel("test/data/comments/section2.kt") { model -> with(model.members.single().members.single()) { assertEquals("Summary", content.summary.toTestString()) @@ -106,7 +106,7 @@ public class CommentTest { } } - Test fun multilineSection() { + @Test fun multilineSection() { verifyModel("test/data/comments/multilineSection.kt") { model -> with(model.members.single().members.single()) { assertEquals("Summary", content.summary.toTestString()) @@ -120,7 +120,7 @@ line two""", toTestString()) } } - Test fun directive() { + @Test fun directive() { verifyModel("test/data/comments/directive.kt") { model -> with(model.members.single().members.first()) { assertEquals("Summary", content.summary.toTestString()) diff --git a/test/src/model/FunctionTest.kt b/test/src/model/FunctionTest.kt index e40777af..8d1cf609 100644 --- a/test/src/model/FunctionTest.kt +++ b/test/src/model/FunctionTest.kt @@ -1,11 +1,13 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.Content +import org.jetbrains.dokka.DocumentationNode import org.junit.Test -import kotlin.test.* -import org.jetbrains.dokka.* +import kotlin.test.assertEquals +import kotlin.test.assertTrue public class FunctionTest { - Test fun function() { + @Test fun function() { verifyModel("test/data/functions/function.kt") { model -> with(model.members.single().members.single()) { assertEquals("fn", name) @@ -18,18 +20,17 @@ public class FunctionTest { } } - Test fun functionWithReceiver() { + @Test fun functionWithReceiver() { verifyModel("test/data/functions/functionWithReceiver.kt") { model -> with(model.members.single().members.single()) { - assertEquals("String", name) + assertEquals("kotlin.String", name) assertEquals(DocumentationNode.Kind.ExternalClass, kind) assertEquals(2, members.count()) with(members[0]) { assertEquals("fn", name) assertEquals(DocumentationNode.Kind.Function, kind) assertEquals("Function with receiver", content.summary.toTestString()) - assertEquals(4, details.count()) - assertEquals("internal", details.elementAt(0).name) + assertEquals("public", details.elementAt(0).name) assertEquals("final", details.elementAt(1).name) with(details.elementAt(2)) { assertEquals("<this>", name) @@ -51,14 +52,13 @@ public class FunctionTest { } } - Test fun genericFunction() { + @Test fun genericFunction() { verifyModel("test/data/functions/genericFunction.kt") { model -> with(model.members.single().members.single()) { assertEquals("generic", name) assertEquals(DocumentationNode.Kind.Function, kind) assertEquals("generic function", content.summary.toTestString()) - assertEquals(4, details.count()) assertEquals("private", details.elementAt(0).name) assertEquals("final", details.elementAt(1).name) with(details.elementAt(2)) { @@ -76,14 +76,13 @@ public class FunctionTest { } } } - Test fun genericFunctionWithConstraints() { + @Test fun genericFunctionWithConstraints() { verifyModel("test/data/functions/genericFunctionWithConstraints.kt") { model -> with(model.members.single().members.single()) { assertEquals("generic", name) assertEquals(DocumentationNode.Kind.Function, kind) assertEquals("generic function", content.summary.toTestString()) - assertEquals(5, details.count()) assertEquals("public", details.elementAt(0).name) assertEquals("final", details.elementAt(1).name) with(details.elementAt(2)) { @@ -116,7 +115,7 @@ public class FunctionTest { } } - Test fun functionWithParams() { + @Test fun functionWithParams() { verifyModel("test/data/functions/functionWithParams.kt") { model -> with(model.members.single().members.single()) { assertEquals("function", name) @@ -125,8 +124,7 @@ public class FunctionTest { assertEquals("""Function Documentation""", content.description.toTestString()) - assertEquals(4, details.count()) - assertEquals("internal", details.elementAt(0).name) + assertEquals("public", details.elementAt(0).name) assertEquals("final", details.elementAt(1).name) with(details.elementAt(2)) { assertEquals("x", name) @@ -143,26 +141,37 @@ Documentation""", content.description.toTestString()) } } - Test fun annotatedFunction() { - verifyModel("test/data/functions/annotatedFunction.kt") { model -> - with(model.members.single().members.single()) { - assertEquals(1, annotations.count()) - with(annotations[0]) { - assertEquals("inline", name) - assertEquals(Content.Empty, content) - assertEquals(DocumentationNode.Kind.Annotation, kind) - } + @Test fun annotatedFunction() { + verifyPackageMember("test/data/functions/annotatedFunction.kt", withKotlinRuntime = true) { func -> + assertEquals(1, func.annotations.count()) + with(func.annotations[0]) { + assertEquals("Strictfp", name) + assertEquals(Content.Empty, content) + assertEquals(DocumentationNode.Kind.Annotation, kind) } } } - Test fun functionWithAnnotatedParam() { + @Test fun functionWithNotDocumentedAnnotation() { + verifyPackageMember("test/data/functions/functionWithNotDocumentedAnnotation.kt") { func -> + assertEquals(0, func.annotations.count()) + } + } + + @Test fun inlineFunction() { + verifyPackageMember("test/data/functions/inlineFunction.kt") { func -> + val modifiers = func.details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("inline" in modifiers) + } + } + + @Test fun functionWithAnnotatedParam() { verifyModel("test/data/functions/functionWithAnnotatedParam.kt") { model -> - with(model.members.single().members.single()) { + with(model.members.single().members.single { it.name == "function"} ) { with(details.elementAt(2)) { assertEquals(1, annotations.count()) with(annotations[0]) { - assertEquals("noinline", name) + assertEquals("Fancy", name) assertEquals(Content.Empty, content) assertEquals(DocumentationNode.Kind.Annotation, kind) } @@ -171,12 +180,21 @@ Documentation""", content.description.toTestString()) } } - Test fun annotatedFunctionWithAnnotationParameters() { + @Test fun functionWithNoinlineParam() { + verifyPackageMember("test/data/functions/functionWithNoinlineParam.kt") { func -> + with(func.details.elementAt(2)) { + val modifiers = details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("noinline" in modifiers) + } + } + } + + @Test fun annotatedFunctionWithAnnotationParameters() { verifyModel("test/data/functions/annotatedFunctionWithAnnotationParameters.kt") { model -> - with(model.members.single().members.single()) { + with(model.members.single().members.single { it.name == "f"}) { assertEquals(1, annotations.count()) with(annotations[0]) { - assertEquals("inlineOptions", name) + assertEquals("Fancy", name) assertEquals(Content.Empty, content) assertEquals(DocumentationNode.Kind.Annotation, kind) assertEquals(1, details.count()) @@ -185,7 +203,7 @@ Documentation""", content.description.toTestString()) assertEquals(1, details.count()) with(details[0]) { assertEquals(DocumentationNode.Kind.Value, kind) - assertEquals("[InlineOption.LOCAL_CONTINUE_AND_BREAK]", name) + assertEquals("1", name) } } } @@ -193,7 +211,7 @@ Documentation""", content.description.toTestString()) } } - Test fun functionWithDefaultParameter() { + @Test fun functionWithDefaultParameter() { verifyModel("test/data/functions/functionWithDefaultParameter.kt") { model -> with(model.members.single().members.single()) { with(details.elementAt(2)) { diff --git a/test/src/model/JavaTest.kt b/test/src/model/JavaTest.kt index 3129bcc0..5ec29b25 100644 --- a/test/src/model/JavaTest.kt +++ b/test/src/model/JavaTest.kt @@ -1,11 +1,14 @@ package org.jetbrains.dokka.tests -import kotlin.test.* -import org.jetbrains.dokka.* -import org.junit.* +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.DocumentationReference +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue public class JavaTest { - Test fun function() { + @Test fun function() { verifyPackageMember("test/data/java/member.java") { cls -> assertEquals("Test", cls.name) assertEquals(DocumentationNode.Kind.Class, cls.kind) @@ -13,7 +16,7 @@ public class JavaTest { assertEquals("fn", name) assertEquals(DocumentationNode.Kind.Function, kind) assertEquals("Summary for Function", content.summary.toTestString().trimEnd()) - assertEquals(3, content.sections.size()) + assertEquals(3, content.sections.size) with(content.sections[0]) { assertEquals("Parameters", tag) assertEquals("name", subjectName) @@ -43,7 +46,7 @@ public class JavaTest { } } - Test fun memberWithModifiers() { + @Test fun memberWithModifiers() { verifyPackageMember("test/data/java/memberWithModifiers.java") { cls -> assertEquals("abstract", cls.details[0].name) with(cls.members.single { it.name == "fn" }) { @@ -55,16 +58,16 @@ public class JavaTest { } } - Test fun superClass() { + @Test fun superClass() { verifyPackageMember("test/data/java/superClass.java") { cls -> val superTypes = cls.details(DocumentationNode.Kind.Supertype) - assertEquals(2, superTypes.size()) + assertEquals(2, superTypes.size) assertEquals("Exception", superTypes[0].name) assertEquals("Cloneable", superTypes[1].name) } } - Test fun arrayType() { + @Test fun arrayType() { verifyPackageMember("test/data/java/arrayType.java") { cls -> with(cls.members.single()) { val type = detail(DocumentationNode.Kind.Type) @@ -79,7 +82,7 @@ public class JavaTest { } } - Test fun typeParameter() { + @Test fun typeParameter() { verifyPackageMember("test/data/java/typeParameter.java") { cls -> val typeParameters = cls.details(DocumentationNode.Kind.TypeParameter) with(typeParameters.single()) { @@ -98,24 +101,24 @@ public class JavaTest { } } - Test fun constructors() { + @Test fun constructors() { verifyPackageMember("test/data/java/constructors.java") { cls -> val constructors = cls.members(DocumentationNode.Kind.Constructor) - assertEquals(2, constructors.size()) + assertEquals(2, constructors.size) with(constructors[0]) { assertEquals("<init>", name) } } } - Test fun innerClass() { + @Test fun innerClass() { verifyPackageMember("test/data/java/innerClass.java") { cls -> val innerClass = cls.members(DocumentationNode.Kind.Class).single() assertEquals("D", innerClass.name) } } - Test fun varargs() { + @Test fun varargs() { verifyPackageMember("test/data/java/varargs.java") { cls -> val fn = cls.members(DocumentationNode.Kind.Function).single() val param = fn.detail(DocumentationNode.Kind.Parameter) @@ -126,7 +129,7 @@ public class JavaTest { } } - Test fun fields() { + @Test fun fields() { verifyPackageMember("test/data/java/field.java") { cls -> val i = cls.members(DocumentationNode.Kind.Property).single { it.name == "i" } assertEquals("Int", i.detail(DocumentationNode.Kind.Type).name) @@ -137,16 +140,16 @@ public class JavaTest { } } - Test fun staticMethod() { + @Test fun staticMethod() { verifyPackageMember("test/data/java/staticMethod.java") { cls -> val m = cls.members(DocumentationNode.Kind.CompanionObjectFunction).single { it.name == "foo" } assertFalse("static" in m.details(DocumentationNode.Kind.Modifier).map { it.name }) } } - Test fun annotatedAnnotation() { + @Test fun annotatedAnnotation() { verifyPackageMember("test/data/java/annotatedAnnotation.java") { cls -> - assertEquals(2, cls.annotations.size()) + assertEquals(2, cls.annotations.size) with(cls.annotations[0]) { assertEquals(1, details.count()) with(details[0]) { @@ -161,8 +164,8 @@ public class JavaTest { } } - Test fun deprecation() { - verifyPackageMember("test/data/java/deprecation.java") { cls -> + @Test fun deprecation() { + verifyPackageMember("test/data/java/deprecation.java", withJdk = true) { cls -> val fn = cls.members(DocumentationNode.Kind.Function).single() with(fn.deprecation!!) { assertEquals(1, details.count()) @@ -178,26 +181,26 @@ public class JavaTest { } } - Test fun javaLangObject() { - verifyPackageMember("test/data/java/javaLangObject.java") { cls -> + @Test fun javaLangObject() { + verifyPackageMember("test/data/java/javaLangObject.java", withJdk = true) { cls -> val fn = cls.members(DocumentationNode.Kind.Function).single() assertEquals("Any", fn.detail(DocumentationNode.Kind.Type).name) } } - Test fun enumValues() { - verifyPackageMember("test/data/java/enumValues.java") { cls -> + @Test fun enumValues() { + verifyPackageMember("test/data/java/enumValues.java", withJdk = true) { cls -> val superTypes = cls.details(DocumentationNode.Kind.Supertype) - assertEquals(0, superTypes.size()) - assertEquals(1, cls.members(DocumentationNode.Kind.EnumItem).size()) + assertEquals(0, superTypes.size) + assertEquals(1, cls.members(DocumentationNode.Kind.EnumItem).size) } } - Test fun inheritorLinks() { + @Test fun inheritorLinks() { verifyPackageMember("test/data/java/inheritorLinks.java") { cls -> val fooClass = cls.members.single { it.name == "Foo" } val inheritors = fooClass.references(DocumentationReference.Kind.Inheritor) - assertEquals(1, inheritors.size()) + assertEquals(1, inheritors.size) } } } diff --git a/test/src/model/LinkTest.kt b/test/src/model/LinkTest.kt index 151d2696..a8004367 100644 --- a/test/src/model/LinkTest.kt +++ b/test/src/model/LinkTest.kt @@ -5,7 +5,7 @@ import kotlin.test.* import org.jetbrains.dokka.* public class LinkTest { - Test fun linkToSelf() { + @Test fun linkToSelf() { verifyModel("test/data/links/linkToSelf.kt") { model -> with(model.members.single().members.single()) { assertEquals("Foo", name) @@ -15,7 +15,7 @@ public class LinkTest { } } - Test fun linkToMember() { + @Test fun linkToMember() { verifyModel("test/data/links/linkToMember.kt") { model -> with(model.members.single().members.single()) { assertEquals("Foo", name) @@ -25,7 +25,7 @@ public class LinkTest { } } - Test fun linkToQualifiedMember() { + @Test fun linkToQualifiedMember() { verifyModel("test/data/links/linkToQualifiedMember.kt") { model -> with(model.members.single().members.single()) { assertEquals("Foo", name) @@ -35,7 +35,7 @@ public class LinkTest { } } - Test fun linkToParam() { + @Test fun linkToParam() { verifyModel("test/data/links/linkToParam.kt") { model -> with(model.members.single().members.single()) { assertEquals("Foo", name) diff --git a/test/src/model/PackageTest.kt b/test/src/model/PackageTest.kt index 701efbf0..52324f1d 100644 --- a/test/src/model/PackageTest.kt +++ b/test/src/model/PackageTest.kt @@ -8,7 +8,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue public class PackageTest { - Test fun rootPackage() { + @Test fun rootPackage() { verifyModel("test/data/packages/rootPackage.kt") { model -> with(model.members.single()) { assertEquals(DocumentationNode.Kind.Package, kind) @@ -21,7 +21,7 @@ public class PackageTest { } } - Test fun simpleNamePackage() { + @Test fun simpleNamePackage() { verifyModel("test/data/packages/simpleNamePackage.kt") { model -> with(model.members.single()) { assertEquals(DocumentationNode.Kind.Package, kind) @@ -34,7 +34,7 @@ public class PackageTest { } } - Test fun dottedNamePackage() { + @Test fun dottedNamePackage() { verifyModel("test/data/packages/dottedNamePackage.kt") { model -> with(model.members.single()) { assertEquals(DocumentationNode.Kind.Package, kind) @@ -47,7 +47,7 @@ public class PackageTest { } } - Test fun multipleFiles() { + @Test fun multipleFiles() { verifyModel(KotlinSourceRoot("test/data/packages/dottedNamePackage.kt"), KotlinSourceRoot("test/data/packages/simpleNamePackage.kt")) { model -> assertEquals(2, model.members.count()) @@ -69,7 +69,7 @@ public class PackageTest { } } - Test fun multipleFilesSamePackage() { + @Test fun multipleFilesSamePackage() { verifyModel(KotlinSourceRoot("test/data/packages/simpleNamePackage.kt"), KotlinSourceRoot("test/data/packages/simpleNamePackage2.kt")) { model -> assertEquals(1, model.members.count()) diff --git a/test/src/model/PropertyTest.kt b/test/src/model/PropertyTest.kt index 93a0f681..093772b4 100644 --- a/test/src/model/PropertyTest.kt +++ b/test/src/model/PropertyTest.kt @@ -1,11 +1,14 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.Content +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.DocumentationReference import org.junit.Test -import kotlin.test.* -import org.jetbrains.dokka.* +import kotlin.test.assertEquals +import kotlin.test.assertTrue public class PropertyTest { - Test fun valueProperty() { + @Test fun valueProperty() { verifyModel("test/data/properties/valueProperty.kt") { model -> with(model.members.single().members.single()) { assertEquals("property", name) @@ -18,7 +21,7 @@ public class PropertyTest { } } - Test fun variableProperty() { + @Test fun variableProperty() { verifyModel("test/data/properties/variableProperty.kt") { model -> with(model.members.single().members.single()) { assertEquals("property", name) @@ -31,7 +34,7 @@ public class PropertyTest { } } - Test fun valuePropertyWithGetter() { + @Test fun valuePropertyWithGetter() { verifyModel("test/data/properties/valuePropertyWithGetter.kt") { model -> with(model.members.single().members.single()) { assertEquals("property", name) @@ -44,17 +47,16 @@ public class PropertyTest { } } - Test fun variablePropertyWithAccessors() { + @Test fun variablePropertyWithAccessors() { verifyModel("test/data/properties/variablePropertyWithAccessors.kt") { model -> with(model.members.single().members.single()) { assertEquals("property", name) assertEquals(DocumentationNode.Kind.Property, kind) assertEquals(Content.Empty, content) - assertEquals(4, details.count()) assertEquals("String", detail(DocumentationNode.Kind.Type).name) val modifiers = details(DocumentationNode.Kind.Modifier).map { it.name } assertTrue("final" in modifiers) - assertTrue("internal" in modifiers) + assertTrue("public" in modifiers) assertTrue("var" in modifiers) assertTrue(links.none()) assertTrue(members.none()) @@ -62,12 +64,12 @@ public class PropertyTest { } } - Test fun annotatedProperty() { - verifyModel("test/data/properties/annotatedProperty.kt") { model -> + @Test fun annotatedProperty() { + verifyModel("test/data/properties/annotatedProperty.kt", withKotlinRuntime = true) { model -> with(model.members.single().members.single()) { assertEquals(1, annotations.count()) with(annotations[0]) { - assertEquals("inline", name) + assertEquals("Volatile", name) assertEquals(Content.Empty, content) assertEquals(DocumentationNode.Kind.Annotation, kind) } @@ -75,10 +77,10 @@ public class PropertyTest { } } - Test fun propertyWithReceiver() { + @Test fun propertyWithReceiver() { verifyModel("test/data/properties/propertyWithReceiver.kt") { model -> with(model.members.single().members.single()) { - assertEquals("String", name) + assertEquals("kotlin.String", name) assertEquals(DocumentationNode.Kind.ExternalClass, kind) with(members.single()) { assertEquals("foobar", name) @@ -88,7 +90,7 @@ public class PropertyTest { } } - Test fun propertyOverride() { + @Test fun propertyOverride() { verifyModel("test/data/properties/propertyOverride.kt") { model -> with(model.members.single().members.single { it.name == "Bar" }.members.single { it.name == "xyzzy"}) { assertEquals("xyzzy", name) |