From 87edf7c5778a9e1ac3e17c9046110d69e8d197a6 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Mon, 27 Jul 2015 16:11:36 +0300 Subject: Eliminate warnings caused by API changes --- src/Kotlin/ContentBuilder.kt | 2 +- src/Model/Content.kt | 2 +- src/Model/DocumentationNode.kt | 1 + src/Model/PackageDocs.kt | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt index 273009ab..34018217 100644 --- a/src/Kotlin/ContentBuilder.kt +++ b/src/Kotlin/ContentBuilder.kt @@ -121,7 +121,7 @@ fun DocumentationBuilder.functionBody(descriptor: DeclarationDescriptor, functio 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 rootPackage = session.getModuleDescriptor().getPackage(FqName.ROOT) val rootScope = rootPackage.memberScope val symbol = resolveInScope(functionName, scope) ?: resolveInScope(functionName, rootScope) if (symbol == null) { diff --git a/src/Model/Content.kt b/src/Model/Content.kt index 810d6417..032de268 100644 --- a/src/Model/Content.kt +++ b/src/Model/Content.kt @@ -142,7 +142,7 @@ public open class MutableContent() : Content() { public override val summary: ContentNode get() = children.firstOrNull() ?: ContentEmpty - public override val description: ContentNode by Delegates.lazy { + public override val description: ContentNode by lazy { val descriptionNodes = children.drop(1) if (descriptionNodes.isEmpty()) { ContentEmpty diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt index 2f0638bc..b4343347 100644 --- a/src/Model/DocumentationNode.kt +++ b/src/Model/DocumentationNode.kt @@ -134,6 +134,7 @@ fun DocumentationNode.findOrCreatePackageNode(packageName: String, packageConten fun DocumentationNode.append(child: DocumentationNode, kind: DocumentationReference.Kind) { addReferenceTo(child, kind) + @suppress("NON_EXHAUSTIVE_WHEN") when (kind) { DocumentationReference.Kind.Detail -> child.addReferenceTo(this, DocumentationReference.Kind.Owner) DocumentationReference.Kind.Member -> child.addReferenceTo(this, DocumentationReference.Kind.Owner) diff --git a/src/Model/PackageDocs.kt b/src/Model/PackageDocs.kt index 3b0be547..b5b34942 100644 --- a/src/Model/PackageDocs.kt +++ b/src/Model/PackageDocs.kt @@ -13,8 +13,8 @@ public class PackageDocs(val documentationBuilder: DocumentationBuilder, public val packageContent: Map get() = _packageContent - fun parse(file: String) { - val file = File(file) + fun parse(path: String) { + val file = File(path) if (file.exists()) { val text = file.readText() val tree = parseMarkdown(text) -- cgit From 12f91ee7d491b21359ff8e8822c594f35b904def Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Tue, 28 Jul 2015 14:15:55 +0300 Subject: Initial javadoc generation module --- .idea/gradle.xml | 11 + .idea/misc.xml | 1 + .idea/modules.xml | 1 + javadoc/build.gradle | 55 + javadoc/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 52271 bytes javadoc/gradle/wrapper/gradle-wrapper.properties | 6 + javadoc/gradlew | 164 +++ javadoc/gradlew.bat | 90 ++ javadoc/javadoc.iml | 1483 ++++++++++++++++++++++ javadoc/settings.gradle | 2 + javadoc/src/main/kotlin/docbase.kt | 500 ++++++++ javadoc/src/main/kotlin/main.kt | 24 + javadoc/src/main/kotlin/reporter.kt | 30 + javadoc/src/main/kotlin/source-position.kt | 18 + javadoc/src/main/kotlin/tags.kt | 180 +++ javadoc/src/main/kotlin/utils.kt | 10 + src/Languages/JavaLanguageService.kt | 2 +- 17 files changed, 2576 insertions(+), 1 deletion(-) create mode 100644 javadoc/build.gradle create mode 100644 javadoc/gradle/wrapper/gradle-wrapper.jar create mode 100644 javadoc/gradle/wrapper/gradle-wrapper.properties create mode 100755 javadoc/gradlew create mode 100644 javadoc/gradlew.bat create mode 100644 javadoc/javadoc.iml create mode 100644 javadoc/settings.gradle create mode 100644 javadoc/src/main/kotlin/docbase.kt create mode 100644 javadoc/src/main/kotlin/main.kt create mode 100644 javadoc/src/main/kotlin/reporter.kt create mode 100644 javadoc/src/main/kotlin/source-position.kt create mode 100644 javadoc/src/main/kotlin/tags.kt create mode 100644 javadoc/src/main/kotlin/utils.kt (limited to 'src') diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 8efac87e..00b45e99 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -23,6 +23,17 @@ \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 053c9043..543b1856 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,6 +10,7 @@ + \ No newline at end of file diff --git a/javadoc/build.gradle b/javadoc/build.gradle new file mode 100644 index 00000000..5c1d464d --- /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:(,0.2)" + 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 new file mode 100644 index 00000000..30d399d8 Binary files /dev/null and b/javadoc/gradle/wrapper/gradle-wrapper.jar differ 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/javadoc.iml b/javadoc/javadoc.iml new file mode 100644 index 00000000..bc2537e7 --- /dev/null +++ b/javadoc/javadoc.iml @@ -0,0 +1,1483 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file 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/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt new file mode 100644 index 00000000..fe66a672 --- /dev/null +++ b/javadoc/src/main/kotlin/docbase.kt @@ -0,0 +1,500 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.* +import org.jetbrains.dokka.* +import java.lang.reflect.Modifier +import java.util.Collections +import java.util.HashSet + +open class DocumentationNodeBareAdapter(val docNode: DocumentationNode) : Doc { + private var rawCommentText_ = rawCommentText + + override fun name(): String = docNode.name + override fun position(): SourcePosition? = SourcePositionAdapter(docNode) + + override fun inlineTags(): Array? = emptyArray() + override fun firstSentenceTags(): Array? = emptyArray() + override fun tags(): Array = emptyArray() + override fun tags(tagname: String?): Array? = tags().filter { it.kind() == tagname || it.kind() == "@$tagname" }.toTypedArray() + override fun seeTags(): Array? = tags().filterIsInstance().toTypedArray() + override fun commentText(): String = "" + + override fun setRawCommentText(rawDocumentation: String?) { + rawCommentText_ = rawDocumentation ?: "" + } + + override fun getRawCommentText(): String = rawCommentText_ + + override fun isError(): Boolean = false + override fun isException(): Boolean = docNode.kind == DocumentationNode.Kind.Exception + override fun isEnumConstant(): Boolean = docNode.kind == DocumentationNode.Kind.EnumItem + override fun isEnum(): Boolean = docNode.kind == DocumentationNode.Kind.Enum + override fun isMethod(): Boolean = docNode.kind == DocumentationNode.Kind.Function + override fun isInterface(): Boolean = docNode.kind == DocumentationNode.Kind.Interface + override fun isField(): Boolean = docNode.kind == DocumentationNode.Kind.Property + override fun isClass(): Boolean = docNode.kind == DocumentationNode.Kind.Class + override fun isAnnotationType(): Boolean = docNode.kind == DocumentationNode.Kind.AnnotationClass + override fun isConstructor(): Boolean = docNode.kind == DocumentationNode.Kind.Constructor + override fun isOrdinaryClass(): Boolean = docNode.kind == DocumentationNode.Kind.Class + override fun isAnnotationTypeElement(): Boolean = docNode.kind == DocumentationNode.Kind.Annotation + + override fun compareTo(other: Any?): Int = when (other) { + !is DocumentationNodeAdapter -> 1 + else -> docNode.name.compareTo(other.docNode.name) + } + + override fun equals(other: Any?): Boolean = docNode.qualifiedName == (other as? DocumentationNodeAdapter)?.docNode?.qualifiedName + override fun hashCode(): Int = docNode.name.hashCode() + + override fun isIncluded(): Boolean = docNode.kind != DocumentationNode.Kind.ExternalClass +} + + +// TODO think of source position instead of null +// TODO tags +open class DocumentationNodeAdapter(val module: ModuleNodeAdapter, docNode: DocumentationNode) : DocumentationNodeBareAdapter(docNode) { + override fun inlineTags(): Array = buildInlineTags(module, this, docNode.content).toTypedArray() + override fun firstSentenceTags(): Array = buildInlineTags(module, this, docNode.summary).toTypedArray() + override fun tags(): Array = (buildInlineTags(module, this, docNode.content) + docNode.content.sections.flatMap { + when (it.tag) { + "See Also" -> buildInlineTags(module, this, it) + else -> emptyList() + } + }).toTypedArray() +} + +private val allClassKinds = setOf(DocumentationNode.Kind.Class, DocumentationNode.Kind.Enum, DocumentationNode.Kind.Interface, DocumentationNode.Kind.Object, DocumentationNode.Kind.Exception) + +class PackageAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc { + private val allClasses = node.members.filter { it.kind in allClassKinds }.toMap { it.name } + private val packageFacade = PackageFacadeAdapter(module, node) + + override fun findClass(className: String?): ClassDoc? = + allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) } + ?: if (packageFacade.name() == className) packageFacade else null + + override fun annotationTypes(): Array = emptyArray() + override fun annotations(): Array = node.members(DocumentationNode.Kind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray() + override fun exceptions(): Array = node.members(DocumentationNode.Kind.Exception).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun ordinaryClasses(): Array = (node.members(DocumentationNode.Kind.Class).map { ClassDocumentationNodeAdapter(module, it) } + packageFacade).toTypedArray() + override fun interfaces(): Array = node.members(DocumentationNode.Kind.Interface).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun errors(): Array = emptyArray() + override fun enums(): Array = node.members(DocumentationNode.Kind.Enum).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun allClasses(filter: Boolean): Array = (allClasses.values().map { ClassDocumentationNodeAdapter(module, it) } + packageFacade).toTypedArray() + override fun allClasses(): Array = allClasses(true) + + override fun isIncluded(): Boolean = node.name in module.allPackages +} + +class AnnotationTypeDocAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ClassDocumentationNodeAdapter(module, node), AnnotationTypeDoc { + override fun elements(): Array? = emptyArray() // TODO +} + +class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : AnnotationDesc { + override fun annotationType(): AnnotationTypeDoc? = AnnotationTypeDocAdapter(module, node) // TODO ????? + override fun isSynthesized(): Boolean = false + override fun elementValues(): Array? = emptyArray() // TODO +} + +class ProgramElementAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc { + override fun isPublic(): Boolean = true + override fun isPackagePrivate(): Boolean = false + override fun isStatic(): Boolean = node.owner?.kind in listOf(DocumentationNode.Kind.Package, DocumentationNode.Kind.ExternalClass) + override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0 + override fun qualifiedName(): String? = node.qualifiedName + override fun annotations(): Array? = node.annotations.map { AnnotationDescAdapter(module, it) }.toTypedArray() + override fun modifiers(): String? = "public ${if (isStatic) "static" else ""}".trim() + override fun isProtected(): Boolean = false + + override fun isFinal(): Boolean = node.details(DocumentationNode.Kind.Modifier).any { it.name == "final" } + + override fun containingPackage(): PackageDoc? { + var owner: DocumentationNode? = node + while (owner != null) { + if (owner.kind == DocumentationNode.Kind.Package) { + return PackageAdapter(module, owner) + } + owner = owner.owner + } + + return null + } + + override fun containingClass(): ClassDoc? { + var owner = node.owner + while (owner != null) { + when (owner.kind) { + DocumentationNode.Kind.Class -> return ClassDocumentationNodeAdapter(module, owner) + DocumentationNode.Kind.Package -> return PackageFacadeAdapter(module, owner) + else -> owner = owner.owner + } + } + + return null + } + + override fun isPrivate(): Boolean = false + override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true +} + +public fun DocumentationNode.getArrayElementType(): DocumentationNode? = when (name) { + "Array" -> details(DocumentationNode.Kind.Type).singleOrNull()?.let { et -> et.getArrayElementType() ?: et } ?: DocumentationNode("Object", content, DocumentationNode.Kind.ExternalClass) + "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> DocumentationNode(name.removeSuffix("Array").toLowerCase(), content, DocumentationNode.Kind.Type) + else -> null +} + +fun DocumentationNode.getArrayDimension(): Int = when (name) { + "Array" -> 1 + (details(DocumentationNode.Kind.Type).singleOrNull()?.getArrayDimension() ?: 0) + "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> 1 + else -> 0 +} + +//fun DocumentationNode.convertNativeType(): DocumentationNode = when (name) { +// "Unit" -> DocumentationNode("void", content, kind) +// "Int" -> DocumentationNode("int", content, kind) +//} + +open class TypeAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : Type { + override fun qualifiedTypeName(): String = node.getArrayElementType()?.qualifiedName ?: node.qualifiedName + override fun typeName(): String = node.getArrayElementType()?.name ?: node.name + override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName() + + override fun dimension(): String = Collections.nCopies(node.getArrayDimension(), "[]").joinToString("") + override fun isPrimitive(): Boolean = node.name in setOf("Int", "Long", "Short", "Byte", "Char", "Double", "Float", "Boolean", "Unit") + override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else + elementType?.asClassDoc() ?: + when (node.kind) { + DocumentationNode.Kind.Class, + DocumentationNode.Kind.ExternalClass, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Object, + DocumentationNode.Kind.Exception, + DocumentationNode.Kind.Enum -> ClassDocumentationNodeAdapter(module, node) + + else -> when { + node.links.isNotEmpty() -> TypeAdapter(module, node.links.first()).asClassDoc() + else -> ClassDocumentationNodeAdapter(module, node) // TODO ? + } + } + + override fun asTypeVariable(): TypeVariable? = if (node.kind == DocumentationNode.Kind.TypeParameter) TypeVariableAdapter(module, node) else null + override fun asParameterizedType(): ParameterizedType? = + if (node.details(DocumentationNode.Kind.Type).isNotEmpty()) ParameterizedTypeAdapter(module, node) + else null // TODO it should ignore dimensions + + override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == DocumentationNode.Kind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null + override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null + override fun getElementType(): Type? = node.getArrayElementType()?.let { et -> TypeAdapter(module, et) } + override fun asWildcardType(): WildcardType? = null + + override fun toString(): String = qualifiedTypeName() + dimension() + override fun hashCode(): Int = node.name.hashCode() + override fun equals(other: Any?): Boolean = other is TypeAdapter && toString() == other.toString() +} + +class AnnotatedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), AnnotatedType { + override fun underlyingType(): Type? = this + override fun annotations(): Array = node.annotations.map { AnnotationDescAdapter(module, it) }.toTypedArray() +} + +class WildcardTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), WildcardType { + override fun extendsBounds(): Array = node.details(DocumentationNode.Kind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray() + override fun superBounds(): Array = node.details(DocumentationNode.Kind.LowerBound).map { TypeAdapter(module, it) }.toTypedArray() +} + +class TypeVariableAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), TypeVariable { + override fun owner(): ProgramElementDoc = node.owner!!.let { owner -> + when (owner.kind) { + DocumentationNode.Kind.Function, + DocumentationNode.Kind.Constructor -> ExecutableMemberAdapter(module, owner) + + DocumentationNode.Kind.Class, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Enum -> ClassDocumentationNodeAdapter(module, owner) + + else -> ProgramElementAdapter(module, node.owner!!) + } + } + + override fun bounds(): Array? = node.details(DocumentationNode.Kind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray() + override fun annotations(): Array? = node.members(DocumentationNode.Kind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray() + + override fun qualifiedTypeName(): String = node.name + override fun simpleTypeName(): String = node.name + override fun typeName(): String = node.name + + override fun hashCode(): Int = node.name.hashCode() + override fun equals(other: Any?): Boolean = other is Type && other.typeName() == typeName() && other.asTypeVariable()?.owner() == owner() + + override fun asTypeVariable(): TypeVariableAdapter = this + // override fun asClassDoc(): ClassDoc? = null +} + +class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType { + override fun typeArguments(): Array = node.details(DocumentationNode.Kind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray() + override fun superclassType(): Type? = + node.lookupSuperClasses(module) + .firstOrNull { it.kind == DocumentationNode.Kind.Class || it.kind == DocumentationNode.Kind.ExternalClass } + ?.let { ClassDocumentationNodeAdapter(module, it) } + + override fun interfaceTypes(): Array = + node.lookupSuperClasses(module) + .filter { it.kind == DocumentationNode.Kind.Interface } + .map { ClassDocumentationNodeAdapter(module, it) } + .toTypedArray() + + override fun containingType(): Type? = when (node.owner?.kind) { + DocumentationNode.Kind.Package -> null + DocumentationNode.Kind.Class, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Object, + DocumentationNode.Kind.Enum -> ClassDocumentationNodeAdapter(module, node.owner!!) + + else -> null + } +} + +class ParameterAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter { + override fun typeName(): String? = JavaLanguageService().renderType(node.detail(DocumentationNode.Kind.Type)) + override fun type(): Type? = TypeAdapter(module, node.detail(DocumentationNode.Kind.Type)) + override fun annotations(): Array? = node.details(DocumentationNode.Kind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray() +} + +class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode) : DocumentationNodeAdapter(module, receiverType), Parameter { + override fun typeName(): String? = receiverType.name + override fun type(): Type? = TypeAdapter(module, receiverType) + override fun annotations(): Array = emptyArray() + override fun name(): String = "receiver" +} + +fun classOf(fqName: String, kind: DocumentationNode.Kind = DocumentationNode.Kind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node -> + val pkg = fqName.substringBeforeLast(".", "") + if (pkg.isNotEmpty()) { + node.append(DocumentationNode(pkg, Content.Empty, DocumentationNode.Kind.Package), DocumentationReference.Kind.Owner) + } + + node +} + +open class ExecutableMemberAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), ExecutableMemberDoc { + + override fun isSynthetic(): Boolean = false + override fun isNative(): Boolean = node.annotations.any { it.name == "native" } + + override fun thrownExceptions(): Array = emptyArray() // TODO + override fun throwsTags(): Array = + node.content.sections + .filter { it.tag == "Exceptions" } + .map { it.subjectName } + .filterNotNull() + .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it, DocumentationNode.Kind.Exception))) } + .toTypedArray() + + override fun isVarArgs(): Boolean = node.details(DocumentationNode.Kind.Parameter).any { false } // TODO + + override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" } + override fun paramTags(): Array = node.details(DocumentationNode.Kind.Parameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map { + ParamTagAdapter(module, this, it.name, false, it.content.children) + }.toTypedArray() + + override fun thrownExceptionTypes(): Array = emptyArray() + override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) } + override fun flatSignature(): String = node.details(DocumentationNode.Kind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") + override fun signature(): String = node.details(DocumentationNode.Kind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types + + override fun parameters(): Array = + ((receiverNode()?.let { receiver -> listOf(ReceiverParameterAdapter(module, receiver)) } ?: emptyList()) + + node.details(DocumentationNode.Kind.Parameter).map { ParameterAdapter(module, it) } + ).toTypedArray() + + override fun typeParameters(): Array = node.details(DocumentationNode.Kind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray() + + override fun typeParamTags(): Array = node.details(DocumentationNode.Kind.TypeParameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map { + ParamTagAdapter(module, this, it.name, true, it.content.children) + }.toTypedArray() + + private fun receiverNode() = node.details(DocumentationNode.Kind.Receiver).let { receivers -> + when { + receivers.isNotEmpty() -> receivers.single().detail(DocumentationNode.Kind.Type) + else -> null + } + } +} + +class ConstructorAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), ConstructorDoc { + override fun name(): String = node.owner?.name ?: throw IllegalStateException("No owner for $node") +} + +class MethodAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ExecutableMemberDoc by ExecutableMemberAdapter(module, node), MethodDoc { + override fun overrides(meth: MethodDoc?): Boolean = false // TODO + + override fun overriddenType(): Type? = node.overrides.firstOrNull()?.owner?.let { owner -> TypeAdapter(module, owner) } + + override fun overriddenMethod(): MethodDoc? = node.overrides.map { MethodAdapter(module, it) }.firstOrNull() + override fun overriddenClass(): ClassDoc? = overriddenMethod()?.containingClass() + + override fun isAbstract(): Boolean = false // TODO + + override fun isDefault(): Boolean = false + + override fun returnType(): Type = TypeAdapter(module, node.detail(DocumentationNode.Kind.Type)) +} + +class FieldAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), FieldDoc { + override fun isSynthetic(): Boolean = false + + override fun constantValueExpression(): String? = null // TODO + override fun constantValue(): Any? = null + + override fun type(): Type = TypeAdapter(module, node.detail(DocumentationNode.Kind.Type)) + override fun isTransient(): Boolean = false // TODO + override fun serialFieldTags(): Array = emptyArray() + + override fun isVolatile(): Boolean = false // TODO +} + +open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode) : DocumentationNodeAdapter(module, classNode), Type by TypeAdapter(module, classNode), ProgramElementDoc by ProgramElementAdapter(module, classNode), ClassDoc { + override fun constructors(filter: Boolean): Array = classNode.members(DocumentationNode.Kind.Constructor).map { ConstructorAdapter(module, it) }.toTypedArray() + override fun constructors(): Array = constructors(true) + override fun importedPackages(): Array = emptyArray() + override fun importedClasses(): Array? = emptyArray() + override fun typeParameters(): Array = classNode.details(DocumentationNode.Kind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray() + override fun asTypeVariable(): TypeVariable? = if (classNode.kind == DocumentationNode.Kind.Class) TypeVariableAdapter(module, classNode) else null + override fun isExternalizable(): Boolean = interfaces().any { it.qualifiedName() == "java.io.Externalizable" } + override fun definesSerializableFields(): Boolean = false + override fun methods(filter: Boolean): Array = classNode.members(DocumentationNode.Kind.Function).map { MethodAdapter(module, it) }.toTypedArray() // TODO include get/set methods + override fun methods(): Array = methods(true) + override fun enumConstants(): Array? = classNode.members(DocumentationNode.Kind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray() + override fun isAbstract(): Boolean = classNode.details(DocumentationNode.Kind.Modifier).any { it.name == "abstract" } + override fun interfaceTypes(): Array = classNode.lookupSuperClasses(module) + .filter { it.kind == DocumentationNode.Kind.Interface } + .map { ClassDocumentationNodeAdapter(module, it) } + .toTypedArray() + + override fun interfaces(): Array = classNode.lookupSuperClasses(module) + .filter { it.kind == DocumentationNode.Kind.Interface } + .map { ClassDocumentationNodeAdapter(module, it) } + .toTypedArray() + + override fun typeParamTags(): Array = (classNode.details(DocumentationNode.Kind.TypeParameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map { + ParamTagAdapter(module, this, it.name, true, it.content.children) + } + classNode.content.sections.filter { it.subjectName in typeParameters().map { it.simpleTypeName() } }.map { + ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) + }).toTypedArray() + + override fun fields(): Array = emptyArray() + override fun fields(filter: Boolean): Array = emptyArray() + + override fun findClass(className: String?): ClassDoc? = null // TODO !!! + override fun serializableFields(): Array = emptyArray() + override fun superclassType(): Type? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == DocumentationNode.Kind.Class }?.let { ClassDocumentationNodeAdapter(module, it) } + override fun serializationMethods(): Array = emptyArray() // TODO + override fun superclass(): ClassDoc? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == DocumentationNode.Kind.Class }?.let { ClassDocumentationNodeAdapter(module, it) } + override fun isSerializable(): Boolean = false // TODO + override fun subclassOf(cd: ClassDoc?): Boolean { + if (cd == null) { + return false + } + + val expectedFQName = cd.qualifiedName() + val types = arrayListOf(classNode) + val visitedTypes = HashSet() + + while (types.isNotEmpty()) { + val type = types.remove(types.lastIndex) + val fqName = type.qualifiedName + + if (expectedFQName == fqName) { + return true + } + + visitedTypes.add(fqName) + types.addAll(type.details(DocumentationNode.Kind.Supertype).filter { it.qualifiedName !in visitedTypes }) + } + + return false + } + + override fun innerClasses(): Array = classNode.members(DocumentationNode.Kind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun innerClasses(filter: Boolean): Array = innerClasses() +} + +class PackageFacadeAdapter(val module: ModuleNodeAdapter, val packageNode: DocumentationNode) : ProgramElementDoc by ProgramElementAdapter(module, packageNode), ClassDoc { + override fun simpleTypeName(): String = packageNode.name.substringAfterLast(".", packageNode.name).capitalize() + "Package" + override fun typeName(): String = simpleTypeName() + override fun qualifiedTypeName(): String = packageNode.name.split(".").let { parts -> parts.take(parts.size() - 1) + parts.takeLast(1).map { it.capitalize() + "Package" } }.joinToString(".") + override fun qualifiedName(): String = qualifiedTypeName() + override fun name(): String = simpleTypeName() + + override fun isPrimitive(): Boolean = false + override fun dimension(): String = "" + override fun getElementType(): Type? = null + override fun asParameterizedType(): ParameterizedType? = null + override fun asClassDoc(): ClassDoc = this + override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = null + override fun asAnnotatedType(): AnnotatedType? = null + override fun asWildcardType(): WildcardType? = null + override fun asTypeVariable(): TypeVariable? = null + override fun importedPackages(): Array = emptyArray() + override fun typeParameters(): Array = emptyArray() + override fun importedClasses(): Array = emptyArray() + override fun isExternalizable(): Boolean = false + override fun definesSerializableFields(): Boolean = false + override fun methods(): Array = members(DocumentationNode.Kind.Function).map { MethodAdapter(module, it) }.toTypedArray() + override fun fields(): Array = members(DocumentationNode.Kind.Property).map { FieldAdapter(module, it) }.toTypedArray() + override fun methods(filter: Boolean): Array = methods() + override fun fields(filter: Boolean): Array = fields() + override fun constructors(): Array = emptyArray() + override fun constructors(filter: Boolean): Array = constructors() + override fun enumConstants(): Array = emptyArray() + override fun isAbstract(): Boolean = false + override fun interfaceTypes(): Array = emptyArray() + override fun interfaces(): Array = emptyArray() + override fun typeParamTags(): Array = emptyArray() + override fun findClass(className: String?): ClassDoc? = null // TODO ??? + override fun serializableFields(): Array = emptyArray() + override fun superclassType(): Type? = null + override fun serializationMethods(): Array = emptyArray() + override fun superclass(): ClassDoc? = null + override fun isSerializable(): Boolean = false + override fun subclassOf(cd: ClassDoc?): Boolean = false + override fun innerClasses(): Array = emptyArray() + override fun innerClasses(filter: Boolean): Array = innerClasses() + override fun isOrdinaryClass(): Boolean = true + override fun isClass(): Boolean = true + + private fun members(kind: DocumentationNode.Kind) = packageNode.members(kind) + packageNode.members(DocumentationNode.Kind.ExternalClass).flatMap { it.members(kind) } +} + +fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) = + details(DocumentationNode.Kind.Supertype) + .map { it.links.firstOrNull() } + .map { module.allTypes[it?.qualifiedName] } + .filterNotNull() + +class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { + val allPackages = module.members(DocumentationNode.Kind.Package).toMap { it.name } + val allTypes = module.members(DocumentationNode.Kind.Package) + .flatMap { it.members(DocumentationNode.Kind.Class) + it.members(DocumentationNode.Kind.Interface) + it.members(DocumentationNode.Kind.Enum) } + .toMap { it.qualifiedName } + val packageFacades = module.members(DocumentationNode.Kind.Package).map { PackageFacadeAdapter(this, it) }.toMap { it.qualifiedName() } + + override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) } + + override fun classes(): Array = + (allTypes.values().map { ClassDocumentationNodeAdapter(this, it) } + packageFacades.values()) + .toTypedArray() + + override fun options(): Array> = arrayOf( + arrayOf("-d", "out/javadoc"), + arrayOf("-docencoding", "UTF-8") + ) + + override fun specifiedPackages(): Array? = module.members(DocumentationNode.Kind.Package).map { PackageAdapter(this, it) }.toTypedArray() + + override fun classNamed(qualifiedName: String?): ClassDoc? = + allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) } + ?: packageFacades[qualifiedName] + + override fun specifiedClasses(): Array = classes() +} diff --git a/javadoc/src/main/kotlin/main.kt b/javadoc/src/main/kotlin/main.kt new file mode 100644 index 00000000..0c3821c3 --- /dev/null +++ b/javadoc/src/main/kotlin/main.kt @@ -0,0 +1,24 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.tools.doclets.formats.html.HtmlDoclet +import org.jetbrains.dokka.DocumentationOptions +import org.jetbrains.dokka.DokkaConsoleLogger +import org.jetbrains.dokka.DokkaGenerator +import org.jetbrains.dokka.buildDocumentationModule +import java.io.File + +/** + * Test me, my friend + */ +public fun main(args: Array) { + val generator = DokkaGenerator(DokkaConsoleLogger, System.getProperty("java.class.path").split(File.pathSeparator), listOf(File("test").absolutePath), emptyList(), emptyList(), "me", "out/dokka", "html", emptyList(), false) + val env = generator.createAnalysisEnvironment() + val module = buildDocumentationModule(env, generator.moduleName, DocumentationOptions(includeNonPublic = true, sourceLinks = emptyList()), emptyList(), { + generator.isSample(it) + }, generator.logger) + + DokkaConsoleLogger.report() + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter)) +} + +public fun String.a(): Int = 1 \ No newline at end of file diff --git a/javadoc/src/main/kotlin/reporter.kt b/javadoc/src/main/kotlin/reporter.kt new file mode 100644 index 00000000..ce80ec7b --- /dev/null +++ b/javadoc/src/main/kotlin/reporter.kt @@ -0,0 +1,30 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.DocErrorReporter +import com.sun.javadoc.SourcePosition + +object StandardReporter : DocErrorReporter { + override fun printWarning(msg: String?) { + System.err?.println("[WARN] $msg") + } + + override fun printWarning(pos: SourcePosition?, msg: String?) { + System.err?.println("[WARN] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + } + + override fun printError(msg: String?) { + System.err?.println("[ERROR] $msg") + } + + override fun printError(pos: SourcePosition?, msg: String?) { + System.err?.println("[ERROR] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + } + + override fun printNotice(msg: String?) { + System.err?.println("[NOTICE] $msg") + } + + override fun printNotice(pos: SourcePosition?, msg: String?) { + System.err?.println("[NOTICE] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + } +} \ No newline at end of file diff --git a/javadoc/src/main/kotlin/source-position.kt b/javadoc/src/main/kotlin/source-position.kt new file mode 100644 index 00000000..0e4c6e3c --- /dev/null +++ b/javadoc/src/main/kotlin/source-position.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.SourcePosition +import org.jetbrains.dokka.DocumentationNode +import java.io.File + +class SourcePositionAdapter(val docNode: DocumentationNode) : SourcePosition { + + private val sourcePositionParts: List by lazy { + docNode.details(DocumentationNode.Kind.SourcePosition).firstOrNull()?.name?.split(":") ?: emptyList() + } + + override fun file(): File? = if (sourcePositionParts.isEmpty()) null else File(sourcePositionParts[0]) + + override fun line(): Int = sourcePositionParts.getOrNull(1)?.toInt() ?: -1 + + override fun column(): Int = sourcePositionParts.getOrNull(2)?.toInt() ?: -1 +} diff --git a/javadoc/src/main/kotlin/tags.kt b/javadoc/src/main/kotlin/tags.kt new file mode 100644 index 00000000..120154f9 --- /dev/null +++ b/javadoc/src/main/kotlin/tags.kt @@ -0,0 +1,180 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.* +import org.jetbrains.dokka.* +import java.util.ArrayList + +class TextTag(val holder: Doc, val content: ContentText) : Tag { + val plainText: String + get() = content.text + + override fun name(): String = "Text" + override fun kind(): String = name() + override fun text(): String? = plainText + override fun inlineTags(): Array = arrayOf(this) + override fun holder(): Doc = holder + override fun firstSentenceTags(): Array = arrayOf(this) + override fun position(): SourcePosition = holder.position() +} + +abstract class SeeTagAdapter(val holder: Doc, val content: ContentNodeLink) : SeeTag { + override fun position(): SourcePosition? = holder.position() + override fun name(): String = "@see" + override fun kind(): String = "@see" + override fun holder(): Doc = holder + + override fun text(): String? = content.node?.name ?: "(?)" +} + +class SeeExternalLinkTagAdapter(val holder: Doc, val link: ContentExternalLink) : SeeTag { + override fun position(): SourcePosition = holder.position() + override fun text(): String = label() + override fun inlineTags(): Array = emptyArray() // TODO + override fun label(): String = "${link.href}" + override fun referencedPackage(): PackageDoc? = null + override fun referencedClass(): ClassDoc? = null + override fun referencedMemberName(): String? = null + override fun referencedClassName(): String? = null + override fun referencedMember(): MemberDoc? = null + override fun holder(): Doc = holder + override fun firstSentenceTags(): Array = inlineTags() + override fun name(): String = "@link" + override fun kind(): String = "@see" +} + +class SeeMethodTagAdapter(holder: Doc, val method: MethodAdapter, content: ContentNodeLink) : SeeTagAdapter(holder, content) { + override fun referencedMember(): MemberDoc = method + override fun referencedMemberName(): String = method.name() + override fun referencedPackage(): PackageDoc? = null + override fun referencedClass(): ClassDoc = method.containingClass() + override fun referencedClassName(): String = method.containingClass().name() + override fun label(): String = "fun ${method.containingClass().name()}.${method.name()}" + + override fun inlineTags(): Array = emptyArray() // TODO + override fun firstSentenceTags(): Array = inlineTags() // TODO +} + +class SeeClassTagAdapter(holder: Doc, val clazz: ClassDocumentationNodeAdapter, content: ContentNodeLink) : SeeTagAdapter(holder, content) { + override fun referencedMember(): MemberDoc? = null + override fun referencedMemberName(): String? = null + override fun referencedPackage(): PackageDoc? = null + override fun referencedClass(): ClassDoc = clazz + override fun referencedClassName(): String = clazz.name() + override fun label(): String = "${clazz.classNode.kind.name().toLowerCase()} ${clazz.name()}" // TODO + + override fun inlineTags(): Array = emptyArray() // TODO + override fun firstSentenceTags(): Array = inlineTags() // TODO +} + +class ParamTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val parameterName: String, val isTypeParameter: Boolean, val content: List) : ParamTag { + constructor(module: ModuleNodeAdapter, holder: Doc, parameterName: String, isTypeParameter: Boolean, content: ContentNode) : this(module, holder, parameterName, isTypeParameter, listOf(content)) + + override fun name(): String = "@param" + override fun kind(): String = name() + override fun holder(): Doc = holder + override fun position(): SourcePosition? = holder.position() + + override fun text(): String = "@param $parameterName ..." + override fun inlineTags(): Array = content.flatMap { buildInlineTags(module, holder, it) }.toTypedArray() + override fun firstSentenceTags(): Array = arrayOf(TextTag(holder, ContentText(text()))) + + override fun isTypeParameter(): Boolean = isTypeParameter + override fun parameterComment(): String = content.toString() // TODO + override fun parameterName(): String = parameterName +} + + +class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter) : ThrowsTag { + override fun name(): String = "@throws" + override fun kind(): String = name() + override fun holder(): Doc = holder + override fun position(): SourcePosition? = holder.position() + + override fun text(): String = "@throws ${type.qualifiedTypeName()}" + override fun inlineTags(): Array = emptyArray() + override fun firstSentenceTags(): Array = emptyArray() + + override fun exceptionComment(): String = "" + override fun exceptionType(): Type = type + override fun exception(): ClassDoc = type + override fun exceptionName(): String = type.qualifiedName() +} + +fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List = ArrayList().let { buildInlineTags(module, holder, root, it); it } + +private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, node: ContentNode, result: MutableList) { + when (node) { + is ContentText -> result.add(TextTag(holder, node)) + is ContentNodeLink -> { + when (node.node?.kind) { + DocumentationNode.Kind.Function -> result.add(SeeMethodTagAdapter(holder, MethodAdapter(module, node.node!!), node)) + + DocumentationNode.Kind.Class, + DocumentationNode.Kind.ExternalClass, + DocumentationNode.Kind.Enum -> result.add(SeeClassTagAdapter(holder, ClassDocumentationNodeAdapter(module, node.node!!), node)) + + else -> result.add(TextTag(holder, ContentText("other link: ${node.node}"))) // TODO + } + } + is ContentExternalLink -> result.add(SeeExternalLinkTagAdapter(holder, node)) + is ContentCode -> surroundWith(module, holder, "", "", node, result) + is ContentBlockCode -> surroundWith(module, holder, "
", "
", node, result) + is ContentEmpty -> {} + is ContentEmphasis -> surroundWith(module, holder, "", "", node, result) + is ContentHeading -> surroundWith(module, holder, "", "", node, result) + is ContentEntity -> result.add(TextTag(holder, ContentText(node.text))) // TODO ?? + is ContentIdentifier -> result.add(TextTag(holder, ContentText(node.text))) // TODO + is ContentKeyword -> result.add(TextTag(holder, ContentText(node.text))) // TODO + is ContentListItem -> surroundWith(module, holder, "
  • ", "
  • ", node, result) + is ContentOrderedList -> surroundWith(module, holder, "
      ", "
    ", node, result) + is ContentUnorderedList -> surroundWith(module, holder, "
      ", "
    ", node, result) + is ContentParagraph -> surroundWith(module, holder, "

    ", "

    ", node, result) + is ContentSection -> surroundWith(module, holder, "

    ", "

    ", node, result) // TODO how section should be represented? + is ContentNonBreakingSpace -> result.add(TextTag(holder, ContentText(" "))) + is ContentStrikethrough -> surroundWith(module, holder, "", "", node, result) + is ContentStrong -> surroundWith(module, holder, "", "", node, result) + is ContentSymbol -> result.add(TextTag(holder, ContentText(node.text))) // TODO? + is Content -> { + surroundWith(module, holder, "

    ", "

    ", node.summary, result) + surroundWith(module, holder, "

    ", "

    ", node.description, result) +// node.sections.forEach { +// buildInlineTags(module, holder, it, result) +// } + } + + else -> result.add(TextTag(holder, ContentText("$node"))) + } +} + +fun surroundWith(module: ModuleNodeAdapter, holder: Doc, prefix: String, postfix: String, node: ContentBlock, result: MutableList) { + if (node.children.isNotEmpty()) { + val open = TextTag(holder, ContentText(prefix)) + val close = TextTag(holder, ContentText(postfix)) + + result.add(open) + node.children.forEach { + buildInlineTags(module, holder, it, result) + } + + if (result.last() === open) { + result.remove(result.lastIndex) + } else { + result.add(close) + } + } +} + +fun surroundWith(module: ModuleNodeAdapter, holder: Doc, prefix: String, postfix: String, node: ContentNode, result: MutableList) { + if (node !is ContentEmpty) { + val open = TextTag(holder, ContentText(prefix)) + val close = TextTag(holder, ContentText(postfix)) + + result.add(open) + buildInlineTags(module, holder, node, result) + if (result.last() === open) { + result.remove(result.lastIndex) + } else { + result.add(close) + } + } +} \ No newline at end of file diff --git a/javadoc/src/main/kotlin/utils.kt b/javadoc/src/main/kotlin/utils.kt new file mode 100644 index 00000000..661de0c8 --- /dev/null +++ b/javadoc/src/main/kotlin/utils.kt @@ -0,0 +1,10 @@ +package org.jetbrains.dokka.javadoc + +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.path +import java.util.* + +val DocumentationNode.qualifiedName: String + get() = this.path.filter { it.kind == DocumentationNode.Kind.Package || it.kind in allClassKinds } + .map { it.name } + .joinToString(".") diff --git a/src/Languages/JavaLanguageService.kt b/src/Languages/JavaLanguageService.kt index e491d1bd..ad8307c1 100644 --- a/src/Languages/JavaLanguageService.kt +++ b/src/Languages/JavaLanguageService.kt @@ -46,7 +46,7 @@ public class JavaLanguageService : LanguageService { } } - private fun renderType(node: DocumentationNode): String { + public fun renderType(node: DocumentationNode): String { return when (node.name) { "Unit" -> "void" "Int" -> "int" -- cgit From e27fb69817b1417c1bc556a507b14f2700c7a736 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Fri, 31 Jul 2015 15:35:34 +0300 Subject: Use Guice injector and ServiceLocator to load implementations on the fly --- ...etbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml | 12 +++ ...jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml | 12 +++ .idea/libraries/com_google_inject_guice_4_0.xml | 13 +++ dokka.iml | 1 + javadoc/src/main/kotlin/docbase.kt | 8 +- javadoc/src/main/kotlin/dokka-adapters.kt | 29 ++++++ javadoc/src/main/kotlin/main.kt | 24 ----- .../resources/dokka/generator/javadoc.properties | 2 + .../src/main/resources/format/javadoc.properties | 1 + lib/aopalliance-1.0.jar | Bin 0 -> 4467 bytes lib/guice-4.0.jar | Bin 0 -> 668235 bytes lib/javax.inject-1.jar | Bin 0 -> 2497 bytes resources/dokka/format/html.properties | 2 + resources/dokka/format/jekyll.properties | 2 + resources/dokka/format/kotlin-website.properties | 2 + resources/dokka/format/markdown.properties | 2 + resources/dokka/generator/default.properties | 2 + resources/dokka/language/java.properties | 1 + resources/dokka/language/kotlin.properties | 1 + resources/dokka/outline/yaml.properties | 1 + src/Formats/FormatDescriptor.kt | 11 +++ src/Formats/HtmlFormatService.kt | 6 +- src/Formats/JekyllFormatService.kt | 4 +- src/Formats/KotlinWebsiteFormatService.kt | 5 +- src/Formats/MarkdownFormatService.kt | 4 +- src/Formats/StandardFormats.kt | 47 +++++++++ src/Formats/YamlOutlineService.kt | 3 +- src/Generation/FileGenerator.kt | 37 +++++--- src/Generation/Generator.kt | 15 +++ src/Locations/FoldersLocationService.kt | 5 +- src/Locations/LocationService.kt | 2 + src/Locations/SingleFolderLocationService.kt | 6 +- src/Utilities/GuiceModule.kt | 58 ++++++++++++ src/Utilities/ServiceLocator.kt | 105 +++++++++++++++++++++ src/main.kt | 37 ++------ test/src/format/HtmlFormatTest.kt | 4 +- 36 files changed, 385 insertions(+), 79 deletions(-) create mode 100644 .idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_runtime_0_1_SNAPSHOT.xml create mode 100644 .idea/libraries/Gradle__org_jetbrains_kotlin_kotlin_stdlib_0_1_SNAPSHOT.xml create mode 100644 .idea/libraries/com_google_inject_guice_4_0.xml create mode 100644 javadoc/src/main/kotlin/dokka-adapters.kt delete mode 100644 javadoc/src/main/kotlin/main.kt create mode 100644 javadoc/src/main/resources/dokka/generator/javadoc.properties create mode 100644 javadoc/src/main/resources/format/javadoc.properties create mode 100644 lib/aopalliance-1.0.jar create mode 100644 lib/guice-4.0.jar create mode 100644 lib/javax.inject-1.jar create mode 100644 resources/dokka/format/html.properties create mode 100644 resources/dokka/format/jekyll.properties create mode 100644 resources/dokka/format/kotlin-website.properties create mode 100644 resources/dokka/format/markdown.properties create mode 100644 resources/dokka/generator/default.properties create mode 100644 resources/dokka/language/java.properties create mode 100644 resources/dokka/language/kotlin.properties create mode 100644 resources/dokka/outline/yaml.properties create mode 100644 src/Formats/FormatDescriptor.kt create mode 100644 src/Formats/StandardFormats.kt create mode 100644 src/Generation/Generator.kt create mode 100644 src/Utilities/GuiceModule.kt create mode 100644 src/Utilities/ServiceLocator.kt (limited to 'src') 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 @@ + + + + + + + + + + + + \ 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 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/com_google_inject_guice_4_0.xml b/.idea/libraries/com_google_inject_guice_4_0.xml new file mode 100644 index 00000000..99d2a5e4 --- /dev/null +++ b/.idea/libraries/com_google_inject_guice_4_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/dokka.iml b/dokka.iml index 67890338..de1cf90b 100644 --- a/dokka.iml +++ b/dokka.iml @@ -23,5 +23,6 @@ + \ No newline at end of file diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index fe66a672..aa1e01a6 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -472,7 +472,7 @@ fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) = .map { module.allTypes[it?.qualifiedName] } .filterNotNull() -class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { +class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { val allPackages = module.members(DocumentationNode.Kind.Package).toMap { it.name } val allTypes = module.members(DocumentationNode.Kind.Package) .flatMap { it.members(DocumentationNode.Kind.Class) + it.members(DocumentationNode.Kind.Interface) + it.members(DocumentationNode.Kind.Enum) } @@ -486,8 +486,10 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR .toTypedArray() override fun options(): Array> = arrayOf( - arrayOf("-d", "out/javadoc"), - arrayOf("-docencoding", "UTF-8") + arrayOf("-d", outputPath), + arrayOf("-docencoding", "UTF-8"), + arrayOf("-charset", "UTF-8"), + arrayOf("-keywords") ) override fun specifiedPackages(): Array? = module.members(DocumentationNode.Kind.Package).map { PackageAdapter(this, it) }.toTypedArray() diff --git a/javadoc/src/main/kotlin/dokka-adapters.kt b/javadoc/src/main/kotlin/dokka-adapters.kt new file mode 100644 index 00000000..c9183d50 --- /dev/null +++ b/javadoc/src/main/kotlin/dokka-adapters.kt @@ -0,0 +1,29 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.tools.doclets.formats.html.HtmlDoclet +import org.jetbrains.dokka.* +import org.jetbrains.dokka.Formats.FormatDescriptor + +class JavadocGenerator(val conf: DokkaGenerator) : Generator { + override fun buildPages(nodes: Iterable) { + val module = nodes.single() as DocumentationModule + + DokkaConsoleLogger.report() + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter, conf.outputDir)) + } + + override fun buildOutlines(nodes: Iterable) { + // no outline could be generated separately + } +} + +class JavadocFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class? + get() = null + override val outlineServiceClass: Class? + get() = null + + override val generatorServiceClass: Class + get() = javaClass() +} + diff --git a/javadoc/src/main/kotlin/main.kt b/javadoc/src/main/kotlin/main.kt deleted file mode 100644 index 0c3821c3..00000000 --- a/javadoc/src/main/kotlin/main.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.tools.doclets.formats.html.HtmlDoclet -import org.jetbrains.dokka.DocumentationOptions -import org.jetbrains.dokka.DokkaConsoleLogger -import org.jetbrains.dokka.DokkaGenerator -import org.jetbrains.dokka.buildDocumentationModule -import java.io.File - -/** - * Test me, my friend - */ -public fun main(args: Array) { - val generator = DokkaGenerator(DokkaConsoleLogger, System.getProperty("java.class.path").split(File.pathSeparator), listOf(File("test").absolutePath), emptyList(), emptyList(), "me", "out/dokka", "html", emptyList(), false) - val env = generator.createAnalysisEnvironment() - val module = buildDocumentationModule(env, generator.moduleName, DocumentationOptions(includeNonPublic = true, sourceLinks = emptyList()), emptyList(), { - generator.isSample(it) - }, generator.logger) - - DokkaConsoleLogger.report() - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter)) -} - -public fun String.a(): Int = 1 \ No newline at end of file diff --git a/javadoc/src/main/resources/dokka/generator/javadoc.properties b/javadoc/src/main/resources/dokka/generator/javadoc.properties new file mode 100644 index 00000000..4075704f --- /dev/null +++ b/javadoc/src/main/resources/dokka/generator/javadoc.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.javadoc.JavadocGenerator +description=Produces output via JDK javadoc tool \ No newline at end of file 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/aopalliance-1.0.jar b/lib/aopalliance-1.0.jar new file mode 100644 index 00000000..578b1a0c Binary files /dev/null and b/lib/aopalliance-1.0.jar differ diff --git a/lib/guice-4.0.jar b/lib/guice-4.0.jar new file mode 100644 index 00000000..f4fc9ffd Binary files /dev/null and b/lib/guice-4.0.jar differ diff --git a/lib/javax.inject-1.jar b/lib/javax.inject-1.jar new file mode 100644 index 00000000..b2a9d0bf Binary files /dev/null and b/lib/javax.inject-1.jar differ diff --git a/resources/dokka/format/html.properties b/resources/dokka/format/html.properties new file mode 100644 index 00000000..7881dfae --- /dev/null +++ b/resources/dokka/format/html.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.HtmlFormatDescriptor +description=Produces output in HTML format \ No newline at end of file diff --git a/resources/dokka/format/jekyll.properties b/resources/dokka/format/jekyll.properties new file mode 100644 index 00000000..b11401a4 --- /dev/null +++ b/resources/dokka/format/jekyll.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.JekyllFormatDescriptor +description=Produces documentation in Jekyll format \ No newline at end of file diff --git a/resources/dokka/format/kotlin-website.properties b/resources/dokka/format/kotlin-website.properties new file mode 100644 index 00000000..c13e7675 --- /dev/null +++ b/resources/dokka/format/kotlin-website.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.KotlinWebsiteFormatDescriptor +description=Generates Kotlin website documentation \ No newline at end of file diff --git a/resources/dokka/format/markdown.properties b/resources/dokka/format/markdown.properties new file mode 100644 index 00000000..6217a6df --- /dev/null +++ b/resources/dokka/format/markdown.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.MarkdownFormatDescriptor +description=Produces documentation in markdown format \ No newline at end of file diff --git a/resources/dokka/generator/default.properties b/resources/dokka/generator/default.properties new file mode 100644 index 00000000..a4a16200 --- /dev/null +++ b/resources/dokka/generator/default.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.FileGenerator +description=Default documentation generator \ No newline at end of file diff --git a/resources/dokka/language/java.properties b/resources/dokka/language/java.properties new file mode 100644 index 00000000..ab42f532 --- /dev/null +++ b/resources/dokka/language/java.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.JavaLanguageService \ No newline at end of file diff --git a/resources/dokka/language/kotlin.properties b/resources/dokka/language/kotlin.properties new file mode 100644 index 00000000..16092007 --- /dev/null +++ b/resources/dokka/language/kotlin.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.KotlinLanguageService \ No newline at end of file diff --git a/resources/dokka/outline/yaml.properties b/resources/dokka/outline/yaml.properties new file mode 100644 index 00000000..7268af37 --- /dev/null +++ b/resources/dokka/outline/yaml.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.YamlOutlineService \ No newline at end of file diff --git a/src/Formats/FormatDescriptor.kt b/src/Formats/FormatDescriptor.kt new file mode 100644 index 00000000..beff730f --- /dev/null +++ b/src/Formats/FormatDescriptor.kt @@ -0,0 +1,11 @@ +package org.jetbrains.dokka.Formats + +import org.jetbrains.dokka.FormatService +import org.jetbrains.dokka.Generator +import org.jetbrains.dokka.OutlineFormatService + +public interface FormatDescriptor { + val formatServiceClass: Class? + val outlineServiceClass: Class? + val generatorServiceClass: Class +} \ No newline at end of file diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt index 78d3cff2..5dcd432b 100644 --- a/src/Formats/HtmlFormatService.kt +++ b/src/Formats/HtmlFormatService.kt @@ -1,10 +1,12 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File -public open class HtmlFormatService(locationService: LocationService, +public open class HtmlFormatService @Inject constructor(@Named("folders") locationService: LocationService, signatureGenerator: LanguageService, - val templateService: HtmlTemplateService = HtmlTemplateService.default()) + val templateService: HtmlTemplateService) : StructuredFormatService(locationService, signatureGenerator, "html"), OutlineFormatService { override public fun formatText(text: String): String { return text.htmlEscape() diff --git a/src/Formats/JekyllFormatService.kt b/src/Formats/JekyllFormatService.kt index e4c3ccd5..113f229f 100644 --- a/src/Formats/JekyllFormatService.kt +++ b/src/Formats/JekyllFormatService.kt @@ -1,6 +1,8 @@ package org.jetbrains.dokka -public open class JekyllFormatService(locationService: LocationService, +import com.google.inject.Inject + +public open class JekyllFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : MarkdownFormatService(locationService, signatureGenerator) { diff --git a/src/Formats/KotlinWebsiteFormatService.kt b/src/Formats/KotlinWebsiteFormatService.kt index 21fc9dae..8fbebaae 100644 --- a/src/Formats/KotlinWebsiteFormatService.kt +++ b/src/Formats/KotlinWebsiteFormatService.kt @@ -1,8 +1,11 @@ package org.jetbrains.dokka -public class KotlinWebsiteFormatService(locationService: LocationService, +import com.google.inject.Inject + +public class KotlinWebsiteFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : JekyllFormatService(locationService, signatureGenerator) { + override fun appendFrontMatter(nodes: Iterable, to: StringBuilder) { super.appendFrontMatter(nodes, to) to.appendln("layout: api") diff --git a/src/Formats/MarkdownFormatService.kt b/src/Formats/MarkdownFormatService.kt index ba7d8f7b..29a9f5c4 100644 --- a/src/Formats/MarkdownFormatService.kt +++ b/src/Formats/MarkdownFormatService.kt @@ -1,7 +1,9 @@ package org.jetbrains.dokka +import com.google.inject.Inject -public open class MarkdownFormatService(locationService: LocationService, + +public open class MarkdownFormatService @Inject constructor(locationService: LocationService, signatureGenerator: LanguageService) : StructuredFormatService(locationService, signatureGenerator, "md") { override public fun formatBreadcrumbs(items: Iterable): String { diff --git a/src/Formats/StandardFormats.kt b/src/Formats/StandardFormats.kt new file mode 100644 index 00000000..1d5ffe13 --- /dev/null +++ b/src/Formats/StandardFormats.kt @@ -0,0 +1,47 @@ +package org.jetbrains.dokka.Formats + +import org.jetbrains.dokka.* + +class HtmlFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class + get() = javaClass() + + override val outlineServiceClass: Class + get() = javaClass() + + override val generatorServiceClass: Class + get() = javaClass() +} + +class KotlinWebsiteFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class + get() = javaClass() + + override val outlineServiceClass: Class + get() = javaClass() + + override val generatorServiceClass: Class + get() = javaClass() +} + +class JekyllFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class + get() = javaClass() + + override val outlineServiceClass: Class? + get() = null + + override val generatorServiceClass: Class + get() = javaClass() +} + +class MarkdownFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class + get() = javaClass() + + override val outlineServiceClass: Class? + get() = null + + override val generatorServiceClass: Class + get() = javaClass() +} diff --git a/src/Formats/YamlOutlineService.kt b/src/Formats/YamlOutlineService.kt index cdab4eeb..7968824c 100644 --- a/src/Formats/YamlOutlineService.kt +++ b/src/Formats/YamlOutlineService.kt @@ -1,8 +1,9 @@ package org.jetbrains.dokka +import com.google.inject.Inject import java.io.File -class YamlOutlineService(val locationService: LocationService, +class YamlOutlineService @Inject constructor(val locationService: LocationService, val languageService: LanguageService) : OutlineFormatService { override fun getOutlineFileName(location: Location): File = File("${location.path}.yml") diff --git a/src/Generation/FileGenerator.kt b/src/Generation/FileGenerator.kt index abe4257f..08a885ab 100644 --- a/src/Generation/FileGenerator.kt +++ b/src/Generation/FileGenerator.kt @@ -1,36 +1,41 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import java.io.File import java.io.FileOutputStream +import java.io.IOException import java.io.OutputStreamWriter -public class FileGenerator(val signatureGenerator: LanguageService, - val locationService: FileLocationService, +public class FileGenerator @Inject constructor(val locationService: FileLocationService, val formatService: FormatService, - val outlineService: OutlineFormatService?) { + @Inject(optional = true) val outlineService: OutlineFormatService?) : Generator { - public fun buildPage(node: DocumentationNode): Unit = buildPages(listOf(node)) - public fun buildOutline(node: DocumentationNode): Unit = buildOutlines(listOf(node)) + override fun buildPages(nodes: Iterable) { + val specificLocationService = locationService.withExtension(formatService.extension) - public fun buildPages(nodes: Iterable) { - for ((location, items) in nodes.groupBy { locationService.location(it) }) { + for ((location, items) in nodes.groupBy { specificLocationService.location(it) }) { val file = location.file - file.getParentFile()?.mkdirs() - FileOutputStream(file).use { - OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(formatService.format(location, items)) + file.parentFile?.mkdirsOrFail() + try { + FileOutputStream(file).use { + OutputStreamWriter(it, Charsets.UTF_8).use { + it.write(formatService.format(location, items)) + } } + } catch (e: Throwable) { + println(e) } buildPages(items.flatMap { it.members }) } } - public fun buildOutlines(nodes: Iterable) { + override fun buildOutlines(nodes: Iterable) { if (outlineService == null) { return } for ((location, items) in nodes.groupBy { locationService.location(it) }) { val file = outlineService.getOutlineFileName(location) - file.getParentFile()?.mkdirs() + file.parentFile?.mkdirsOrFail() FileOutputStream(file).use { OutputStreamWriter(it, Charsets.UTF_8).use { it.write(outlineService.formatOutline(location, items)) @@ -38,4 +43,10 @@ public class FileGenerator(val signatureGenerator: LanguageService, } } } +} + +private fun File.mkdirsOrFail() { + if (!mkdirs() && !exists()) { + throw IOException("Failed to create directory $this") + } } \ No newline at end of file diff --git a/src/Generation/Generator.kt b/src/Generation/Generator.kt new file mode 100644 index 00000000..7dcabb0b --- /dev/null +++ b/src/Generation/Generator.kt @@ -0,0 +1,15 @@ +package org.jetbrains.dokka + +public interface Generator { + fun buildPages(nodes: Iterable) + fun buildOutlines(nodes: Iterable) + + final fun buildAll(nodes: Iterable) { + buildPages(nodes) + buildOutlines(nodes) + } + + final fun buildPage(node: DocumentationNode): Unit = buildPages(listOf(node)) + final fun buildOutline(node: DocumentationNode): Unit = buildOutlines(listOf(node)) + final fun buildAll(node: DocumentationNode): Unit = buildAll(listOf(node)) +} diff --git a/src/Locations/FoldersLocationService.kt b/src/Locations/FoldersLocationService.kt index e85c2c98..8a0cf6be 100644 --- a/src/Locations/FoldersLocationService.kt +++ b/src/Locations/FoldersLocationService.kt @@ -1,9 +1,12 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File public fun FoldersLocationService(root: String): FoldersLocationService = FoldersLocationService(File(root), "") -public class FoldersLocationService(val root: File, val extension: String) : FileLocationService { +public class FoldersLocationService @Inject constructor(@Named("outputDir") val root: File, val extension: String) : FileLocationService { + override fun withExtension(newExtension: String): FileLocationService { return if (extension.isEmpty()) FoldersLocationService(root, newExtension) else this } diff --git a/src/Locations/LocationService.kt b/src/Locations/LocationService.kt index 7d0b8b56..000b2c5e 100644 --- a/src/Locations/LocationService.kt +++ b/src/Locations/LocationService.kt @@ -55,6 +55,8 @@ public interface LocationService { public interface FileLocationService: LocationService { + override fun withExtension(newExtension: String): FileLocationService = this + override fun location(node: DocumentationNode): FileLocation = location(node.path.map { it.name }, node.members.any()) override fun location(qualifiedName: List, hasMembers: Boolean): FileLocation } diff --git a/src/Locations/SingleFolderLocationService.kt b/src/Locations/SingleFolderLocationService.kt index c26d2b34..049636c0 100644 --- a/src/Locations/SingleFolderLocationService.kt +++ b/src/Locations/SingleFolderLocationService.kt @@ -1,10 +1,12 @@ package org.jetbrains.dokka +import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File public fun SingleFolderLocationService(root: String): SingleFolderLocationService = SingleFolderLocationService(File(root), "") -public class SingleFolderLocationService(val root: File, val extension: String) : FileLocationService { - override fun withExtension(newExtension: String): LocationService = +public class SingleFolderLocationService @Inject constructor(@Named("outputDir") val root: File, val extension: String) : FileLocationService { + override fun withExtension(newExtension: String): FileLocationService = SingleFolderLocationService(root, newExtension) override fun location(qualifiedName: List, hasMembers: Boolean): FileLocation { diff --git a/src/Utilities/GuiceModule.kt b/src/Utilities/GuiceModule.kt new file mode 100644 index 00000000..4ce4863d --- /dev/null +++ b/src/Utilities/GuiceModule.kt @@ -0,0 +1,58 @@ +package org.jetbrains.dokka.Utilities + +import com.google.inject.Binder +import com.google.inject.Module +import com.google.inject.Provider +import com.google.inject.name.Names +import org.jetbrains.dokka.* +import org.jetbrains.dokka.Formats.FormatDescriptor +import java.io.File + +class GuiceModule(val config: DokkaGenerator) : Module { + override fun configure(binder: Binder) { + binder.bind(javaClass()).toInstance(config) + binder.bind(javaClass()).annotatedWith(Names.named("outputDir")).toInstance(File(config.outputDir)) + + binder.bindNameAnnotated("singleFolder") + binder.bindNameAnnotated("singleFolder") + binder.bindNameAnnotated("folders") + binder.bindNameAnnotated("folders") + + // defaults + binder.bind(javaClass()).to(javaClass()) + binder.bind(javaClass()).to(javaClass()) + binder.bind(javaClass()).to(javaClass()) + + binder.bind(javaClass()).toProvider(object : Provider { + override fun get(): HtmlTemplateService = HtmlTemplateService.default("/dokka/styles/style.css") + }) + + binder.registerCategory("language") + binder.registerCategory("outline") + binder.registerCategory("format") + binder.registerCategory("generator") + + val descriptor = ServiceLocator.lookup("format", config.outputFormat, config) + + descriptor.outlineServiceClass?.let { clazz -> + binder.bind(javaClass()).to(clazz) + } + descriptor.formatServiceClass?.let { clazz -> + binder.bind(javaClass()).to(clazz) + } + binder.bind(javaClass()).to(descriptor.generatorServiceClass) + } + +} + +private inline fun Binder.registerCategory(category: String) { + ServiceLocator.allServices(category).forEach { + @suppress("UNCHECKED_CAST") + bind(javaClass()).annotatedWith(Names.named(it.name)).to(javaClass().classLoader.loadClass(it.className) as Class) + } +} + +private inline fun Binder.bindNameAnnotated(name: String) { + bind(javaClass()).annotatedWith(Names.named(name)).to(javaClass()) +} + diff --git a/src/Utilities/ServiceLocator.kt b/src/Utilities/ServiceLocator.kt new file mode 100644 index 00000000..e2ed0499 --- /dev/null +++ b/src/Utilities/ServiceLocator.kt @@ -0,0 +1,105 @@ +package org.jetbrains.dokka.Utilities + +import org.jetbrains.dokka.DokkaGenerator +import java.io.File +import java.util.Properties +import java.util.jar.JarFile +import java.util.zip.ZipEntry + +data class ServiceDescriptor(val name: String, val category: String, val description: String?, val className: String) + +class ServiceLookupException(message: String) : Exception(message) + +public object ServiceLocator { + public fun lookup(clazz: Class, category: String, implementationName: String, conf: DokkaGenerator): T { + val descriptor = lookupDescriptor(category, implementationName) + 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() } + .firstOrNull() ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor") + + val implementationRawType: Any = if (constructor.parameterTypes.isEmpty()) constructor.newInstance() else constructor.newInstance(constructor) + + if (!clazz.isInstance(implementationRawType)) { + throw ServiceLookupException("Class ${descriptor.className} is not a subtype of ${clazz.name}") + } + + @suppress("UNCHECKED_CAST") + return implementationRawType as T + } + + public fun lookupClass(clazz: Class, category: String, implementationName: String): Class = lookupDescriptor(category, implementationName).className.let { className -> + javaClass.classLoader.loadClass(className).let { loaded -> + if (!clazz.isAssignableFrom(loaded)) { + throw ServiceLookupException("Class $className is not a subtype of ${clazz.name}") + } + + @suppress("UNCHECKED_CAST") + val casted = loaded as Class + + casted + } + } + + private fun lookupDescriptor(category: String, implementationName: String): ServiceDescriptor { + val properties = javaClass.classLoader.getResourceAsStream("dokka/$category/$implementationName.properties")?.use { stream -> + Properties().let { properties -> + properties.load(stream) + properties + } + } ?: throw ServiceLookupException("No implementation with name $implementationName found in category $category") + + val className = properties["class"]?.toString() ?: throw ServiceLookupException("Implementation $implementationName has no class configured") + + return ServiceDescriptor(implementationName, category, properties["description"]?.toString(), className) + } + + fun allServices(category: String): List = javaClass.classLoader.getResourceAsStream("dokka/$category")?.use { stream -> + val entries = this.javaClass.classLoader.getResources("dokka/$category")?.toList() ?: emptyList() + + entries.flatMap { + when (it.protocol) { + "file" -> File(it.file).listFiles()?.filter { it.extension == "properties" }?.map { lookupDescriptor(category, it.nameWithoutExtension) } ?: emptyList() + "jar" -> { + val file = JarFile(it.file.removePrefix("file:").substringBefore("!")) + try { + val jarPath = it.file.substringAfterLast("!").removePrefix("/") + file.entries() + .asSequence() + .filter { entry -> !entry.isDirectory && entry.path == jarPath && entry.extension == "properties" } + .map { entry -> + lookupDescriptor(category, entry.fileName.substringBeforeLast(".")) + }.toList() + } finally { + file.close() + } + } + else -> emptyList() + } + } + } ?: emptyList() +} + +public inline fun ServiceLocator.lookup(category: String, implementationName: String, conf: DokkaGenerator): T = lookup(javaClass(), category, implementationName, conf) +public inline fun ServiceLocator.lookupClass(category: String, implementationName: String): Class = lookupClass(javaClass(), category, implementationName) +public inline fun ServiceLocator.lookupOrNull(category: String, implementationName: String, conf: DokkaGenerator): T? = try { + lookup(javaClass(), category, implementationName, conf) +} catch (any: Throwable) { + null +} + +fun main(args: Array) { + ServiceLocator.allServices("format").forEach { + println(it) + } +} + +private val ZipEntry.fileName: String + get() = name.substringAfterLast("/", name) + +private val ZipEntry.path: String + get() = name.substringBeforeLast("/", "").removePrefix("/") + +private val ZipEntry.extension: String? + get() = fileName.let { fn -> if ("." in fn) fn.substringAfterLast(".") else null } diff --git a/src/main.kt b/src/main.kt index 4a0c22f8..29a22672 100644 --- a/src/main.kt +++ b/src/main.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import com.google.inject.Guice import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile @@ -7,6 +8,7 @@ import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import com.sampullara.cli.Args import com.sampullara.cli.Argument +import org.jetbrains.dokka.Utilities.GuiceModule import org.jetbrains.kotlin.cli.common.arguments.ValueDescription import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -17,6 +19,7 @@ import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.utils.PathUtil 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)") @@ -141,8 +144,8 @@ class DokkaGenerator(val logger: DokkaLogger, fun generate() { val environment = createAnalysisEnvironment() - logger.info("Module: ${moduleName}") - logger.info("Output: ${File(outputDir).getAbsolutePath()}") + logger.info("Module: $moduleName") + logger.info("Output: ${File(outputDir).absolutePath}") logger.info("Sources: ${environment.sources.join()}") logger.info("Classpath: ${environment.classpath.joinToString()}") @@ -155,34 +158,12 @@ class DokkaGenerator(val logger: DokkaLogger, val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") - val startBuild = System.currentTimeMillis() - val signatureGenerator = KotlinLanguageService() - val locationService = FoldersLocationService(outputDir) - val templateService = HtmlTemplateService.default("/dokka/styles/style.css") - - val (formatter, outlineFormatter) = when (outputFormat) { - "html" -> { - val htmlFormatService = HtmlFormatService(locationService, signatureGenerator, templateService) - htmlFormatService to htmlFormatService - } - "markdown" -> MarkdownFormatService(locationService, signatureGenerator) to null - "jekyll" -> JekyllFormatService(locationService.withExtension("html"), signatureGenerator) to null - "kotlin-website" -> KotlinWebsiteFormatService(locationService.withExtension("html"), signatureGenerator) to - YamlOutlineService(locationService, signatureGenerator) - else -> { - logger.error("Unrecognized output format ${outputFormat}") - null to null - } + val timeBuild = measureTimeMillis { + logger.info("Generating pages... ") + Guice.createInjector(GuiceModule(this)).getInstance(javaClass()).buildAll(documentation) } - if (formatter == null) return - - val generator = FileGenerator(signatureGenerator, locationService.withExtension(formatter.extension), - formatter, outlineFormatter) - logger.info("Generating pages... ") - generator.buildPage(documentation) - generator.buildOutline(documentation) - val timeBuild = System.currentTimeMillis() - startBuild logger.info("done in ${timeBuild / 1000} secs") + Disposer.dispose(environment) } diff --git a/test/src/format/HtmlFormatTest.kt b/test/src/format/HtmlFormatTest.kt index 3d744b95..b7fef79f 100644 --- a/test/src/format/HtmlFormatTest.kt +++ b/test/src/format/HtmlFormatTest.kt @@ -1,15 +1,15 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.HtmlFormatService +import org.jetbrains.dokka.HtmlTemplateService import org.jetbrains.dokka.KotlinLanguageService import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot -import org.jetbrains.kotlin.config.ContentRoot import org.jetbrains.kotlin.config.KotlinSourceRoot import org.junit.Test import java.io.File public class HtmlFormatTest { - private val htmlService = HtmlFormatService(InMemoryLocationService, KotlinLanguageService()) + private val htmlService = HtmlFormatService(InMemoryLocationService, KotlinLanguageService(), HtmlTemplateService.default()) Test fun classWithCompanionObject() { verifyOutput("test/data/format/classWithCompanionObject.kt", ".html") { model, output -> -- cgit From e1f7ce7a16954d238345fe0e30257492c0886f37 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Tue, 4 Aug 2015 18:47:25 +0300 Subject: ~ see also --- javadoc/src/main/kotlin/docbase.kt | 2 +- src/Java/JavaDocumentationBuilder.kt | 2 +- src/Kotlin/DocumentationBuilder.kt | 2 +- src/Model/Content.kt | 7 +++++-- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index aa1e01a6..a513a3e1 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -57,7 +57,7 @@ open class DocumentationNodeAdapter(val module: ModuleNodeAdapter, docNode: Docu override fun firstSentenceTags(): Array = buildInlineTags(module, this, docNode.summary).toTypedArray() override fun tags(): Array = (buildInlineTags(module, this, docNode.content) + docNode.content.sections.flatMap { when (it.tag) { - "See Also" -> buildInlineTags(module, this, it) + ContentTags.SeeAlso -> buildInlineTags(module, this, it) else -> emptyList() } }).toTypedArray() diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaDocumentationBuilder.kt index fdd385fb..aae82c18 100644 --- a/src/Java/JavaDocumentationBuilder.kt +++ b/src/Java/JavaDocumentationBuilder.kt @@ -112,7 +112,7 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, if (linkElement == null) { return } - val seeSection = findSectionByTag("See Also") ?: addSection("See Also", null) + val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) val linkSignature = resolveLink(linkElement) val text = ContentText(linkElement.getText()) if (linkSignature != null) { diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index eda69841..8e36ae43 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -210,7 +210,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, private fun MutableContent.addTagToSeeAlso(descriptor: DeclarationDescriptor, seeTag: KDocTag) { val subjectName = seeTag.getSubjectName() if (subjectName != null) { - val seeSection = findSectionByTag("See Also") ?: addSection("See Also", null) + val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) val link = resolveContentLink(descriptor, subjectName) link.append(ContentText(subjectName)) val para = ContentParagraph() diff --git a/src/Model/Content.kt b/src/Model/Content.kt index 032de268..cd387b61 100644 --- a/src/Model/Content.kt +++ b/src/Model/Content.kt @@ -1,7 +1,5 @@ package org.jetbrains.dokka -import kotlin.properties.Delegates - public abstract class ContentNode public object ContentEmpty : ContentNode() @@ -87,6 +85,11 @@ public class ContentSection(public val tag: String, public val subjectName: Stri children.hashCode() * 31 * 31 + tag.hashCode() * 31 + (subjectName?.hashCode() ?: 0) } +public object ContentTags { + val Description = "Description" + val SeeAlso = "See Also" +} + fun content(body: ContentBlock.() -> Unit): ContentBlock { val block = ContentBlock() block.body() -- cgit From 4ed808d935125ab370d988f9cb32d96839959964 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 11:36:38 +0300 Subject: ~ description constant --- src/Formats/StructuredFormatService.kt | 2 +- src/Model/Content.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt index a90c60b1..1c2e5338 100644 --- a/src/Formats/StructuredFormatService.kt +++ b/src/Formats/StructuredFormatService.kt @@ -139,7 +139,7 @@ public abstract class StructuredFormatService(locationService: LocationService, fun appendDescription(location: Location, to: StringBuilder, node: DocumentationNode) { if (node.content.description != ContentEmpty) { - appendHeader(to, "Description", 3) + appendHeader(to, ContentTags.Description, 3) appendLine(to, formatText(location, node.content.description)) appendLine(to) } diff --git a/src/Model/Content.kt b/src/Model/Content.kt index cd387b61..0bb78454 100644 --- a/src/Model/Content.kt +++ b/src/Model/Content.kt @@ -150,7 +150,7 @@ public open class MutableContent() : Content() { if (descriptionNodes.isEmpty()) { ContentEmpty } else { - val result = ContentSection("Description", null) + val result = ContentSection(ContentTags.Description, null) result.children.addAll(descriptionNodes) result } -- cgit From 9b0c1b9b0d132aba484cafbb7e12d2e132522715 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 11:52:46 +0300 Subject: ~ move array type conversion to JavaLanguageService --- javadoc/src/main/kotlin/docbase.kt | 27 ++++++--------------------- src/Languages/JavaLanguageService.kt | 12 ++++++++++++ 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index bafc96eb..4e822fc8 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -139,29 +139,14 @@ class ProgramElementAdapter(module: ModuleNodeAdapter, val node: DocumentationNo override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true } -public fun DocumentationNode.getArrayElementType(): DocumentationNode? = when (name) { - "Array" -> details(DocumentationNode.Kind.Type).singleOrNull()?.let { et -> et.getArrayElementType() ?: et } ?: DocumentationNode("Object", content, DocumentationNode.Kind.ExternalClass) - "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> DocumentationNode(name.removeSuffix("Array").toLowerCase(), content, DocumentationNode.Kind.Type) - else -> null -} - -fun DocumentationNode.getArrayDimension(): Int = when (name) { - "Array" -> 1 + (details(DocumentationNode.Kind.Type).singleOrNull()?.getArrayDimension() ?: 0) - "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> 1 - else -> 0 -} - -//fun DocumentationNode.convertNativeType(): DocumentationNode = when (name) { -// "Unit" -> DocumentationNode("void", content, kind) -// "Int" -> DocumentationNode("int", content, kind) -//} - open class TypeAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : Type { - override fun qualifiedTypeName(): String = node.getArrayElementType()?.qualifiedName ?: node.qualifiedName - override fun typeName(): String = node.getArrayElementType()?.name ?: node.name + private val javaLanguageService = JavaLanguageService() + + override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedName ?: node.qualifiedName + override fun typeName(): String = javaLanguageService.getArrayElementType(node)?.name ?: node.name override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName() - override fun dimension(): String = Collections.nCopies(node.getArrayDimension(), "[]").joinToString("") + override fun dimension(): String = Collections.nCopies(javaLanguageService.getArrayDimension(node), "[]").joinToString("") override fun isPrimitive(): Boolean = node.name in setOf("Int", "Long", "Short", "Byte", "Char", "Double", "Float", "Boolean", "Unit") override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else elementType?.asClassDoc() ?: @@ -186,7 +171,7 @@ open class TypeAdapter(val module: ModuleNodeAdapter, val node: DocumentationNod override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == DocumentationNode.Kind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null - override fun getElementType(): Type? = node.getArrayElementType()?.let { et -> TypeAdapter(module, et) } + override fun getElementType(): Type? = javaLanguageService.getArrayElementType(node)?.let { et -> TypeAdapter(module, et) } override fun asWildcardType(): WildcardType? = null override fun toString(): String = qualifiedTypeName() + dimension() diff --git a/src/Languages/JavaLanguageService.kt b/src/Languages/JavaLanguageService.kt index ad8307c1..488a2dc4 100644 --- a/src/Languages/JavaLanguageService.kt +++ b/src/Languages/JavaLanguageService.kt @@ -46,6 +46,18 @@ public class JavaLanguageService : LanguageService { } } + public fun getArrayElementType(node: DocumentationNode): DocumentationNode? = when (node.name) { + "Array" -> node.details(Kind.Type).singleOrNull()?.let { et -> getArrayElementType(et) ?: et } ?: DocumentationNode("Object", node.content, DocumentationNode.Kind.ExternalClass) + "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> DocumentationNode(node.name.removeSuffix("Array").toLowerCase(), node.content, DocumentationNode.Kind.Type) + else -> null + } + + public fun getArrayDimension(node: DocumentationNode): Int = when (node.name) { + "Array" -> 1 + (node.details(DocumentationNode.Kind.Type).singleOrNull()?.let { getArrayDimension(it) } ?: 0) + "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> 1 + else -> 0 + } + public fun renderType(node: DocumentationNode): String { return when (node.name) { "Unit" -> "void" -- cgit From b0b94df732fc6fa7a8c64da2398d729e57af74ca Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 14:35:24 +0300 Subject: ~ remove unused function --- src/Kotlin/DocumentationBuilder.kt | 7 ------- 1 file changed, 7 deletions(-) (limited to 'src') diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index 8e36ae43..7f3063af 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -17,9 +17,7 @@ import org.jetbrains.kotlin.lexer.JetSingleValueToken import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.JetParameter 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.lazy.ResolveSession import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi @@ -697,11 +695,6 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return node } - fun CompileTimeConstant.build(): DocumentationNode? = when (this) { - is TypedCompileTimeConstant -> constantValue.toDocumentationNode() - else -> null - } - fun ConstantValue<*>.toDocumentationNode(): DocumentationNode? = value?.let { value -> when (value) { is String -> -- cgit From 97bea8c614bfea408c845f07ddc42c29db1e81ba Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 14:43:37 +0300 Subject: ~ Use new property access syntax --- src/Kotlin/DocumentationBuilder.kt | 224 ++++++++++++++++++------------------- 1 file changed, 112 insertions(+), 112 deletions(-) (limited to 'src') diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index 7f3063af..6bfeb360 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -69,13 +69,13 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, if (kdoc is KDocSection) { val tags = kdoc.getTags() tags.forEach { - when (it.getName()) { + when (it.name) { "sample" -> content.append(functionBody(descriptor, it.getSubjectName())) "see" -> content.addTagToSeeAlso(descriptor, it) else -> { - val section = content.addSection(javadocSectionDisplayName(it.getName()), it.getSubjectName()) + val section = content.addSection(javadocSectionDisplayName(it.name), it.getSubjectName()) val sectionContent = it.getContent() val markdownNode = parseMarkdown(sectionContent) buildInlineContentTo(markdownNode, section, { href -> resolveContentLink(descriptor, href) }) @@ -94,16 +94,16 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, if (descriptor !is CallableMemberDescriptor) { return null } - val name = descriptor.getName().asString() + val name = descriptor.name.asString() if (name == "equals" || name == "hashCode" || name == "toString") { var deepestDescriptor: CallableMemberDescriptor = descriptor - while (!deepestDescriptor.getOverriddenDescriptors().isEmpty()) { - deepestDescriptor = deepestDescriptor.getOverriddenDescriptors().first() + while (!deepestDescriptor.overriddenDescriptors.isEmpty()) { + deepestDescriptor = deepestDescriptor.overriddenDescriptors.first() } - if (DescriptorUtils.getFqName(deepestDescriptor.getContainingDeclaration()).asString() == "kotlin.Any") { + if (DescriptorUtils.getFqName(deepestDescriptor.containingDeclaration).asString() == "kotlin.Any") { val anyClassDescriptors = session.getTopLevelClassDescriptors(FqName.fromSegments(listOf("kotlin", "Any"))) anyClassDescriptors.forEach { - val anyMethod = it.getMemberScope(listOf()).getFunctions(descriptor.getName()).single() + val anyMethod = it.getMemberScope(listOf()).getFunctions(descriptor.name).single() val kdoc = KDocFinder.findKDoc(anyMethod) if (kdoc != null) { return kdoc @@ -114,51 +114,51 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return null } - fun DeclarationDescriptor.isDeprecated(): Boolean = getAnnotations().any { - DescriptorUtils.getFqName(it.getType().getConstructor().getDeclarationDescriptor()!!).asString() == "kotlin.deprecated" - } || (this is ConstructorDescriptor && getContainingDeclaration().isDeprecated()) + fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any { + DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.deprecated" + } || (this is ConstructorDescriptor && containingDeclaration.isDeprecated()) fun DeclarationDescriptor.signature(): String = when(this) { is ClassDescriptor, is PackageFragmentDescriptor -> DescriptorUtils.getFqName(this).asString() - is PropertyDescriptor -> getContainingDeclaration().signature() + "#" + getName() + receiverSignature() - is FunctionDescriptor -> getContainingDeclaration().signature() + "#" + getName() + parameterSignature() - is ValueParameterDescriptor -> getContainingDeclaration().signature() + ":" + getName() - is TypeParameterDescriptor -> getContainingDeclaration().signature() + "<" + getName() + is PropertyDescriptor -> containingDeclaration.signature() + "#" + name + receiverSignature() + is FunctionDescriptor -> containingDeclaration.signature() + "#" + name + parameterSignature() + is ValueParameterDescriptor -> containingDeclaration.signature() + ":" + name + is TypeParameterDescriptor -> containingDeclaration.signature() + "<" + name else -> throw UnsupportedOperationException("Don't know how to calculate signature for $this") } fun PropertyDescriptor.receiverSignature(): String { - val receiver = getExtensionReceiverParameter() + val receiver = extensionReceiverParameter if (receiver != null) { - return "#" + receiver.getType().signature() + return "#" + receiver.type.signature() } return "" } fun CallableMemberDescriptor.parameterSignature(): String { - val params = getValueParameters().map { it.getType() }.toArrayList() - val extensionReceiver = getExtensionReceiverParameter() + val params = valueParameters.map { it.type }.toArrayList() + val extensionReceiver = extensionReceiverParameter if (extensionReceiver != null) { - params.add(0, extensionReceiver.getType()) + params.add(0, extensionReceiver.type) } return "(" + params.map { it.signature() }.join() + ")" } fun JetType.signature(): String { - val declarationDescriptor = getConstructor().getDeclarationDescriptor() ?: return "" + val declarationDescriptor = constructor.declarationDescriptor ?: return "" val typeName = DescriptorUtils.getFqName(declarationDescriptor).asString() - if (typeName == "Array" && getArguments().size() == 1) { - return "Array<" + getArguments().first().getType().signature() + ">" + if (typeName == "Array" && arguments.size() == 1) { + return "Array<" + arguments.first().type.signature() + ">" } return typeName } fun DeclarationDescriptor.sourceLocation(): String? { if (this is DeclarationDescriptorWithSource) { - val psi = (this.getSource() as? PsiSourceElement)?.getPsi() + val psi = (this.source as? PsiSourceElement)?.getPsi() if (psi != null) { - val fileName = psi.getContainingFile().getName() + val fileName = psi.containingFile.name val lineNumber = psi.lineNumber() return if (lineNumber != null) "$fileName:$lineNumber" else fileName } @@ -197,8 +197,8 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, return null } val symbol = symbols.first() - if (symbol is CallableMemberDescriptor && symbol.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - return symbol.getOverriddenDescriptors().firstOrNull() + if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + return symbol.overriddenDescriptors.firstOrNull() } return symbol } @@ -233,7 +233,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun DocumentationNode(descriptor: T, kind: Kind): DocumentationNode where T : DeclarationDescriptor, T : Named { val doc = parseDocumentation(descriptor) - val node = DocumentationNode(descriptor.getName().asString(), doc, kind).withModifiers(descriptor) + val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor) return node } @@ -248,10 +248,10 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun DocumentationNode.appendModality(descriptor: MemberDescriptor) { - var modality = descriptor.getModality() + var modality = descriptor.modality if (modality == Modality.OPEN) { - val containingClass = descriptor.getContainingDeclaration() as? ClassDescriptor - if (containingClass?.getModality() == Modality.FINAL) { + val containingClass = descriptor.containingDeclaration as? ClassDescriptor + if (containingClass?.modality == Modality.FINAL) { modality = Modality.FINAL } } @@ -260,22 +260,22 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun DocumentationNode.appendVisibility(descriptor: DeclarationDescriptorWithVisibility) { - val modifier = descriptor.getVisibility().toString() + val modifier = descriptor.visibility.toString() appendTextNode(modifier, DocumentationNode.Kind.Modifier) } fun DocumentationNode.appendSupertypes(descriptor: ClassDescriptor) { - val superTypes = descriptor.getTypeConstructor().getSupertypes() + val superTypes = descriptor.typeConstructor.supertypes for (superType in superTypes) { if (!ignoreSupertype(superType)) { appendType(superType, DocumentationNode.Kind.Supertype) - link(superType?.getConstructor()?.getDeclarationDescriptor(), descriptor, DocumentationReference.Kind.Inheritor) + link(superType?.constructor?.declarationDescriptor, descriptor, DocumentationReference.Kind.Inheritor) } } } private fun ignoreSupertype(superType: JetType): Boolean { - val superClass = superType.getConstructor().getDeclarationDescriptor() as? ClassDescriptor + val superClass = superType.constructor.declarationDescriptor as? ClassDescriptor if (superClass != null) { val fqName = DescriptorUtils.getFqNameSafe(superClass).asString() return fqName == "kotlin.Annotation" || fqName == "kotlin.Enum" || fqName == "kotlin.Any" @@ -284,31 +284,31 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun DocumentationNode.appendProjection(projection: TypeProjection, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type) { - appendType(projection.getType(), kind, projection.getProjectionKind().label) + appendType(projection.type, kind, projection.projectionKind.label) } fun DocumentationNode.appendType(jetType: JetType?, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type, prefix: String = "") { if (jetType == null) return - val classifierDescriptor = jetType.getConstructor().getDeclarationDescriptor() + val classifierDescriptor = jetType.constructor.declarationDescriptor val name = when (classifierDescriptor) { is ClassDescriptor -> { - if (classifierDescriptor.isCompanionObject()) { - classifierDescriptor.getContainingDeclaration().getName().asString() + - "." + classifierDescriptor.getName().asString() + if (classifierDescriptor.isCompanionObject) { + classifierDescriptor.containingDeclaration.name.asString() + + "." + classifierDescriptor.name.asString() } else { - classifierDescriptor.getName().asString() + classifierDescriptor.name.asString() } } - is Named -> classifierDescriptor.getName().asString() + is Named -> classifierDescriptor.name.asString() else -> "" } val node = DocumentationNode(name, Content.Empty, kind) if (prefix != "") { node.appendTextNode(prefix, Kind.Modifier) } - if (jetType.isMarkedNullable()) { + if (jetType.isMarkedNullable) { node.appendTextNode("?", Kind.NullabilityModifier) } if (classifierDescriptor != null && !classifierDescriptor.isBoringBuiltinClass()) { @@ -316,7 +316,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } append(node, DocumentationReference.Kind.Detail) - for (typeArgument in jetType.getArguments()) + for (typeArgument in jetType.arguments) node.appendProjection(typeArgument) } @@ -324,7 +324,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses fun DocumentationNode.appendAnnotations(annotated: Annotated) { - annotated.getAnnotations().forEach { + annotated.annotations.forEach { val annotationNode = it.build() if (annotationNode != null) { append(annotationNode, @@ -339,7 +339,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: DocumentationReference.Kind): DocumentationNode? { // do not include generated code - if (descriptor is CallableMemberDescriptor && descriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) + if (descriptor is CallableMemberDescriptor && descriptor.kind != CallableMemberDescriptor.Kind.DECLARATION) return null if (descriptor.isDocumented()) { @@ -353,7 +353,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, private fun DeclarationDescriptor.isDocumented(): Boolean { return (options.includeNonPublic || this !is MemberDescriptor - || this.getVisibility() in visibleToDocumentation) && + || this.visibility in visibleToDocumentation) && !isDocumentationSuppressed() && (!options.skipDeprecated || !isDeprecated()) } @@ -424,10 +424,10 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, else -> throw IllegalStateException("Descriptor $this is not known") } - fun ScriptDescriptor.build(): DocumentationNode = getClassDescriptor().build() + fun ScriptDescriptor.build(): DocumentationNode = classDescriptor.build() fun ClassDescriptor.build(): DocumentationNode { - val kind = when (getKind()) { + val kind = when (kind) { ClassKind.OBJECT -> Kind.Object ClassKind.INTERFACE -> Kind.Interface ClassKind.ENUM_CLASS -> Kind.Enum @@ -436,52 +436,52 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, else -> Kind.Class } val node = DocumentationNode(this, kind) - if (isInner()) { + if (isInner) { node.appendTextNode("inner", Kind.Modifier) } node.appendSupertypes(this) if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { - node.appendInPageChildren(getTypeConstructor().getParameters(), DocumentationReference.Kind.Detail) + node.appendInPageChildren(typeConstructor.parameters, DocumentationReference.Kind.Detail) val constructorsToDocument = if (getKind() == ClassKind.ENUM_CLASS) - getConstructors().filter { it.getValueParameters().size() > 0 } + constructors.filter { it.valueParameters.size() > 0 } else - getConstructors() + constructors node.appendChildren(constructorsToDocument, DocumentationReference.Kind.Member) } - val members = getDefaultType().getMemberScope().getAllDescriptors().filter { it != getCompanionObjectDescriptor() } + val members = defaultType.memberScope.getAllDescriptors().filter { it != companionObjectDescriptor } node.appendChildren(members, DocumentationReference.Kind.Member) - val companionObjectDescriptor = getCompanionObjectDescriptor() + val companionObjectDescriptor = companionObjectDescriptor if (companionObjectDescriptor != null) { - node.appendChildren(companionObjectDescriptor.getDefaultType().getMemberScope().getAllDescriptors(), + node.appendChildren(companionObjectDescriptor.defaultType.memberScope.getAllDescriptors(), DocumentationReference.Kind.Member) } node.appendAnnotations(this) - node.appendSourceLink(getSource()) + node.appendSourceLink(source) register(this, node) return node } fun ConstructorDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, Kind.Constructor) - node.appendInPageChildren(getValueParameters(), DocumentationReference.Kind.Detail) + node.appendInPageChildren(valueParameters, DocumentationReference.Kind.Detail) register(this, node) return node } private fun CallableMemberDescriptor.inCompanionObject(): Boolean { - val containingDeclaration = getContainingDeclaration() - if ((containingDeclaration as? ClassDescriptor)?.isCompanionObject() ?: false) { + val containingDeclaration = containingDeclaration + if ((containingDeclaration as? ClassDescriptor)?.isCompanionObject ?: false) { return true } - val receiver = getExtensionReceiverParameter() - return (receiver?.getType()?.getConstructor()?.getDeclarationDescriptor() as? ClassDescriptor)?.isCompanionObject() ?: false + val receiver = extensionReceiverParameter + return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false } fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? { - val extensionReceiver = getExtensionReceiverParameter() + val extensionReceiver = extensionReceiverParameter if (extensionReceiver != null) { - val type = extensionReceiver.getType() - return type.getConstructor().getDeclarationDescriptor() as? ClassDescriptor + val type = extensionReceiver.type + return type.constructor.declarationDescriptor as? ClassDescriptor } return null } @@ -493,15 +493,15 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, val node = DocumentationNode(this, if (inCompanionObject()) Kind.CompanionObjectFunction else Kind.Function) - node.appendInPageChildren(getTypeParameters(), DocumentationReference.Kind.Detail) - getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } - node.appendInPageChildren(getValueParameters(), DocumentationReference.Kind.Detail) - node.appendType(getReturnType()) + node.appendInPageChildren(typeParameters, DocumentationReference.Kind.Detail) + extensionReceiverParameter?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } + node.appendInPageChildren(valueParameters, DocumentationReference.Kind.Detail) + node.appendType(returnType) node.appendAnnotations(this) - node.appendSourceLink(getSource()) + node.appendSourceLink(source) node.appendOperatorOverloadNote(this) - getOverriddenDescriptors().forEach { + overriddenDescriptors.forEach { addOverrideLink(it, this) } @@ -510,11 +510,11 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun addOverrideLink(baseClassFunction: CallableMemberDescriptor, overridingFunction: CallableMemberDescriptor) { - val source = baseClassFunction.getOriginal().getSource().getPsi() + val source = baseClassFunction.original.source.getPsi() if (source != null) { link(overridingFunction, baseClassFunction, DocumentationReference.Kind.Override) } else { - baseClassFunction.getOverriddenDescriptors().forEach { + baseClassFunction.overriddenDescriptors.forEach { addOverrideLink(it, overridingFunction) } } @@ -537,36 +537,36 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun FunctionDescriptor.getImplementedOperator(): String? { - var arity = getValueParameters().size() - if (getContainingDeclaration() is ClassDescriptor) { + var arity = valueParameters.size() + if (containingDeclaration is ClassDescriptor) { arity++ } - if (getExtensionReceiverParameter() != null) { + if (extensionReceiverParameter != null) { arity++ } val token = if (arity == 2) { - OperatorConventions.BINARY_OPERATION_NAMES.inverse()[getName()] ?: - OperatorConventions.ASSIGNMENT_OPERATIONS.inverse()[getName()] ?: - OperatorConventions.BOOLEAN_OPERATIONS.inverse()[getName()] + 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()[getName()] + OperatorConventions.UNARY_OPERATION_NAMES.inverse()[name] } else null if (token is JetSingleValueToken) { - return token.getValue() + return token.value } - val name = getName().asString() + val name = name.asString() if (arity == 2 && name == "contains") { return "in" } if (arity >= 2 && (name == "get" || name == "set")) { return "[]" } - if (arity == 2 && name == "equals" && getValueParameters().size() == 1 && - KotlinBuiltIns.isNullableAny(getValueParameters().first().getType())) { + if (arity == 2 && name == "equals" && valueParameters.size() == 1 && + KotlinBuiltIns.isNullableAny(valueParameters.first().type)) { return "==" } return null @@ -574,26 +574,26 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun PropertyDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, if (inCompanionObject()) Kind.CompanionObjectProperty else Kind.Property) - node.appendInPageChildren(getTypeParameters(), DocumentationReference.Kind.Detail) - getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } - node.appendType(getReturnType()) + node.appendInPageChildren(typeParameters, DocumentationReference.Kind.Detail) + extensionReceiverParameter?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } + node.appendType(returnType) node.appendAnnotations(this) - node.appendSourceLink(getSource()) - if (isVar()) { + node.appendSourceLink(source) + if (isVar) { node.appendTextNode("var", DocumentationNode.Kind.Modifier) } - getGetter()?.let { - if (!it.isDefault()) { + getter?.let { + if (!it.isDefault) { node.addAccessorDocumentation(parseDocumentation(it), "Getter") } } - getSetter()?.let { - if (!it.isDefault()) { + setter?.let { + if (!it.isDefault) { node.addAccessorDocumentation(parseDocumentation(it), "Setter") } } - getOverriddenDescriptors().forEach { + overriddenDescriptors.forEach { addOverrideLink(it, this) } @@ -617,17 +617,17 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun ValueParameterDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, Kind.Parameter) - val varargType = getVarargElementType() + val varargType = varargElementType if (varargType != null) { node.appendTextNode("vararg", Kind.Annotation, DocumentationReference.Kind.Annotation) node.appendType(varargType) } else { - node.appendType(getType()) + node.appendType(type) } if (hasDefaultValue()) { - val psi = getSource().getPsi() as? JetParameter + val psi = source.getPsi() as? JetParameter if (psi != null) { - val defaultValueText = psi.getDefaultValue()?.getText() + val defaultValueText = psi.defaultValue?.text if (defaultValueText != null) { node.appendTextNode(defaultValueText, Kind.Value) } @@ -640,8 +640,8 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun TypeParameterDescriptor.build(): DocumentationNode { val doc = parseDocumentation(this) - val name = getName().asString() - val prefix = getVariance().label + val name = name.asString() + val prefix = variance.label val node = DocumentationNode(name, doc, DocumentationNode.Kind.TypeParameter) if (prefix != "") { @@ -649,13 +649,13 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } val builtIns = KotlinBuiltIns.getInstance() - for (constraint in getUpperBounds()) { - if (constraint == builtIns.getDefaultBound()) + for (constraint in upperBounds) { + if (constraint == builtIns.defaultBound) continue node.appendType(constraint, Kind.UpperBound) } - for (constraint in getLowerBounds()) { + for (constraint in lowerBounds) { if (KotlinBuiltIns.isNothing(constraint)) continue node.appendType(constraint, Kind.LowerBound) @@ -664,30 +664,30 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } fun ReceiverParameterDescriptor.build(): DocumentationNode { - var receiverClass: DeclarationDescriptor = getType().getConstructor().getDeclarationDescriptor()!! - if ((receiverClass as? ClassDescriptor)?.isCompanionObject() ?: false) { - receiverClass = receiverClass.getContainingDeclaration()!! + var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!! + if ((receiverClass as? ClassDescriptor)?.isCompanionObject ?: false) { + receiverClass = receiverClass.containingDeclaration!! } link(receiverClass, - getContainingDeclaration(), + containingDeclaration, DocumentationReference.Kind.Extension) - val node = DocumentationNode(getName().asString(), Content.Empty, Kind.Receiver) - node.appendType(getType()) + val node = DocumentationNode(name.asString(), Content.Empty, Kind.Receiver) + node.appendType(type) return node } fun AnnotationDescriptor.build(): DocumentationNode? { - val annotationClass = getType().getConstructor().getDeclarationDescriptor() + val annotationClass = type.constructor.declarationDescriptor if (annotationClass == null || ErrorUtils.isError(annotationClass)) { return null } - val node = DocumentationNode(annotationClass.getName().asString(), Content.Empty, DocumentationNode.Kind.Annotation) - val arguments = getAllValueArguments().toList().sortBy { it.first.getIndex() } + val node = DocumentationNode(annotationClass.name.asString(), Content.Empty, DocumentationNode.Kind.Annotation) + val arguments = allValueArguments.toList().sortBy { it.first.index } arguments.forEach { val valueNode = it.second.toDocumentationNode() if (valueNode != null) { - val paramNode = DocumentationNode(it.first.getName().asString(), Content.Empty, DocumentationNode.Kind.Parameter) + val paramNode = DocumentationNode(it.first.name.asString(), Content.Empty, DocumentationNode.Kind.Parameter) paramNode.append(valueNode, DocumentationReference.Kind.Detail) node.append(paramNode, DocumentationReference.Kind.Detail) } -- cgit From d1ff5949b5807b57eab6010175b3c6f1e7c1945c Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Fri, 7 Aug 2015 12:12:06 +0300 Subject: ~ minor cleanup --- src/Model/DocumentationNode.kt | 4 +--- src/Utilities/ServiceLocator.kt | 6 ------ 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'src') diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt index b4343347..c3b9942d 100644 --- a/src/Model/DocumentationNode.kt +++ b/src/Model/DocumentationNode.kt @@ -114,9 +114,7 @@ public open class DocumentationNode(val name: String, val DocumentationNode.path: List get() { - val parent = owner - if (parent == null) - return listOf(this) + val parent = owner ?: return listOf(this) return parent.path + this } diff --git a/src/Utilities/ServiceLocator.kt b/src/Utilities/ServiceLocator.kt index e2ed0499..b3610a53 100644 --- a/src/Utilities/ServiceLocator.kt +++ b/src/Utilities/ServiceLocator.kt @@ -89,12 +89,6 @@ public inline fun ServiceLocator.lookupOrNull(category: String null } -fun main(args: Array) { - ServiceLocator.allServices("format").forEach { - println(it) - } -} - private val ZipEntry.fileName: String get() = name.substringAfterLast("/", name) -- cgit From bdd02a3112397b711f16d411869c0c610899aebf Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Fri, 7 Aug 2015 12:32:17 +0300 Subject: ~ Use new property access syntax --- src/Analysis/AnalysisEnvironment.kt | 2 +- src/Analysis/CompilerAPI.kt | 14 ++-- src/Java/JavaDocumentationBuilder.kt | 144 +++++++++++++++++------------------ src/Kotlin/ContentBuilder.kt | 12 +-- src/Locations/LocationService.kt | 2 +- src/Utilities/Path.kt | 5 +- 6 files changed, 85 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/Analysis/AnalysisEnvironment.kt b/src/Analysis/AnalysisEnvironment.kt index 39a05604..a2836592 100644 --- a/src/Analysis/AnalysisEnvironment.kt +++ b/src/Analysis/AnalysisEnvironment.kt @@ -50,7 +50,7 @@ public class AnalysisEnvironment(val messageCollector: MessageCollector, body: A val projectComponentManager = environment.project as MockComponentManager val moduleManager = CoreModuleManager(environment.project, this) - CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.getPicoContainer(), + CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.picoContainer, javaClass(), moduleManager) projectComponentManager.registerService(javaClass(), diff --git a/src/Analysis/CompilerAPI.kt b/src/Analysis/CompilerAPI.kt index 8b877204..5ab2037b 100644 --- a/src/Analysis/CompilerAPI.kt +++ b/src/Analysis/CompilerAPI.kt @@ -1,17 +1,13 @@ package org.jetbrains.dokka -import org.jetbrains.kotlin.cli.common.arguments.* -import org.jetbrains.kotlin.cli.jvm.compiler.* -import org.jetbrains.kotlin.utils.* -import java.io.* -import org.jetbrains.kotlin.resolve.jvm.* -import org.jetbrains.kotlin.analyzer.* -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.resolve.scopes.* -import org.jetbrains.kotlin.context.GlobalContext 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 { diff --git a/src/Java/JavaDocumentationBuilder.kt b/src/Java/JavaDocumentationBuilder.kt index aae82c18..9717c1a6 100644 --- a/src/Java/JavaDocumentationBuilder.kt +++ b/src/Java/JavaDocumentationBuilder.kt @@ -11,11 +11,11 @@ import org.jsoup.nodes.TextNode public class JavaDocumentationBuilder(private val options: DocumentationOptions, private val refGraph: NodeReferenceGraph) { fun appendFile(file: PsiJavaFile, module: DocumentationModule) { - if (file.getClasses().all { skipElement(it) }) { + if (file.classes.all { skipElement(it) }) { return } - val packageNode = module.findOrCreatePackageNode(file.getPackageName(), emptyMap()) - packageNode.appendChildren(file.getClasses()) { build() } + val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap()) + packageNode.appendChildren(file.classes) { build() } } data class JavadocParseResult(val content: Content, val deprecatedContent: Content?) @@ -26,9 +26,9 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, var deprecatedContent: Content? = null val para = ContentParagraph() result.append(para) - para.convertJavadocElements(docComment.getDescriptionElements().dropWhile { it.getText().trim().isEmpty() }) - docComment.getTags().forEach { tag -> - when(tag.getName()) { + para.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }) + docComment.tags.forEach { tag -> + when(tag.name) { "see" -> result.convertSeeTag(tag) "deprecated" -> { deprecatedContent = Content() @@ -36,7 +36,7 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, } else -> { val subjectName = tag.getSubjectName() - val section = result.addSection(javadocSectionDisplayName(tag.getName()), subjectName) + val section = result.addSection(javadocSectionDisplayName(tag.name), subjectName) section.convertJavadocElements(tag.contentElements()) } @@ -46,10 +46,10 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, } private fun PsiDocTag.contentElements(): Iterable { - val tagValueElements = getChildren() - .dropWhile { it.getNode().getElementType() == JavaDocTokenType.DOC_TAG_NAME } + val tagValueElements = children + .dropWhile { it.node.elementType == JavaDocTokenType.DOC_TAG_NAME } .dropWhile { it is PsiWhiteSpace } - .filterNot { it.getNode().getElementType() == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } + .filterNot { it.node.elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } return if (getSubjectName() != null) tagValueElements.dropWhile { it is PsiDocTagValue } else tagValueElements } @@ -59,7 +59,7 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, if (it is PsiInlineDocTag) { htmlBuilder.append(convertInlineDocTag(it)) } else { - htmlBuilder.append(it.getText()) + htmlBuilder.append(it.text) } } val doc = Jsoup.parse(htmlBuilder.toString().trimStart()) @@ -114,9 +114,9 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, } val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) val linkSignature = resolveLink(linkElement) - val text = ContentText(linkElement.getText()) + val text = ContentText(linkElement.text) if (linkSignature != null) { - val linkNode = ContentNodeLazyLink(tag.getValueElement()!!.getText(), { -> refGraph.lookup(linkSignature)}) + val linkNode = ContentNodeLazyLink(tag.valueElement!!.text, { -> refGraph.lookup(linkSignature)}) linkNode.append(text) seeSection.append(linkNode) } else { @@ -124,35 +124,35 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, } } - private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.getName()) { + private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) { "link", "linkplain" -> { val valueElement = tag.linkElement() val linkSignature = resolveLink(valueElement) if (linkSignature != null) { - val labelText = tag.getDataElements().firstOrNull { it is PsiDocToken }?.getText() ?: valueElement!!.getText() + val labelText = tag.dataElements.firstOrNull { it is PsiDocToken }?.text ?: valueElement!!.text val link = "${labelText.htmlEscape()}" - if (tag.getName() == "link") "$link" else link + if (tag.name == "link") "$link" else link } else if (valueElement != null) { - valueElement.getText() + valueElement.text } else { "" } } "code", "literal" -> { val text = StringBuilder() - tag.getDataElements().forEach { text.append(it.getText()) } + tag.dataElements.forEach { text.append(it.text) } val escaped = text.toString().trimStart().htmlEscape() - if (tag.getName() == "code") "$escaped" else escaped + if (tag.name == "code") "$escaped" else escaped } - else -> tag.getText() + else -> tag.text } private fun PsiDocTag.linkElement(): PsiElement? = - getValueElement() ?: getDataElements().firstOrNull { it !is PsiWhiteSpace } + valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } private fun resolveLink(valueElement: PsiElement?): String? { - val target = valueElement?.getReference()?.resolve() + val target = valueElement?.reference?.resolve() if (target != null) { return getSignature(target) } @@ -160,8 +160,8 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, } fun PsiDocTag.getSubjectName(): String? { - if (getName() == "param" || getName() == "throws" || getName() == "exception") { - return getValueElement()?.getText() + if (name == "param" || name == "throws" || name == "exception") { + return valueElement?.text } return null } @@ -188,32 +188,32 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, } private fun getSignature(element: PsiElement?) = when(element) { - is PsiClass -> element.getQualifiedName() - is PsiField -> element.getContainingClass()!!.getQualifiedName() + "#" + element.getName() + is PsiClass -> element.qualifiedName + is PsiField -> element.containingClass!!.qualifiedName + "#" + element.name is PsiMethod -> - element.getContainingClass()!!.getQualifiedName() + "#" + element.getName() + "(" + - element.getParameterList().getParameters().map { it.getType().typeSignature() }.join(",") + ")" + element.containingClass!!.qualifiedName + "#" + element.name + "(" + + element.parameterList.parameters.map { it.type.typeSignature() }.join(",") + ")" else -> null } private fun PsiType.typeSignature(): String = when(this) { - is PsiArrayType -> "Array<${getComponentType().typeSignature()}>" + is PsiArrayType -> "Array<${componentType.typeSignature()}>" else -> mapTypeName(this) } fun DocumentationNode(element: PsiNamedElement, kind: Kind, - name: String = element.getName() ?: ""): DocumentationNode { - val (docComment, deprecatedContent) = parseDocumentation((element as? PsiDocCommentOwner)?.getDocComment()) + name: String = element.name ?: ""): DocumentationNode { + val (docComment, deprecatedContent) = parseDocumentation((element as? PsiDocCommentOwner)?.docComment) val node = DocumentationNode(name, docComment, kind) if (element is PsiModifierListOwner) { node.appendModifiers(element) - val modifierList = element.getModifierList() + val modifierList = element.modifierList if (modifierList != null) { - modifierList.getAnnotations().filter { !ignoreAnnotation(it) }.forEach { + modifierList.annotations.filter { !ignoreAnnotation(it) }.forEach { val annotation = it.build() node.append(annotation, - if (it.getQualifiedName() == "java.lang.Deprecated") DocumentationReference.Kind.Deprecation else DocumentationReference.Kind.Annotation) + if (it.qualifiedName == "java.lang.Deprecated") DocumentationReference.Kind.Deprecation else DocumentationReference.Kind.Annotation) } } } @@ -224,7 +224,7 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, return node } - fun ignoreAnnotation(annotation: PsiAnnotation) = when(annotation.getQualifiedName()) { + fun ignoreAnnotation(annotation: PsiAnnotation) = when(annotation.qualifiedName) { "java.lang.SuppressWarnings" -> true else -> false } @@ -246,7 +246,7 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, (element.hasModifierProperty(PsiModifier.PRIVATE) || element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) private fun hasSuppressTag(element: Any) = - element is PsiDocCommentOwner && element.getDocComment()?.let { it.findTagByName("suppress") != null } ?: false + element is PsiDocCommentOwner && element.docComment?.let { it.findTagByName("suppress") != null } ?: false fun DocumentationNode.appendMembers(elements: Array, buildFn: T.() -> DocumentationNode) = appendChildren(elements, DocumentationReference.Kind.Member, buildFn) @@ -256,23 +256,23 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, fun PsiClass.build(): DocumentationNode { val kind = when { - isInterface() -> DocumentationNode.Kind.Interface - isEnum() -> DocumentationNode.Kind.Enum - isAnnotationType() -> DocumentationNode.Kind.AnnotationClass + isInterface -> DocumentationNode.Kind.Interface + isEnum -> DocumentationNode.Kind.Enum + isAnnotationType -> DocumentationNode.Kind.AnnotationClass else -> DocumentationNode.Kind.Class } val node = DocumentationNode(this, kind) - getSuperTypes().filter { !ignoreSupertype(it) }.forEach { + superTypes.filter { !ignoreSupertype(it) }.forEach { node.appendType(it, Kind.Supertype) val superClass = it.resolve() if (superClass != null) { link(superClass, node, DocumentationReference.Kind.Inheritor) } } - node.appendDetails(getTypeParameters()) { build() } - node.appendMembers(getMethods()) { build() } - node.appendMembers(getFields()) { build() } - node.appendMembers(getInnerClasses()) { build() } + node.appendDetails(typeParameters) { build() } + node.appendMembers(methods) { build() } + node.appendMembers(fields) { build() } + node.appendMembers(innerClasses) { build() } register(this, node) return node } @@ -282,9 +282,9 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, fun PsiClassType.isClass(qName: String): Boolean { val shortName = qName.substringAfterLast('.') - if (getClassName() == shortName) { + if (className == shortName) { val psiClass = resolve() - return psiClass?.getQualifiedName() == qName + return psiClass?.qualifiedName == qName } return false } @@ -294,7 +294,7 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, if (!hasModifierProperty(PsiModifier.FINAL)) { node.appendTextNode("var", Kind.Modifier) } - node.appendType(getType()) + node.appendType(type) register(this, node) return node } @@ -307,27 +307,27 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, fun PsiMethod.build(): DocumentationNode { val node = DocumentationNode(this, nodeKind(), - if (isConstructor()) "" else getName()) + if (isConstructor) "" else name) - if (!isConstructor()) { - node.appendType(getReturnType()) + if (!isConstructor) { + node.appendType(returnType) } - node.appendDetails(getParameterList().getParameters()) { build() } - node.appendDetails(getTypeParameters()) { build() } + node.appendDetails(parameterList.parameters) { build() } + node.appendDetails(typeParameters) { build() } register(this, node) return node } private fun PsiMethod.nodeKind(): Kind = when { - isConstructor() -> Kind.Constructor + isConstructor -> Kind.Constructor hasModifierProperty(PsiModifier.STATIC) -> Kind.CompanionObjectFunction else -> Kind.Function } fun PsiParameter.build(): DocumentationNode { val node = DocumentationNode(this, Kind.Parameter) - node.appendType(getType()) - if (getType() is PsiEllipsisType) { + node.appendType(type) + if (type is PsiEllipsisType) { node.appendTextNode("vararg", Kind.Annotation, DocumentationReference.Kind.Annotation) } return node @@ -335,22 +335,20 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, fun PsiTypeParameter.build(): DocumentationNode { val node = DocumentationNode(this, Kind.TypeParameter) - getExtendsListTypes().forEach { node.appendType(it, Kind.UpperBound) } - getImplementsListTypes().forEach { node.appendType(it, Kind.UpperBound) } + extendsListTypes.forEach { node.appendType(it, Kind.UpperBound) } + implementsListTypes.forEach { node.appendType(it, Kind.UpperBound) } return node } fun DocumentationNode.appendModifiers(element: PsiModifierListOwner) { - val modifierList = element.getModifierList() - if (modifierList == null) { - return - } + val modifierList = element.modifierList ?: return + PsiModifier.MODIFIERS.forEach { if (it != "static" && modifierList.hasExplicitModifier(it)) { appendTextNode(it, Kind.Modifier) } } - if ((element is PsiClass || (element is PsiMethod && !element.isConstructor())) && + if ((element is PsiClass || (element is PsiMethod && !element.isConstructor)) && !element.hasModifierProperty(PsiModifier.FINAL)) { appendTextNode("open", Kind.Modifier) } @@ -367,34 +365,34 @@ public class JavaDocumentationBuilder(private val options: DocumentationOptions, val name = mapTypeName(this) val node = DocumentationNode(name, Content.Empty, kind) if (this is PsiClassType) { - node.appendDetails(getParameters()) { build(Kind.Type) } + node.appendDetails(parameters) { build(Kind.Type) } link(node, resolve()) } if (this is PsiArrayType && this !is PsiEllipsisType) { - node.append(getComponentType().build(Kind.Type), DocumentationReference.Kind.Detail) + node.append(componentType.build(Kind.Type), DocumentationReference.Kind.Detail) } return node } private fun mapTypeName(psiType: PsiType): String = when (psiType) { PsiType.VOID -> "Unit" - is PsiPrimitiveType -> psiType.getCanonicalText().capitalize() + is PsiPrimitiveType -> psiType.canonicalText.capitalize() is PsiClassType -> { val psiClass = psiType.resolve() - if (psiClass?.getQualifiedName() == "java.lang.Object") "Any" else psiType.getClassName() + if (psiClass?.qualifiedName == "java.lang.Object") "Any" else psiType.className } - is PsiEllipsisType -> mapTypeName(psiType.getComponentType()) + is PsiEllipsisType -> mapTypeName(psiType.componentType) is PsiArrayType -> "Array" - else -> psiType.getCanonicalText() + else -> psiType.canonicalText } fun PsiAnnotation.build(): DocumentationNode { - val node = DocumentationNode(getNameReferenceElement()?.getText() ?: "", Content.Empty, DocumentationNode.Kind.Annotation) - getParameterList().getAttributes().forEach { - val parameter = DocumentationNode(it.getName() ?: "value", Content.Empty, DocumentationNode.Kind.Parameter) - val value = it.getValue() + val node = DocumentationNode(nameReferenceElement?.text ?: "", Content.Empty, DocumentationNode.Kind.Annotation) + parameterList.attributes.forEach { + val parameter = DocumentationNode(it.name ?: "value", Content.Empty, DocumentationNode.Kind.Parameter) + val value = it.value if (value != null) { - val valueText = (value as? PsiLiteralExpression)?.getValue() as? String ?: value.getText() + val valueText = (value as? PsiLiteralExpression)?.value as? String ?: value.text val valueNode = DocumentationNode(valueText, Content.Empty, DocumentationNode.Kind.Value) parameter.append(valueNode, DocumentationReference.Kind.Detail) } diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt index 34018217..9ce81cee 100644 --- a/src/Kotlin/ContentBuilder.kt +++ b/src/Kotlin/ContentBuilder.kt @@ -136,13 +136,13 @@ fun DocumentationBuilder.functionBody(descriptor: DeclarationDescriptor, functio val text = when (psiElement) { is JetDeclarationWithBody -> ContentBlockCode().let() { - val bodyExpression = psiElement.getBodyExpression() + val bodyExpression = psiElement.bodyExpression when (bodyExpression) { - is JetBlockExpression -> bodyExpression.getText().removeSurrounding("{", "}") - else -> bodyExpression!!.getText() + is JetBlockExpression -> bodyExpression.text.removeSurrounding("{", "}") + else -> bodyExpression!!.text } } - else -> psiElement.getText() + else -> psiElement.text } val lines = text.trimEnd().split("\n".toRegex()).toTypedArray().filterNot { it.length() == 0 } @@ -160,14 +160,14 @@ private fun DocumentationBuilder.resolveInScope(functionName: String, scope: Jet for (part in parts) { // short name val symbolName = Name.guess(part) - val partSymbol = currentScope.getAllDescriptors().filter { it.getName() == symbolName }.firstOrNull() + val partSymbol = currentScope.getAllDescriptors().filter { it.name == symbolName }.firstOrNull() if (partSymbol == null) { symbol = null break } currentScope = if (partSymbol is ClassDescriptor) - partSymbol.getDefaultType().getMemberScope() + partSymbol.defaultType.memberScope else getResolutionScope(resolutionFacade, partSymbol) symbol = partSymbol diff --git a/src/Locations/LocationService.kt b/src/Locations/LocationService.kt index 000b2c5e..4f587361 100644 --- a/src/Locations/LocationService.kt +++ b/src/Locations/LocationService.kt @@ -26,7 +26,7 @@ public data class FileLocation(val file: File): Location { if (file.path.substringBeforeLast(".") == other.file.path.substringBeforeLast(".") && anchor == null) { return "." } - val ownerFolder = file.getParentFile()!! + val ownerFolder = file.parentFile!! val relativePath = ownerFolder.getRelativePath(other.file).path return if (anchor == null) relativePath else relativePath + "#" + anchor } diff --git a/src/Utilities/Path.kt b/src/Utilities/Path.kt index 24420ec7..fea22250 100644 --- a/src/Utilities/Path.kt +++ b/src/Utilities/Path.kt @@ -3,10 +3,7 @@ package org.jetbrains.dokka import java.io.* fun File.getRelativePath(name: File): File { - val parent = getParentFile() - - if (parent == null) - throw IOException("No common directory"); + val parent = parentFile ?: throw IOException("No common directory") val basePath = getCanonicalPath() + File.separator; val targetPath = name.getCanonicalPath(); -- cgit