diff options
author | Kamil Doległo <kamilok1965@interia.pl> | 2020-02-10 15:02:26 +0100 |
---|---|---|
committer | Kamil Doległo <kamilok1965@interia.pl> | 2020-02-10 15:02:26 +0100 |
commit | 0d0d41f594f1095b4ccc999cffe01a6ef9a22dbb (patch) | |
tree | 32b09319400677750af154034e09d82d4706a396 | |
parent | 23fbfa0e8e793314cea8d96ac1584d72ec70bb60 (diff) | |
parent | 465ea3d23be40d0d21df7f7cab51ec2d42e3237f (diff) | |
download | dokka-0d0d41f594f1095b4ccc999cffe01a6ef9a22dbb.tar.gz dokka-0d0d41f594f1095b4ccc999cffe01a6ef9a22dbb.tar.bz2 dokka-0d0d41f594f1095b4ccc999cffe01a6ef9a22dbb.zip |
Merge dev-0.10.1 into master
30 files changed, 638 insertions, 533 deletions
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml index 79ee123c..6e6eec11 100644 --- a/.idea/codeStyles/codeStyleConfig.xml +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -1,5 +1,6 @@ <component name="ProjectCodeStyleConfiguration"> <state> <option name="USE_PER_PROJECT_SETTINGS" value="true" /> + <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" /> </state> </component>
\ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 71547e0e..5d169de7 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -11,14 +11,6 @@ <entry name="!?*.kt" /> <entry name="!?*.clj" /> </wildcardResourcePatterns> - <annotationProcessing> - <profile name="Maven default annotation processors profile" enabled="true"> - <sourceOutputDir name="target/generated-sources/annotations" /> - <sourceTestOutputDir name="target/generated-test-sources/test-annotations" /> - <outputRelativeToContentRoot value="true" /> - <module name="dokka-maven-plugin" /> - </profile> - </annotationProcessing> <bytecodeTargetLevel> <module name="android-gradle-plugin_main" target="1.8" /> <module name="android-gradle-plugin_test" target="1.8" /> diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..664d1ad2 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="RemoteRepositoriesConfiguration"> + <remote-repository> + <option name="id" value="central" /> + <option name="name" value="Maven Central repository" /> + <option name="url" value="https://repo1.maven.org/maven2" /> + </remote-repository> + <remote-repository> + <option name="id" value="jboss.community" /> + <option name="name" value="JBoss Community repository" /> + <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven8" /> + <option name="name" value="maven8" /> + <option name="url" value="https://www.jetbrains.com/intellij-repository/snapshots" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven5" /> + <option name="name" value="maven5" /> + <option name="url" value="https://kotlin.bintray.com/kotlinx" /> + </remote-repository> + <remote-repository> + <option name="id" value="MavenRepo" /> + <option name="name" value="MavenRepo" /> + <option name="url" value="https://repo.maven.apache.org/maven2/" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven4" /> + <option name="name" value="maven4" /> + <option name="url" value="https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/1.3.20-dev-564/maven" /> + </remote-repository> + <remote-repository> + <option name="id" value="MavenLocal" /> + <option name="name" value="MavenLocal" /> + <option name="url" value="file:$MAVEN_REPOSITORY$/" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven7" /> + <option name="name" value="maven7" /> + <option name="url" value="https://dl.bintray.com/orangy/maven" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven" /> + <option name="name" value="maven" /> + <option name="url" value="https://dl.bintray.com/jetbrains/markdown" /> + </remote-repository> + <remote-repository> + <option name="id" value="BintrayJCenter" /> + <option name="name" value="BintrayJCenter" /> + <option name="url" value="https://jcenter.bintray.com/" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven9" /> + <option name="name" value="maven9" /> + <option name="url" value="https://www.jetbrains.com/intellij-repository/releases" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven2" /> + <option name="name" value="maven2" /> + <option name="url" value="https://dl.bintray.com/kotlin/kotlin-eap" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven3" /> + <option name="name" value="maven3" /> + <option name="url" value="https://dl.bintray.com/kotlin/kotlin-dev" /> + </remote-repository> + <remote-repository> + <option name="id" value="maven6" /> + <option name="name" value="maven6" /> + <option name="url" value="https://dl.bintray.com/kotlin/kotlinx" /> + </remote-repository> + <remote-repository> + <option name="id" value="Google" /> + <option name="name" value="Google" /> + <option name="url" value="https://dl.google.com/dl/android/maven2/" /> + </remote-repository> + </component> +</project>
\ No newline at end of file diff --git a/.idea/kotlinScripting.xml b/.idea/kotlinScripting.xml new file mode 100644 index 00000000..a6fe551d --- /dev/null +++ b/.idea/kotlinScripting.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="KotlinScriptingSettings"> + <option name="isAutoReloadEnabled" value="true" /> + </component> +</project>
\ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..3e81c6d4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,35 @@ +## Branches + +As of late January 2020: + +* master is the latest released version (0.10.0). +* dev-0.10.1 is the maintenance branch for 0.10.0. It will contain mostly bugfixes. +* dev-0.11.0 is a big rewrite of dokka, it's changing fast and things may break but this is where new features should be developed. + +## Building dokka + +Dokka is built with Gradle. To build it, use `./gradlew build`. +Alternatively, open the project directory in IntelliJ IDEA and use the IDE to build and run dokka. + +Here's how to import and configure Dokka in IntelliJ IDEA: + * Select "Open" from the IDEA welcome screen, or File > Open if a project is + already open +* Select the directory with your clone of Dokka + * Note: IDEA may have an error after the project is initally opened; it is OK + to ignore this as the next step will address this error +* After IDEA opens the project, select File > New > Module from existing sources + and select the `build.gradle` file from the root directory of your Dokka clone +* Use the default options and select "OK" +* After Dokka is loaded into IDEA, open the Gradle tool window (View > Tool + Windows > Gradle) and click on the top left "Refresh all Gradle projects" + button +* Verify the following project settings. In File > Settings > Build, Execution, + Deployment > Build Tools > Gradle > Runner: + * Ensure "Delegate IDE build/run actions to gradle" is checked + * "Gradle Test Runner" should be selected in the "Run tests using" drop-down + menu +* Note: After closing and re-opening the project, IDEA may give an error + message: "Error Loading Project: Cannot load 3 modules". Open up the details + of the error, and click "Remove Selected", as these module `.iml` files are + safe to remove. + @@ -29,7 +29,7 @@ or using the plugins block: ```groovy plugins { - id 'org.jetbrains.dokka' version '0.10.0' + id 'org.jetbrains.dokka' version '0.10.1' } repositories { jcenter() // or maven { url 'https://dl.bintray.com/kotlin/dokka' } @@ -106,9 +106,6 @@ dokka { // Property used for manual addition of files to the classpath // This property does not override the classpath collected automatically but appends to it classpath = [new File("$buildDir/other.jar")] - - // By default, sourceRoots are taken from Kotlin Plugin, subProjects and kotlinTasks, following roots will be appended to them - sourceRoots = [files('src/main/kotlin')] // List of files with module and package documentation // https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation @@ -316,7 +313,7 @@ repositories { } dependencies { - dokkaRuntime "org.jetbrains.dokka:dokka-fatjar:0.10.0" + dokkaRuntime "org.jetbrains.dokka:dokka-fatjar:0.10.1" } dokka { @@ -339,7 +336,7 @@ To use your Fat Jar, just set the path to it: } dependencies { - dokkaRuntime files("/path/to/fatjar/dokka-fatjar-0.10.0.jar") + dokkaRuntime files("/path/to/fatjar/dokka-fatjar-0.10.1.jar") } dokka { @@ -376,8 +373,15 @@ apply plugin: 'org.jetbrains.dokka' ``` There is also a `noAndroidSdkLink` configuration parameter that works similar to `noJdkLink` and `noStdlibLink` -By default the variant documented by dokka is the first release variant encountered. If you want to change that, -you can disable the autoconfiguration and configure dokka manually. +By default the variant documented by dokka is the first release variant encountered. +You can override that by setting the `androidVariants` property inside the `configuration` (or specific platform) block: +```groovy +dokka { + configuration { + androidVariants = ["debug", "release"] + } +} +``` ### Using the Maven plugin @@ -579,7 +583,7 @@ Inside the `dokka` tag you can create another tags named `<passconfig/>` that su ### Using the Command Line -To run Dokka from the command line, download the [Dokka jar](https://github.com/Kotlin/dokka/releases/download/0.10.0/dokka-fatjar-0.10.0.jar). +To run Dokka from the command line, download the [Dokka jar](https://github.com/Kotlin/dokka/releases/download/0.10.1/dokka-fatjar-0.10.1.jar). To generate documentation, run the following command: java -jar dokka-fatjar.jar <arguments> @@ -634,29 +638,3 @@ doesn't affect analysis of source code, it just changes the result. You can thin * `native` * `common` -## Building dokka - -Dokka is built with Gradle. To build it, use `./gradlew build`. -Alternatively, open the project directory in IntelliJ IDEA and use the IDE to build and run dokka. - -Here's how to import and configure Dokka in IntelliJ IDEA: - * Select "Open" from the IDEA welcome screen, or File > Open if a project is - already open -* Select the directory with your clone of Dokka - * Note: IDEA may have an error after the project is initally opened; it is OK - to ignore this as the next step will address this error -* After IDEA opens the project, select File > New > Module from existing sources - and select the `build.gradle` file from the root directory of your Dokka clone -* Use the default options and select "OK" -* After Dokka is loaded into IDEA, open the Gradle tool window (View > Tool - Windows > Gradle) and click on the top left "Refresh all Gradle projects" - button -* Verify the following project settings. In File > Settings > Build, Execution, - Deployment > Build Tools > Gradle > Runner: - * Ensure "Delegate IDE build/run actions to gradle" is checked - * "Gradle Test Runner" should be selected in the "Run tests using" drop-down - menu -* Note: After closing and re-opening the project, IDEA may give an error - message: "Error Loading Project: Cannot load 3 modules". Open up the details - of the error, and click "Remove Selected", as these module `.iml` files are - safe to remove. diff --git a/build.gradle b/build.gradle index 73636b24..777d45dd 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,3 @@ -import org.jetbrains.DependenciesVersionGetter - allprojects { ext { if (!project.findProperty("dokka_version")) { @@ -41,6 +39,8 @@ allprojects { jcenter() mavenCentral() mavenLocal() + maven { url 'https://kotlin.bintray.com/kotlin-plugin' } + maven { url 'https://www.jetbrains.com/intellij-repository/releases' } maven { url "https://dl.bintray.com/jetbrains/markdown" } maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } @@ -78,10 +78,6 @@ def bintrayPublication(project, List<String> _publications) { }) } -def versions = DependenciesVersionGetter.getVersions(project, bundled_kotlin_compiler_version) - -ext.ideaVersion = versions["idea.build.id"] -ext.markdownVersion = versions["markdown.build.id"].replace("%20", " ") configurations { ideaIC @@ -89,13 +85,14 @@ configurations { } repositories { + maven { url 'https://kotlin.bintray.com/kotlin-plugin' } maven { url 'https://www.jetbrains.com/intellij-repository/snapshots' } maven { url 'https://www.jetbrains.com/intellij-repository/releases' } } dependencies { - intellijCore "com.jetbrains.intellij.idea:intellij-core:$ideaVersion" - ideaIC "com.jetbrains.intellij.idea:ideaIC:$ideaVersion" + intellijCore "com.jetbrains.intellij.idea:intellij-core:$idea_version" + ideaIC "com.jetbrains.intellij.idea:ideaIC:$idea_version" } def intellijCoreAnalysis() { @@ -116,17 +113,6 @@ configurations { kotlin_plugin_full } -dependencies { - final String ijVersion = "20" + ideaVersion.take(2) + "." + ideaVersion[2] - kotlin_plugin_full "teamcity:kotlin-plugin-$bundled_kotlin_compiler_version-IJ$ijVersion-1:$bundled_kotlin_compiler_version@zip" -} - -def kotlinPluginDependency() { - return zipTree(configurations.kotlin_plugin_full.singleFile).matching({ - include("Kotlin/lib/kotlin-plugin.jar") - }) -} - allprojects { diff --git a/core/build.gradle b/core/build.gradle index 697fd726..9e3026cb 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -28,12 +28,11 @@ dependencies { compile "org.jetbrains.kotlin:kotlin-compiler:$bundled_kotlin_compiler_version" compile "org.jetbrains.kotlin:kotlin-script-runtime:$bundled_kotlin_compiler_version" - compile "teamcity:kotlin-ide-common:$bundled_kotlin_compiler_version" - compile "org.jetbrains:markdown:$markdownVersion" + compile "org.jetbrains:markdown:0.1.41" compile intellijCoreAnalysis() - - compile kotlinPluginDependency() + + compile "org.jetbrains.kotlin:kotlin-plugin-ij193:$kotlin_plugin_version" //TODO: parametrize ij version after 1.3.70 compile 'org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.8' diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index c816106e..f5705c89 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -3,8 +3,10 @@ package org.jetbrains.dokka import com.google.common.collect.ImmutableMap import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreModuleManager +import com.intellij.mock.MockApplication import com.intellij.mock.MockComponentManager import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager @@ -16,16 +18,13 @@ import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope -import com.intellij.util.io.URLUtil -import org.jetbrains.dokka.Analysis.DokkaJsAnalyzerFacade -import org.jetbrains.dokka.Analysis.DokkaNativeAnalyzerFacade import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters -import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade +import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices +import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns -import org.jetbrains.kotlin.caches.project.LibraryModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.config.ContentRoot @@ -42,20 +41,36 @@ import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext +import org.jetbrains.kotlin.context.withModule import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.ide.konan.NativeLibraryInfo +import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory +import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCache import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.js.config.JSConfigurationKeys -import org.jetbrains.kotlin.js.resolve.JsPlatform +import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices +import org.jetbrains.kotlin.js.resolve.JsResolverForModuleFactory +import org.jetbrains.kotlin.library.impl.createKotlinLibrary import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.CommonPlatforms +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.js.JsPlatforms +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms.unspecifiedJvmPlatform +import org.jetbrains.kotlin.platform.konan.KonanPlatforms import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics -import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform -import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform +import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModuleFactory +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices +import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.types.KotlinType @@ -63,6 +78,9 @@ import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice import org.jetbrains.kotlin.util.slicedMap.WritableSlice import java.io.File +const val JAR_SEPARATOR = "!/" +const val KLIB_EXTENSION = "klib" + /** * Kotlin as a service entry point * @@ -86,65 +104,83 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl Platform.native -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES } + val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles) val projectComponentManager = environment.project as MockComponentManager - val projectFileIndex = CoreProjectFileIndex(environment.project, - environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) - + val projectFileIndex = CoreProjectFileIndex( + environment.project, + environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS) + ) val moduleManager = object : CoreModuleManager(environment.project, this) { override fun getModules(): Array<out Module> = arrayOf(projectFileIndex.module) } - CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.picoContainer, - ModuleManager::class.java, moduleManager) + CoreApplicationEnvironment.registerComponentInstance( + projectComponentManager.picoContainer, + ModuleManager::class.java, moduleManager + ) Extensions.registerAreaClass("IDEA_MODULE", null) - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), - OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java) + CoreApplicationEnvironment.registerExtensionPoint( + Extensions.getRootArea(), + OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java + ) + + projectComponentManager.registerService( + ProjectFileIndex::class.java, + projectFileIndex + ) + + projectComponentManager.registerService( + ProjectRootManager::class.java, + CoreProjectRootManager(projectFileIndex) + ) - projectComponentManager.registerService(ProjectFileIndex::class.java, - projectFileIndex) - projectComponentManager.registerService(ProjectRootManager::class.java, - CoreProjectRootManager(projectFileIndex)) return environment } - fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope = + private fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope = when (analysisPlatform) { Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - Platform.js, Platform.common, Platform.native -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + Platform.js, Platform.common, Platform.native -> GlobalSearchScope.filesScope( + project, + sourceFiles.map { it.virtualFile }.toSet() + ) } - fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair<DokkaResolutionFacade, DokkaResolutionFacade> { - - val projectContext = ProjectContext(environment.project) + val projectContext = ProjectContext(environment.project, "Dokka") val sourceFiles = environment.getSourceFiles() val targetPlatform = when (analysisPlatform) { - Platform.js -> JsPlatform - Platform.common -> TargetPlatform.Common - Platform.native -> KonanPlatform - Platform.jvm -> JvmPlatform + Platform.js -> JsPlatforms.defaultJsPlatform + Platform.common -> CommonPlatforms.defaultCommonPlatform + Platform.native -> KonanPlatforms.defaultKonanPlatform + Platform.jvm -> JvmPlatforms.defaultJvmPlatform } - val library = object : LibraryModuleInfo { - override val platform: TargetPlatform - get() = targetPlatform - - override fun getLibraryRoots(): Collection<String> { - return classpath.map { it.absolutePath } - } + val nativeLibraries = classpath.filter { it.extension == KLIB_EXTENSION } + .map { createNativeLibraryModuleInfo(it) } + val library = object : LibraryModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = + analysisPlatform.analyzerServices() override val name: Name = Name.special("<library>") + override val platform: TargetPlatform = targetPlatform override fun dependencies(): List<ModuleInfo> = listOf(this) + override fun getLibraryRoots(): Collection<String> = + classpath.filterNot { it.extension == KLIB_EXTENSION }.map { it.absolutePath } } + val module = object : ModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = + analysisPlatform.analyzerServices() override val name: Name = Name.special("<module>") - override fun dependencies(): List<ModuleInfo> = listOf(this, library) + override val platform: TargetPlatform = targetPlatform + override fun dependencies(): List<ModuleInfo> = listOf(this, library) + nativeLibraries } val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) @@ -152,6 +188,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl when (it) { library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) + in nativeLibraries -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) else -> throw IllegalArgumentException("Unexpected module info") } } @@ -160,20 +197,39 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl val resolverForProject = when (analysisPlatform) { Platform.jvm -> { - builtIns = JvmBuiltIns(projectContext.storageManager) - createJvmResolverForProject(projectContext, module, library, modulesContent, sourcesScope, builtIns) + builtIns = JvmBuiltIns( + projectContext.storageManager, + JvmBuiltIns.Kind.FROM_CLASS_LOADER + ) // TODO we should use FROM_DEPENDENCIES + createJvmResolverForProject( + projectContext, + module, + library, + modulesContent, + sourcesScope, + builtIns + ) } - Platform.common -> createCommonResolverForProject(projectContext, module, library, modulesContent, environment) + Platform.common -> createCommonResolverForProject( + projectContext, + module, + library, + modulesContent, + environment + ) Platform.js -> createJsResolverForProject(projectContext, module, library, modulesContent) Platform.native -> createNativeResolverForProject(projectContext, module, library, modulesContent) } - val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly - val resolverForModule = resolverForProject.resolverForModule(module) val libraryModuleDescriptor = resolverForProject.descriptorForModule(library) val moduleDescriptor = resolverForProject.descriptorForModule(module) builtIns?.initialize(moduleDescriptor, true) - val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary) + + val resolverForLibrary = + resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForModule = resolverForProject.resolverForModule(module) + val libraryResolutionFacade = + DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary) val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) val projectComponentManager = environment.project as MockComponentManager projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) @@ -181,29 +237,64 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl return created to libraryResolutionFacade } + private fun Platform.analyzerServices() = when (this) { + Platform.js -> JsPlatformAnalyzerServices + Platform.common -> CommonPlatformAnalyzerServices + Platform.native -> NativePlatformAnalyzerServices + Platform.jvm -> JvmPlatformAnalyzerServices + } + + private fun createNativeLibraryModuleInfo(libraryFile: File): LibraryModuleInfo { + val kotlinLibrary = createKotlinLibrary(org.jetbrains.kotlin.konan.file.File(libraryFile.absolutePath), false) + return object : LibraryModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = + analysisPlatform.analyzerServices() + override val name: Name = Name.special("<klib>") + override val platform: TargetPlatform = KonanPlatforms.defaultKonanPlatform + override fun dependencies(): List<ModuleInfo> = listOf(this) + override fun getLibraryRoots(): Collection<String> = listOf(libraryFile.absolutePath) + override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> + get() = super.capabilities + (NativeLibraryInfo.NATIVE_LIBRARY_CAPABILITY to kotlinLibrary) + } + } + private fun createCommonResolverForProject( projectContext: ProjectContext, module: ModuleInfo, library: LibraryModuleInfo, modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, environment: KotlinCoreEnvironment - ): ResolverForProjectImpl<ModuleInfo> { - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = modulesContent, - modulePlatforms = { MultiTargetPlatform.Common }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade }, - platformParameters = { _ -> - CommonAnalysisParameters { content -> - environment.createPackagePartProvider(content.moduleContentScope) - } - }, - targetEnvironment = CompilerEnvironment, - builtIns = DefaultBuiltIns.Instance - ) + ): ResolverForProject<ModuleInfo> { + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = listOf(module, library) + ) { + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) + + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance + + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule = + CommonResolverForModuleFactory( + CommonAnalysisParameters { content -> + environment.createPackagePartProvider(content.moduleContentScope) + }, + CompilerEnvironment, + unspecifiedJvmPlatform, + true + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + } } private fun createJsResolverForProject( @@ -211,19 +302,30 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module: ModuleInfo, library: LibraryModuleInfo, modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> - ): ResolverForProjectImpl<ModuleInfo> { - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = modulesContent, - modulePlatforms = { JsPlatform.multiTargetPlatform }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { DokkaJsAnalyzerFacade }, - platformParameters = { _ -> PlatformAnalysisParameters.Empty }, - targetEnvironment = CompilerEnvironment, - builtIns = JsPlatform.builtIns - ) + ): ResolverForProject<ModuleInfo> { + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = listOf(module, library) + ) { + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule = JsResolverForModuleFactory( + CompilerEnvironment + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance + + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + } } private fun createNativeResolverForProject( @@ -231,19 +333,39 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module: ModuleInfo, library: LibraryModuleInfo, modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> - ): ResolverForProjectImpl<ModuleInfo> { - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = modulesContent, - modulePlatforms = { KonanPlatform.multiTargetPlatform }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { DokkaNativeAnalyzerFacade }, - platformParameters = { _ -> PlatformAnalysisParameters.Empty }, - targetEnvironment = CompilerEnvironment - ) + ): ResolverForProject<ModuleInfo> { + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = module.dependencies() + ) { + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule { + (ApplicationManager.getApplication() as MockApplication).addComponent( + KotlinNativeLoadingMetadataCache::class.java, + KotlinNativeLoadingMetadataCache() + ) + + return NativeResolverForModuleFactory( + PlatformAnalysisParameters.Empty, + CompilerEnvironment, + KonanPlatforms.defaultKonanPlatform + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + } + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance + + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + } } private fun createJvmResolverForProject( @@ -253,38 +375,39 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, sourcesScope: GlobalSearchScope, builtIns: KotlinBuiltIns - ): ResolverForProjectImpl<ModuleInfo> { + ): ResolverForProject<ModuleInfo> { val javaRoots = classpath .mapNotNull { - val rootFile = when { - it.extension == "jar" -> - StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}") - else -> - StandardFileSystems.local().findFileByPath(it.absolutePath) + val rootFile = when (it.extension) { + "jar" -> StandardFileSystems.jar().findFileByPath("${it.absolutePath}${JAR_SEPARATOR}") + else -> StandardFileSystems.local().findFileByPath(it.absolutePath) } - rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } } - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(library, module), - modulesContent = { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), sourcesScope) + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = listOf(module, library) + ) { + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = + when (module) { + library -> ModuleContent(module, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(module, emptyList(), sourcesScope) else -> throw IllegalArgumentException("Unexpected module info") } - }, - modulePlatforms = { JvmPlatform.multiTargetPlatform }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade }, - platformParameters = { - JvmPlatformParameters ({ content -> + + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = builtIns + + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule = JvmResolverForModuleFactory( + JvmPlatformParameters({ content -> JvmPackagePartProvider( configuration.languageVersionSettings, - content.moduleContentScope) + content.moduleContentScope + ) .apply { addRoots(javaRoots, messageCollector) } @@ -294,16 +417,25 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module else library - }) - }, - targetEnvironment = CompilerEnvironment, - builtIns = builtIns - ) + }), + CompilerEnvironment, + KonanPlatforms.defaultKonanPlatform + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + } } fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { val languageVersion = LanguageVersion.fromVersionString(languageVersionString) ?: LanguageVersion.LATEST_STABLE - val apiVersion = apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion) + val apiVersion = + apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion) configuration.languageVersionSettings = LanguageVersionSettingsImpl(languageVersion, apiVersion) } @@ -340,8 +472,8 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl */ val sources: List<String> get() = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) - ?.filterIsInstance<KotlinSourceRoot>() - ?.map { it.path } ?: emptyList() + ?.filterIsInstance<KotlinSourceRoot>() + ?.map { it.path } ?: emptyList() /** * Adds list of paths to source roots. @@ -375,9 +507,11 @@ fun contentRootFromPath(path: String): ContentRoot { } -class DokkaResolutionFacade(override val project: Project, - override val moduleDescriptor: ModuleDescriptor, - val resolverForModule: ResolverForModule) : ResolutionFacade { +class DokkaResolutionFacade( + override val project: Project, + override val moduleDescriptor: ModuleDescriptor, + val resolverForModule: ResolverForModule +) : ResolutionFacade { override fun analyzeWithAllCompilerChecks(elements: Collection<KtElement>): AnalysisResult { throw UnsupportedOperationException() } @@ -386,7 +520,10 @@ class DokkaResolutionFacade(override val project: Project, return resolverForModule.componentProvider.tryGetService(serviceClass) } - override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor { + override fun resolveToDescriptor( + declaration: KtDeclaration, + bodyResolveMode: BodyResolveMode + ): DeclarationDescriptor { return resolveSession.resolveToDescriptor(declaration) } diff --git a/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt b/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt index 31b8ffc7..d9093760 100644 --- a/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt +++ b/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt @@ -5,7 +5,6 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache @@ -14,11 +13,24 @@ class CoreKotlinCacheService(private val resolutionFacade: DokkaResolutionFacade return resolutionFacade } - override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade { + override fun getResolutionFacade( + elements: List<KtElement>, + platform: org.jetbrains.kotlin.platform.TargetPlatform + ): ResolutionFacade { return resolutionFacade } - override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? { + override fun getResolutionFacadeByFile( + file: PsiFile, + platform: org.jetbrains.kotlin.platform.TargetPlatform + ): ResolutionFacade? { + return resolutionFacade + } + + override fun getResolutionFacadeByModuleInfo( + moduleInfo: ModuleInfo, + platform: org.jetbrains.kotlin.platform.TargetPlatform + ): ResolutionFacade? { return resolutionFacade } diff --git a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt index f5fbf991..ef45e840 100644 --- a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt +++ b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt @@ -15,6 +15,7 @@ import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Key import com.intellij.openapi.util.UserDataHolderBase import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VfsUtilCore.getVirtualFileForJar import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileFilter import com.intellij.psi.search.GlobalSearchScope @@ -328,7 +329,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont throw UnsupportedOperationException() } - override fun <R : Any?> processOrder(p0: RootPolicy<R>?, p1: R): R { + override fun <R : Any?> processOrder(p0: RootPolicy<R>, p1: R): R { throw UnsupportedOperationException() } @@ -403,7 +404,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont throw UnsupportedOperationException() } - override fun isDependsOn(p0: Module?): Boolean { + override fun isDependsOn(p0: Module): Boolean { throw UnsupportedOperationException() } @@ -515,7 +516,7 @@ class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : Proje throw UnsupportedOperationException() } - override fun getContentRootsFromAllModules(): Array<out VirtualFile>? { + override fun getContentRootsFromAllModules(): Array<out VirtualFile> { throw UnsupportedOperationException() } @@ -523,7 +524,7 @@ class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : Proje throw UnsupportedOperationException() } - override fun setProjectSdkName(p0: String?) { + override fun setProjectSdkName(p0: String) { throw UnsupportedOperationException() } @@ -558,7 +559,7 @@ class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : Proje fun ContentRoot.contains(file: VirtualFile) = when (this) { is JvmContentRoot -> { val path = if (file.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL) - StandardFileSystems.getVirtualFileForJar(file)?.path ?: file.path + getVirtualFileForJar(file)?.path ?: file.path else file.path File(path).startsWith(this.file.absoluteFile) diff --git a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt deleted file mode 100644 index 874341dd..00000000 --- a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt +++ /dev/null @@ -1,164 +0,0 @@ -package org.jetbrains.dokka.Analysis - -import org.jetbrains.kotlin.analyzer.* -import org.jetbrains.kotlin.caches.project.LibraryModuleInfo -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.config.TargetPlatformVersion -import org.jetbrains.kotlin.container.StorageComponentContainer -import org.jetbrains.kotlin.container.get -import org.jetbrains.kotlin.container.useImpl -import org.jetbrains.kotlin.container.useInstance -import org.jetbrains.kotlin.context.ModuleContext -import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.frontend.di.configureModule -import org.jetbrains.kotlin.ide.konan.KOTLIN_NATIVE_CURRENT_ABI_VERSION -import org.jetbrains.kotlin.ide.konan.createPackageFragmentProvider -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.js.resolve.JsPlatform -import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.library.createKonanLibrary -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform -import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService -import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil -import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider -import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils - -fun createContainerForLazyResolve( - moduleContext: ModuleContext, - declarationProviderFactory: DeclarationProviderFactory, - bindingTrace: BindingTrace, - platform: TargetPlatform, - targetPlatformVersion: TargetPlatformVersion, - targetEnvironment: TargetEnvironment, - languageVersionSettings: LanguageVersionSettings -): StorageComponentContainer = createContainer("LazyResolve", platform) { - configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace) - - useInstance(declarationProviderFactory) - useInstance(languageVersionSettings) - - useImpl<AnnotationResolverImpl>() - useImpl<CompilerDeserializationConfiguration>() - targetEnvironment.configure(this) - - useImpl<ResolveSession>() - useImpl<LazyTopDownAnalyzer>() -} - - -object DokkaJsAnalyzerFacade : ResolverForModuleFactory() { - override fun <M : ModuleInfo> createResolverForModule( - moduleDescriptor: ModuleDescriptorImpl, - moduleContext: ModuleContext, - moduleContent: ModuleContent<M>, - platformParameters: PlatformAnalysisParameters, - targetEnvironment: TargetEnvironment, - resolverForProject: ResolverForProject<M>, - languageVersionSettings: LanguageVersionSettings, - targetPlatformVersion: TargetPlatformVersion - ): ResolverForModule { - val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent - val project = moduleContext.project - val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( - project, - moduleContext.storageManager, - syntheticFiles, - moduleContentScope, - moduleInfo - ) - - val container = createContainerForLazyResolve( - moduleContext, - declarationProviderFactory, - BindingTraceContext(), - JsPlatform, - TargetPlatformVersion.NoVersion, - targetEnvironment, - languageVersionSettings - ) - var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider - - if (moduleInfo is LibraryModuleInfo && moduleInfo.platform == JsPlatform) { - val providers = moduleInfo.getLibraryRoots() - .flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) } - .filter { it.version.isCompatible() } - .map { metadata -> - val (header, packageFragmentProtos) = - KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version) - createKotlinJavascriptPackageFragmentProvider( - moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, metadata.version, - container.get(), LookupTracker.DO_NOTHING - ) - } - - if (providers.isNotEmpty()) { - packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers) - } - } - - return ResolverForModule(packageFragmentProvider, container) - } - - override val targetPlatform: TargetPlatform - get() = JsPlatform -} - -object DokkaNativeAnalyzerFacade : ResolverForModuleFactory() { - override val targetPlatform: TargetPlatform - get() = KonanPlatform - - override fun <M : ModuleInfo> createResolverForModule( - moduleDescriptor: ModuleDescriptorImpl, - moduleContext: ModuleContext, - moduleContent: ModuleContent<M>, - platformParameters: PlatformAnalysisParameters, - targetEnvironment: TargetEnvironment, - resolverForProject: ResolverForProject<M>, - languageVersionSettings: LanguageVersionSettings, - targetPlatformVersion: TargetPlatformVersion - ): ResolverForModule { - - val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( - moduleContext.project, - moduleContext.storageManager, - moduleContent.syntheticFiles, - moduleContent.moduleContentScope, - moduleContent.moduleInfo - ) - - val container = createContainerForLazyResolve( - moduleContext, - declarationProviderFactory, - BindingTraceContext(), - targetPlatform, - TargetPlatformVersion.NoVersion, - targetEnvironment, - languageVersionSettings - ) - - val packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider - val fragmentProviders = mutableListOf(packageFragmentProvider) - - val moduleInfo = moduleContent.moduleInfo - - if (moduleInfo is LibraryModuleInfo) { - moduleInfo.getLibraryRoots() - .filter { File(it).extension != "jar" } - .map { createKonanLibrary(File(it), KOTLIN_NATIVE_CURRENT_ABI_VERSION) } - .mapTo(fragmentProviders) { - it.createPackageFragmentProvider( - moduleContext.storageManager, - languageVersionSettings, - moduleDescriptor - ) - } - - } - - return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container) - } -} diff --git a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt index 4dc6b366..4a4c78e5 100644 --- a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt +++ b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt @@ -19,7 +19,6 @@ package org.jetbrains.dokka import com.intellij.psi.* -import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.descriptors.* @@ -29,11 +28,9 @@ import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.impl.* import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.psiUtil.parameterIndex import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -128,4 +125,4 @@ private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElemen } fun PsiElement.javaResolutionFacade() = - KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)!! + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatforms.defaultJvmPlatform)!! diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 3b368329..d6743e60 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -29,7 +29,7 @@ fun getSignature(element: PsiElement?) = when(element) { } private fun methodSignature(method: PsiMethod): String { - return method.containingClass!!.qualifiedName + "$" + method.name + "(" + + return method.containingClass?.qualifiedName + "$" + method.name + "(" + method.parameterList.parameters.map { it.type.typeSignature() }.joinToString(",") + ")" } @@ -167,7 +167,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { element.isInternal()) private fun skipElementBySuppressedFiles(element: Any): Boolean = - element is PsiElement && element.containingFile.virtualFile.path in passConfiguration.suppressedFiles + element is PsiElement && element.containingFile.virtualFile?.path in passConfiguration.suppressedFiles private fun PsiElement.isInternal(): Boolean { val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false @@ -196,8 +196,16 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { link(superClass, node, RefKind.Inheritor) } } + + var methodsAndConstructors = methods + if (constructors.isEmpty()) { + // Having no constructor represents a class that only has an implicit/default constructor + // so we create one synthetically for documentation + val factory = JavaPsiFacade.getElementFactory(this.project) + methodsAndConstructors += factory.createMethodFromText("public $name() {}", this) + } node.appendDetails(typeParameters) { build() } - node.appendMembers(methods) { build() } + node.appendMembers(methodsAndConstructors) { build() } node.appendMembers(fields) { build() } node.appendMembers(innerClasses) { build() } register(this, node) diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 25a974a3..318bad28 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -4,7 +4,6 @@ import com.intellij.psi.* import com.intellij.psi.impl.source.tree.JavaDocElementType import com.intellij.psi.javadoc.* import com.intellij.psi.util.PsiTreeUtil -import com.intellij.util.containers.isNullOrEmpty import org.jetbrains.kotlin.utils.keysToMap import org.jsoup.Jsoup import org.jsoup.nodes.Element diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 3168e033..13bbbb11 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -423,7 +423,7 @@ class DocumentationBuilder fun DocumentationModule.appendFragments(fragments: Collection<PackageFragmentDescriptor>, packageContent: Map<String, Content>, packageDocumentationBuilder: PackageDocumentationBuilder) { - val allFqNames = fragments.filter{ it.isDocumented(passConfiguration) }.map { it.fqName }.distinct() + val allFqNames = fragments.filter { it.isDocumented(passConfiguration) }.map { it.fqName }.distinct() for (packageName in allFqNames) { if (packageName.isRoot && !passConfiguration.includeRootPackage) continue @@ -713,7 +713,7 @@ class DocumentationBuilder } fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode { - if (ErrorUtils.containsErrorType(this)) { + if (ErrorUtils.containsErrorTypeInParameters(this) || ErrorUtils.containsErrorType(this.returnType)) { logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}") } @@ -1157,7 +1157,9 @@ fun ClassDescriptor.supertypesWithAnyPrecise(): Collection<KotlinType> { fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions { val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated, false) - return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions + return perPackageOptions.firstOrNull { pack == it.prefix } + ?: perPackageOptions.firstOrNull { pack.startsWith(it.prefix + ".") } + ?: rootPackageOptions } fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString()) diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 793f9589..bd8b9cf5 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -42,7 +42,7 @@ class PackageListProvider @Inject constructor( configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") configuration.cacheRoot != null -> Paths.get(configuration.cacheRoot) else -> null - }?.resolve("packageListCache")?.apply { createDirectories() } + }?.resolve("packageListCache")?.apply { toFile().mkdirs() } val cachedProtocols = setOf("http", "https", "ftp") @@ -105,13 +105,13 @@ class PackageListProvider @Inject constructor( val digest = MessageDigest.getInstance("SHA-256") val hash = digest.digest(packageListLink.toByteArray(Charsets.UTF_8)).toHexString() - val cacheEntry = cacheDir.resolve(hash) + val cacheEntry = cacheDir.resolve(hash).toFile() if (cacheEntry.exists()) { try { val connection = packageListUrl.doOpenConnectionToReadContent() val originModifiedDate = connection.date - val cacheDate = cacheEntry.lastModified().toMillis() + val cacheDate = cacheEntry.lastModified() if (originModifiedDate > cacheDate || originModifiedDate == 0L) { if (originModifiedDate == 0L) logger.warn("No date header for $packageListUrl, downloading anyway") diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index 4525e9d9..a67306f4 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -165,7 +165,7 @@ open class KotlinWebsiteSampleProcessingService return sampleBuilder.text } - val importsToIgnore = arrayOf("samples.*").map { ImportPath.fromString(it) } + val importsToIgnore = arrayOf("samples.*", "samples.Sample").map { ImportPath.fromString(it) } override fun processImports(psiElement: PsiElement): ContentBlockCode { val psiFile = psiElement.containingFile diff --git a/core/src/main/kotlin/Utilities/Links.kt b/core/src/main/kotlin/Utilities/Links.kt new file mode 100644 index 00000000..34423e4e --- /dev/null +++ b/core/src/main/kotlin/Utilities/Links.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.Utilities + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.ExternalDocumentationLinkImpl + +fun DokkaConfiguration.PassConfiguration.defaultLinks(): List<ExternalDocumentationLinkImpl> { + val links = mutableListOf<ExternalDocumentationLinkImpl>() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink + .Builder("https://docs.oracle.com/javase/${jdkVersion}/docs/api/") + .build() as ExternalDocumentationLinkImpl + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink + .Builder("https://kotlinlang.org/api/latest/jvm/stdlib/") + .build() as ExternalDocumentationLinkImpl + return links +} diff --git a/core/src/test/kotlin/model/KotlinAsJavaTest.kt b/core/src/test/kotlin/model/KotlinAsJavaTest.kt index 8249dd0f..c29776be 100644 --- a/core/src/test/kotlin/model/KotlinAsJavaTest.kt +++ b/core/src/test/kotlin/model/KotlinAsJavaTest.kt @@ -16,9 +16,8 @@ class KotlinAsJavaTest { val facadeClass = pkg.members.single { it.name == "FunctionKt" } assertEquals(NodeKind.Class, facadeClass.kind) - val fn = facadeClass.members.single() + val fn = facadeClass.members.single { it.kind == NodeKind.Function} assertEquals("fn", fn.name) - assertEquals(NodeKind.Function, fn.kind) } } diff --git a/gradle.properties b/gradle.properties index 7741642b..e4745ed8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,12 @@ -dokka_version_base=0.10.0 +dokka_version_base=0.10.1 dokka_publication_channel=dokka # Kotlin compiler and plugin -bundled_kotlin_compiler_version=1.3.20-dev-564 -kotlin_version=1.3.30 -kotlin_for_gradle_runtime_version=1.1.60 +bundled_kotlin_compiler_version=1.3.61 +kotlin_version=1.3.61 +kotlin_plugin_version=1.3.61-release-180 +idea_version=192.5728.98 +kotlin_for_gradle_runtime_version=1.3.61 language_version=1.3 ant_version=1.9.6 diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index 52815e75..55601b21 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink +import org.jetbrains.dokka.Utilities.defaultLinks import java.io.File import java.net.MalformedURLException import java.net.URL @@ -261,10 +262,11 @@ object MainKt { return configuration } + fun GlobalArguments.addDefaultLinks() = passesConfigurations.forEach { it.externalDocumentationLinks += it.defaultLinks() } + @JvmStatic fun main(args: Array<String>) { - val configuration = createConfiguration(args) - + val configuration = createConfiguration(args).apply { addDefaultLinks() } if (configuration.format.toLowerCase() == "javadoc") startWithToolsJar(configuration) else diff --git a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt index 3e61d79e..6ab9fd52 100644 --- a/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt +++ b/runners/gradle-integration-tests/src/test/kotlin/org/jetbrains/dokka/gradle/MultiplatformProjectTest.kt @@ -40,8 +40,8 @@ class MultiplatformProjectTest : AbstractDokkaGradleTest() { checkNoUnresolvedLinks(docsOutput) } - @Test fun `test kotlin 1_3_30 and gradle 4_7`() { - doTest("4.7", "1.3.30") + @Test fun `test kotlin 1_3_30 and gradle 4_9`() { + doTest("4.9", "1.3.30") } @Test fun `test kotlin 1_3_40 and gradle 4_10_3`() { diff --git a/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle b/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle index 8688ae41..444d2ab3 100644 --- a/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle +++ b/runners/gradle-integration-tests/testData/typeSafeConfiguration/build.gradle @@ -52,11 +52,12 @@ def configureDokkaTypeSafely(DokkaTask dokka) { sourceRoot.path = "some String" } }) - externalDocumentationLink(new Action<GradleExternalDocumentationLinkImpl>() { + externalDocumentationLink(new Action<GradleExternalDocumentationLinkImpl.Builder>() { @Override - void execute(GradleExternalDocumentationLinkImpl link) { - link.url = uri("some URI").toURL() - link.packageListUrl = uri("some URI").toURL() + void execute(GradleExternalDocumentationLinkImpl.Builder builder) { + builder.url = uri("some URI").toURL() + builder.packageListUrl = uri("some URI").toURL() + builder.build() } }) kotlinTasks(new Callable<List<Object>>() { diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt index c66998d9..39672b9a 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/ConfigurationExtractor.kt @@ -26,12 +26,19 @@ import java.io.Serializable class ConfigurationExtractor(private val project: Project) { - fun extractFromSinglePlatform(variantName: String? = null): PlatformData? { + fun extractConfiguration(targetName: String, variantNames: List<String>) = + if (project.isMultiplatformProject()) { + extractFromMultiPlatform(targetName, variantNames) + } else { + extractFromSinglePlatform(variantNames) + } + + private fun extractFromSinglePlatform(variantNames: List<String>): PlatformData? { val target: KotlinTarget try { target = project.extensions.getByType(KotlinSingleTargetExtension::class.java).target } catch (e: Throwable) { - when (e){ + when (e) { is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> return null else -> throw e @@ -39,34 +46,38 @@ class ConfigurationExtractor(private val project: Project) { } return try { - PlatformData(null, getClasspath(target, variantName), getSourceSet(target, variantName), getPlatformName(target.platformType)) - } catch(e: NoSuchMethodError){ + PlatformData( + null, + accumulateClassPaths(variantNames, target), + accumulateSourceSets(variantNames, target), + getPlatformName(target.platformType) + ) + } catch (e: NoSuchMethodError) { null } } - fun extractFromMultiPlatform(): List<PlatformData>? { - val targets: NamedDomainObjectCollection<KotlinTarget> + private fun extractFromMultiPlatform(targetName: String, variantNames: List<String>): PlatformData? = try { - targets = project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets + project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets } catch (e: Throwable) { - when (e){ + when (e) { is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> - return null + null else -> throw e } + }?.let { + val fixedName = if (targetName.toLowerCase() == "common") "metadata" else targetName.toLowerCase() + it.find { target -> target.name.toLowerCase() == fixedName }?.let { target -> + PlatformData( + fixedName, + accumulateClassPaths(variantNames, target), + accumulateSourceSets(variantNames, target), + target.platformType.toString() + ) + } } - val commonTargetPlatformData = targets.find { it.platformType == KotlinPlatformType.common }?.let { - PlatformData("common", getClasspath(it), getSourceSet(it), "common") - } - val config = targets.filter { it.platformType != KotlinPlatformType.common }.map { - PlatformData(it.name, getClasspath(it), getSourceSet(it), it.platformType.toString()) - } - - return (config + commonTargetPlatformData).filterNotNull() - } - fun extractFromJavaPlugin(): PlatformData? = project.convention.findPlugin(JavaPluginConvention::class.java) ?.run { sourceSets.findByName(SourceSet.MAIN_SOURCE_SET_NAME)?.allSource?.srcDirs } @@ -75,10 +86,15 @@ class ConfigurationExtractor(private val project: Project) { fun extractFromKotlinTasks(kotlinTasks: List<Task>): PlatformData? = try { kotlinTasks.map { extractFromKotlinTask(it) }.let { platformDataList -> - PlatformData(null, platformDataList.flatMap { it.classpath }, platformDataList.flatMap { it.sourceRoots }, "") + PlatformData( + null, + platformDataList.flatMap { it.classpath }, + platformDataList.flatMap { it.sourceRoots }, + "" + ) } } catch (e: Throwable) { - when (e){ + when (e) { is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> extractFromKotlinTasksTheHardWay(kotlinTasks) else -> throw e @@ -91,7 +107,7 @@ class ConfigurationExtractor(private val project: Project) { .compilations .find { it.compileKotlinTask == task } } catch (e: Throwable) { - when (e){ + when (e) { is UnknownDomainObjectException, is NoClassDefFoundError, is ClassNotFoundException -> project.extensions.getByType(KotlinMultiplatformExtension::class.java).targets .firstNotNullResult { target -> target.compilations.find { it.compileKotlinTask == task } } @@ -134,25 +150,22 @@ class ConfigurationExtractor(private val project: Project) { } catch (e: ResolveException) { mutableListOf() } - classpath.addAll (project.files(allClasspath).toList()) + classpath.addAll(project.files(allClasspath).toList()) return PlatformData(null, classpath, allSourceRoots.toList(), "") } - private fun getSourceSet(target: KotlinTarget, variantName: String? = null): List<File> = - if(variantName != null) + private fun getSourceSet(target: KotlinTarget, variantName: String): List<File> = + if (target.isAndroidTarget()) getSourceSet(getCompilation(target, variantName)) else getSourceSet(getMainCompilation(target)) - private fun getClasspath(target: KotlinTarget, variantName: String? = null): List<File> = if (target.isAndroidTarget()) { - if(variantName != null) + private fun getClasspath(target: KotlinTarget, variantName: String): List<File> = + if (target.isAndroidTarget()) getClasspathFromAndroidTask(getCompilation(target, variantName)) else - getClasspathFromAndroidTask(getMainCompilation(target)) - } else { - getClasspath(getMainCompilation(target)) - } + getClasspath(getMainCompilation(target)) private fun getSourceSet(compilation: KotlinCompilation<*>?): List<File> = compilation ?.allKotlinSourceSets @@ -185,7 +198,7 @@ class ConfigurationExtractor(private val project: Project) { private fun getVariants(project: Project): Set<BaseVariant> { val androidExtension = project.extensions.getByName("android") - val baseVariants = when (androidExtension) { + val baseVariants = when (androidExtension) { is AppExtension -> androidExtension.applicationVariants.toSet() is LibraryExtension -> { androidExtension.libraryVariants.toSet() + @@ -210,8 +223,26 @@ class ConfigurationExtractor(private val project: Project) { private fun getPlatformName(platform: KotlinPlatformType): String = if (platform == KotlinPlatformType.androidJvm) KotlinPlatformType.jvm.toString() else platform.toString() - data class PlatformData(val name: String?, - val classpath: List<File>, - val sourceRoots: List<File>, - val platform: String) : Serializable + private fun accumulateClassPaths(variantNames: List<String>, target: KotlinTarget) = + if (variantNames.isNotEmpty()) { + variantNames.flatMap { getClasspath(target, it) }.distinct() + } else { + if (target.isAndroidTarget()) + getClasspathFromAndroidTask(getMainCompilation(target)) + else + getClasspath(getMainCompilation(target)) + } + + private fun accumulateSourceSets(variantNames: List<String>, target: KotlinTarget) = + if (variantNames.isNotEmpty()) + variantNames.flatMap { getSourceSet(target, it) }.distinct() + else + getSourceSet(getMainCompilation(target)) + + data class PlatformData( + val name: String?, + val classpath: List<File>, + val sourceRoots: List<File>, + val platform: String + ) : Serializable }
\ No newline at end of file diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt index 5153ae1c..bafe657e 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/DokkaTask.kt @@ -8,13 +8,13 @@ import org.gradle.api.internal.plugins.DslObject import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.tasks.* import org.jetbrains.dokka.DokkaBootstrap -import org.jetbrains.dokka.DokkaConfiguration import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink.Builder import org.jetbrains.dokka.DokkaConfiguration.SourceRoot import org.jetbrains.dokka.Platform import org.jetbrains.dokka.ReflectDsl import org.jetbrains.dokka.ReflectDsl.isNotInstance import org.jetbrains.dokka.gradle.ConfigurationExtractor.PlatformData +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import java.io.File import java.net.URLClassLoader import java.util.concurrent.Callable @@ -53,6 +53,9 @@ open class DokkaTask : DefaultTask() { var dokkaRuntime: Configuration? = null @Input + var subProjects: List<String> = emptyList() + + @Input var impliedPlatforms: MutableList<String> = arrayListOf() @Optional @@ -72,31 +75,18 @@ open class DokkaTask : DefaultTask() { // Configure Dokka with closure in Gradle Kotlin DSL fun configuration(action: Action<in GradlePassConfigurationImpl>) = action.execute(configuration) - private var externalDocumentationLinks: MutableList<DokkaConfiguration.ExternalDocumentationLink> = mutableListOf() - private val kotlinTasks: List<Task> by lazy { extractKotlinCompileTasks(configuration.collectKotlinTasks ?: { defaultKotlinTasks() }) } private val configExtractor = ConfigurationExtractor(project) @Input - var subProjects: List<String> = emptyList() - - @Input var disableAutoconfiguration: Boolean = false private var outputDiagnosticInfo: Boolean = false // Workaround for Gradle, which fires some methods (like collectConfigurations()) multiple times in its lifecycle - private fun tryResolveFatJar(configuration: Configuration?): Set<File> { - return try { - configuration!!.resolve() - } catch (e: Exception) { - project.parent?.let { tryResolveFatJar(configuration) } ?: throw e - } - } - private fun loadFatJar() { if (ClassloaderContainer.fatJarClassLoader == null) { - val jars = tryResolveFatJar(dokkaRuntime).toList() + val jars = dokkaRuntime!!.resolve().toList() ClassloaderContainer.fatJarClassLoader = URLClassLoader(jars.map { it.toURI().toURL() }.toTypedArray(), ClassLoader.getSystemClassLoader().parent) } } @@ -124,7 +114,7 @@ open class DokkaTask : DefaultTask() { private fun Iterable<File>.toSourceRoots(): List<GradleSourceRootImpl> = this.filter { it.exists() }.map { GradleSourceRootImpl().apply { path = it.path } } private fun Iterable<String>.toProjects(): List<Project> = project.subprojects.toList().filter { this.contains(it.name) } - private fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) = + protected open fun collectSuppressedFiles(sourceRoots: List<SourceRoot>) = if(project.isAndroidProject()) { val generatedRoot = project.buildDir.resolve("generated").absoluteFile sourceRoots @@ -153,7 +143,7 @@ open class DokkaTask : DefaultTask() { val globalConfig = multiplatform.toList().find { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME } val passConfigurationList = collectConfigurations() - .map { defaultPassConfiguration(globalConfig, it) } + .map { defaultPassConfiguration(it, globalConfig) } val configuration = GradleDokkaConfigurationImpl() configuration.outputDir = outputDirectory @@ -163,6 +153,11 @@ open class DokkaTask : DefaultTask() { configuration.impliedPlatforms = impliedPlatforms configuration.passesConfigurations = passConfigurationList + if(passConfigurationList.isEmpty() || passConfigurationList == listOf(globalConfig)) { + println("No pass configurations for generation detected!") + return + } + bootstrapProxy.configure( BiConsumer { level, message -> when (level) { @@ -181,38 +176,15 @@ open class DokkaTask : DefaultTask() { } } - private fun collectConfigurations(): List<GradlePassConfigurationImpl> = - if (this.isMultiplatformProject()) collectFromMultiPlatform() else collectFromSinglePlatform() - - private fun collectFromMultiPlatform(): List<GradlePassConfigurationImpl> { - val userConfig = multiplatform - .filterNot { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME } - .map { - if (it.collectKotlinTasks != null) { - configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it.collectKotlinTasks!!)) - ?.let { platformData -> mergeUserConfigurationAndPlatformData(it, platformData) } ?: it - } else { - it - } - } - - if (disableAutoconfiguration) return userConfig - - val baseConfig = mergeUserAndAutoConfigurations( - userConfig, - configExtractor.extractFromMultiPlatform().orEmpty() - ) + protected open fun collectConfigurations() = + if (this.isMultiplatformProject()) collectMultiplatform() else listOf(collectSinglePlatform(configuration)) - return if (subProjects.isNotEmpty()) - subProjects.toProjects().fold(baseConfig) { list, subProject -> - mergeUserAndAutoConfigurations(list, ConfigurationExtractor(subProject).extractFromMultiPlatform().orEmpty()) - } - else - baseConfig - } + protected open fun collectMultiplatform() = multiplatform + .filterNot { it.name.toLowerCase() == GLOBAL_PLATFORM_NAME } + .map { collectSinglePlatform(it) } - private fun collectFromSinglePlatform(): List<GradlePassConfigurationImpl> { - val userConfig = configuration.let { + protected open fun collectSinglePlatform(config: GradlePassConfigurationImpl): GradlePassConfigurationImpl { + val userConfig = config.let { if (it.collectKotlinTasks != null) { configExtractor.extractFromKotlinTasks(extractKotlinCompileTasks(it.collectKotlinTasks!!)) ?.let { platformData -> mergeUserConfigurationAndPlatformData(it, platformData) } ?: it @@ -221,21 +193,27 @@ open class DokkaTask : DefaultTask() { } } - if (disableAutoconfiguration) return listOf(userConfig) + if (disableAutoconfiguration) return userConfig - val extractedConfig = configExtractor.extractFromSinglePlatform(userConfig.androidVariant) - val baseConfig = if (extractedConfig != null) - listOf(mergeUserConfigurationAndPlatformData(userConfig, extractedConfig)) - else - collectFromSinglePlatformOldPlugin() + val baseConfig = configExtractor.extractConfiguration(userConfig.name, userConfig.androidVariants) + ?.let { mergeUserConfigurationAndPlatformData(userConfig, it) } + ?: if (this.isMultiplatformProject()) { + if (outputDiagnosticInfo) + logger.warn("Could not find target with name: ${userConfig.name} in Kotlin Gradle Plugin, " + + "using only user provided configuration for this target") + userConfig + } else { + logger.warn("Could not find target with name: ${userConfig.name} in Kotlin Gradle Plugin") + collectFromSinglePlatformOldPlugin() + } return if (subProjects.isNotEmpty()) { try { - subProjects.toProjects().fold(baseConfig) { list, subProject -> - listOf(mergeUserConfigurationAndPlatformData( - list.first(), - ConfigurationExtractor(subProject).extractFromSinglePlatform()!! - )) + subProjects.toProjects().fold(baseConfig) { config, subProject -> + mergeUserConfigurationAndPlatformData( + config, + ConfigurationExtractor(subProject).extractConfiguration(config.name, config.androidVariants)!! + ) } } catch(e: NullPointerException) { logger.warn("Cannot extract sources from subProjects. Do you have the Kotlin plugin in version 1.3.30+ " + @@ -247,41 +225,14 @@ open class DokkaTask : DefaultTask() { } } - private fun collectFromSinglePlatformOldPlugin(): List<GradlePassConfigurationImpl> { - val kotlinTasks = configExtractor.extractFromKotlinTasks(kotlinTasks) - return if (kotlinTasks != null) { - listOf(mergeUserConfigurationAndPlatformData(configuration, kotlinTasks)) - } else { - val javaPlugin = configExtractor.extractFromJavaPlugin() - if (javaPlugin != null) - listOf(mergeUserConfigurationAndPlatformData(configuration, javaPlugin)) else listOf(configuration) - } - } - - private fun mergeUserAndAutoConfigurations(userConfigurations: List<GradlePassConfigurationImpl>, - autoConfigurations: List<PlatformData>): List<GradlePassConfigurationImpl> { - val merged: MutableList<GradlePassConfigurationImpl> = mutableListOf() - merged.addAll( - userConfigurations.map { userConfig -> - val autoConfig = autoConfigurations.find { autoConfig -> autoConfig.name == userConfig.name } - if (autoConfig != null) { - mergeUserConfigurationAndPlatformData(userConfig, autoConfig) - } else { - if(outputDiagnosticInfo) { - logger.warn( - "Could not find platform with name: ${userConfig.name} in Kotlin Gradle Plugin, " + - "using only user provided configuration for this platform" - ) - } - userConfig - } - } - ) - return merged.toList() - } + protected open fun collectFromSinglePlatformOldPlugin() = + configExtractor.extractFromKotlinTasks(kotlinTasks) + ?.let { mergeUserConfigurationAndPlatformData(configuration, it) } + ?: configExtractor.extractFromJavaPlugin() + ?.let { mergeUserConfigurationAndPlatformData(configuration, it) } + ?: configuration - private fun mergeUserConfigurationAndPlatformData(userConfig: GradlePassConfigurationImpl, - autoConfig: PlatformData): GradlePassConfigurationImpl = + protected open fun mergeUserConfigurationAndPlatformData(userConfig: GradlePassConfigurationImpl, autoConfig: PlatformData) = userConfig.copy().apply { sourceRoots.addAll(userConfig.sourceRoots.union(autoConfig.sourceRoots.toSourceRoots()).distinct()) classpath = userConfig.classpath.union(autoConfig.classpath.map { it.absolutePath }).distinct() @@ -289,7 +240,10 @@ open class DokkaTask : DefaultTask() { platform = autoConfig.platform } - private fun defaultPassConfiguration(globalConfig: GradlePassConfigurationImpl?, config: GradlePassConfigurationImpl): GradlePassConfigurationImpl { + protected open fun defaultPassConfiguration( + config: GradlePassConfigurationImpl, + globalConfig: GradlePassConfigurationImpl? + ): GradlePassConfigurationImpl { if (config.moduleName == "") { config.moduleName = project.name } @@ -304,7 +258,6 @@ open class DokkaTask : DefaultTask() { if (project.isAndroidProject() && !config.noAndroidSdkLink) { // TODO: introduce Android as a separate Dokka platform? config.externalDocumentationLinks.add(ANDROID_REFERENCE_URL) } - config.externalDocumentationLinks.addAll(externalDocumentationLinks) if (config.platform != null && config.platform.toString().isNotEmpty()) { config.analysisPlatform = dokkaPlatformFromString(config.platform.toString()) } @@ -319,7 +272,8 @@ open class DokkaTask : DefaultTask() { } private fun dokkaPlatformFromString(platform: String) = when (platform.toLowerCase()) { - "androidjvm", "android" -> Platform.jvm + KotlinPlatformType.androidJvm.toString().toLowerCase(), "androidjvm", "android" -> Platform.jvm + "metadata" -> Platform.common else -> Platform.fromString(platform) } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt index 767bf4f4..65afad04 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/configurationImplementations.kt @@ -33,7 +33,7 @@ open class GradlePassConfigurationImpl(@Transient val name: String = ""): PassCo @Input override var includeNonPublic: Boolean = false @Input override var includeRootPackage: Boolean = false @Input override var reportUndocumented: Boolean = false - @Input override var skipEmptyPackages: Boolean = false + @Input override var skipEmptyPackages: Boolean = true @Input override var skipDeprecated: Boolean = false @Input override var jdkVersion: Int = 6 @Input override var sourceLinks: MutableList<SourceLinkDefinition> = mutableListOf() @@ -51,7 +51,7 @@ open class GradlePassConfigurationImpl(@Transient val name: String = ""): PassCo @Input override var targets: List<String> = emptyList() @Input @Optional override var sinceKotlin: String? = null @Transient var collectKotlinTasks: (() -> List<Any?>?)? = null - @Input @Optional @Transient var androidVariant: String? = null + @Input @Transient var androidVariants: List<String> = emptyList() fun kotlinTasks(taskSupplier: Callable<List<Any>>) { collectKotlinTasks = { taskSupplier.call() } @@ -95,14 +95,14 @@ open class GradlePassConfigurationImpl(@Transient val name: String = ""): PassCo } fun externalDocumentationLink(c: Closure<Unit>) { - val link = ConfigureUtil.configure(c, GradleExternalDocumentationLinkImpl()) - externalDocumentationLinks.add(link) + val builder = ConfigureUtil.configure(c, GradleExternalDocumentationLinkImpl.Builder()) + externalDocumentationLinks.add(builder.build()) } - fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkImpl>) { - val link = GradleExternalDocumentationLinkImpl() - action.execute(link) - externalDocumentationLinks.add(link) + fun externalDocumentationLink(action: Action<in GradleExternalDocumentationLinkImpl.Builder>) { + val builder = GradleExternalDocumentationLinkImpl.Builder() + action.execute(builder) + externalDocumentationLinks.add(builder.build()) } } @@ -112,9 +112,23 @@ class GradleSourceLinkDefinitionImpl : SourceLinkDefinition, Serializable { override var lineSuffix: String? = null } -class GradleExternalDocumentationLinkImpl : ExternalDocumentationLink, Serializable { - override var url: URL = URL("http://") - override var packageListUrl: URL = URL("http://") +class GradleExternalDocumentationLinkImpl( + override val url: URL, + override val packageListUrl: URL +): ExternalDocumentationLink, Serializable { + open class Builder(open var url: URL? = null, + open var packageListUrl: URL? = null) { + + constructor(root: String, packageList: String? = null) : this(URL(root), packageList?.let { URL(it) }) + + fun build(): ExternalDocumentationLink = + if (packageListUrl != null && url != null) + GradleExternalDocumentationLinkImpl(url!!, packageListUrl!!) + else if (url != null) + GradleExternalDocumentationLinkImpl(url!!, URL(url!!, "package-list")) + else + throw IllegalArgumentException("url or url && packageListUrl must not be null for external documentation link") + } } class GradleDokkaConfigurationImpl: DokkaConfiguration { @@ -129,8 +143,8 @@ class GradleDokkaConfigurationImpl: DokkaConfiguration { class GradlePackageOptionsImpl: PackageOptions, Serializable { override var prefix: String = "" override var includeNonPublic: Boolean = false - override var reportUndocumented: Boolean = true - override var skipDeprecated: Boolean = true + override var reportUndocumented: Boolean = false + override var skipDeprecated: Boolean = false override var suppress: Boolean = false } diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt index 6f8d55e4..7ed29c58 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/main.kt @@ -27,7 +27,7 @@ open class DokkaPlugin : Plugin<Project> { defaultDependencies{ dependencies -> dependencies.add(project.dependencies.create("org.jetbrains.dokka:dokka-fatjar:${DokkaVersion.version}")) } } - private fun addTasks(project: Project, runtimeConfiguration: Configuration, taskClass: Class<out DokkaTask>) { + protected open fun addTasks(project: Project, runtimeConfiguration: Configuration, taskClass: Class<out DokkaTask>) { if(GradleVersion.current() >= GradleVersion.version("4.10")) { project.tasks.register(taskName, taskClass) } else { diff --git a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt index d70b0499..31892e8e 100644 --- a/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt +++ b/runners/gradle-plugin/src/main/kotlin/org/jetbrains/dokka/gradle/utils.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka.gradle import org.gradle.api.Project import org.gradle.api.UnknownDomainObjectException +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinTarget @@ -15,5 +16,16 @@ fun Project.isAndroidProject() = try { false } +fun Project.isMultiplatformProject() = try { + project.extensions.getByType(KotlinMultiplatformExtension::class.java) + true +} catch(e: UnknownDomainObjectException) { + false +} catch (e: NoClassDefFoundError){ + false +} catch(e: ClassNotFoundException) { + false +} + fun KotlinTarget.isAndroidTarget() = this.platformType == KotlinPlatformType.androidJvm fun DokkaTask.isMultiplatformProject() = this.multiplatform.isNotEmpty()
\ No newline at end of file diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index fb11ecac..1cbe39f3 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -11,6 +11,7 @@ import org.apache.maven.project.MavenProjectHelper import org.codehaus.plexus.archiver.Archiver import org.codehaus.plexus.archiver.jar.JarArchiver import org.jetbrains.dokka.* +import org.jetbrains.dokka.Utilities.defaultLinks import java.io.File import java.net.URL @@ -183,6 +184,8 @@ abstract class AbstractDokkaMojo : AbstractMojo() { includeRootPackage = includeRootPackage ) + passConfiguration.externalDocumentationLinks += passConfiguration.defaultLinks() + val configuration = DokkaConfigurationImpl( outputDir = getOutDir(), format = getOutFormat(), |