From 9ea429920e07c77e1241c4beb172bb36735af783 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Tue, 10 Jul 2018 19:27:16 +0300 Subject: Add js platform support --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 110 +++++++++++++++++---- core/src/main/kotlin/Generation/DokkaGenerator.kt | 24 +++-- .../main/kotlin/Generation/configurationImpl.kt | 13 ++- 3 files changed, 117 insertions(+), 30 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index b2e4b490..453c0311 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -18,6 +18,8 @@ import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* +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.messages.MessageCollector @@ -32,14 +34,17 @@ import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters @@ -59,7 +64,7 @@ import java.io.File * $messageCollector: required by compiler infrastructure and will receive all compiler messages * $body: optional and can be used to configure environment without creating local variable */ -class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { +class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPlatform: Platform) : Disposable { val configuration = CompilerConfiguration() init { @@ -68,7 +73,12 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { fun createCoreEnvironment(): KotlinCoreEnvironment { System.setProperty("idea.io.use.fallback", "true") - val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + + val configFiles = when (analysisPlatform) { + Platform.jvm -> EnvironmentConfigFiles.JVM_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, @@ -92,14 +102,71 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { return environment } - fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope { - // TODO: Fix when going to implement dokka for JS - return TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) + fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope = when (analysisPlatform) { + Platform.js -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) } fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + return when(analysisPlatform) { + Platform.jvm -> createJVMResolutionFacade(environment) + Platform.js -> createJSResolutionFacade(environment) + } + } + private fun createJSResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + val projectContext = ProjectContext(environment.project) + val sourceFiles = environment.getSourceFiles() + + val library = object : LibraryModuleInfo { + override val platform: TargetPlatform + get() = JsPlatform + + override fun getLibraryRoots(): Collection { + return classpath.map { it.absolutePath } + } + + override val name: Name = Name.special("") + override fun dependencies(): List = listOf(this) + } + val module = object : ModuleInfo { + override val name: Name = Name.special("") + override fun dependencies(): List = listOf(this, library) + } + + val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) + + val resolverForProject = ResolverForProjectImpl( + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(library, module), + modulesContent = { + when (it) { + library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(it, emptyList(), sourcesScope) + else -> throw IllegalArgumentException("Unexpected module info") + } + }, + modulePlatforms = { JsPlatform.multiTargetPlatform }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { JsAnalyzerFacade }, + platformParameters = object : PlatformAnalysisParameters {}, + targetEnvironment = CompilerEnvironment, + builtIns = JsPlatform.builtIns + ) + + resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForModule = resolverForProject.resolverForModule(module) + val moduleDescriptor = resolverForProject.descriptorForModule(module) + val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) + val projectComponentManager = environment.project as MockComponentManager + projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) + return created + + } + + private fun createJVMResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() @@ -131,30 +198,27 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } val resolverForProject = ResolverForProjectImpl( - "Dokka", - projectContext, - listOf(library, module), - { + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(library, module), + modulesContent = { when (it) { library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) module -> ModuleContent(it, emptyList(), sourcesScope) else -> throw IllegalArgumentException("Unexpected module info") } }, - { - JvmPlatform.multiTargetPlatform - }, - LanguageSettingsProvider.Default /* TODO: Fix this */, - { JvmAnalyzerFacade }, - - JvmPlatformParameters { + modulePlatforms = { JvmPlatform.multiTargetPlatform }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade }, + platformParameters = JvmPlatformParameters { val file = (it as JavaClassImpl).psi.containingFile.virtualFile if (file in sourcesScope) module else library }, - CompilerEnvironment, + targetEnvironment = CompilerEnvironment, packagePartProviderFactory = { content -> JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { addRoots(javaRoots) @@ -191,7 +255,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * $paths: collection of files to add */ fun addClasspath(paths: List) { - configuration.addJvmClasspathRoots(paths) + when (analysisPlatform) { + Platform.js -> configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map{it.absolutePath}) + Platform.jvm -> configuration.addJvmClasspathRoots(paths) + } } /** @@ -199,7 +266,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * $path: path to add */ fun addClasspath(path: File) { - configuration.addJvmClasspathRoot(path) + when (analysisPlatform) { + Platform.js -> configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) + Platform.jvm -> configuration.addJvmClasspathRoot(path) + } } /** diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 09e5cedf..a0a6eef7 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -35,9 +35,10 @@ class DokkaGenerator(val logger: DokkaLogger, private val documentationModule = DocumentationModule(moduleName) fun generate() { - val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() } - for ((platform, roots) in sourcesGroupedByPlatform) { - appendSourceModule(platform, roots) + val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } + for ((platformsInfo, roots) in sourcesGroupedByPlatform) { + val (platform, analysisPlatform) = platformsInfo + appendSourceModule(platform, analysisPlatform, roots) } documentationModule.prepareForGeneration(options) @@ -49,9 +50,14 @@ class DokkaGenerator(val logger: DokkaLogger, logger.info("done in ${timeBuild / 1000} secs") } - private fun appendSourceModule(defaultPlatform: String?, sourceRoots: List) { + private fun appendSourceModule(defaultPlatform: String?, + analysisPlatform: Platform, + sourceRoots: List + + ) { + val sourcePaths = sourceRoots.map { it.path } - val environment = createAnalysisEnvironment(sourcePaths) + val environment = createAnalysisEnvironment(sourcePaths, analysisPlatform) logger.info("Module: $moduleName") logger.info("Output: ${File(options.outputDir)}") @@ -82,11 +88,13 @@ class DokkaGenerator(val logger: DokkaLogger, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List): AnalysisEnvironment { - val environment = AnalysisEnvironment(DokkaMessageCollector(logger)) + fun createAnalysisEnvironment(sourcePaths: List, analysisPlatform: Platform): AnalysisEnvironment { + val environment = AnalysisEnvironment(DokkaMessageCollector(logger), analysisPlatform) environment.apply { - addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) + if (analysisPlatform == Platform.jvm) { + addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) + } // addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) for (element in this@DokkaGenerator.classpath) { addClasspath(File(element)) diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 34d4154e..0d916345 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -18,13 +18,22 @@ data class SourceLinkDefinitionImpl(override val path: String, } } -class SourceRootImpl(path: String, override val platforms: List = emptyList()) : SourceRoot { +class SourceRootImpl(path: String, override val platforms: List = emptyList(), + override val analysisPlatform: Platform = Platform.DEFAULT) : SourceRoot { override val path: String = File(path).absolutePath companion object { fun parseSourceRoot(sourceRoot: String): SourceRoot { val components = sourceRoot.split("::", limit = 2) - return SourceRootImpl(components.last(), if (components.size == 1) listOf() else components[0].split(',')) + + // TODO: create syntax for cli + val platform = if (components.size == 1) { + Platform.DEFAULT + } else { + Platform.fromString(components[0]) + } + + return SourceRootImpl(components.last(), emptyList(), platform) } } } -- cgit From 65b61e31b761071589e257381bea33557d932412 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Thu, 12 Jul 2018 15:32:19 +0300 Subject: AnalysisEnvironment classpath for js platform fix --- .../src/main/kotlin/Analysis/AnalysisEnvironment.kt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index 453c0311..27881cad 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -102,14 +102,15 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl return environment } - fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope = when (analysisPlatform) { - Platform.js -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope = + when (analysisPlatform) { Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - } + Platform.js -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + } fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { - return when(analysisPlatform) { + return when (analysisPlatform) { Platform.jvm -> createJVMResolutionFacade(environment) Platform.js -> createJSResolutionFacade(environment) } @@ -255,10 +256,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl * $paths: collection of files to add */ fun addClasspath(paths: List) { - when (analysisPlatform) { - Platform.js -> configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map{it.absolutePath}) - Platform.jvm -> configuration.addJvmClasspathRoots(paths) + if (analysisPlatform == Platform.js) { + configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath }) } + configuration.addJvmClasspathRoots(paths) } /** @@ -266,10 +267,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl * $path: path to add */ fun addClasspath(path: File) { - when (analysisPlatform) { - Platform.js -> configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) - Platform.jvm -> configuration.addJvmClasspathRoot(path) + if (analysisPlatform == Platform.js) { + configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) } + configuration.addJvmClasspathRoot(path) } /** -- cgit From b4fcc57ab7f335459131ce105924eeaa5fa77375 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Thu, 12 Jul 2018 19:25:51 +0300 Subject: Add common platform support --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 73 +++++++++++++++++++--- .../kotlin/org/jetbrains/dokka/configuration.kt | 6 +- 2 files changed, 66 insertions(+), 13 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index 27881cad..2558942b 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -18,6 +18,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.caches.project.LibraryModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService @@ -34,6 +35,7 @@ import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.PackagePartProvider import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.js.config.JSConfigurationKeys @@ -41,10 +43,7 @@ import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.BindingTrace -import org.jetbrains.kotlin.resolve.CompilerEnvironment -import org.jetbrains.kotlin.resolve.TargetPlatform +import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters @@ -75,7 +74,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl System.setProperty("idea.io.use.fallback", "true") val configFiles = when (analysisPlatform) { - Platform.jvm -> EnvironmentConfigFiles.JVM_CONFIG_FILES + Platform.jvm, Platform.common -> EnvironmentConfigFiles.JVM_CONFIG_FILES Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES } val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles) @@ -105,15 +104,67 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope = when (analysisPlatform) { Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - Platform.js -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + Platform.js, Platform.common -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) } - fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { - return when (analysisPlatform) { - Platform.jvm -> createJVMResolutionFacade(environment) - Platform.js -> createJSResolutionFacade(environment) + fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade = when (analysisPlatform) { + Platform.jvm -> createJVMResolutionFacade(environment) + Platform.js -> createJSResolutionFacade(environment) + Platform.common -> createCommonResolutionFacade(environment) + } + + fun createCommonResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + val projectContext = ProjectContext(environment.project) + val sourceFiles = environment.getSourceFiles() + + val library = object : LibraryModuleInfo { + override val platform: TargetPlatform + get() = TargetPlatform.Common + + override fun getLibraryRoots(): Collection { + return classpath.map { it.absolutePath } + } + + override val name: Name = Name.special("") + override fun dependencies(): List = listOf(this) + } + val module = object : ModuleInfo { + override val name: Name = Name.special("") + override fun dependencies(): List = listOf(this, library) } + + val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) + + val resolverForProject = ResolverForProjectImpl( + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(module, library), + modulesContent = { + when (it) { + library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) + else -> throw IllegalArgumentException("Unexpected module info") + } + }, + modulePlatforms = { MultiTargetPlatform.Common }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade }, + platformParameters = object : PlatformAnalysisParameters {}, + targetEnvironment = CompilerEnvironment, + packagePartProviderFactory = { content -> + environment.createPackagePartProvider(content.moduleContentScope) + } + ) + + resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForModule = resolverForProject.resolverForModule(module) + val moduleDescriptor = resolverForProject.descriptorForModule(module) + val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) + val projectComponentManager = environment.project as MockComponentManager + projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) + + return created } private fun createJSResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { @@ -259,6 +310,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl if (analysisPlatform == Platform.js) { configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath }) } + configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath }) configuration.addJvmClasspathRoots(paths) } @@ -270,6 +322,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl if (analysisPlatform == Platform.js) { configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) } + configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) configuration.addJvmClasspathRoot(path) } diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index b18e5daf..d1794953 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -19,8 +19,8 @@ class UrlSerializer : ValueSerializer { enum class Platform(val key: String) { jvm("jvm"), - js("js"); -// common("common"); + js("js"), + common("common"); companion object { @@ -30,7 +30,7 @@ enum class Platform(val key: String) { return when (key.toLowerCase()) { jvm.key -> jvm js.key -> js -// common.key -> common + common.key -> common else -> TODO("write normal exception") } } -- cgit From eca10911658bc48cd5508fbe1fd371adc881f392 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Thu, 12 Jul 2018 21:59:25 +0300 Subject: AnalysisPlatform refactoring --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 197 +++++++++------------ 1 file changed, 83 insertions(+), 114 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index 2558942b..f03e9eea 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -19,6 +19,8 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade +import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.caches.project.LibraryModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService @@ -108,19 +110,20 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl } - fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade = when (analysisPlatform) { - Platform.jvm -> createJVMResolutionFacade(environment) - Platform.js -> createJSResolutionFacade(environment) - Platform.common -> createCommonResolutionFacade(environment) - } - - fun createCommonResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() + + val targetPlatform = when (analysisPlatform) { + Platform.js -> JsPlatform + Platform.common -> TargetPlatform.Common + Platform.jvm -> JvmPlatform + } + val library = object : LibraryModuleInfo { override val platform: TargetPlatform - get() = TargetPlatform.Common + get() = targetPlatform override fun getLibraryRoots(): Collection { return classpath.map { it.absolutePath } @@ -135,31 +138,29 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl } val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) + val modulesContent: (ModuleInfo) -> ModuleContent = { + when (it) { + library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) + else -> throw IllegalArgumentException("Unexpected module info") + } + } - val resolverForProject = ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) - else -> throw IllegalArgumentException("Unexpected module info") - } - }, - modulePlatforms = { MultiTargetPlatform.Common }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade }, - platformParameters = object : PlatformAnalysisParameters {}, - targetEnvironment = CompilerEnvironment, - packagePartProviderFactory = { content -> - environment.createPackagePartProvider(content.moduleContentScope) + var builtIns: JvmBuiltIns? = null + + val resolverForProject = when (analysisPlatform) { + Platform.jvm -> { + builtIns = JvmBuiltIns(projectContext.storageManager) + createJvmResolverForProject(projectContext, module, library, modulesContent, sourcesScope, builtIns) } - ) + Platform.js -> createJsResolverForProject(projectContext, module, library, modulesContent) + Platform.common -> createCommonResolverForProject(projectContext, module, library, modulesContent, environment) + } resolverForProject.resolverForModule(library) // Required before module to initialize library properly val resolverForModule = resolverForProject.resolverForModule(module) val moduleDescriptor = resolverForProject.descriptorForModule(module) + builtIns?.initialize(moduleDescriptor, true) val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) val projectComponentManager = environment.project as MockComponentManager projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) @@ -167,99 +168,76 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl return created } - private fun createJSResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { - val projectContext = ProjectContext(environment.project) - val sourceFiles = environment.getSourceFiles() - - val library = object : LibraryModuleInfo { - override val platform: TargetPlatform - get() = JsPlatform - - override fun getLibraryRoots(): Collection { - return classpath.map { it.absolutePath } - } - - override val name: Name = Name.special("") - override fun dependencies(): List = listOf(this) - } - val module = object : ModuleInfo { - override val name: Name = Name.special("") - override fun dependencies(): List = listOf(this, library) - } - - val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) - - val resolverForProject = ResolverForProjectImpl( + private fun createCommonResolverForProject( + projectContext: ProjectContext, + module: ModuleInfo, + library: LibraryModuleInfo, + modulesContent: (ModuleInfo) -> ModuleContent, + environment: KotlinCoreEnvironment + ): ResolverForProjectImpl { + return ResolverForProjectImpl( debugName = "Dokka", projectContext = projectContext, - modules = listOf(library, module), - modulesContent = { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), sourcesScope) - else -> throw IllegalArgumentException("Unexpected module info") - } + modules = listOf(module, library), + modulesContent = modulesContent, + modulePlatforms = { MultiTargetPlatform.Common }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade }, + platformParameters = object : PlatformAnalysisParameters {}, + targetEnvironment = CompilerEnvironment, + packagePartProviderFactory = { content -> + environment.createPackagePartProvider(content.moduleContentScope) }, + builtIns = DefaultBuiltIns.Instance + ) + } + + private fun createJsResolverForProject( + projectContext: ProjectContext, + module: ModuleInfo, + library: LibraryModuleInfo, + modulesContent: (ModuleInfo) -> ModuleContent + ): ResolverForProjectImpl { + return ResolverForProjectImpl( + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(module, library), + modulesContent = modulesContent, modulePlatforms = { JsPlatform.multiTargetPlatform }, moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, resolverForModuleFactoryByPlatform = { JsAnalyzerFacade }, platformParameters = object : PlatformAnalysisParameters {}, targetEnvironment = CompilerEnvironment, + packagePartProviderFactory = { PackagePartProvider.Empty }, builtIns = JsPlatform.builtIns ) - - resolverForProject.resolverForModule(library) // Required before module to initialize library properly - val resolverForModule = resolverForProject.resolverForModule(module) - val moduleDescriptor = resolverForProject.descriptorForModule(module) - val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) - val projectComponentManager = environment.project as MockComponentManager - projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) - return created - } - private fun createJVMResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { - val projectContext = ProjectContext(environment.project) - val sourceFiles = environment.getSourceFiles() - - - val library = object : ModuleInfo { - override val name: Name = Name.special("") - override fun dependencies(): List = listOf(this) - } - val module = object : ModuleInfo { - override val name: Name = Name.special("") - override fun dependencies(): List = listOf(this, library) - } - - val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) - - val builtIns = JvmBuiltIns(projectContext.storageManager) - - + private fun createJvmResolverForProject( + projectContext: ProjectContext, + module: ModuleInfo, + library: LibraryModuleInfo, + modulesContent: (ModuleInfo) -> ModuleContent, + sourcesScope: GlobalSearchScope, + builtIns: KotlinBuiltIns + ): ResolverForProjectImpl { val javaRoots = classpath - .mapNotNull { - val rootFile = when { - it.extension == "jar" -> - StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}") - else -> - StandardFileSystems.local().findFileByPath(it.absolutePath) - } - - rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } + .mapNotNull { + val rootFile = when { + it.extension == "jar" -> + StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}") + else -> + StandardFileSystems.local().findFileByPath(it.absolutePath) } - val resolverForProject = ResolverForProjectImpl( + rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } + } + + return ResolverForProjectImpl( debugName = "Dokka", projectContext = projectContext, - modules = listOf(library, module), - modulesContent = { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), sourcesScope) - else -> throw IllegalArgumentException("Unexpected module info") - } - }, + modules = listOf(module, library), + modulesContent = modulesContent, modulePlatforms = { JvmPlatform.multiTargetPlatform }, moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade }, @@ -269,7 +247,8 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module else library - }, + } + , targetEnvironment = CompilerEnvironment, packagePartProviderFactory = { content -> JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { @@ -278,16 +257,6 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl }, builtIns = builtIns ) - - resolverForProject.resolverForModule(library) // Required before module to initialize library properly - val resolverForModule = resolverForProject.resolverForModule(module) - val moduleDescriptor = resolverForProject.descriptorForModule(module) - builtIns.initialize(moduleDescriptor, true) - val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) - val projectComponentManager = environment.project as MockComponentManager - projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) - - return created } fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { -- cgit From fe20206eecd22cb4bd4de03efc0e9c28e1981bac Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Fri, 13 Jul 2018 15:04:56 +0300 Subject: Minor style fixes --- core/src/main/kotlin/Analysis/AnalysisEnvironment.kt | 3 +-- core/src/test/kotlin/TestAPI.kt | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index f03e9eea..3d70bd84 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -247,8 +247,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module else library - } - , + }, targetEnvironment = CompilerEnvironment, packagePartProviderFactory = { content -> JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 7042f41b..ae69412b 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -117,8 +117,7 @@ fun appendDocumentation(documentation: DocumentationModule, fun checkSourceExistsAndVerifyModel(source: String, modelConfig: ModelConfig = ModelConfig(), - verifier: (DocumentationModule) -> Unit -) { + verifier: (DocumentationModule) -> Unit) { if (!File(source).exists()) { throw IllegalArgumentException("Can't find test data file $source") } -- cgit From 93a9052d8434879f8fdf192d9d498285a6a31127 Mon Sep 17 00:00:00 2001 From: Zubakov Aleksey Date: Tue, 17 Jul 2018 17:13:01 +0300 Subject: NodeReferenceGraph style fixes --- core/src/main/kotlin/Model/DocumentationReference.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 89ec1b3e..5db1f05a 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -37,24 +37,24 @@ class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, } } -class NodeReferenceGraph() { +class NodeReferenceGraph { private val nodeMap = hashMapOf() val references = arrayListOf() fun register(signature: String, node: DocumentationNode) { - nodeMap.put(signature, node) + nodeMap[signature] = node } fun link(fromNode: DocumentationNode, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ -> fromNode}, { -> nodeMap[toSignature]}, kind)) + references.add(PendingDocumentationReference({ fromNode }, { nodeMap[toSignature] }, kind)) } fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) { - references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> toNode}, kind)) + references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { toNode }, kind)) } fun link(fromSignature: String, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> nodeMap[toSignature]}, kind)) + references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { nodeMap[toSignature] }, kind)) } fun lookup(signature: String) = nodeMap[signature] -- cgit From 899c11d36f565cd192945573860568ff62c16ef2 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Wed, 25 Jul 2018 17:24:00 +0300 Subject: Add logic of merging different platforms graphs --- .../main/kotlin/Formats/StructuredFormatService.kt | 12 +- core/src/main/kotlin/Generation/DokkaGenerator.kt | 232 ++++++++++++++++++++- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 6 +- core/src/main/kotlin/Model/DocumentationNode.kt | 10 +- .../main/kotlin/Model/DocumentationReference.kt | 53 ++++- 5 files changed, 288 insertions(+), 25 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index ebc9cde6..41c8f29a 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -514,15 +514,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendSection("Exceptions", node.membersOrGroupMembers(NodeKind.Exception)) appendSection("Type Aliases", node.membersOrGroupMembers(NodeKind.TypeAlias)) appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass)) - appendSection("Enum Values", node.members(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true) - appendSection("Constructors", node.members(NodeKind.Constructor), omitSamePlatforms = true) - appendSection("Properties", node.members(NodeKind.Property), omitSamePlatforms = true) + appendSection("Enum Values", node.membersOrGroupMembers(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true) + appendSection("Constructors", node.membersOrGroupMembers(NodeKind.Constructor), omitSamePlatforms = true) + appendSection("Properties", node.membersOrGroupMembers(NodeKind.Property), omitSamePlatforms = true) appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property)) - appendSection("Functions", node.members(NodeKind.Function), omitSamePlatforms = true) + appendSection("Functions", node.membersOrGroupMembers(NodeKind.Function), omitSamePlatforms = true) appendSection("Inherited Functions", node.inheritedMembers(NodeKind.Function)) - appendSection("Companion Object Properties", node.members(NodeKind.CompanionObjectProperty), omitSamePlatforms = true) + appendSection("Companion Object Properties", node.membersOrGroupMembers(NodeKind.CompanionObjectProperty), omitSamePlatforms = true) appendSection("Inherited Companion Object Properties", node.inheritedCompanionObjectMembers(NodeKind.Property)) - appendSection("Companion Object Functions", node.members(NodeKind.CompanionObjectFunction), omitSamePlatforms = true) + appendSection("Companion Object Functions", node.membersOrGroupMembers(NodeKind.CompanionObjectFunction), omitSamePlatforms = true) appendSection("Inherited Companion Object Functions", node.inheritedCompanionObjectMembers(NodeKind.Function)) appendSection("Other members", node.members.filter { it.kind !in setOf( diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 9de4396b..0c4b3b7e 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Guice import com.google.inject.Injector +import com.intellij.openapi.application.PathManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile @@ -17,6 +18,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.KotlinSourceRoot import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode @@ -32,28 +34,34 @@ class DokkaGenerator(val logger: DokkaLogger, val moduleName: String, val options: DocumentationOptions) { - private val documentationModule = DocumentationModule(moduleName) + private val documentationModules: MutableList = mutableListOf() fun generate() { val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } for ((platformsInfo, roots) in sourcesGroupedByPlatform) { val (platform, analysisPlatform) = platformsInfo - appendSourceModule(platform, analysisPlatform, roots) + + val documentationModule = DocumentationModule(moduleName) + appendSourceModule(platform, analysisPlatform, roots, documentationModule) + documentationModules.add(documentationModule) } - documentationModule.prepareForGeneration(options) + + val totalDocumentationModule = DocumentationMerger(documentationModules).merge() + totalDocumentationModule.prepareForGeneration(options) val timeBuild = measureTimeMillis { logger.info("Generating pages... ") val outputInjector = Guice.createInjector(DokkaOutputModule(options, logger)) - outputInjector.getInstance(Generator::class.java).buildAll(documentationModule) + outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } - private fun appendSourceModule(defaultPlatform: String?, - analysisPlatform: Platform, - sourceRoots: List - + private fun appendSourceModule( + defaultPlatform: String?, + analysisPlatform: Platform, + sourceRoots: List, + documentationModule: DocumentationModule ) { val sourcePaths = sourceRoots.map { it.path } @@ -81,6 +89,12 @@ class DokkaGenerator(val logger: DokkaLogger, DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentationModule.nodeRefGraph, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it) }, includes) + documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> + node.addReferenceTo( + DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), + RefKind.Platform + ) + } val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") @@ -214,3 +228,205 @@ fun KotlinCoreEnvironment.getJavaSourceFiles(): List { } return result } + +class DocumentationMerger( + private val documentationModules: List +) { + private val producedNodeRefGraph: NodeReferenceGraph + private val signatureMap: Map + + init { + signatureMap = documentationModules + .flatMap { it.nodeRefGraph.nodeMapView.entries } + .map { (k, v) -> v to k } + .toMap() + + producedNodeRefGraph = NodeReferenceGraph() + documentationModules.map { it.nodeRefGraph } + .flatMap { it.references } + .distinct() + .forEach { producedNodeRefGraph.addReference(it) } + } + + private fun splitReferencesByKind( + source: List, + kind: RefKind + ): Pair, List> = + Pair(source.filter { it.kind == kind }, source.filterNot { it.kind == kind }) + + + private fun mergePackageReferences( + from: DocumentationNode, + packages: List + ): List { + val packagesByName = packages + .map { it.to } + .groupBy { it.name } + + val mutableList: MutableList = mutableListOf() + for ((name, listOfPackages) in packagesByName) { + val producedPackage = mergePackagesWithEqualNames(from, listOfPackages) + updatePendingReferences(name, producedPackage) + + mutableList.add( + DocumentationReference(from, producedPackage, RefKind.Member) + ) + } + + return mutableList + } + + private fun mergePackagesWithEqualNames( + from: DocumentationNode, + packages: List + ): DocumentationNode { + val references = packages.flatMap { it.allReferences() } + + val mergedPackage = + DocumentationNode( + packages.first().name, + Content.Empty, + NodeKind.Package + ) + + val mergedReferences = mergeReferences(mergedPackage, references) + + for (packageNode in packages) { + mergedPackage.updateContent { + for (otherChild in packageNode.content.children) { + children.add(otherChild) + } + } + } + + mergedPackage.dropReferences { true } // clear() + for (ref in mergedReferences.distinct()) { + mergedPackage.addReference(ref) + } + + from.append(mergedPackage, RefKind.Member) + + return mergedPackage + } + + + private fun mergeMembers( + from: DocumentationNode, + refs: List + ): List { + val membersBySignature: Map> = refs.map { it.to } + .filter { signatureMap.containsKey(it) } + .groupBy { signatureMap[it]!! } + + val mergedMembers: MutableList = mutableListOf() + for ((signature, members) in membersBySignature) { + val newNode = mergeMembersWithEqualSignature(signature, from, members) + + producedNodeRefGraph.register(signature, newNode) + updatePendingReferences(signature, newNode) + from.append(newNode, RefKind.Member) + + mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member)) + } + + return mergedMembers + } + + private fun mergeMembersWithEqualSignature( + signature: String, + from: DocumentationNode, + refs: List + ): DocumentationNode { + if (refs.size == 1) { + val singleNode = refs.single() + singleNode.owner?.let { owner -> + singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } + } + return singleNode + } + val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) + groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) + + for (node in refs) { + if (node != groupNode) { + node.owner?.let { owner -> + node.dropReferences { it.to == owner && it.kind == RefKind.Owner } + from.dropReferences { it.to == node && it.kind == RefKind.Member } + } + groupNode.append(node, RefKind.Member) + } + } + return groupNode + } + + + private fun mergeReferences( + from: DocumentationNode, + refs: List + ): List { + val allRefsToPackages = refs.map { it.to } + .all { it.kind == NodeKind.Package } + + if (allRefsToPackages) { + return mergePackageReferences(from, refs) + } + + val (memberRefs, notMemberRefs) = splitReferencesByKind(refs, RefKind.Member) + val mergedMembers = mergeMembers(from, memberRefs) + + return (mergedMembers + notMemberRefs).distinctBy { + it.kind to it.to.name + } + } + + + private fun updatePendingReferences( + signature: String, + nodeToUpdate: DocumentationNode + ) { + producedNodeRefGraph.references.forEach { + it.lazyNodeFrom.update(signature, nodeToUpdate) + it.lazyNodeTo.update(signature, nodeToUpdate) + } + } + + private fun NodeResolver.update(signature: String, nodeToUpdate: DocumentationNode) { + when (this) { + is NodeResolver.BySignature -> update(signature, nodeToUpdate) + is NodeResolver.Exact -> update(signature, nodeToUpdate) + } + } + + private fun NodeResolver.BySignature.update(signature: String, nodeToUpdate: DocumentationNode) { + if (signature == nodeToUpdate.name) { + nodeMap = producedNodeRefGraph.nodeMapView + } + } + + private fun NodeResolver.Exact.update(signature: String, nodeToUpdate: DocumentationNode) { + exactNode?.let { it -> + val equalSignature = + it.anyReference { ref -> ref.to.kind == NodeKind.Signature && ref.to.name == signature } + + if (equalSignature) { + exactNode = nodeToUpdate + } + } + } + + fun merge(): DocumentationModule { + val refs = documentationModules.flatMap { + it.allReferences() + } + val mergedDocumentationModule = DocumentationModule( + name = documentationModules.first().name, + nodeRefGraph = producedNodeRefGraph + ) + + mergeReferences(mergedDocumentationModule, refs) + + return mergedDocumentationModule + } + + +} \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index f1b8e3d3..e3675f9d 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1079,7 +1079,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name @@ -1149,7 +1149,9 @@ fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) { fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) - .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass } } + .flatMap { it.members.filter { + it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass + || (it.kind == NodeKind.GroupNode && it.anyReference { it.to.kind in NodeKind.classLike }) } } .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a3388031..bdb7cf20 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -134,6 +134,10 @@ open class DocumentationNode(val name: String, references.add(DocumentationReference(this, to, kind)) } + fun addReference(reference: DocumentationReference) { + references.add(reference) + } + fun dropReferences(predicate: (DocumentationReference) -> Boolean) { references.removeAll(predicate) } @@ -159,6 +163,8 @@ open class DocumentationNode(val name: String, fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single() fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single() + fun anyReference(predicate: (DocumentationReference) -> Boolean): Boolean = references.any(predicate) + fun references(kind: RefKind): List = references.filter { it.kind == kind } fun allReferences(): Set = references @@ -167,9 +173,9 @@ open class DocumentationNode(val name: String, } } -class DocumentationModule(name: String, content: Content = Content.Empty) +class DocumentationModule(name: String, content: Content = Content.Empty, val nodeRefGraph: NodeReferenceGraph = NodeReferenceGraph()) : DocumentationNode(name, content, NodeKind.Module) { - val nodeRefGraph = NodeReferenceGraph() + } val DocumentationNode.path: List diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 5db1f05a..9223c17a 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -25,12 +25,27 @@ enum class RefKind { data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { } -class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, - val lazyNodeTo: () -> DocumentationNode?, +sealed class NodeResolver { + abstract fun resolve(): DocumentationNode? + class BySignature(var signature: String, var nodeMap: Map) : NodeResolver() { + override fun resolve(): DocumentationNode? { + return nodeMap[signature] + } + } + + class Exact(var exactNode: DocumentationNode?) : NodeResolver() { + override fun resolve(): DocumentationNode? { + return exactNode + } + } +} + +class PendingDocumentationReference(val lazyNodeFrom: NodeResolver, + val lazyNodeTo: NodeResolver, val kind: RefKind) { fun resolve() { - val fromNode = lazyNodeFrom() - val toNode = lazyNodeTo() + val fromNode = lazyNodeFrom.resolve() + val toNode = lazyNodeTo.resolve() if (fromNode != null && toNode != null) { fromNode.addReferenceTo(toNode, kind) } @@ -39,6 +54,9 @@ class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, class NodeReferenceGraph { private val nodeMap = hashMapOf() + val nodeMapView: Map + get() = HashMap(nodeMap) + val references = arrayListOf() fun register(signature: String, node: DocumentationNode) { @@ -46,15 +64,36 @@ class NodeReferenceGraph { } fun link(fromNode: DocumentationNode, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ fromNode }, { nodeMap[toSignature] }, kind)) + references.add( + PendingDocumentationReference( + NodeResolver.Exact(fromNode), + NodeResolver.BySignature(toSignature, nodeMap), + kind + )) } fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) { - references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { toNode }, kind)) + references.add( + PendingDocumentationReference( + NodeResolver.BySignature(fromSignature, nodeMap), + NodeResolver.Exact(toNode), + kind + ) + ) } fun link(fromSignature: String, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { nodeMap[toSignature] }, kind)) + references.add( + PendingDocumentationReference( + NodeResolver.BySignature(fromSignature, nodeMap), + NodeResolver.BySignature(toSignature, nodeMap), + kind + ) + ) + } + + fun addReference(reference: PendingDocumentationReference) { + references.add(reference) } fun lookup(signature: String) = nodeMap[signature] -- cgit From 052a218dcf8bc565d5e78dc900a9647f0da5350a Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Wed, 1 Aug 2018 19:48:45 +0300 Subject: Refactoring, replace DocumentationOption with PassConfiguration --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 32 +----- core/src/main/kotlin/Generation/DokkaGenerator.kt | 58 +++++------ core/src/main/kotlin/Generation/FileGenerator.kt | 5 +- .../main/kotlin/Generation/configurationImpl.kt | 70 ++++++++----- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 25 +++-- .../main/kotlin/Kotlin/DeclarationLinkResolver.kt | 4 +- .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 2 +- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 108 ++++++--------------- .../Kotlin/ExternalDocumentationLinkResolver.kt | 13 ++- .../Kotlin/KotlinAsJavaDocumentationBuilder.kt | 2 +- .../Samples/DefaultSampleProcessingService.kt | 2 +- .../KotlinWebsiteSampleProcessingService.kt | 4 +- core/src/main/kotlin/Utilities/DokkaModules.kt | 18 ++-- core/src/main/kotlin/javadoc/dokka-adapters.kt | 9 +- core/src/test/kotlin/TestAPI.kt | 44 +++++---- .../test/kotlin/format/KotlinWebSiteFormatTest.kt | 19 ++-- .../kotlin/format/KotlinWebSiteHtmlFormatTest.kt | 22 +++-- core/src/test/kotlin/format/MarkdownFormatTest.kt | 36 ++++--- .../kotlin/org/jetbrains/dokka/configuration.kt | 71 ++++++-------- runners/ant/src/main/kotlin/ant/dokka.kt | 49 +++++----- runners/cli/src/main/kotlin/cli/main.kt | 36 ++++--- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 47 ++++----- 22 files changed, 323 insertions(+), 353 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index e18ab6cf..ccafcd12 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import org.jetbrains.dokka.DokkaConfiguration.PackageOptions import ru.yole.jkid.deserialization.deserialize -import java.io.File import java.util.function.BiConsumer @@ -44,36 +43,7 @@ class DokkaBootstrapImpl : DokkaBootstrap { = configure(DokkaProxyLogger(logger), deserialize(serializedConfigurationJSON)) fun configure(logger: DokkaLogger, configuration: DokkaConfiguration) = with(configuration) { - generator = DokkaGenerator( - logger, - classpath, - sourceRoots, - samples, - includes, - moduleName, - DocumentationOptions( - outputDir = outputDir, - outputFormat = format, - includeNonPublic = includeNonPublic, - includeRootPackage = includeRootPackage, - reportUndocumented = reportUndocumented, - skipEmptyPackages = skipEmptyPackages, - skipDeprecated = skipDeprecated, - jdkVersion = jdkVersion, - generateIndexPages = generateIndexPages, - sourceLinks = sourceLinks, - impliedPlatforms = impliedPlatforms, - perPackageOptions = perPackageOptions, - externalDocumentationLinks = externalDocumentationLinks, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - languageVersion = languageVersion, - apiVersion = apiVersion, - cacheRoot = cacheRoot, - suppressedFiles = suppressedFiles.map { File(it) }.toSet(), - collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries - ) - ) + generator = DokkaGenerator(configuration, logger) } override fun generate() = generator.generate() diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 0c4b3b7e..2e46d908 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -2,13 +2,11 @@ package org.jetbrains.dokka import com.google.inject.Guice import com.google.inject.Injector -import com.intellij.openapi.application.PathManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager -import org.jetbrains.dokka.DokkaConfiguration.SourceRoot import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation @@ -18,7 +16,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.KotlinSourceRoot import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode @@ -26,56 +23,49 @@ import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis -class DokkaGenerator(val logger: DokkaLogger, - val classpath: List, - val sources: List, - val samples: List, - val includes: List, - val moduleName: String, - val options: DocumentationOptions) { +class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, + val logger: DokkaLogger) { private val documentationModules: MutableList = mutableListOf() - fun generate() { - val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } - for ((platformsInfo, roots) in sourcesGroupedByPlatform) { - val (platform, analysisPlatform) = platformsInfo - val documentationModule = DocumentationModule(moduleName) - appendSourceModule(platform, analysisPlatform, roots, documentationModule) + fun generate() = with(dokkaConfiguration) { + + + for (pass in passesConfigurations) { + val documentationModule = DocumentationModule(pass.moduleName) + appendSourceModule(pass, documentationModule) documentationModules.add(documentationModule) } val totalDocumentationModule = DocumentationMerger(documentationModules).merge() - totalDocumentationModule.prepareForGeneration(options) + totalDocumentationModule.prepareForGeneration(dokkaConfiguration) val timeBuild = measureTimeMillis { logger.info("Generating pages... ") - val outputInjector = Guice.createInjector(DokkaOutputModule(options, logger)) + val outputInjector = Guice.createInjector(DokkaOutputModule(dokkaConfiguration, logger)) outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } private fun appendSourceModule( - defaultPlatform: String?, - analysisPlatform: Platform, - sourceRoots: List, + passConfiguration: DokkaConfiguration.PassConfiguration, documentationModule: DocumentationModule - ) { + ) = with(passConfiguration) { - val sourcePaths = sourceRoots.map { it.path } - val environment = createAnalysisEnvironment(sourcePaths, analysisPlatform) + val sourcePaths = passConfiguration.sourceRoots.map { it.path } + val environment = createAnalysisEnvironment(sourcePaths, passConfiguration) logger.info("Module: $moduleName") - logger.info("Output: ${File(options.outputDir)}") + logger.info("Output: ${File(dokkaConfiguration.outputDir)}") logger.info("Sources: ${sourcePaths.joinToString()}") logger.info("Classpath: ${environment.classpath.joinToString()}") logger.info("Analysing sources and libraries... ") val startAnalyse = System.currentTimeMillis() - val defaultPlatformAsList = defaultPlatform?.let { listOf(it) }.orEmpty() + val defaultPlatformAsList = listOf(passConfiguration.analysisPlatform.key) val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List { val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath @@ -86,9 +76,9 @@ class DokkaGenerator(val logger: DokkaLogger, } val injector = Guice.createInjector( - DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentationModule.nodeRefGraph, logger)) + DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) - buildDocumentationModule(injector, documentationModule, { isNotSample(it) }, includes) + buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> node.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), @@ -102,28 +92,28 @@ class DokkaGenerator(val logger: DokkaLogger, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List, analysisPlatform: Platform): AnalysisEnvironment { - val environment = AnalysisEnvironment(DokkaMessageCollector(logger), analysisPlatform) + fun createAnalysisEnvironment(sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration): AnalysisEnvironment { + val environment = AnalysisEnvironment(DokkaMessageCollector(logger), passConfiguration.analysisPlatform) environment.apply { if (analysisPlatform == Platform.jvm) { addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) } // addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) - for (element in this@DokkaGenerator.classpath) { + for (element in passConfiguration.classpath) { addClasspath(File(element)) } addSources(sourcePaths) - addSources(this@DokkaGenerator.samples) + addSources(passConfiguration.samples) - loadLanguageVersionSettings(options.languageVersion, options.apiVersion) + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) } return environment } - fun isNotSample(file: PsiFile): Boolean { + fun isNotSample(file: PsiFile, samples: List): Boolean { val sourceFile = File(file.virtualFile!!.path) return samples.none { sample -> val canonicalSample = File(sample).canonicalPath diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index b7c6cf63..eb6800b3 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named -import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -12,7 +11,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F @set:Inject(optional = true) var outlineService: OutlineFormatService? = null @set:Inject(optional = true) lateinit var formatService: FormatService - @set:Inject(optional = true) lateinit var options: DocumentationOptions + @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null override fun location(node: DocumentationNode): FileLocation { @@ -74,7 +73,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F val moduleRoot = location(module).file.parentFile val packageListFile = File(moduleRoot, "package-list") - packageListFile.writeText("\$dokka.format:${options.outputFormat}\n" + + packageListFile.writeText("\$dokka.format:${dokkaConfiguration.format}\n" + packageListService!!.formatPackageList(module as DocumentationModule)) } diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 8829682a..3e39b4ed 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -45,29 +45,47 @@ data class PackageOptionsImpl(override val prefix: String, override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions data class DokkaConfigurationImpl( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val noJdkLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String?, - override val collectInheritedExtensionsFromLibraries: Boolean -) : DokkaConfiguration \ No newline at end of file + override val outputDir: String = "", + override val format: String = "html", + override val generateIndexPages: Boolean = false, + override val cacheRoot: String? = null, + override val impliedPlatforms: List = listOf(), + override val passesConfigurations: List = listOf() +) : DokkaConfiguration + +class PassConfigurationImpl ( + override val classpath: List = listOf(), + override val moduleName: String = "", + override val sourceRoots: List = listOf(), + override val samples: List = listOf(), + override val includes: List = listOf(), + override val includeNonPublic: Boolean = false, + override val includeRootPackage: Boolean = false, + override val reportUndocumented: Boolean = false, + override val skipEmptyPackages: Boolean = false, + override val skipDeprecated: Boolean = false, + override val jdkVersion: Int = 6, + override val sourceLinks: List = listOf(), + override val perPackageOptions: List = listOf(), + externalDocumentationLinks: List = listOf(), + override val languageVersion: String? = null, + override val apiVersion: String? = null, + override val noStdlibLink: Boolean = false, + override val noJdkLink: Boolean = false, + override val suppressedFiles: List = listOf(), + override val collectInheritedExtensionsFromLibraries: Boolean = false, + override val analysisPlatform: Platform = Platform.DEFAULT, + override val targets: List = listOf() +): DokkaConfiguration.PassConfiguration { + private val defaultLinks = run { + val links = mutableListOf() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() + links + } + override val externalDocumentationLinks = defaultLinks + externalDocumentationLinks +} + diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 332afffb..1fe4d180 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtModifierListOwner -import java.io.File fun getSignature(element: PsiElement?) = when(element) { is PsiPackage -> element.qualifiedName @@ -44,24 +43,24 @@ interface JavaDocumentationBuilder { } class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { - private val options: DocumentationOptions + private val passConfiguration: DokkaConfiguration.PassConfiguration private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser @Inject constructor( - options: DocumentationOptions, - refGraph: NodeReferenceGraph, - logger: DokkaLogger, - signatureProvider: ElementSignatureProvider, - externalDocumentationLinkResolver: ExternalDocumentationLinkResolver + passConfiguration: DokkaConfiguration.PassConfiguration, + refGraph: NodeReferenceGraph, + logger: DokkaLogger, + signatureProvider: ElementSignatureProvider, + externalDocumentationLinkResolver: ExternalDocumentationLinkResolver ) { - this.options = options + this.passConfiguration = passConfiguration this.refGraph = refGraph this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver) } - constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { - this.options = options + constructor(passConfiguration: DokkaConfiguration.PassConfiguration, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { + this.passConfiguration = passConfiguration this.refGraph = refGraph this.docParser = docParser } @@ -141,7 +140,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { } } - private fun skipFile(javaFile: PsiJavaFile): Boolean = options.effectivePackageOptions(javaFile.packageName).suppress + private fun skipFile(javaFile: PsiJavaFile): Boolean = passConfiguration.effectivePackageOptions(javaFile.packageName).suppress private fun skipElement(element: Any) = skipElementByVisibility(element) || @@ -151,13 +150,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private fun skipElementByVisibility(element: Any): Boolean = element is PsiModifierListOwner && element !is PsiParameter && - !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && + !(passConfiguration.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && (element.hasModifierProperty(PsiModifier.PRIVATE) || element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || element.isInternal()) private fun skipElementBySuppressedFiles(element: Any): Boolean = - element is PsiElement && File(element.containingFile.virtualFile.path).absoluteFile in options.suppressedFiles + element is PsiElement && element.containingFile.virtualFile.path in passConfiguration.suppressedFiles private fun PsiElement.isInternal(): Boolean { val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index d73bef4a..c3a84e57 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -10,7 +10,7 @@ class DeclarationLinkResolver @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, val logger: DokkaLogger, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver, val elementSignatureProvider: ElementSignatureProvider) { @@ -63,7 +63,7 @@ class DeclarationLinkResolver if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { return symbol.overriddenDescriptors.firstOrNull() } - if (symbol is TypeAliasDescriptor && !symbol.isDocumented(options)) { + if (symbol is TypeAliasDescriptor && !symbol.isDocumented(passConfiguration)) { return symbol.classDescriptor } return symbol diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 7817da18..d0650d45 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement class DescriptorDocumentationParser - @Inject constructor(val options: DocumentationOptions, + @Inject constructor(val options: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger, val linkResolver: DeclarationLinkResolver, val resolutionFacade: DokkaResolutionFacade, diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e3675f9d..fb0b898a 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -4,7 +4,7 @@ import com.google.inject.Inject import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiField import com.intellij.psi.PsiJavaFile -import org.jetbrains.dokka.DokkaConfiguration.* +import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* @@ -35,62 +35,8 @@ import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.util.supertypesWithAny -import java.io.File -import java.nio.file.Path -import java.nio.file.Paths import com.google.inject.name.Named as GuiceNamed -class DocumentationOptions(val outputDir: String, - val outputFormat: String, - includeNonPublic: Boolean = false, - val includeRootPackage: Boolean = false, - reportUndocumented: Boolean = true, - val skipEmptyPackages: Boolean = true, - skipDeprecated: Boolean = false, - jdkVersion: Int = 6, - val generateIndexPages: Boolean = true, - val sourceLinks: List = emptyList(), - val impliedPlatforms: List = emptyList(), - // Sorted by pattern length - perPackageOptions: List = emptyList(), - externalDocumentationLinks: List = emptyList(), - noStdlibLink: Boolean, - noJdkLink: Boolean = false, - val languageVersion: String?, - val apiVersion: String?, - cacheRoot: String? = null, - val suppressedFiles: Set = emptySet(), - val collectInheritedExtensionsFromLibraries: Boolean = false) { - init { - if (perPackageOptions.any { it.prefix == "" }) - throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead") - } - - val perPackageOptions = perPackageOptions.sortedByDescending { it.prefix.length } - val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated) - - fun effectivePackageOptions(pack: String): PackageOptions = perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions - fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString()) - - val defaultLinks = run { - val links = mutableListOf() - if (!noJdkLink) - links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() - - if (!noStdlibLink) - links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() - links - } - - val externalDocumentationLinks = defaultLinks + externalDocumentationLinks - - val cacheRoot: Path? = when { - cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") - cacheRoot != null -> Paths.get(cacheRoot) - else -> null - } -} - private fun isExtensionForExternalClass(extensionFunctionDescriptor: DeclarationDescriptor, extensionReceiverDescriptor: DeclarationDescriptor, allFqNames: Collection): Boolean { @@ -120,7 +66,7 @@ val ignoredSupertypes = setOf( class DocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val descriptorDocumentationParser: DescriptorDocumentationParser, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val refGraph: NodeReferenceGraph, val platformNodeRegistry: PlatformNodeRegistry, val logger: DokkaLogger, @@ -352,7 +298,7 @@ class DocumentationBuilder fun DocumentationNode.isSinceKotlin() = name == "SinceKotlin" && kind == NodeKind.Annotation fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) { - appendSourceLink(sourceElement.getPsi(), options.sourceLinks) + appendSourceLink(sourceElement.getPsi(), passConfiguration.sourceLinks) } fun DocumentationNode.appendSignature(descriptor: DeclarationDescriptor) { @@ -360,7 +306,7 @@ class DocumentationBuilder } fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? { - if (!descriptor.isGenerated() && descriptor.isDocumented(options)) { + if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) { val node = descriptor.build() append(node, kind) return node @@ -387,7 +333,7 @@ class DocumentationBuilder fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) { - if (descriptor.isGenerated() || !descriptor.isDocumented(options)) return + if (descriptor.isGenerated() || !descriptor.isDocumented(passConfiguration)) return val existingNode = refGraph.lookup(descriptor.signature()) if (existingNode != null) { @@ -459,10 +405,10 @@ class DocumentationBuilder val allFqNames = fragments.map { it.fqName }.distinct() for (packageName in allFqNames) { - if (packageName.isRoot && !options.includeRootPackage) continue + if (packageName.isRoot && !passConfiguration.includeRootPackage) continue val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getContributedDescriptors() } - if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue + if (passConfiguration.skipEmptyPackages && declarations.none { it.isDocumented(passConfiguration) }) continue logger.info(" package $packageName: ${declarations.count()} declarations") val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode, @@ -489,7 +435,7 @@ class DocumentationBuilder }.flatten() val allDescriptors = - if (options.collectInheritedExtensionsFromLibraries) { + if (passConfiguration.collectInheritedExtensionsFromLibraries) { allPackageViewDescriptors.map { it.memberScope } } else { fragments.asSequence().map { it.getMemberScope() } @@ -694,7 +640,7 @@ class DocumentationBuilder .mapTo(result) { ClassMember(it, extraModifier = "static") } val companionObjectDescriptor = companionObjectDescriptor - if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(options)) { + if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(passConfiguration)) { val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors() val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() } descriptorsToDocument.mapTo(result) { @@ -967,12 +913,12 @@ class DocumentationBuilder } -fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean { - return (options.effectivePackageOptions(fqNameSafe).includeNonPublic +fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean { + return (passConfiguration.effectivePackageOptions(fqNameSafe).includeNonPublic || this !is MemberDescriptor || this.visibility.isPublicAPI) - && !isDocumentationSuppressed(options) - && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) + && !isDocumentationSuppressed(passConfiguration) + && (!passConfiguration.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) } private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION @@ -986,7 +932,7 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { val externalClassNodes = hashMapOf() declarations.forEach { descriptor -> with(documentationBuilder) { - if (descriptor.isDocumented(options)) { + if (descriptor.isDocumented(passConfiguration)) { val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames) parent.appendOrUpdateMember(descriptor) } @@ -998,14 +944,14 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { class KotlinJavaDocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val documentationBuilder: DocumentationBuilder, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger) : JavaDocumentationBuilder { override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map) { val classDescriptors = file.classes.map { it.getJavaClassDescriptor(resolutionFacade) } - if (classDescriptors.any { it != null && it.isDocumented(options) }) { + if (classDescriptors.any { it != null && it.isDocumented(passConfiguration) }) { val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph) for (descriptor in classDescriptors.filterNotNull()) { @@ -1035,13 +981,13 @@ fun AnnotationDescriptor.mustBeDocumented(): Boolean { return annotationClass.isDocumentedAnnotation() } -fun DeclarationDescriptor.isDocumentationSuppressed(options: DocumentationOptions): Boolean { +fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean { - if (options.effectivePackageOptions(fqNameSafe).suppress) return true + if (passConfiguration.effectivePackageOptions(fqNameSafe).suppress) return true val path = this.findPsi()?.containingFile?.virtualFile?.path if (path != null) { - if (File(path).absoluteFile in options.suppressedFiles) return true + if (path in passConfiguration.suppressedFiles) return true } val doc = findKDoc() @@ -1079,7 +1025,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name @@ -1140,8 +1086,8 @@ fun DeclarationDescriptor.sourceLocation(): String? { return null } -fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) { - if (options.generateIndexPages) { +fun DocumentationModule.prepareForGeneration(configuration: DokkaConfiguration) { + if (configuration.generateIndexPages) { generateAllTypesNode() } nodeRefGraph.resolveReferences() @@ -1167,4 +1113,12 @@ fun ClassDescriptor.supertypesWithAnyPrecise(): Collection { return emptyList() } return typeConstructor.supertypesWithAny() -} \ No newline at end of file +} + +fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions { + val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated) + return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions +} + +fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString()) + diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index a8129793..2fc207b9 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -22,6 +22,7 @@ import java.net.HttpURLConnection import java.net.URL import java.net.URLConnection import java.nio.file.Path +import java.nio.file.Paths import java.security.MessageDigest import javax.inject.Named import kotlin.reflect.full.findAnnotation @@ -30,7 +31,8 @@ fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format( @Singleton class ExternalDocumentationLinkResolver @Inject constructor( - val options: DocumentationOptions, + val configuration: DokkaConfiguration, + val passConfiguration: DokkaConfiguration.PassConfiguration, @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, val logger: DokkaLogger ) { @@ -42,7 +44,12 @@ class ExternalDocumentationLinkResolver @Inject constructor( override fun toString(): String = rootUrl.toString() } - val cacheDir: Path? = options.cacheRoot?.resolve("packageListCache")?.apply { createDirectories() } + + val cacheDir: Path? = when { + configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") + configuration.cacheRoot != null -> Paths.get(configuration.cacheRoot) + else -> null + }?.resolve("packageListCache")?.apply { createDirectories() } val cachedProtocols = setOf("http", "https", "ftp") @@ -157,7 +164,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( } init { - options.externalDocumentationLinks.forEach { + passConfiguration.externalDocumentationLinks.forEach { try { loadPackageList(it) } catch (e: Exception) { diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt index c7ed8292..be6dd2e1 100644 --- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt @@ -28,7 +28,7 @@ class KotlinAsJavaDocumentationBuilder return } - val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.options, + val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.passConfiguration, documentationBuilder.refGraph, kotlinAsJavaDocumentationParser) diff --git a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt index 116a5c02..f3f45c3f 100644 --- a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.resolve.scopes.ResolutionScope open class DefaultSampleProcessingService -@Inject constructor(val options: DocumentationOptions, +@Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger, val resolutionFacade: DokkaResolutionFacade) : SampleProcessingService { diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index b0988c35..b5801457 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -12,10 +12,10 @@ import org.jetbrains.kotlin.psi.psiUtil.prevLeaf import org.jetbrains.kotlin.resolve.ImportPath open class KotlinWebsiteSampleProcessingService -@Inject constructor(options: DocumentationOptions, +@Inject constructor(dokkaConfiguration: DokkaConfiguration, logger: DokkaLogger, resolutionFacade: DokkaResolutionFacade) - : DefaultSampleProcessingService(options, logger, resolutionFacade) { + : DefaultSampleProcessingService(dokkaConfiguration, logger, resolutionFacade) { private class SampleBuilder : KtTreeVisitorVoid() { val builder = StringBuilder() diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 732cbc48..251d5c23 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -14,9 +14,10 @@ import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" class DokkaAnalysisModule(val environment: AnalysisEnvironment, - val options: DocumentationOptions, + val configuration: DokkaConfiguration, val defaultPlatformsProvider: DefaultPlatformsProvider, val nodeReferenceGraph: NodeReferenceGraph, + val passConfiguration: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { binder.bind().toInstance(logger) @@ -28,29 +29,30 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(dokkaResolutionFacade) binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) - binder.bind().toInstance(options) + binder.bind().toInstance(configuration) + binder.bind().toInstance(passConfiguration) binder.bind().toInstance(defaultPlatformsProvider) binder.bind().toInstance(nodeReferenceGraph) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) + val descriptor = ServiceLocator.lookup("format", configuration.format) descriptor.configureAnalysis(binder) } } object StringListType : TypeLiteral<@JvmSuppressWildcards List>() -class DokkaOutputModule(val options: DocumentationOptions, +class DokkaOutputModule(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) + binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) - binder.bind().toInstance(options) + binder.bind().toInstance(configuration) binder.bind().toInstance(logger) - binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(options.impliedPlatforms) + binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) + val descriptor = ServiceLocator.lookup("format", configuration.format) descriptor.configureOutput(binder) } diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt index 483fb3cd..1329876a 100644 --- a/core/src/main/kotlin/javadoc/dokka-adapters.kt +++ b/core/src/main/kotlin/javadoc/dokka-adapters.kt @@ -4,16 +4,19 @@ import com.google.inject.Binder import com.google.inject.Inject import com.sun.tools.doclets.formats.html.HtmlDoclet import org.jetbrains.dokka.* -import org.jetbrains.dokka.Formats.* +import org.jetbrains.dokka.Formats.DefaultAnalysisComponent +import org.jetbrains.dokka.Formats.DefaultAnalysisComponentServices +import org.jetbrains.dokka.Formats.FormatDescriptor +import org.jetbrains.dokka.Formats.KotlinAsJava import org.jetbrains.dokka.Utilities.bind import org.jetbrains.dokka.Utilities.toType -class JavadocGenerator @Inject constructor(val options: DocumentationOptions, val logger: DokkaLogger) : Generator { +class JavadocGenerator @Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Generator { override fun buildPages(nodes: Iterable) { val module = nodes.single() as DocumentationModule - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), options.outputDir)) + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), configuration.outputDir)) } override fun buildOutlines(nodes: Iterable) { diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 4a755130..b65efbe9 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -35,31 +35,35 @@ fun verifyModel(modelConfig: ModelConfig, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") - val options = DocumentationOptions( - "", - modelConfig.format, - includeNonPublic = modelConfig.includeNonPublic, - skipEmptyPackages = false, - includeRootPackage = true, - sourceLinks = listOf(), - perPackageOptions = modelConfig.perPackageOptions, - generateIndexPages = false, - noStdlibLink = modelConfig.noStdlibLink, - noJdkLink = false, - cacheRoot = "default", - languageVersion = null, - apiVersion = null, - collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + val passConfiguration = PassConfigurationImpl ( + includeNonPublic = modelConfig.includeNonPublic, + skipEmptyPackages = false, + includeRootPackage = true, + sourceLinks = listOf(), + perPackageOptions = modelConfig.perPackageOptions, + noStdlibLink = modelConfig.noStdlibLink, + noJdkLink = false, + languageVersion = null, + apiVersion = null, + collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = modelConfig.format, + generateIndexPages = false, + cacheRoot = "default", + passesConfigurations = listOf(passConfiguration) ) - appendDocumentation(documentation, options, modelConfig) - documentation.prepareForGeneration(options) + appendDocumentation(documentation, configuration, passConfiguration, modelConfig) + documentation.prepareForGeneration(configuration) verifier(documentation) } fun appendDocumentation(documentation: DocumentationModule, - options: DocumentationOptions, + dokkaConfiguration: DokkaConfiguration, + passConfiguration: DokkaConfiguration.PassConfiguration, modelConfig: ModelConfig ) { val messageCollector = object : MessageCollector { @@ -108,13 +112,13 @@ fun appendDocumentation(documentation: DocumentationModule, } addRoots(modelConfig.roots.toList()) - loadLanguageVersionSettings(options.languageVersion, options.apiVersion) + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) } val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms } val injector = Guice.createInjector( - DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentation.nodeRefGraph, DokkaConsoleLogger)) + DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentation.nodeRefGraph, passConfiguration, DokkaConsoleLogger)) buildDocumentationModule(injector, documentation) Disposer.dispose(environment) } diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt index 643b5b2d..4f292e37 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt @@ -48,17 +48,20 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, - noStdlibLink = true, + val passConfiguration = PassConfigurationImpl(noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf(passConfiguration) + ) + appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/jvm.kt")), defaultPlatforms = listOf("JVM") ) @@ -67,13 +70,13 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/jre7.kt")), defaultPlatforms = listOf("JVM", "JRE7") ) ) appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/js.kt")), defaultPlatforms = listOf("JS") ) diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index 3ae0930e..1901154f 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -64,29 +64,37 @@ abstract class BaseKotlinWebSiteHtmlFormatTest(val analysisPlatform: Platform): private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "kotlin-website-html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "kotlin-website-html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + + ) + appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jvm.kt")), defaultPlatforms = listOf("JVM") ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jre7.kt")), defaultPlatforms = listOf("JVM", "JRE7") ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/js.kt")), defaultPlatforms = listOf("JS") ) diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 4de70751..29d2d20f 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -1,7 +1,6 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* -import org.junit.Before import org.junit.Test abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() { @@ -249,16 +248,23 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener @Test fun packagePlatformsWithExtExtensions() { val path = "multiplatform/packagePlatformsWithExtExtensions" val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) - appendDocumentation(module, options, ModelConfig( + + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + ) + + appendDocumentation(module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")), defaultPlatforms = listOf("JVM"), withKotlinRuntime = true, @@ -373,24 +379,30 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + + ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")), defaultPlatforms = listOf("JVM"), analysisPlatform = Platform.jvm ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/js.kt")), defaultPlatforms = listOf("JS"), analysisPlatform = Platform.js diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 287b628a..e0fa27d1 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -39,31 +39,37 @@ enum class Platform(val key: String) { } interface DokkaConfiguration { - val moduleName: String - val classpath: List - val sourceRoots: List - val samples: List - val includes: List val outputDir: String val format: String - val includeNonPublic: Boolean - val includeRootPackage: Boolean - val reportUndocumented: Boolean - val skipEmptyPackages: Boolean - val skipDeprecated: Boolean - val jdkVersion: Int val generateIndexPages: Boolean - val sourceLinks: List - val impliedPlatforms: List - val perPackageOptions: List - val externalDocumentationLinks: List - val languageVersion: String? - val apiVersion: String? - val noStdlibLink: Boolean - val noJdkLink: Boolean val cacheRoot: String? - val suppressedFiles: List - val collectInheritedExtensionsFromLibraries: Boolean + val passesConfigurations: List + val impliedPlatforms: List + + interface PassConfiguration { + val moduleName: String + val classpath: List + val sourceRoots: List + val samples: List + val includes: List + val includeNonPublic: Boolean + val includeRootPackage: Boolean + val reportUndocumented: Boolean + val skipEmptyPackages: Boolean + val skipDeprecated: Boolean + val jdkVersion: Int + val sourceLinks: List + val perPackageOptions: List + val externalDocumentationLinks: List + val languageVersion: String? + val apiVersion: String? + val noStdlibLink: Boolean + val noJdkLink: Boolean + val suppressedFiles: List + val collectInheritedExtensionsFromLibraries: Boolean + val analysisPlatform: Platform + val targets: List + } interface SourceRoot { val path: String @@ -106,31 +112,12 @@ interface DokkaConfiguration { } data class SerializeOnlyDokkaConfiguration( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, override val outputDir: String, override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val noJdkLink: Boolean, override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String?, - override val collectInheritedExtensionsFromLibraries: Boolean + override val impliedPlatforms: List, + override val passesConfigurations: List ) : DokkaConfiguration diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 0b1ccc13..4f629198 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -116,29 +116,34 @@ class DokkaAntTask: Task() { SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix) } - val generator = DokkaGenerator( - AntLogger(this), - compileClasspath.list().toList(), - sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }, - samplesPath.list().toList(), - includesPath.list().toList(), - moduleName!!, - DocumentationOptions( - outputDir!!, - outputFormat, - skipDeprecated = skipDeprecated, - sourceLinks = sourceLinks, - jdkVersion = jdkVersion, - impliedPlatforms = impliedPlatforms.split(','), - perPackageOptions = antPackageOptions, - externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - cacheRoot = cacheRoot, - languageVersion = languageVersion, - apiVersion = apiVersion - ) + val passConfiguration = PassConfigurationImpl( + classpath = compileClasspath.list().toList(), + sourceRoots = sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }, + samples = samplesPath.list().toList(), + includes = includesPath.list().toList(), + moduleName = moduleName!!, + skipDeprecated = skipDeprecated, + sourceLinks = sourceLinks, + jdkVersion = jdkVersion, + perPackageOptions = antPackageOptions, + externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion ) + + val configuration = DokkaConfigurationImpl( + outputDir = outputDir!!, + format = outputFormat, + impliedPlatforms = impliedPlatforms.split(','), + cacheRoot = cacheRoot, + passesConfigurations = listOf( + passConfiguration + ) + ) + + val generator = DokkaGenerator(configuration, AntLogger(this)) generator.generate() } } \ No newline at end of file diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index f871f406..330de5e1 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -44,7 +44,7 @@ class DokkaArguments { @set:Argument(value = "impliedPlatforms", description = "List of implied platforms (comma-separated)") var impliedPlatforms: String = "" - @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ") + @set:Argument(value = "packageOptions", description = "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ") var packageOptions: String = "" @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...") @@ -111,31 +111,37 @@ object MainKt { val classPath = arguments.classpath.split(File.pathSeparatorChar).toList() - val documentationOptions = DocumentationOptions( - arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, - arguments.outputFormat, + val passConfig = PassConfigurationImpl( skipDeprecated = arguments.nodeprecated, sourceLinks = sourceLinks, - impliedPlatforms = arguments.impliedPlatforms.split(','), perPackageOptions = parsePerPackageOptions(arguments.packageOptions), jdkVersion = arguments.jdkVersion, externalDocumentationLinks = parseLinks(arguments.links), noStdlibLink = arguments.noStdlibLink, - cacheRoot = arguments.cacheRoot, languageVersion = arguments.languageVersion, apiVersion = arguments.apiVersion, collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries, - noJdkLink = arguments.noJdkLink + noJdkLink = arguments.noJdkLink, + sourceRoots = sources.map(SourceRootImpl.Companion::parseSourceRoot), + analysisPlatform = sources.map (SourceRootImpl.Companion::parseSourceRoot).single().analysisPlatform, + samples = samples, + includes = includes, + moduleName = arguments.moduleName, + classpath = classPath + ) + + val config = DokkaConfigurationImpl( + outputDir = arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, + format = arguments.outputFormat, + impliedPlatforms = arguments.impliedPlatforms.split(','), + cacheRoot = arguments.cacheRoot, + + passesConfigurations = listOf( + passConfig + ) ) - val generator = DokkaGenerator( - DokkaConsoleLogger, - classPath, - sources.map(SourceRootImpl.Companion::parseSourceRoot), - samples, - includes, - arguments.moduleName, - documentationOptions) + val generator = DokkaGenerator(config, DokkaConsoleLogger) generator.generate() DokkaConsoleLogger.report() diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index ea55c8fe..78fd2d86 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -129,30 +129,33 @@ abstract class AbstractDokkaMojo : AbstractMojo() { return } - val gen = DokkaGenerator( - MavenDokkaLogger(log), - classpath, - sourceDirectories.map { SourceRootImpl(it) } + sourceRoots, - samplesDirs, - includeDirs + includes, - moduleName, - DocumentationOptions(getOutDir(), getOutFormat(), - sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) }, - jdkVersion = jdkVersion, - skipDeprecated = skipDeprecated, - skipEmptyPackages = skipEmptyPackages, - reportUndocumented = reportNotDocumented, - impliedPlatforms = impliedPlatforms, - perPackageOptions = perPackageOptions, - externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - cacheRoot = cacheRoot, - languageVersion = languageVersion, - apiVersion = apiVersion - ) + val passConfiguration = PassConfigurationImpl( + sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) }, + jdkVersion = jdkVersion, + skipDeprecated = skipDeprecated, + skipEmptyPackages = skipEmptyPackages, + reportUndocumented = reportNotDocumented, + perPackageOptions = perPackageOptions, + externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion + + ) + + val configuration = DokkaConfigurationImpl( + outputDir = getOutDir(), + format = getOutFormat(), + impliedPlatforms = impliedPlatforms, + cacheRoot = cacheRoot, + passesConfigurations = listOf( + passConfiguration + ) ) + val gen = DokkaGenerator(configuration, MavenDokkaLogger(log)) + gen.generate() } } -- cgit From ba09711a1ecbdaede86cab9e76d13ff1047f89b2 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Thu, 2 Aug 2018 18:59:20 +0300 Subject: ExternalDocumentationLinkResolver refactoring, extract common dependencies from guice modules --- core/src/main/kotlin/Generation/DokkaGenerator.kt | 11 +- .../Kotlin/ExternalDocumentationLinkResolver.kt | 114 ++++++++++++++------- core/src/main/kotlin/Utilities/DokkaModules.kt | 19 ++-- core/src/test/kotlin/TestAPI.kt | 19 +++- 4 files changed, 112 insertions(+), 51 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 2e46d908..22d1519f 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule +import org.jetbrains.dokka.Utilities.DokkaRunModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -27,6 +28,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val logger: DokkaLogger) { private val documentationModules: MutableList = mutableListOf() + private val globalInjector = Guice.createInjector(DokkaRunModule(dokkaConfiguration)) fun generate() = with(dokkaConfiguration) { @@ -43,8 +45,9 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val timeBuild = measureTimeMillis { logger.info("Generating pages... ") - val outputInjector = Guice.createInjector(DokkaOutputModule(dokkaConfiguration, logger)) - outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) + val outputInjector = globalInjector.createChildInjector(DokkaOutputModule(dokkaConfiguration, logger)) + val instance = outputInjector.getInstance(Generator::class.java) + instance.buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } @@ -75,11 +78,11 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, } } - val injector = Guice.createInjector( + val injector = globalInjector.createChildInjector( DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> + documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> // FIXME: change to full graph visiting node.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), RefKind.Platform diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 2fc207b9..9d986aee 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -29,21 +29,14 @@ import kotlin.reflect.full.findAnnotation fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) } +typealias PackageFqNameToLocation = MutableMap + @Singleton -class ExternalDocumentationLinkResolver @Inject constructor( - val configuration: DokkaConfiguration, - val passConfiguration: DokkaConfiguration.PassConfiguration, - @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, - val logger: DokkaLogger +class PackageListProvider @Inject constructor( + val configuration: DokkaConfiguration, + val logger: DokkaLogger ) { - - val packageFqNameToLocation = mutableMapOf() - val formats = mutableMapOf() - - class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map) { - override fun toString(): String = rootUrl.toString() - } - + val storage = mutableMapOf() val cacheDir: Path? = when { configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") @@ -53,6 +46,25 @@ class ExternalDocumentationLinkResolver @Inject constructor( val cachedProtocols = setOf("http", "https", "ftp") + init { + for (conf in configuration.passesConfigurations) { + for (link in conf.externalDocumentationLinks) { + if (link in storage) { + continue + } + + try { + loadPackageList(link) + } catch (e: Exception) { + throw RuntimeException("Exception while loading package-list from $link", e) + } + } + + } + } + + + fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection { val connection = this.openConnection() connection.connectTimeout = timeout @@ -127,23 +139,23 @@ class ExternalDocumentationLinkResolver @Inject constructor( val (params, packages) = packageListStream - .bufferedReader() - .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } } + .bufferedReader() + .useLines { lines -> lines.partition { it.startsWith(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX) } } val paramsMap = params.asSequence() - .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) } - .groupBy({ (key, _) -> key }, { (_, value) -> value }) + .map { it.removePrefix(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX).split(":", limit = 2) } + .groupBy({ (key, _) -> key }, { (_, value) -> value }) val format = paramsMap["format"]?.singleOrNull() ?: "javadoc" val locations = paramsMap["location"].orEmpty() - .map { it.split("\u001f", limit = 2) } - .map { (key, value) -> key to value } - .toMap() + .map { it.split("\u001f", limit = 2) } + .map { (key, value) -> key to value } + .toMap() - val defaultResolverDesc = services["dokka-default"]!! - val resolverDesc = services[format] + val defaultResolverDesc = ExternalDocumentationLinkResolver.services["dokka-default"]!! + val resolverDesc = ExternalDocumentationLinkResolver.services[format] ?: defaultResolverDesc.takeIf { format in formatsWithDefaultResolver } ?: defaultResolverDesc.also { logger.warn("Couldn't find InboundExternalLinkResolutionService(format = `$format`) for $link, using Dokka default") @@ -160,16 +172,52 @@ class ExternalDocumentationLinkResolver @Inject constructor( val rootInfo = ExternalDocumentationRoot(link.url, resolver, locations) - packages.map { FqName(it) }.forEach { packageFqNameToLocation[it] = rootInfo } + val packageFqNameToLocation = mutableMapOf() + storage[link] = packageFqNameToLocation + + val fqNames = packages.map { FqName(it) } + for(name in fqNames) { + packageFqNameToLocation[name] = rootInfo + } + } + + + + class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map) { + override fun toString(): String = rootUrl.toString() } + companion object { + private val formatsWithDefaultResolver = + ServiceLocator + .allServices("format") + .filter { + val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor + desc?.generatorServiceClass == FileGenerator::class + }.map { it.name } + .toSet() + + } + +} + +class ExternalDocumentationLinkResolver @Inject constructor( + val configuration: DokkaConfiguration, + val passConfiguration: DokkaConfiguration.PassConfiguration, + @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, + val logger: DokkaLogger, + val packageListProvider: PackageListProvider +) { + + val formats = mutableMapOf() + val packageFqNameToLocation = mutableMapOf() + init { - passConfiguration.externalDocumentationLinks.forEach { - try { - loadPackageList(it) - } catch (e: Exception) { - throw RuntimeException("Exception while loading package-list from $it", e) - } + val fqNameToLocationMaps = passConfiguration.externalDocumentationLinks + .mapNotNull { packageListProvider.storage[it] } + + for(map in fqNameToLocationMaps) { + packageFqNameToLocation.putAll(map) } } @@ -198,14 +246,6 @@ class ExternalDocumentationLinkResolver @Inject constructor( companion object { const val DOKKA_PARAM_PREFIX = "\$dokka." val services = ServiceLocator.allServices("inbound-link-resolver").associateBy { it.name } - private val formatsWithDefaultResolver = - ServiceLocator - .allServices("format") - .filter { - val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor - desc?.generatorServiceClass == FileGenerator::class - }.map { it.name } - .toSet() } } diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 251d5c23..c2e652b6 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -1,8 +1,6 @@ package org.jetbrains.dokka.Utilities -import com.google.inject.Binder -import com.google.inject.Module -import com.google.inject.TypeLiteral +import com.google.inject.* import com.google.inject.binder.AnnotatedBindingBuilder import com.google.inject.name.Names import org.jetbrains.dokka.* @@ -13,6 +11,16 @@ import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" +class DokkaRunModule(val configuration: DokkaConfiguration) : Module { + override fun configure(binder: Binder) { + binder.bind().toInstance(configuration) + binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) + + binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) + } + +} + class DokkaAnalysisModule(val environment: AnalysisEnvironment, val configuration: DokkaConfiguration, val defaultPlatformsProvider: DefaultPlatformsProvider, @@ -29,7 +37,6 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(dokkaResolutionFacade) binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) - binder.bind().toInstance(configuration) binder.bind().toInstance(passConfiguration) binder.bind().toInstance(defaultPlatformsProvider) @@ -46,11 +53,7 @@ object StringListType : TypeLiteral<@JvmSuppressWildcards List>() class DokkaOutputModule(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) - - binder.bind().toInstance(configuration) binder.bind().toInstance(logger) - binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) val descriptor = ServiceLocator.lookup("format", configuration.format) diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index b65efbe9..8974bd0b 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* import org.jetbrains.dokka.Utilities.DokkaAnalysisModule +import org.jetbrains.dokka.Utilities.DokkaRunModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -117,8 +118,22 @@ fun appendDocumentation(documentation: DocumentationModule, val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms } - val injector = Guice.createInjector( - DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentation.nodeRefGraph, passConfiguration, DokkaConsoleLogger)) + + val globalInjector = Guice.createInjector( + DokkaRunModule(dokkaConfiguration) + ) + + val injector = globalInjector.createChildInjector( + DokkaAnalysisModule( + environment, + dokkaConfiguration, + defaultPlatformsProvider, + documentation.nodeRefGraph, + passConfiguration, + DokkaConsoleLogger + ) + ) + buildDocumentationModule(injector, documentation) Disposer.dispose(environment) } -- cgit From 77ce80517f79a774ef985be47ae00db828e34273 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Mon, 6 Aug 2018 13:42:44 +0300 Subject: DocumentationMerger refactoring --- .../main/kotlin/Generation/DocumentationMerger.kt | 179 ++++++++++++++++ core/src/main/kotlin/Generation/DokkaGenerator.kt | 227 ++------------------- core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- .../main/kotlin/Generation/configurationImpl.kt | 1 - .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 1 - .../main/kotlin/Model/DocumentationReference.kt | 26 +-- 7 files changed, 212 insertions(+), 226 deletions(-) create mode 100644 core/src/main/kotlin/Generation/DocumentationMerger.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt new file mode 100644 index 00000000..c2089821 --- /dev/null +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -0,0 +1,179 @@ +package org.jetbrains.dokka.Generation + +import org.jetbrains.dokka.* + +class DocumentationMerger( + private val documentationModules: List +) { + private val producedNodeRefGraph: NodeReferenceGraph + private val signatureMap: Map + private val oldToNewNodeMap: MutableMap = mutableMapOf() + + init { + if (documentationModules.groupBy { it.name }.size > 1) { + throw IllegalArgumentException("Modules should have similar names") + } + + signatureMap = documentationModules + .flatMap { it.nodeRefGraph.nodeMapView.entries } + .associate { (k, v) -> v to k } + + + producedNodeRefGraph = NodeReferenceGraph() + documentationModules.map { it.nodeRefGraph } + .flatMap { it.references } + .distinct() + .forEach { producedNodeRefGraph.addReference(it) } + } + + private fun mergePackageReferences( + from: DocumentationNode, + packages: List + ): List { + + val packagesByName = packages + .map { it.to } + .groupBy { it.name } + + val mutableList = mutableListOf() + for ((name, listOfPackages) in packagesByName) { + val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages) + updatePendingReferences() + + mutableList.add( + DocumentationReference(from, producedPackage, RefKind.Member) + ) + } + + return mutableList + } + + private fun mergePackagesWithEqualNames( + name: String, + from: DocumentationNode, + packages: List + ): DocumentationNode { + val mergedPackage = DocumentationNode(name, Content.Empty, NodeKind.Package) + for (packageNode in packages) { + // TODO: Discuss + mergedPackage.updateContent { + for (otherChild in packageNode.content.children) { + children.add(otherChild) + } + } + oldToNewNodeMap[packageNode] = mergedPackage + } + mergedPackage.clear() + + val references = packages.flatMap { it.allReferences() } + val mergedReferences = mergeReferences(mergedPackage, references) + for (ref in mergedReferences.distinct()) { + mergedPackage.addReference(ref) + } + + from.append(mergedPackage, RefKind.Member) + + return mergedPackage + } + + private fun DocumentationNode.clear() = dropReferences { true } + + private fun mergeMembers( + from: DocumentationNode, + refs: List + ): List { + val membersBySignature: Map> = refs.map { it.to } + .groupBy { signatureMap[it]!! } + + val mergedMembers: MutableList = mutableListOf() + for ((signature, members) in membersBySignature) { + val newNode = mergeMembersWithEqualSignature(signature, from, members) + + producedNodeRefGraph.register(signature, newNode) + updatePendingReferences() + from.append(newNode, RefKind.Member) + + mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member)) + } + + return mergedMembers + } + + private fun mergeMembersWithEqualSignature( + signature: String, + from: DocumentationNode, + refs: List + ): DocumentationNode { + val singleNode = refs.singleOrNull() + if (singleNode != null) { + singleNode.owner?.let { owner -> + singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } + } + return singleNode + } + val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) + groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) + + for (node in refs) { + if (node != groupNode) { + node.owner?.let { owner -> + node.dropReferences { it.to == owner && it.kind == RefKind.Owner } + from.dropReferences { it.to == node && it.kind == RefKind.Member } + } + groupNode.append(node, RefKind.Member) + + oldToNewNodeMap[node] = groupNode + } + } + return groupNode + } + + + private fun mergeReferences( + from: DocumentationNode, + refs: List + ): List { + val (refsToPackages, usualRefs) = refs.partition { it.to.kind == NodeKind.Package } + val mergedPackages = mergePackageReferences(from, refsToPackages) + + val (refsToMembers, refsNotToMembers) = usualRefs.partition { it.kind == RefKind.Member } + val mergedMembers = mergeMembers(from, refsToMembers) + + // TODO: think about + return mergedPackages + (mergedMembers + refsNotToMembers).distinctBy { + it.to.kind to it.to.name + } + } + + + private fun updatePendingReferences() { + producedNodeRefGraph.references.forEach { + it.lazyNodeFrom.update() + it.lazyNodeTo.update() + } + } + + private fun NodeResolver.update() { + if (this is NodeResolver.Exact) { + if (exactNode != null && oldToNewNodeMap.containsKey(exactNode!!)) { + exactNode = oldToNewNodeMap[exactNode!!] + } + } + } + + fun merge(): DocumentationModule { + val mergedDocumentationModule = DocumentationModule( + name = documentationModules.first().name, + nodeRefGraph = producedNodeRefGraph + ) + + val refs = documentationModules.flatMap { + it.allReferences() + } + mergeReferences(mergedDocumentationModule, refs) + + return mergedDocumentationModule + } + + +} \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 22d1519f..37f62ed6 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager +import org.jetbrains.dokka.Generation.DocumentationMerger import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule import org.jetbrains.dokka.Utilities.DokkaRunModule @@ -82,8 +83,8 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> // FIXME: change to full graph visiting - node.addReferenceTo( + documentationModule.visit { it -> + it.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), RefKind.Platform ) @@ -95,7 +96,19 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration): AnalysisEnvironment { + private fun DocumentationNode.visit(action: (DocumentationNode) -> Unit) { + action(this) + + for (member in members) { + member.visit(action) + } + } + + + fun createAnalysisEnvironment( + sourcePaths: List, + passConfiguration: DokkaConfiguration.PassConfiguration + ): AnalysisEnvironment { val environment = AnalysisEnvironment(DokkaMessageCollector(logger), passConfiguration.analysisPlatform) environment.apply { @@ -116,7 +129,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, return environment } - fun isNotSample(file: PsiFile, samples: List): Boolean { + private fun isNotSample(file: PsiFile, samples: List): Boolean { val sourceFile = File(file.virtualFile!!.path) return samples.none { sample -> val canonicalSample = File(sample).canonicalPath @@ -155,9 +168,7 @@ fun buildDocumentationModule(injector: Injector, val analyzer = resolutionFacade.getFrontendService(LazyTopDownAnalyzer::class.java) analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, fragmentFiles) - val fragments = fragmentFiles - .map { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) } - .filterNotNull() + val fragments = fragmentFiles.mapNotNull { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) } .distinct() val packageDocs = injector.getInstance(PackageDocs::class.java) @@ -220,206 +231,4 @@ fun KotlinCoreEnvironment.getJavaSourceFiles(): List { } } return result -} - -class DocumentationMerger( - private val documentationModules: List -) { - private val producedNodeRefGraph: NodeReferenceGraph - private val signatureMap: Map - - init { - signatureMap = documentationModules - .flatMap { it.nodeRefGraph.nodeMapView.entries } - .map { (k, v) -> v to k } - .toMap() - - producedNodeRefGraph = NodeReferenceGraph() - documentationModules.map { it.nodeRefGraph } - .flatMap { it.references } - .distinct() - .forEach { producedNodeRefGraph.addReference(it) } - } - - private fun splitReferencesByKind( - source: List, - kind: RefKind - ): Pair, List> = - Pair(source.filter { it.kind == kind }, source.filterNot { it.kind == kind }) - - - private fun mergePackageReferences( - from: DocumentationNode, - packages: List - ): List { - val packagesByName = packages - .map { it.to } - .groupBy { it.name } - - val mutableList: MutableList = mutableListOf() - for ((name, listOfPackages) in packagesByName) { - val producedPackage = mergePackagesWithEqualNames(from, listOfPackages) - updatePendingReferences(name, producedPackage) - - mutableList.add( - DocumentationReference(from, producedPackage, RefKind.Member) - ) - } - - return mutableList - } - - private fun mergePackagesWithEqualNames( - from: DocumentationNode, - packages: List - ): DocumentationNode { - val references = packages.flatMap { it.allReferences() } - - val mergedPackage = - DocumentationNode( - packages.first().name, - Content.Empty, - NodeKind.Package - ) - - val mergedReferences = mergeReferences(mergedPackage, references) - - for (packageNode in packages) { - mergedPackage.updateContent { - for (otherChild in packageNode.content.children) { - children.add(otherChild) - } - } - } - - mergedPackage.dropReferences { true } // clear() - for (ref in mergedReferences.distinct()) { - mergedPackage.addReference(ref) - } - - from.append(mergedPackage, RefKind.Member) - - return mergedPackage - } - - - private fun mergeMembers( - from: DocumentationNode, - refs: List - ): List { - val membersBySignature: Map> = refs.map { it.to } - .filter { signatureMap.containsKey(it) } - .groupBy { signatureMap[it]!! } - - val mergedMembers: MutableList = mutableListOf() - for ((signature, members) in membersBySignature) { - val newNode = mergeMembersWithEqualSignature(signature, from, members) - - producedNodeRefGraph.register(signature, newNode) - updatePendingReferences(signature, newNode) - from.append(newNode, RefKind.Member) - - mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member)) - } - - return mergedMembers - } - - private fun mergeMembersWithEqualSignature( - signature: String, - from: DocumentationNode, - refs: List - ): DocumentationNode { - if (refs.size == 1) { - val singleNode = refs.single() - singleNode.owner?.let { owner -> - singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } - } - return singleNode - } - val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) - groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) - - for (node in refs) { - if (node != groupNode) { - node.owner?.let { owner -> - node.dropReferences { it.to == owner && it.kind == RefKind.Owner } - from.dropReferences { it.to == node && it.kind == RefKind.Member } - } - groupNode.append(node, RefKind.Member) - } - } - return groupNode - } - - - private fun mergeReferences( - from: DocumentationNode, - refs: List - ): List { - val allRefsToPackages = refs.map { it.to } - .all { it.kind == NodeKind.Package } - - if (allRefsToPackages) { - return mergePackageReferences(from, refs) - } - - val (memberRefs, notMemberRefs) = splitReferencesByKind(refs, RefKind.Member) - val mergedMembers = mergeMembers(from, memberRefs) - - return (mergedMembers + notMemberRefs).distinctBy { - it.kind to it.to.name - } - } - - - private fun updatePendingReferences( - signature: String, - nodeToUpdate: DocumentationNode - ) { - producedNodeRefGraph.references.forEach { - it.lazyNodeFrom.update(signature, nodeToUpdate) - it.lazyNodeTo.update(signature, nodeToUpdate) - } - } - - private fun NodeResolver.update(signature: String, nodeToUpdate: DocumentationNode) { - when (this) { - is NodeResolver.BySignature -> update(signature, nodeToUpdate) - is NodeResolver.Exact -> update(signature, nodeToUpdate) - } - } - - private fun NodeResolver.BySignature.update(signature: String, nodeToUpdate: DocumentationNode) { - if (signature == nodeToUpdate.name) { - nodeMap = producedNodeRefGraph.nodeMapView - } - } - - private fun NodeResolver.Exact.update(signature: String, nodeToUpdate: DocumentationNode) { - exactNode?.let { it -> - val equalSignature = - it.anyReference { ref -> ref.to.kind == NodeKind.Signature && ref.to.name == signature } - - if (equalSignature) { - exactNode = nodeToUpdate - } - } - } - - fun merge(): DocumentationModule { - val refs = documentationModules.flatMap { - it.allReferences() - } - val mergedDocumentationModule = DocumentationModule( - name = documentationModules.first().name, - nodeRefGraph = producedNodeRefGraph - ) - - mergeReferences(mergedDocumentationModule, refs) - - return mergedDocumentationModule - } - - } \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index eb6800b3..d7b35581 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -10,7 +10,7 @@ import java.io.OutputStreamWriter class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @set:Inject(optional = true) var outlineService: OutlineFormatService? = null - @set:Inject(optional = true) lateinit var formatService: FormatService + @set:Inject lateinit var formatService: FormatService @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 3e39b4ed..f2a91002 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -26,7 +26,6 @@ class SourceRootImpl(path: String, override val platforms: List = emptyL fun parseSourceRoot(sourceRoot: String): SourceRoot { val components = sourceRoot.split("::", limit = 2) - // TODO: create syntax for cli val platform = if (components.size == 1) { Platform.DEFAULT } else { diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index fb0b898a..be3eef71 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1097,7 +1097,7 @@ fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass - || (it.kind == NodeKind.GroupNode && it.anyReference { it.to.kind in NodeKind.classLike }) } } + || (it.kind == NodeKind.GroupNode && it.members.all { it.kind in NodeKind.classLike }) } } .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index bdb7cf20..23137364 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -163,7 +163,6 @@ open class DocumentationNode(val name: String, fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single() fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single() - fun anyReference(predicate: (DocumentationReference) -> Boolean): Boolean = references.any(predicate) fun references(kind: RefKind): List = references.filter { it.kind == kind } fun allReferences(): Set = references diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 9223c17a..282d87d8 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -26,15 +26,15 @@ data class DocumentationReference(val from: DocumentationNode, val to: Documenta } sealed class NodeResolver { - abstract fun resolve(): DocumentationNode? - class BySignature(var signature: String, var nodeMap: Map) : NodeResolver() { - override fun resolve(): DocumentationNode? { - return nodeMap[signature] + abstract fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? + class BySignature(var signature: String) : NodeResolver() { + override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? { + return nodeRephGraph.lookup(signature) } } class Exact(var exactNode: DocumentationNode?) : NodeResolver() { - override fun resolve(): DocumentationNode? { + override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? { return exactNode } } @@ -43,9 +43,9 @@ sealed class NodeResolver { class PendingDocumentationReference(val lazyNodeFrom: NodeResolver, val lazyNodeTo: NodeResolver, val kind: RefKind) { - fun resolve() { - val fromNode = lazyNodeFrom.resolve() - val toNode = lazyNodeTo.resolve() + fun resolve(nodeRephGraph: NodeReferenceGraph) { + val fromNode = lazyNodeFrom.resolve(nodeRephGraph) + val toNode = lazyNodeTo.resolve(nodeRephGraph) if (fromNode != null && toNode != null) { fromNode.addReferenceTo(toNode, kind) } @@ -67,7 +67,7 @@ class NodeReferenceGraph { references.add( PendingDocumentationReference( NodeResolver.Exact(fromNode), - NodeResolver.BySignature(toSignature, nodeMap), + NodeResolver.BySignature(toSignature), kind )) } @@ -75,7 +75,7 @@ class NodeReferenceGraph { fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) { references.add( PendingDocumentationReference( - NodeResolver.BySignature(fromSignature, nodeMap), + NodeResolver.BySignature(fromSignature), NodeResolver.Exact(toNode), kind ) @@ -85,8 +85,8 @@ class NodeReferenceGraph { fun link(fromSignature: String, toSignature: String, kind: RefKind) { references.add( PendingDocumentationReference( - NodeResolver.BySignature(fromSignature, nodeMap), - NodeResolver.BySignature(toSignature, nodeMap), + NodeResolver.BySignature(fromSignature), + NodeResolver.BySignature(toSignature), kind ) ) @@ -107,7 +107,7 @@ class NodeReferenceGraph { } fun resolveReferences() { - references.forEach { it.resolve() } + references.forEach { it.resolve(this) } } } -- cgit From 4456ead8b702e4881321488969cb4ce1711e5663 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Mon, 6 Aug 2018 17:14:28 +0300 Subject: Optional dependency bug workaround: google/guice#847 --- core/src/main/kotlin/Formats/FormatDescriptor.kt | 1 + core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt index b497fb0f..4bac8aa0 100644 --- a/core/src/main/kotlin/Formats/FormatDescriptor.kt +++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt @@ -25,6 +25,7 @@ abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor { override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toType NodeLocationAwareGenerator::class bind() toType generatorServiceClass + bind(generatorServiceClass.java) // https://github.com/google/guice/issues/847 bind() toType languageServiceClass diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index d7b35581..eb6800b3 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -10,7 +10,7 @@ import java.io.OutputStreamWriter class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @set:Inject(optional = true) var outlineService: OutlineFormatService? = null - @set:Inject lateinit var formatService: FormatService + @set:Inject(optional = true) lateinit var formatService: FormatService @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null -- cgit From fc517baac7ba381f0f4f2529e59700b1191dd0ce Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 10 Jan 2018 21:56:20 +0300 Subject: Fix crash on incorrect sample conversion --- .../KotlinWebsiteSampleProcessingService.kt | 48 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index b5801457..b12e3a66 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -1,15 +1,18 @@ package org.jetbrains.dokka.Samples import com.google.inject.Inject -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiWhiteSpace +import com.intellij.psi.* import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.dokka.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.allChildren import org.jetbrains.kotlin.psi.psiUtil.prevLeaf +import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.ImportPath +import java.io.PrintWriter +import java.io.StringWriter + open class KotlinWebsiteSampleProcessingService @Inject constructor(dokkaConfiguration: DokkaConfiguration, @@ -22,6 +25,10 @@ open class KotlinWebsiteSampleProcessingService val text: String get() = builder.toString() + val errors = mutableListOf() + + data class ConvertError(val e: Exception, val text: String, val loc: String) + fun KtValueArgument.extractStringArgumentValue() = (getArgumentExpression() as KtStringTemplateExpression) .entries.joinToString("") { it.text } @@ -92,16 +99,51 @@ open class KotlinWebsiteSampleProcessingService } } + private fun reportProblemConvertingElement(element: PsiElement, e: Exception) { + val text = element.text + val document = PsiDocumentManager.getInstance(element.project).getDocument(element.containingFile) + + val lineInfo = if (document != null) { + val lineNumber = document.getLineNumber(element.startOffset) + "$lineNumber, ${element.startOffset - document.getLineStartOffset(lineNumber)}" + } else { + "offset: ${element.startOffset}" + } + errors += ConvertError(e, text, lineInfo) + } + override fun visitElement(element: PsiElement) { if (element is LeafPsiElement) builder.append(element.text) - super.visitElement(element) + + element.acceptChildren(object : PsiElementVisitor() { + override fun visitElement(element: PsiElement) { + try { + element.accept(this@SampleBuilder) + } catch (e: Exception) { + try { + reportProblemConvertingElement(element, e) + } finally { + builder.append(element.text) //recover + } + } + } + }) } + } private fun PsiElement.buildSampleText(): String { val sampleBuilder = SampleBuilder() this.accept(sampleBuilder) + + sampleBuilder.errors.forEach { + val sw = StringWriter() + val pw = PrintWriter(sw) + it.e.printStackTrace(pw) + + logger.error("${containingFile.name}: (${it.loc}): Exception thrown while converting \n```\n${it.text}\n```\n$sw") + } return sampleBuilder.text } -- cgit From a838a096da246babd93dc518dec8d2470d1c14f5 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 10 Jan 2018 22:25:11 +0300 Subject: Convert assertFails in kws samples without message properly --- .../KotlinWebsiteSampleProcessingService.kt | 40 ++++++++++++++++------ .../format/website-html/sampleWithAsserts.html | 2 ++ .../format/website-html/sampleWithAsserts.kt | 2 ++ 3 files changed, 33 insertions(+), 11 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index b12e3a66..4525e9d9 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -1,7 +1,10 @@ package org.jetbrains.dokka.Samples import com.google.inject.Inject -import com.intellij.psi.* +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiElementVisitor +import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.source.tree.LeafPsiElement import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.dokka.* @@ -61,27 +64,42 @@ open class KotlinWebsiteSampleProcessingService } fun convertAssertFails(expression: KtCallExpression) { - val (message, funcArgument) = expression.valueArguments + val valueArguments = expression.valueArguments + + val funcArgument: KtValueArgument + val message: KtValueArgument? + + if (valueArguments.size == 1) { + message = null + funcArgument = valueArguments.first() + } else { + message = valueArguments.first() + funcArgument = valueArguments.last() + } + builder.apply { - val argument = if (funcArgument.getArgumentExpression() is KtLambdaExpression) - PsiTreeUtil.findChildOfType(funcArgument, KtBlockExpression::class.java)?.text ?: "" - else - funcArgument.text + val argument = funcArgument.extractFunctionalArgumentText() append(argument.lines().joinToString(separator = "\n") { "// $it" }) append(" // ") - append(message.extractStringArgumentValue()) + if (message != null) { + append(message.extractStringArgumentValue()) + } append(" will fail") } } + private fun KtValueArgument.extractFunctionalArgumentText(): String { + return if (getArgumentExpression() is KtLambdaExpression) + PsiTreeUtil.findChildOfType(this, KtBlockExpression::class.java)?.text ?: "" + else + text + } + fun convertAssertFailsWith(expression: KtCallExpression) { val (funcArgument) = expression.valueArguments val (exceptionType) = expression.typeArguments builder.apply { - val argument = if (funcArgument.firstChild is KtLambdaExpression) - PsiTreeUtil.findChildOfType(funcArgument, KtBlockExpression::class.java)?.text ?: "" - else - funcArgument.text + val argument = funcArgument.extractFunctionalArgumentText() append(argument.lines().joinToString(separator = "\n") { "// $it" }) append(" // will fail with ") append(exceptionType.text) diff --git a/core/testdata/format/website-html/sampleWithAsserts.html b/core/testdata/format/website-html/sampleWithAsserts.html index e91232f5..2b2a9ac5 100644 --- a/core/testdata/format/website-html/sampleWithAsserts.html +++ b/core/testdata/format/website-html/sampleWithAsserts.html @@ -14,6 +14,8 @@ println("a() == b() is ${a() == b()}") // true // readSomeFile(File("some.txt")) // reading file now will fail // readSomeFile(File("some.txt")) // will fail with FileNotFoundException +// readSomeFile(File("some.txt")) // will fail + fun indented() { // A neq B println("a() != b() is ${a() != b()}") // false diff --git a/core/testdata/format/website-html/sampleWithAsserts.kt b/core/testdata/format/website-html/sampleWithAsserts.kt index b3bce11d..bb5848e6 100644 --- a/core/testdata/format/website-html/sampleWithAsserts.kt +++ b/core/testdata/format/website-html/sampleWithAsserts.kt @@ -26,6 +26,8 @@ fun sample() { assertFails("reading file now") { readSomeFile(File("some.txt")) } assertFailsWith { readSomeFile(File("some.txt")) } + assertFails { readSomeFile(File("some.txt")) } + fun indented() { assertFalse(a() != b(), "A neq B") } -- cgit From 1f45cac76a79abb6eaad99b541234cbf34fbce9c Mon Sep 17 00:00:00 2001 From: Zubakov Aleksey Date: Fri, 17 Aug 2018 13:00:06 +0300 Subject: Merger platforms bug fix, refactoring --- .../main/kotlin/Formats/StructuredFormatService.kt | 2 + .../main/kotlin/Generation/DocumentationMerger.kt | 58 ++++++++-------------- core/src/main/kotlin/Generation/DokkaGenerator.kt | 19 +------ .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 23 ++++++--- 4 files changed, 42 insertions(+), 60 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 41c8f29a..b810dfca 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -404,6 +404,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, fun String.isKotlinVersion() = this.startsWith("Kotlin") + if (platforms.count() == 0) return emptySet() + // Calculating common platforms for items return platforms.reduce { result, platformsOfItem -> val otherKotlinVersion = result.find { it.isKotlinVersion() } diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index c2089821..c4a40df6 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -22,7 +22,6 @@ class DocumentationMerger( producedNodeRefGraph = NodeReferenceGraph() documentationModules.map { it.nodeRefGraph } .flatMap { it.references } - .distinct() .forEach { producedNodeRefGraph.addReference(it) } } @@ -30,7 +29,6 @@ class DocumentationMerger( from: DocumentationNode, packages: List ): List { - val packagesByName = packages .map { it.to } .groupBy { it.name } @@ -63,11 +61,13 @@ class DocumentationMerger( } oldToNewNodeMap[packageNode] = mergedPackage } - mergedPackage.clear() val references = packages.flatMap { it.allReferences() } val mergedReferences = mergeReferences(mergedPackage, references) - for (ref in mergedReferences.distinct()) { + for (ref in mergedReferences) { + if (ref.kind == RefKind.Owner) { + continue + } mergedPackage.addReference(ref) } @@ -76,8 +76,6 @@ class DocumentationMerger( return mergedPackage } - private fun DocumentationNode.clear() = dropReferences { true } - private fun mergeMembers( from: DocumentationNode, refs: List @@ -106,24 +104,17 @@ class DocumentationMerger( ): DocumentationNode { val singleNode = refs.singleOrNull() if (singleNode != null) { - singleNode.owner?.let { owner -> - singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } - } + singleNode.dropReferences { it.kind == RefKind.Owner } return singleNode } val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) for (node in refs) { - if (node != groupNode) { - node.owner?.let { owner -> - node.dropReferences { it.to == owner && it.kind == RefKind.Owner } - from.dropReferences { it.to == node && it.kind == RefKind.Member } - } - groupNode.append(node, RefKind.Member) + node.dropReferences { it.kind == RefKind.Owner } + groupNode.append(node, RefKind.Member) - oldToNewNodeMap[node] = groupNode - } + oldToNewNodeMap[node] = groupNode } return groupNode } @@ -140,25 +131,7 @@ class DocumentationMerger( val mergedMembers = mergeMembers(from, refsToMembers) // TODO: think about - return mergedPackages + (mergedMembers + refsNotToMembers).distinctBy { - it.to.kind to it.to.name - } - } - - - private fun updatePendingReferences() { - producedNodeRefGraph.references.forEach { - it.lazyNodeFrom.update() - it.lazyNodeTo.update() - } - } - - private fun NodeResolver.update() { - if (this is NodeResolver.Exact) { - if (exactNode != null && oldToNewNodeMap.containsKey(exactNode!!)) { - exactNode = oldToNewNodeMap[exactNode!!] - } - } + return mergedPackages + mergedMembers + refsNotToMembers } fun merge(): DocumentationModule { @@ -175,5 +148,18 @@ class DocumentationMerger( return mergedDocumentationModule } + private fun updatePendingReferences() { + for (ref in producedNodeRefGraph.references) { + ref.lazyNodeFrom.update() + ref.lazyNodeTo.update() + } + } + private fun NodeResolver.update() { + if (this is NodeResolver.Exact) { + if (exactNode != null && exactNode!! in oldToNewNodeMap) { + exactNode = oldToNewNodeMap[exactNode!!] + } + } + } } \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 37f62ed6..1193657e 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -69,13 +69,13 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, logger.info("Analysing sources and libraries... ") val startAnalyse = System.currentTimeMillis() - val defaultPlatformAsList = listOf(passConfiguration.analysisPlatform.key) + val defaultPlatformAsList = passConfiguration.targets val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List { val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath ?.let { File(it).absolutePath } val sourceRoot = containingFilePath?.let { path -> sourceRoots.find { path.startsWith(it.path) } } - return sourceRoot?.platforms ?: defaultPlatformAsList + return /*sourceRoot?.platforms ?: */defaultPlatformAsList } } @@ -83,12 +83,6 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.visit { it -> - it.addReferenceTo( - DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), - RefKind.Platform - ) - } val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") @@ -96,15 +90,6 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, Disposer.dispose(environment) } - private fun DocumentationNode.visit(action: (DocumentationNode) -> Unit) { - action(this) - - for (member in members) { - member.visit(action) - } - } - - fun createAnalysisEnvironment( sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index be3eef71..c25a7069 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -889,23 +889,27 @@ class DocumentationBuilder } - fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor, - externalClassNodes: MutableMap, - allFqNames: Collection): DocumentationNode { + fun DocumentationNode.getParentForPackageMember( + descriptor: DeclarationDescriptor, + externalClassNodes: MutableMap, + allFqNames: Collection, + packageName: FqName + ): DocumentationNode { if (descriptor is CallableMemberDescriptor) { val extensionClassDescriptor = descriptor.getExtensionClassDescriptor() if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) && !ErrorUtils.isError(extensionClassDescriptor)) { val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor) - return externalClassNodes.getOrPut(fqName, { + return externalClassNodes.getOrPut(fqName) { val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass) val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(extensionClassDescriptor) if (externalLink != null) { newNode.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) } append(newNode, RefKind.Member) + refGraph.register("${packageName.asString()}:${extensionClassDescriptor.signature()}", newNode) newNode - }) + } } } return this @@ -933,7 +937,12 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { declarations.forEach { descriptor -> with(documentationBuilder) { if (descriptor.isDocumented(passConfiguration)) { - val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames) + val parent = packageNode.getParentForPackageMember( + descriptor, + externalClassNodes, + allFqNames, + packageName + ) parent.appendOrUpdateMember(descriptor) } } @@ -1025,7 +1034,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name -- cgit From b265a9ffacb8f8e8e6226a9458a92697b02355a8 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 15:08:28 +0300 Subject: Ant runner default external links and classpath resolving fix --- core/src/main/kotlin/Utilities/ServiceLocator.kt | 2 +- runners/ant/src/main/kotlin/ant/dokka.kt | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Utilities/ServiceLocator.kt b/core/src/main/kotlin/Utilities/ServiceLocator.kt index 83c4c65c..fca08f38 100644 --- a/core/src/main/kotlin/Utilities/ServiceLocator.kt +++ b/core/src/main/kotlin/Utilities/ServiceLocator.kt @@ -70,7 +70,7 @@ object ServiceLocator { "jar" -> { val file = JarFile(URL(it.file.substringBefore("!")).toFile()) try { - val jarPath = it.file.substringAfterLast("!").removePrefix("/") + val jarPath = it.file.substringAfterLast("!").removeSurrounding("/") file.entries() .asSequence() .filter { entry -> !entry.isDirectory && entry.path == jarPath && entry.extension == "properties" } diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 9e38aa22..9428a7ce 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -53,7 +53,7 @@ class AntPassConfig(task: Task) : DokkaConfiguration.PassConfiguration { } override val perPackageOptions: MutableList = mutableListOf() override val externalDocumentationLinks: List - get() = buildExternalLinksBuilders.map { it.build() } + get() = buildExternalLinksBuilders.map { it.build() } + defaultExternalDocumentationLinks override var languageVersion: String? = null override var apiVersion: String? = null @@ -76,6 +76,18 @@ class AntPassConfig(task: Task) : DokkaConfiguration.PassConfiguration { private val buildExternalLinksBuilders: MutableList = mutableListOf() val antSourceLinkDefinition: MutableList = mutableListOf() + private val defaultExternalDocumentationLinks: List + get() { + val links = mutableListOf() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() + return links + } + + fun setSamples(ref: Path) { samplesPath.append(ref) } -- cgit From 0b43db4ff81746e44d06780d8d14bb49dc1d87aa Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 16:27:41 +0300 Subject: Introduce origin reference kind, change documentation graph merge logic, minor refactoring --- .../main/kotlin/Formats/StructuredFormatService.kt | 28 +++++----- .../main/kotlin/Generation/DocumentationMerger.kt | 65 +++++++++++++--------- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 4 ++ .../main/kotlin/Model/DocumentationReference.kt | 5 +- 5 files changed, 61 insertions(+), 43 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index b810dfca..1ca636ec 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -192,22 +192,20 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - open fun link(from: DocumentationNode, - to: DocumentationNode, - name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink = link(from, to, extension, name) + open fun link( + from: DocumentationNode, + to: DocumentationNode, + name: (DocumentationNode) -> String = DocumentationNode::name + ): FormatLink = link(from, to, extension, name) + + open fun link( + from: DocumentationNode, + to: DocumentationNode, + extension: String, + name: (DocumentationNode) -> String = DocumentationNode::name + ): FormatLink = + FormatLink(name(to), from.location().relativePathTo(to.location())) - open fun link(from: DocumentationNode, - to: DocumentationNode, - extension: String, - name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink { - if (to.owner?.kind == NodeKind.GroupNode) - return link(from, to.owner!!, extension, name) - - if (from.owner?.kind == NodeKind.GroupNode) - return link(from.owner!!, to, extension, name) - - return FormatLink(name(to), from.location().relativePathTo(to.location())) - } fun locationHref(from: Location, to: DocumentationNode): String { val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index c4a40df6..0394dce2 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -5,7 +5,7 @@ import org.jetbrains.dokka.* class DocumentationMerger( private val documentationModules: List ) { - private val producedNodeRefGraph: NodeReferenceGraph + private val producedNodeRefGraph: NodeReferenceGraph = NodeReferenceGraph() private val signatureMap: Map private val oldToNewNodeMap: MutableMap = mutableMapOf() @@ -19,7 +19,6 @@ class DocumentationMerger( .associate { (k, v) -> v to k } - producedNodeRefGraph = NodeReferenceGraph() documentationModules.map { it.nodeRefGraph } .flatMap { it.references } .forEach { producedNodeRefGraph.addReference(it) } @@ -33,17 +32,17 @@ class DocumentationMerger( .map { it.to } .groupBy { it.name } - val mutableList = mutableListOf() + val resultReferences = mutableListOf() for ((name, listOfPackages) in packagesByName) { val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages) updatePendingReferences() - mutableList.add( + resultReferences.add( DocumentationReference(from, producedPackage, RefKind.Member) ) } - return mutableList + return resultReferences } private fun mergePackagesWithEqualNames( @@ -52,14 +51,17 @@ class DocumentationMerger( packages: List ): DocumentationNode { val mergedPackage = DocumentationNode(name, Content.Empty, NodeKind.Package) - for (packageNode in packages) { - // TODO: Discuss + + for (contentToAppend in packages.map { it.content }.distinct()) { mergedPackage.updateContent { - for (otherChild in packageNode.content.children) { + for (otherChild in contentToAppend.children) { children.add(otherChild) } } - oldToNewNodeMap[packageNode] = mergedPackage + } + + for (node in packages) { + oldToNewNodeMap[node] = mergedPackage } val references = packages.flatMap { it.allReferences() } @@ -76,7 +78,7 @@ class DocumentationMerger( return mergedPackage } - private fun mergeMembers( + private fun mergeMemberReferences( from: DocumentationNode, refs: List ): List { @@ -85,7 +87,7 @@ class DocumentationMerger( val mergedMembers: MutableList = mutableListOf() for ((signature, members) in membersBySignature) { - val newNode = mergeMembersWithEqualSignature(signature, from, members) + val newNode = mergeMembersWithEqualSignature(signature, members) producedNodeRefGraph.register(signature, newNode) updatePendingReferences() @@ -99,23 +101,39 @@ class DocumentationMerger( private fun mergeMembersWithEqualSignature( signature: String, - from: DocumentationNode, - refs: List + nodes: List ): DocumentationNode { - val singleNode = refs.singleOrNull() + val singleNode = nodes.singleOrNull() if (singleNode != null) { singleNode.dropReferences { it.kind == RefKind.Owner } return singleNode } - val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) + + val groupNode = DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode) groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) - for (node in refs) { + for (node in nodes) { node.dropReferences { it.kind == RefKind.Owner } - groupNode.append(node, RefKind.Member) + groupNode.append(node, RefKind.Origin) oldToNewNodeMap[node] = groupNode } + + // if nodes are classes, nested members should be also merged and + // inserted at the same level with class + if (nodes.all { it.kind == NodeKind.Class }) { + val members = nodes.flatMap { it.allReferences() }.filter { it.kind == RefKind.Member } + val mergedMembers = mergeMemberReferences(groupNode, members) + + for (ref in mergedMembers) { + if (ref.kind == RefKind.Owner) { + continue + } + + groupNode.append(ref.to, RefKind.Member) + } + } + return groupNode } @@ -124,13 +142,12 @@ class DocumentationMerger( from: DocumentationNode, refs: List ): List { - val (refsToPackages, usualRefs) = refs.partition { it.to.kind == NodeKind.Package } + val (refsToPackages, otherRefs) = refs.partition { it.to.kind == NodeKind.Package } val mergedPackages = mergePackageReferences(from, refsToPackages) - val (refsToMembers, refsNotToMembers) = usualRefs.partition { it.kind == RefKind.Member } - val mergedMembers = mergeMembers(from, refsToMembers) + val (refsToMembers, refsNotToMembers) = otherRefs.partition { it.kind == RefKind.Member } + val mergedMembers = mergeMemberReferences(from, refsToMembers) - // TODO: think about return mergedPackages + mergedMembers + refsNotToMembers } @@ -156,10 +173,8 @@ class DocumentationMerger( } private fun NodeResolver.update() { - if (this is NodeResolver.Exact) { - if (exactNode != null && exactNode!! in oldToNewNodeMap) { - exactNode = oldToNewNodeMap[exactNode!!] - } + if (this is NodeResolver.Exact && exactNode in oldToNewNodeMap) { + exactNode = oldToNewNodeMap[exactNode]!! } } } \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index c25a7069..e5bc32ab 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1106,7 +1106,7 @@ fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass - || (it.kind == NodeKind.GroupNode && it.members.all { it.kind in NodeKind.classLike }) } } + || (it.kind == NodeKind.GroupNode && it.origins.all { it.kind in NodeKind.classLike }) } } .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 23137364..146c1e99 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -84,6 +84,9 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Detail).map { it.to } val members: List get() = references(RefKind.Member).map { it.to } + val origins: List + get() = references(RefKind.Origin).map { it.to } + val inheritedMembers: List get() = references(RefKind.InheritedMember).map { it.to } val allInheritedMembers: List @@ -203,6 +206,7 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) { RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner) RefKind.Member -> child.addReferenceTo(this, RefKind.Owner) RefKind.Owner -> child.addReferenceTo(this, RefKind.Member) + RefKind.Origin -> child.addReferenceTo(this, RefKind.Owner) else -> { /* Do not add any links back for other types */ } } diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 282d87d8..e10796d2 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -19,7 +19,8 @@ enum class RefKind { Deprecation, TopLevelPage, Platform, - ExternalType + ExternalType, + Origin } data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { @@ -33,7 +34,7 @@ sealed class NodeResolver { } } - class Exact(var exactNode: DocumentationNode?) : NodeResolver() { + class Exact(var exactNode: DocumentationNode) : NodeResolver() { override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? { return exactNode } -- cgit From f7975495c64333cdf625dd970254cca2b796d576 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 16:35:47 +0300 Subject: TODO: remove unnecessary code block --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 1ca636ec..1d201677 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -329,6 +329,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } // All items have exactly the same documentation, so we can use any item to render it val item = items.first() + // TODO: remove this block cause there is no one node with OverloadGroupNote detail item.details(NodeKind.OverloadGroupNote).forEach { appendContent(it.content) } -- cgit From 6034c10de4f208484485e6a53daa48cf11800ef5 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 19:57:34 +0300 Subject: Change render for kotlin mpp signatures rendering --- .../main/kotlin/Formats/StructuredFormatService.kt | 244 +++++++++++++++------ .../main/kotlin/Kotlin/KotlinLanguageService.kt | 2 +- 2 files changed, 173 insertions(+), 73 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 1d201677..b57f21be 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -296,7 +296,12 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } private fun appendDocumentation(overloads: Iterable, isSingleNode: Boolean) { - val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content } + val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> + when (node.kind) { + NodeKind.GroupNode -> node.origins.first().content + else -> node.content + } + } if (breakdownBySummary.size == 1) { formatOverloadGroup(breakdownBySummary.values.single(), isSingleNode) @@ -314,18 +319,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, private fun formatOverloadGroup(items: List, isSingleNode: Boolean = false) { for ((index, item) in items.withIndex()) { if (index > 0) appendLine() - val rendered = languageService.render(item) - item.detailOrNull(NodeKind.Signature)?.let { - if (item.kind !in NodeKind.classLike || !isSingleNode) - appendAnchor(it.name) - } - appendAsSignature(rendered) { - appendCode { appendContent(rendered) } - item.appendSourceLink() + + if (item.kind == NodeKind.GroupNode) { + renderGroupNode(item, isSingleNode) + } else { + renderSimpleNode(item, isSingleNode) } - item.appendOverrides() - item.appendDeprecation() - item.appendPlatforms() + } // All items have exactly the same documentation, so we can use any item to render it val item = items.first() @@ -334,10 +334,75 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendContent(it.content) } - appendContent(item.content.summary) + if (item.kind == NodeKind.GroupNode) { + for (origin in item.origins) { + if (origin.content.isEmpty()) continue + appendParagraph { + appendStrong { to.append("Platform and version requirements:") } + to.append(" " + origin.actualPlatforms) + appendContent(origin.summary) + } + } + } else { + if (!item.content.isEmpty()) { + appendStrong { to.append("Platform and version requirements:") } + to.append(" " + item.actualPlatforms) + appendContent(item.content.summary) + } + } + item.appendDescription() } + + fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean) { + // TODO: use summarizesignatures + val rendered = languageService.render(item) + item.detailOrNull(NodeKind.Signature)?.let { + if (item.kind !in NodeKind.classLike || !isSingleNode) + appendAnchor(it.name) + } + appendAsSignature(rendered) { + appendCode { appendContent(rendered) } + item.appendSourceLink() + } + item.appendOverrides() + item.appendDeprecation() + item.appendPlatforms() + } + + fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean) { + // TODO: use summarizesignatures + val groupBySignature = item.origins.groupBy { + languageService.render(it) + } + + for ((sign, nodes) in groupBySignature) { + val first = nodes.first() + first.detailOrNull(NodeKind.Signature)?.let { + if (item.kind !in NodeKind.classLike || !isSingleNode) + appendAnchor(it.name) + } + + appendAsSignature(sign) { + appendCode { appendContent(sign) } + } + first.appendOverrides() + first.appendDeprecation() + + + appendParagraph { + appendStrong { to.append("Platform and version requirements:") } + to.append(" " + nodes + .flatMap { it.actualPlatforms } + .distinct() + .joinToString() + ) + } + + } + } + private fun DocumentationNode.appendSourceLink() { val sourceUrl = details(NodeKind.SourceUrl).firstOrNull() if (sourceUrl != null) { @@ -362,29 +427,29 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val deprecationParameter = deprecation!!.details(NodeKind.Parameter).firstOrNull() val deprecationValue = deprecationParameter?.details(NodeKind.Value)?.firstOrNull() appendLine() - if (deprecationValue != null) { - appendStrong { to.append("Deprecated:") } - appendText(" " + deprecationValue.name.removeSurrounding("\"")) - appendLine() - appendLine() - } else if (deprecation?.content != Content.Empty) { - appendStrong { to.append("Deprecated:") } - to.append(" ") - appendContent(deprecation!!.content) - } else { - appendStrong { to.append("Deprecated") } - appendLine() - appendLine() + when { + deprecationValue != null -> { + appendStrong { to.append("Deprecated:") } + appendText(" " + deprecationValue.name.removeSurrounding("\"")) + appendLine() + appendLine() + } + deprecation?.content != Content.Empty -> { + appendStrong { to.append("Deprecated:") } + to.append(" ") + appendContent(deprecation!!.content) + } + else -> { + appendStrong { to.append("Deprecated") } + appendLine() + appendLine() + } } } } private fun DocumentationNode.appendPlatforms() { - val platforms = if (isModuleOrPackage()) - platformsToShow.toSet() + platformsOfItems(members) - else - platformsToShow - + val platforms = actualPlatforms if (platforms.isEmpty()) return appendParagraph { @@ -393,10 +458,19 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + val DocumentationNode.actualPlatforms: Collection + get() = if (isModuleOrPackage()) + platformsToShow.toSet() + platformsOfItems(members) + else + platformsToShow + + + protected fun platformsOfItems(items: List): Set { val platforms = items.asSequence().map { when (it.kind) { - NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module, NodeKind.GroupNode -> platformsOfItems(it.members) + NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members) + NodeKind.GroupNode -> platformsOfItems(it.origins) else -> it.platformsToShow.toSet() } } @@ -418,7 +492,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val resultVersion = when { allKotlinVersions.size == 1 -> allKotlinVersions.single() minVersion.endsWith("+") -> minVersion - else -> minVersion + "+" + else -> "$minVersion+" } result.intersect(otherPlatforms) + resultVersion @@ -460,6 +534,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false) : + PageBuilder(listOf(node), noHeader) { + + override fun build() { + super.build() + SectionsBuilder(node).build() + } + } + inner class GroupNodePageBuilder(val node: DocumentationNode) : PageBuilder(listOf(node)) { override fun build() { @@ -470,39 +553,29 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendLine() appendHeader { appendText(node.name) } - fun DocumentationNode.priority(): Int = when (kind) { - NodeKind.TypeAlias -> 1 - NodeKind.Class -> 2 - else -> 3 - } - - for (member in node.members.sortedBy(DocumentationNode::priority)) { - - appendAsOverloadGroup(to, platformsOfItems(listOf(member))) { - formatSubNodeOfGroup(member) - } + renderGroupNode(node, true) + for (origin in node.origins) { + if (origin.content.isEmpty()) continue + appendStrong { to.append("Platform and version requirements:") } + to.append(" " + origin.actualPlatforms) + appendContent(origin.content.summary) } - } - fun formatSubNodeOfGroup(member: DocumentationNode) { - SingleNodePageBuilder(member, true).build() + SectionsBuilder(node).build() } } - inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false) - : PageBuilder(listOf(node), noHeader) { + inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) { override fun build() { - super.build() - if (node.kind == NodeKind.ExternalClass) { appendSection("Extensions for ${node.name}", node.members) return } fun DocumentationNode.membersOrGroupMembers(predicate: (DocumentationNode) -> Boolean): List { - return members.filter(predicate) + members(NodeKind.GroupNode).flatMap { it.members.filter(predicate) } + return members.filter(predicate) + members(NodeKind.GroupNode).filter{ it.origins.isNotEmpty() && predicate(it.origins.first()) } } fun DocumentationNode.membersOrGroupMembers(kind: NodeKind): List { @@ -510,10 +583,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } appendSection("Packages", node.members(NodeKind.Package), platformsBasedOnMembers = true) - appendSection("Types", node.membersOrGroupMembers { it.kind in NodeKind.classLike && it.kind != NodeKind.TypeAlias && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception }) + appendSection("Types", node.membersOrGroupMembers { it.kind in NodeKind.classLike /*&& it.kind != NodeKind.TypeAlias*/ && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception }) appendSection("Annotations", node.membersOrGroupMembers(NodeKind.AnnotationClass)) appendSection("Exceptions", node.membersOrGroupMembers(NodeKind.Exception)) - appendSection("Type Aliases", node.membersOrGroupMembers(NodeKind.TypeAlias)) appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass)) appendSection("Enum Values", node.membersOrGroupMembers(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true) appendSection("Constructors", node.membersOrGroupMembers(NodeKind.Constructor), omitSamePlatforms = true) @@ -558,7 +630,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (node.kind == NodeKind.Module) { appendHeader(3) { to.append("Index") } node.members(NodeKind.AllTypes).singleOrNull()?.let { allTypes -> - appendLink(link(node, allTypes, { "All Types" })) + appendLink(link(node, allTypes) { "All Types" }) } } } @@ -594,11 +666,12 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } appendTableCell { - val breakdownBySummary = members.groupBy { it.summary } - for ((summary, items) in breakdownBySummary) { - appendSummarySignatures(items) - appendContent(summary) + val nodesToAppend = if (members.all { it.kind == NodeKind.GroupNode }) { + members.flatMap { it.origins } + } else { + members } + appendSummarySignatures(nodesToAppend, platformsBasedOnMembers, omitSamePlatforms) } } } @@ -614,27 +687,48 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, return emptySet() } - private fun appendSummarySignatures(items: List) { + private fun appendSummarySignatures(items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { val summarySignature = languageService.summarizeSignatures(items) if (summarySignature != null) { - appendAsSignature(summarySignature) { - summarySignature.appendSignature() - } + appendSummarySignature(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms) return } - val renderedSignatures = items.map { languageService.render(it, RenderMode.SUMMARY) } - renderedSignatures.subList(0, renderedSignatures.size - 1).forEach { - appendAsSignature(it) { - it.appendSignature() - } - appendLine() + + + val groupBySignature = items.groupBy { + languageService.render(it, RenderMode.SUMMARY) } - appendAsSignature(renderedSignatures.last()) { - renderedSignatures.last().appendSignature() + for ((sign, node) in groupBySignature) { + appendSummarySignature(sign, node, platformsBasedOnMembers, omitSamePlatforms) } } + + private fun appendSummarySignature(signature: ContentNode, items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { + val elementPlatforms = platformsOfItems(items, omitSamePlatforms) + val platforms = if (platformsBasedOnMembers) + items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms + else + elementPlatforms + + appendPlatforms(platforms) + appendAsSignature(signature) { + signature.appendSignature() + } + + appendContent(items.first().summary) + appendSoftLineBreak() + } } + private fun DocumentationNode.isClassLikeGroupNode(): Boolean { + if (kind != NodeKind.GroupNode) { + return false + } + + return origins.all { it.kind in NodeKind.classLike } + } + + inner class AllTypesNodeBuilder(val node: DocumentationNode) : PageBuilder(listOf(node)) { @@ -658,7 +752,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } appendTableCell { - appendContent(type.summary) + val summary = if (type.isClassLikeGroupNode()) { + type.origins.first().summary + } else { + type.summary + } + + appendContent(summary) } } } diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 6088d3a5..5b565464 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -198,7 +198,7 @@ class KotlinLanguageService : CommonLanguageService() { nowrap: Boolean ) { when (node.name) { - "final", "public", "var" -> { + "final", "public", "var", "expect", "actual" -> { } else -> { if (node.name !in fullOnlyModifiers || renderMode == RenderMode.FULL) { -- cgit From a4ae451279b4f89b9994d333c6d6d88a0868c5e4 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 21:35:29 +0300 Subject: Drop unnecessary properties in SourceRoot --- core/src/main/kotlin/Generation/configurationImpl.kt | 15 ++------------- .../src/main/kotlin/org/jetbrains/dokka/configuration.kt | 2 -- runners/ant/src/main/kotlin/ant/dokka.kt | 8 +++----- runners/gradle-plugin/src/main/kotlin/main.kt | 8 +------- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 7 ------- 5 files changed, 6 insertions(+), 34 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index f2a91002..2aa0e0d7 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -18,22 +18,11 @@ data class SourceLinkDefinitionImpl(override val path: String, } } -class SourceRootImpl(path: String, override val platforms: List = emptyList(), - override val analysisPlatform: Platform = Platform.DEFAULT) : SourceRoot { +class SourceRootImpl(path: String) : SourceRoot { override val path: String = File(path).absolutePath companion object { - fun parseSourceRoot(sourceRoot: String): SourceRoot { - val components = sourceRoot.split("::", limit = 2) - - val platform = if (components.size == 1) { - Platform.DEFAULT - } else { - Platform.fromString(components[0]) - } - - return SourceRootImpl(components.last(), emptyList(), platform) - } + fun parseSourceRoot(sourceRoot: String): SourceRoot = SourceRootImpl(sourceRoot) } } diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index e0fa27d1..5f1f4bb0 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -73,8 +73,6 @@ interface DokkaConfiguration { interface SourceRoot { val path: String - val platforms: List - val analysisPlatform: Platform } interface SourceLinkDefinition { diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 9428a7ce..8be9246f 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -17,11 +17,9 @@ class AntLogger(val task: Task): DokkaLogger { class AntSourceLinkDefinition(var path: String? = null, var url: String? = null, var lineSuffix: String? = null) -class AntSourceRoot(var path: String? = null, var platforms: String? = null, - var platform: Platform = Platform.DEFAULT) { - fun toSourceRoot(): SourceRootImpl? = path?.let { - path -> - SourceRootImpl(path, platforms?.split(',').orEmpty(), platform) +class AntSourceRoot(var path: String? = null) { + fun toSourceRoot(): SourceRootImpl? = path?.let { path -> + SourceRootImpl(path) } } diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 9c8fd652..91639e11 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -403,13 +403,7 @@ class SourceRoot : DokkaConfiguration.SourceRoot, Serializable { field = File(value).absolutePath } - override var platforms: List = arrayListOf() - - override val analysisPlatform: Platform = Platform.DEFAULT - - override fun toString(): String { - return "${platforms.joinToString()}::$path" - } + override fun toString(): String = path } open class LinkMapping : Serializable, DokkaConfiguration.SourceLinkDefinition { diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index 78fd2d86..a2771306 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -36,13 +36,6 @@ abstract class AbstractDokkaMojo : AbstractMojo() { class SourceRoot : DokkaConfiguration.SourceRoot { @Parameter(required = true) override var path: String = "" - - @Parameter - override var platforms: List = emptyList() - - @Parameter - override var analysisPlatform: Platform = Platform.DEFAULT - } class PackageOptions : DokkaConfiguration.PackageOptions { -- cgit From 0df19264ccae3d294946caf634ee15eea0c4fe4a Mon Sep 17 00:00:00 2001 From: Zubakov Date: Thu, 6 Sep 2018 19:44:50 +0300 Subject: Minor refactoring, kotlin-website format change: add platforms to summary signatures, platform evaluating logic change --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 7 ++ .../main/kotlin/Formats/StructuredFormatService.kt | 123 +++++++++++++++------ core/src/main/kotlin/Model/DocumentationNode.kt | 6 +- 3 files changed, 103 insertions(+), 33 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 6ced75b5..16bec5a6 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -169,6 +169,13 @@ open class KotlinWebsiteHtmlOutputBuilder( appendContent(section) } } + + override fun appendAsBlockWithPlatforms(platforms: Set, block: () -> Unit) { + if (platforms.isNotEmpty()) + wrap("", "", block) + else + block() + } } class KotlinWebsiteHtmlFormatService @Inject constructor( diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index b57f21be..53172563 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -83,6 +83,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + open fun appendAsBlockWithPlatforms(platforms: Set, block: () -> Unit) { + block() + } + open fun appendSymbol(text: String) { appendText(text) } @@ -465,6 +469,18 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, platformsToShow + protected fun mergeVersions(otherKotlinVersion: String, kotlinVersions: List): String { + val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() + + val minVersion = allKotlinVersions.min()!! + val resultVersion: String = when { + allKotlinVersions.size == 1 -> allKotlinVersions.single() + minVersion.endsWith("+") -> minVersion + else -> "$minVersion+" + } + + return resultVersion + } protected fun platformsOfItems(items: List): Set { val platforms = items.asSequence().map { @@ -486,19 +502,38 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, // When no Kotlin version specified, it means that version is 1.0 if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { - val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() + result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions) + } else { + result.intersect(platformsOfItem) + } + } + } - val minVersion = allKotlinVersions.min()!! - val resultVersion = when { - allKotlinVersions.size == 1 -> allKotlinVersions.single() - minVersion.endsWith("+") -> minVersion - else -> "$minVersion+" - } + protected fun unionPlatformsOfItems(items: List): Set { + val platforms = items.asSequence().map { + when (it.kind) { + NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) + else -> it.platformsToShow.toSet() + } + } + + fun String.isKotlinVersion() = this.startsWith("Kotlin") + + if (platforms.count() == 0) return emptySet() + + // Calculating common platforms for items + return platforms.reduce { result, platformsOfItem -> + val otherKotlinVersion = result.find { it.isKotlinVersion() } + val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } - result.intersect(otherPlatforms) + resultVersion + // When no Kotlin version specified, it means that version is 1.0 + if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { + result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions) } else { - result.intersect(platformsOfItem) + result.union(otherPlatforms) } + }.let { + if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } } @@ -566,6 +601,17 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + private fun unionPlatformsOfItems(items: List): Set { + val platforms = items.flatMapTo(mutableSetOf()) { + when (it.kind) { + NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) + else -> it.platforms + } + } + + return platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } + } + inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) { override fun build() { @@ -666,12 +712,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } appendTableCell { - val nodesToAppend = if (members.all { it.kind == NodeKind.GroupNode }) { - members.flatMap { it.origins } - } else { - members - } - appendSummarySignatures(nodesToAppend, platformsBasedOnMembers, omitSamePlatforms) + appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms) } } } @@ -680,6 +721,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } private fun platformsOfItems(items: List, omitSamePlatforms: Boolean = true): Set { + if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) { + return unionPlatformsOfItems(items) + } + val platforms = platformsOfItems(items) if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) { return platforms @@ -688,35 +733,49 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } private fun appendSummarySignatures(items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { - val summarySignature = languageService.summarizeSignatures(items) - if (summarySignature != null) { - appendSummarySignature(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms) - return - } + val groupBySummary = items.groupBy { it.summary } + for ((summary, node) in groupBySummary) { + val nodesToAppend = if (node.all { it.kind == NodeKind.GroupNode }) { + node.flatMap { it.origins } + } else { + node + } - val groupBySignature = items.groupBy { - languageService.render(it, RenderMode.SUMMARY) - } - for ((sign, node) in groupBySignature) { - appendSummarySignature(sign, node, platformsBasedOnMembers, omitSamePlatforms) + val summarySignature = languageService.summarizeSignatures(nodesToAppend) + if (summarySignature != null) { + appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms) + } else { + val groupBySignature = nodesToAppend.groupBy { + languageService.render(it, RenderMode.SUMMARY) + } + for ((sign, members) in groupBySignature) { + appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms) + } + } + + val platforms = platformsOfItems(node) + appendAsBlockWithPlatforms(platforms) { + appendContent(summary) + appendSoftLineBreak() + } } } - private fun appendSummarySignature(signature: ContentNode, items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { + private fun appendSignatures(signature: ContentNode, items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { val elementPlatforms = platformsOfItems(items, omitSamePlatforms) val platforms = if (platformsBasedOnMembers) items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms else elementPlatforms - appendPlatforms(platforms) - appendAsSignature(signature) { - signature.appendSignature() + appendAsBlockWithPlatforms(platforms) { + appendPlatforms(platforms) + appendAsSignature(signature) { + signature.appendSignature() + } + appendSoftLineBreak() } - - appendContent(items.first().summary) - appendSoftLineBreak() } } diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 146c1e99..f2b3a937 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -76,7 +76,11 @@ open class DocumentationNode(val name: String, var content: Content = content private set - val summary: ContentNode get() = content.summary + val summary: ContentNode get() = when (kind) { + NodeKind.GroupNode -> this.origins.first().summary + else -> content.summary + } + val owner: DocumentationNode? get() = references(RefKind.Owner).singleOrNull()?.to -- cgit From b86d9801f7d66c27bbf82608572e7f72b06655bb Mon Sep 17 00:00:00 2001 From: Zubakov Date: Wed, 12 Sep 2018 17:22:33 +0300 Subject: Bundled compiler version upgraded --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 55 +++++++++++++--------- .../main/kotlin/Analysis/CoreProjectFileIndex.kt | 4 +- core/src/main/kotlin/Generation/DokkaGenerator.kt | 5 +- 3 files changed, 38 insertions(+), 26 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index fe9ec2fa..fe599eee 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -18,6 +18,7 @@ import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns @@ -25,6 +26,9 @@ 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 +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot +import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider @@ -38,7 +42,6 @@ import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackagePartProvider import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.js.config.JSConfigurationKeys @@ -84,7 +87,8 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl val projectComponentManager = environment.project as MockComponentManager val projectFileIndex = CoreProjectFileIndex(environment.project, - environment.configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS)) + environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) + val moduleManager = object : CoreModuleManager(environment.project, this) { override fun getModules(): Array = arrayOf(projectFileIndex.module) @@ -187,11 +191,12 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl modulePlatforms = { MultiTargetPlatform.Common }, moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade }, - platformParameters = object : PlatformAnalysisParameters {}, - targetEnvironment = CompilerEnvironment, - packagePartProviderFactory = { content -> - environment.createPackagePartProvider(content.moduleContentScope) + platformParameters = { _ -> + CommonAnalysisParameters { content -> + environment.createPackagePartProvider(content.moduleContentScope) + } }, + targetEnvironment = CompilerEnvironment, builtIns = DefaultBuiltIns.Instance ) } @@ -210,9 +215,8 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl modulePlatforms = { JsPlatform.multiTargetPlatform }, moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, resolverForModuleFactoryByPlatform = { JsAnalyzerFacade }, - platformParameters = object : PlatformAnalysisParameters {}, + platformParameters = { _ -> PlatformAnalysisParameters.Empty },// object : PlatformAnalysisParameters {}, targetEnvironment = CompilerEnvironment, - packagePartProviderFactory = { PackagePartProvider.Empty }, builtIns = JsPlatform.builtIns ) } @@ -245,19 +249,26 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl modulePlatforms = { JvmPlatform.multiTargetPlatform }, moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade }, - platformParameters = JvmPlatformParameters { - val file = (it as JavaClassImpl).psi.containingFile.virtualFile - if (file in sourcesScope) - module - else - library - }, - targetEnvironment = CompilerEnvironment, - packagePartProviderFactory = { content -> - JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { - addRoots(javaRoots) + platformParameters = { targetPlaftorm -> + JvmPlatformParameters( + { content -> + JvmPackagePartProvider( + configuration.languageVersionSettings, + content.moduleContentScope + ).apply { + this.addRoots(javaRoots, configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)) + } + } + ) { it -> + val file = (it as JavaClassImpl).psi.containingFile.virtualFile + if (file in sourcesScope) + module + else + library + } }, + targetEnvironment = CompilerEnvironment, builtIns = builtIns ) } @@ -302,7 +313,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl * List of source roots for this environment. */ val sources: List - get() = configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + get() = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) ?.filterIsInstance() ?.map { it.path } ?: emptyList() @@ -321,7 +332,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl } fun addRoots(list: List) { - configuration.addAll(JVMConfigurationKeys.CONTENT_ROOTS, list) + configuration.addAll(CLIConfigurationKeys.CONTENT_ROOTS, list) } /** @@ -334,7 +345,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl fun contentRootFromPath(path: String): ContentRoot { val file = File(path) - return if (file.extension == "java") JavaSourceRoot(file, null) else KotlinSourceRoot(path) + return if (file.extension == "java") JavaSourceRoot(file, null) else KotlinSourceRoot(path, false) } diff --git a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt index 4f6a7c76..ffd95da2 100644 --- a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt +++ b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt @@ -22,8 +22,8 @@ import com.intellij.util.messages.MessageBus import org.jetbrains.jps.model.module.JpsModuleSourceRootType import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot -import org.jetbrains.kotlin.config.ContentRoot -import org.jetbrains.kotlin.config.KotlinSourceRoot +import org.jetbrains.kotlin.cli.common.config.ContentRoot +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.picocontainer.PicoContainer import java.io.File diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 1193657e..f4161de9 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -11,6 +11,7 @@ import org.jetbrains.dokka.Generation.DocumentationMerger import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule import org.jetbrains.dokka.Utilities.DokkaRunModule +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -184,7 +185,7 @@ fun buildDocumentationModule(injector: Injector, } fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEnvironment) { - val contentRoots = coreEnvironment.configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + val contentRoots = coreEnvironment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) ?.filterIsInstance() ?.map { it.file } ?: listOf() @@ -197,7 +198,7 @@ fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEn fun KotlinCoreEnvironment.getJavaSourceFiles(): List { - val sourceRoots = configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + val sourceRoots = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) ?.filterIsInstance() ?.map { it.file } ?: listOf() -- cgit From 2b21b8b3ea3e6e79895491045bdb8361325dce15 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Wed, 12 Sep 2018 20:50:01 +0300 Subject: Unresolved LazyTopDownAnalyzerFacade hotfix --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 6 +- .../main/kotlin/Analysis/DokkaAnalyzerFacades.kt | 159 +++++++++++++++++++++ 2 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index fe599eee..e6496789 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -42,7 +42,7 @@ import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade +import org.jetbrains.dokka.Analysis.DokkaJsAnalyzerFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.resolve.JsPlatform @@ -214,8 +214,8 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl modulesContent = modulesContent, modulePlatforms = { JsPlatform.multiTargetPlatform }, moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { JsAnalyzerFacade }, - platformParameters = { _ -> PlatformAnalysisParameters.Empty },// object : PlatformAnalysisParameters {}, + resolverForModuleFactoryByPlatform = { DokkaJsAnalyzerFacade }, + platformParameters = { _ -> PlatformAnalysisParameters.Empty }, targetEnvironment = CompilerEnvironment, builtIns = JsPlatform.builtIns ) diff --git a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt new file mode 100644 index 00000000..442940fd --- /dev/null +++ b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt @@ -0,0 +1,159 @@ +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.createPackageFragmentProviderForLibraryModule +import org.jetbrains.kotlin.idea.caches.project.LibraryInfo +import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.js.resolve.JsPlatform +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() + useImpl() + targetEnvironment.configure(this) + + useImpl() + useImpl() +} + + +object DokkaJsAnalyzerFacade : ResolverForModuleFactory() { + override fun createResolverForModule( + moduleDescriptor: ModuleDescriptorImpl, + moduleContext: ModuleContext, + moduleContent: ModuleContent, + platformParameters: PlatformAnalysisParameters, + targetEnvironment: TargetEnvironment, + resolverForProject: ResolverForProject, + 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().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 createResolverForModule( + moduleDescriptor: ModuleDescriptorImpl, + moduleContext: ModuleContext, + moduleContent: ModuleContent, + platformParameters: PlatformAnalysisParameters, + targetEnvironment: TargetEnvironment, + resolverForProject: ResolverForProject, + 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().packageFragmentProvider + val fragmentProviders = mutableListOf(packageFragmentProvider) + + val moduleInfo = moduleContent.moduleInfo + + if (moduleInfo is LibraryInfo) { + val libPackageFragmentProviders = moduleInfo.createPackageFragmentProviderForLibraryModule( + moduleContext.storageManager, + languageVersionSettings, + moduleDescriptor + ) + fragmentProviders.addAll(libPackageFragmentProviders) + //TODO: Forward declarations? + } + + return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container) + } +} + -- cgit From 6fc26eb93e2b86d77f917bee495ba79286791216 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Thu, 13 Sep 2018 00:17:50 +0300 Subject: Added native support --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 31 +++++++++++++++++++--- .../kotlin/org/jetbrains/dokka/configuration.kt | 2 ++ 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index e6496789..f26829b0 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -17,6 +17,8 @@ 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 @@ -42,7 +44,6 @@ import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.dokka.Analysis.DokkaJsAnalyzerFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.js.config.JSConfigurationKeys import org.jetbrains.kotlin.js.resolve.JsPlatform @@ -54,6 +55,7 @@ import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform +import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.types.KotlinType @@ -81,6 +83,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl val configFiles = when (analysisPlatform) { Platform.jvm, Platform.common -> EnvironmentConfigFiles.JVM_CONFIG_FILES + Platform.native -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES } val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles) @@ -111,7 +114,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope = when (analysisPlatform) { Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - Platform.js, Platform.common -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + Platform.js, Platform.common, Platform.native -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) } @@ -124,6 +127,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl val targetPlatform = when (analysisPlatform) { Platform.js -> JsPlatform Platform.common -> TargetPlatform.Common + Platform.native -> KonanPlatform Platform.jvm -> JvmPlatform } @@ -159,8 +163,9 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl builtIns = JvmBuiltIns(projectContext.storageManager) createJvmResolverForProject(projectContext, module, library, modulesContent, sourcesScope, builtIns) } - Platform.js -> createJsResolverForProject(projectContext, module, library, modulesContent) 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 @@ -221,6 +226,26 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl ) } + private fun createNativeResolverForProject( + projectContext: ProjectContext, + module: ModuleInfo, + library: LibraryModuleInfo, + modulesContent: (ModuleInfo) -> ModuleContent + ): ResolverForProjectImpl { + return ResolverForProjectImpl( + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(module, library), + modulesContent = modulesContent, + modulePlatforms = { KonanPlatform.multiTargetPlatform }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { DokkaNativeAnalyzerFacade }, + platformParameters = { _ -> PlatformAnalysisParameters.Empty }, + targetEnvironment = CompilerEnvironment + ) + + } + private fun createJvmResolverForProject( projectContext: ProjectContext, module: ModuleInfo, diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 5f1f4bb0..7eb1d3f2 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -20,6 +20,7 @@ class UrlSerializer : ValueSerializer { enum class Platform(val key: String) { jvm("jvm"), js("js"), + native("native"), common("common"); @@ -30,6 +31,7 @@ enum class Platform(val key: String) { return when (key.toLowerCase()) { jvm.key -> jvm js.key -> js + native.key -> native common.key -> common else -> TODO("write normal exception") } -- cgit From d7791c49635fb966b089e77052617ba71f65792e Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 11:46:30 +0300 Subject: add more debug info in error message --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index 0394dce2..a464ead6 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -11,7 +11,7 @@ class DocumentationMerger( init { if (documentationModules.groupBy { it.name }.size > 1) { - throw IllegalArgumentException("Modules should have similar names") + throw IllegalArgumentException("Modules should have similar names: ${documentationModules.joinToString(", ") {it.name}}") } signatureMap = documentationModules -- cgit From 6ad0c3bd63f9f5a5ed46f6f59bf00b1ddfeec794 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 13:12:43 +0300 Subject: more info instead of NPE --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index a464ead6..45233a50 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -83,7 +83,7 @@ class DocumentationMerger( refs: List ): List { val membersBySignature: Map> = refs.map { it.to } - .groupBy { signatureMap[it]!! } + .groupBy { signatureMap[it] ?: error("Unresolved signatures: ${it.kind} ${it.name}") } val mergedMembers: MutableList = mutableListOf() for ((signature, members) in membersBySignature) { -- cgit From 0b18da608eddfb48a40675d83ae3a92fc9a85fb6 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 13:35:43 +0300 Subject: add nice toString() --- core/src/main/kotlin/Model/Content.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 7c776bdb..77451d41 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -222,7 +222,11 @@ open class Content(): ContentBlock() { sections.firstOrNull { tag.equals(it.tag, ignoreCase = true) } companion object { - val Empty = Content() + val Empty = object: Content() { + override fun toString(): String { + return "EMPTY_CONTENT" + } + } fun of(vararg child: ContentNode): Content { val result = MutableContent() -- cgit From 87a449eb3293448f92c938b4fe9863a32373c439 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 13:38:11 +0300 Subject: more logging --- .../main/kotlin/Generation/DocumentationMerger.kt | 20 +++++++++++++------- core/src/main/kotlin/Generation/DokkaGenerator.kt | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index 45233a50..40a4e30d 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -3,7 +3,8 @@ package org.jetbrains.dokka.Generation import org.jetbrains.dokka.* class DocumentationMerger( - private val documentationModules: List + private val documentationModules: List, + val logger: DokkaLogger ) { private val producedNodeRefGraph: NodeReferenceGraph = NodeReferenceGraph() private val signatureMap: Map @@ -34,12 +35,17 @@ class DocumentationMerger( val resultReferences = mutableListOf() for ((name, listOfPackages) in packagesByName) { - val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages) - updatePendingReferences() - - resultReferences.add( - DocumentationReference(from, producedPackage, RefKind.Member) - ) + try { + val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages) + updatePendingReferences() + + resultReferences.add( + DocumentationReference(from, producedPackage, RefKind.Member) + ) + } catch (t: Throwable) { + val entries = listOfPackages.joinToString(",") { "references:${it.allReferences().size}" } + throw Error("Failed to merge package $name from $from with entries $entries. ${t.message}", t) + } } return resultReferences diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index f4161de9..9d718971 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -42,7 +42,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, documentationModules.add(documentationModule) } - val totalDocumentationModule = DocumentationMerger(documentationModules).merge() + val totalDocumentationModule = DocumentationMerger(documentationModules, logger).merge() totalDocumentationModule.prepareForGeneration(dokkaConfiguration) val timeBuild = measureTimeMillis { -- cgit From b78581dd1f46bf6326c15bc3f3e11e3dd2315e41 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 14:02:48 +0300 Subject: more logging around signature failure --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index 40a4e30d..3be6be83 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -84,12 +84,23 @@ class DocumentationMerger( return mergedPackage } + private fun mergeMemberGroupBy(it: DocumentationNode): String { + val signature = signatureMap[it] + + if (signature != null) { + return signature + } + + logger.error("Failed to find signature for $it in \n${it.allReferences().joinToString { "\n ${it.kind} ${it.to}" }}") + return "" + } + private fun mergeMemberReferences( from: DocumentationNode, refs: List ): List { val membersBySignature: Map> = refs.map { it.to } - .groupBy { signatureMap[it] ?: error("Unresolved signatures: ${it.kind} ${it.name}") } + .groupBy(this::mergeMemberGroupBy) val mergedMembers: MutableList = mutableListOf() for ((signature, members) in membersBySignature) { -- cgit From 9379b68427bcfb44caa3ced02cb1c34789869e41 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 23:15:27 +0300 Subject: report files clash --- core/src/main/kotlin/Generation/FileGenerator.kt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index eb6800b3..f9104110 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -30,6 +30,13 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F for ((file, items) in nodes.groupBy { fileForNode(it, formatService.extension) }) { + if (items.size > 1) { + println("An attempt to generate ${root.toPath().relativize(file.toPath())} for: ") + for (item in items) { + println(" ${item.allReferences().map { "${it.to.kind} ${it.to.name }" } }") + } + } + file.parentFile?.mkdirsOrFail() try { FileOutputStream(file).use { -- cgit From 9521c1100eb8c6c09d71352ba49eca66c7612a55 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 23:30:41 +0300 Subject: avoid clash for empty-named symbols --- core/src/main/kotlin/Locations/Location.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Locations/Location.kt b/core/src/main/kotlin/Locations/Location.kt index 4cb0ac39..4448fb99 100644 --- a/core/src/main/kotlin/Locations/Location.kt +++ b/core/src/main/kotlin/Locations/Location.kt @@ -44,6 +44,7 @@ fun relativePathToNode(qualifiedName: List, hasMembers: Boolean): String fun relativePathToNode(node: DocumentationNode) = relativePathToNode(node.path.map { it.name }, node.members.any()) fun identifierToFilename(path: String): String { + if (path.isEmpty()) return "--root--" val escaped = path.replace('<', '-').replace('>', '-') val lowercase = escaped.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() } return if (lowercase == "index") "--index--" else lowercase -- cgit From dd9e016b11de0cea2e49d8831b2b04fd0b898c3c Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Fri, 14 Sep 2018 00:23:36 +0300 Subject: cleanup --- core/src/main/kotlin/Generation/FileGenerator.kt | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index f9104110..40348be0 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -22,21 +22,13 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F return File(root, relativePathToNode(node)).appendExtension(extension) } - fun locationWithoutExtension(node: DocumentationNode): FileLocation { + private fun locationWithoutExtension(node: DocumentationNode): FileLocation { return FileLocation(fileForNode(node)) } override fun buildPages(nodes: Iterable) { for ((file, items) in nodes.groupBy { fileForNode(it, formatService.extension) }) { - - if (items.size > 1) { - println("An attempt to generate ${root.toPath().relativize(file.toPath())} for: ") - for (item in items) { - println(" ${item.allReferences().map { "${it.to.kind} ${it.to.name }" } }") - } - } - file.parentFile?.mkdirsOrFail() try { FileOutputStream(file).use { @@ -86,10 +78,9 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F } -} - -private fun File.mkdirsOrFail() { - if (!mkdirs() && !exists()) { - throw IOException("Failed to create directory $this") + private fun File.mkdirsOrFail() { + if (!mkdirs() && !exists()) { + throw IOException("Failed to create directory $this") + } } -} \ No newline at end of file +} -- cgit From 9f36e27e3b93bc912888733e7f13df0f48211915 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Fri, 14 Sep 2018 01:46:31 +0300 Subject: include more diagnostics for files clashes --- core/src/main/kotlin/Generation/FileGenerator.kt | 92 +++++++++++++++++------- 1 file changed, 65 insertions(+), 27 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 40348be0..120efc6b 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -3,9 +3,9 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named import java.io.File -import java.io.FileOutputStream import java.io.IOException -import java.io.OutputStreamWriter +import java.io.PrintWriter +import java.io.StringWriter class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @@ -14,6 +14,56 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null + private val createdFiles = mutableMapOf>() + + private fun File.writeFileAndAssert(context: String, action: (File) -> Unit) { + //TODO: there is a possible refactoring to drop FileLocation + //TODO: aad File from API, Location#path. + //TODO: turn [Location] into a final class, + //TODO: Use [Location] all over the place without full + //TODO: reference to the real target path, + //TODO: it opens the way to safely track all files created + //TODO: to make sure no files were overwritten by mistake + //TODO: also, the NodeLocationAwareGenerator should be removed + val stack = "$context\n" + try { + throw Error() + } catch (t: Throwable) { + StringWriter().use { ww -> + PrintWriter(ww).use { + t.printStackTrace(it) + } + ww.toString().replace("\n", "\n ") + } + } + + val writes = createdFiles.getOrDefault(this, listOf()) + stack + createdFiles[this] = writes + if (writes.size > 1) { + println("ERROR. An attempt to write ${this.relativeTo(root)} several times!") + + createdFiles[this] = writes + stack + for (call in writes + stack) { + println(call) + } + println() + return + } + + try { + parentFile?.mkdirsOrFail() + action(this) + } catch (e : Throwable) { + println("Failed to write $this. ${e.message}") + e.printStackTrace() + } + } + + private fun File.mkdirsOrFail() { + if (!mkdirs() && !exists()) { + throw IOException("Failed to create directory $this") + } + } + override fun location(node: DocumentationNode): FileLocation { return FileLocation(fileForNode(node, formatService.linkExtension)) } @@ -29,16 +79,10 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F override fun buildPages(nodes: Iterable) { for ((file, items) in nodes.groupBy { fileForNode(it, formatService.extension) }) { - file.parentFile?.mkdirsOrFail() - try { - FileOutputStream(file).use { - OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(formatService.format(location(items.first()), items)) - } - } - } catch (e: Throwable) { - println(e) + file.writeFileAndAssert("pages") { it -> + it.writeText(formatService.format(location(items.first()), items)) } + buildPages(items.flatMap { it.members }) } } @@ -46,20 +90,18 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F override fun buildOutlines(nodes: Iterable) { val outlineService = this.outlineService ?: return for ((location, items) in nodes.groupBy { locationWithoutExtension(it) }) { - val file = outlineService.getOutlineFileName(location) - file.parentFile?.mkdirsOrFail() - FileOutputStream(file).use { - OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(outlineService.formatOutline(location, items)) - } + outlineService.getOutlineFileName(location).writeFileAndAssert("outlines") { file -> + file.writeText(outlineService.formatOutline(location, items)) } } } override fun buildSupportFiles() { formatService.enumerateSupportFiles { resource, targetPath -> - FileOutputStream(File(root, relativePathToNode(listOf(targetPath), false))).use { - javaClass.getResourceAsStream(resource).copyTo(it) + File(root, relativePathToNode(listOf(targetPath), false)).writeFileAndAssert("support files") { file -> + file.outputStream().use { + javaClass.getResourceAsStream(resource).copyTo(it) + } } } } @@ -72,15 +114,11 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F val moduleRoot = location(module).file.parentFile val packageListFile = File(moduleRoot, "package-list") - packageListFile.writeText("\$dokka.format:${dokkaConfiguration.format}\n" + - packageListService!!.formatPackageList(module as DocumentationModule)) - } - - } + val text = "\$dokka.format:${dokkaConfiguration.format}\n" + packageListService!!.formatPackageList(module as DocumentationModule) - private fun File.mkdirsOrFail() { - if (!mkdirs() && !exists()) { - throw IOException("Failed to create directory $this") + packageListFile.writeFileAndAssert("packages-list") { file -> + file.writeText(text) + } } } } -- cgit From d80b38a15c1a43c687957403c77b35deba05bd9e Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 20 Sep 2018 19:51:58 +0300 Subject: Quick hack to make native work --- .../main/kotlin/Analysis/DokkaAnalyzerFacades.kt | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt index 442940fd..082d3968 100644 --- a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt +++ b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt @@ -12,10 +12,12 @@ 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.createPackageFragmentProviderForLibraryModule -import org.jetbrains.kotlin.idea.caches.project.LibraryInfo +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 @@ -143,17 +145,19 @@ object DokkaNativeAnalyzerFacade : ResolverForModuleFactory() { val moduleInfo = moduleContent.moduleInfo - if (moduleInfo is LibraryInfo) { - val libPackageFragmentProviders = moduleInfo.createPackageFragmentProviderForLibraryModule( - moduleContext.storageManager, - languageVersionSettings, - moduleDescriptor - ) - fragmentProviders.addAll(libPackageFragmentProviders) - //TODO: Forward declarations? + if (moduleInfo is LibraryModuleInfo) { + moduleInfo.getLibraryRoots() + .map { createKonanLibrary(File(it), KOTLIN_NATIVE_CURRENT_ABI_VERSION) } + .mapTo(fragmentProviders) { + it.createPackageFragmentProvider( + moduleContext.storageManager, + languageVersionSettings, + moduleDescriptor + ) + } + } return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container) } } - -- cgit From 312b50005bae6cbdea6a203c37bee3006a90b641 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Fri, 21 Sep 2018 16:03:51 +0300 Subject: Fix number of platforms bubbles --- .../main/kotlin/Formats/StructuredFormatService.kt | 37 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 53172563..927e0827 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -712,7 +712,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } appendTableCell { - appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms) + appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms, platforms) } } } @@ -732,7 +732,12 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, return emptySet() } - private fun appendSummarySignatures(items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { + private fun appendSummarySignatures( + items: List, + platformsBasedOnMembers: Boolean, + omitSamePlatforms: Boolean, + parentPlatforms: Set + ) { val groupBySummary = items.groupBy { it.summary } for ((summary, node) in groupBySummary) { @@ -744,32 +749,50 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val summarySignature = languageService.summarizeSignatures(nodesToAppend) if (summarySignature != null) { - appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms) + appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) } else { val groupBySignature = nodesToAppend.groupBy { languageService.render(it, RenderMode.SUMMARY) } for ((sign, members) in groupBySignature) { - appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms) + appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) } } val platforms = platformsOfItems(node) - appendAsBlockWithPlatforms(platforms) { + val platformsToAppend = if (platforms == parentPlatforms) { + emptySet() + } else { + platforms + } + appendAsBlockWithPlatforms(platformsToAppend) { appendContent(summary) appendSoftLineBreak() } } } - private fun appendSignatures(signature: ContentNode, items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { + private fun appendSignatures( + signature: ContentNode, + items: List, + platformsBasedOnMembers: Boolean, + omitSamePlatforms: Boolean, + parentPlatforms: Set + ) { val elementPlatforms = platformsOfItems(items, omitSamePlatforms) val platforms = if (platformsBasedOnMembers) items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms else elementPlatforms - appendAsBlockWithPlatforms(platforms) { + + val platformsToAppend = if (platforms == parentPlatforms) { + emptySet() + } else { + platforms + } + + appendAsBlockWithPlatforms(platformsToAppend) { appendPlatforms(platforms) appendAsSignature(signature) { signature.appendSignature() -- cgit From d7fdbb7b4ab13d05bbc8ea796518e75ecab97fb7 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Fri, 21 Sep 2018 17:50:29 +0200 Subject: less noise on error --- core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 120efc6b..8a282ef1 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -32,7 +32,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F PrintWriter(ww).use { t.printStackTrace(it) } - ww.toString().replace("\n", "\n ") + ww.toString().split("[\r\n]+").asSequence().drop(1).take(3).joinToString("\n") {" $it"} } } -- cgit From 835c3b1b6f76fff29290949cc14cad2a2b26b265 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Sun, 23 Sep 2018 15:49:11 +0200 Subject: less noise from an attempt to write file several times --- core/src/main/kotlin/Generation/FileGenerator.kt | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 8a282ef1..c90d0735 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -25,27 +25,11 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F //TODO: it opens the way to safely track all files created //TODO: to make sure no files were overwritten by mistake //TODO: also, the NodeLocationAwareGenerator should be removed - val stack = "$context\n" + try { - throw Error() - } catch (t: Throwable) { - StringWriter().use { ww -> - PrintWriter(ww).use { - t.printStackTrace(it) - } - ww.toString().split("[\r\n]+").asSequence().drop(1).take(3).joinToString("\n") {" $it"} - } - } - val writes = createdFiles.getOrDefault(this, listOf()) + stack + val writes = createdFiles.getOrDefault(this, listOf()) + context createdFiles[this] = writes if (writes.size > 1) { println("ERROR. An attempt to write ${this.relativeTo(root)} several times!") - - createdFiles[this] = writes + stack - for (call in writes + stack) { - println(call) - } - println() return } -- cgit From 49b7b776757113139fb7aed9c8959276d844b09b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 24 Sep 2018 21:52:22 +0300 Subject: Get rid of duplicated items with set of platform < than common --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index 3be6be83..f6280fb9 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -120,11 +120,20 @@ class DocumentationMerger( signature: String, nodes: List ): DocumentationNode { + require(nodes.isNotEmpty()) + val singleNode = nodes.singleOrNull() if (singleNode != null) { singleNode.dropReferences { it.kind == RefKind.Owner } return singleNode } + val nodeWithMaxPlatforms = nodes.maxBy { it.platforms.size }!! + val maxPlatforms = nodeWithMaxPlatforms.platforms.toSet() + val notContained = nodes.filterNot { maxPlatforms.containsAll(it.platforms) } + val reducedDuplicates = notContained + nodeWithMaxPlatforms + if (!reducedDuplicates.containsAll(nodes)) { + return mergeMembersWithEqualSignature(signature, reducedDuplicates) + } val groupNode = DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode) groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) -- cgit From 3617e8c0962e32201605c154c5360c1e5defab12 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 24 Sep 2018 21:53:00 +0300 Subject: Use only first target for expect elements --- core/src/main/kotlin/Generation/DokkaGenerator.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 9d718971..9173dfbb 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.MemberDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode import org.jetbrains.kotlin.utils.PathUtil @@ -73,9 +74,12 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val defaultPlatformAsList = passConfiguration.targets val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List { - val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath - ?.let { File(it).absolutePath } - val sourceRoot = containingFilePath?.let { path -> sourceRoots.find { path.startsWith(it.path) } } +// val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath +// ?.let { File(it).absolutePath } +// val sourceRoot = containingFilePath?.let { path -> sourceRoots.find { path.startsWith(it.path) } } + if (descriptor is MemberDescriptor && descriptor.isExpect) { + return defaultPlatformAsList.take(1) + } return /*sourceRoot?.platforms ?: */defaultPlatformAsList } } -- cgit From f2bfbc788a995daed52d3c0d587223d7b21cb3cc Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 26 Sep 2018 00:32:08 +0300 Subject: Refactor platforms & SinceKotlin logic --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 7 +- .../main/kotlin/Formats/StructuredFormatService.kt | 292 ++++++++++++--------- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 7 + .../main/kotlin/Model/DocumentationReference.kt | 3 +- 5 files changed, 180 insertions(+), 131 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 16bec5a6..e5dd57a7 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -125,14 +125,16 @@ open class KotlinWebsiteHtmlOutputBuilder( fun calculateDataAttributes(platforms: Set): String { fun String.isKotlinVersion() = this.startsWith("Kotlin") fun String.isJREVersion() = this.startsWith("JRE") + fun String.isNoBubbles() = this.startsWith("NoBubbles") val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion) val jreVersion = platforms.singleOrNull(String::isJREVersion) - val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } + val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() || it.isNoBubbles() } val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: "" val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: "" val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: "" - return "$platformsAttr$kotlinVersionAttr$jreVersionAttr" + val classes = if (NoBubbles in platforms) " class=\"no-bubbles\"" else "" + return "$classes$platformsAttr$kotlinVersionAttr$jreVersionAttr" } override fun appendIndexRow(platforms: Set, block: () -> Unit) { @@ -191,3 +193,4 @@ class KotlinWebsiteHtmlFormatService @Inject constructor( KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) } +val NoBubbles = "NoBubbles" \ No newline at end of file diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 927e0827..c5b6c8eb 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -10,7 +10,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val generator: NodeLocationAwareGenerator, val languageService: LanguageService, val extension: String, - val impliedPlatforms: List) : FormattedOutputBuilder { + impliedPlatforms: List) : FormattedOutputBuilder { protected fun DocumentationNode.location() = generator.location(this) @@ -312,7 +312,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } else { for ((_, items) in breakdownBySummary) { - appendAsOverloadGroup(to, platformsOfItems(items)) { + appendAsOverloadGroup(to, effectivePlatformsForMembers(items)) { formatOverloadGroup(items) } @@ -463,82 +463,64 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } val DocumentationNode.actualPlatforms: Collection - get() = if (isModuleOrPackage()) - platformsToShow.toSet() + platformsOfItems(members) - else - platformsToShow - - - protected fun mergeVersions(otherKotlinVersion: String, kotlinVersions: List): String { - val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() - - val minVersion = allKotlinVersions.min()!! - val resultVersion: String = when { - allKotlinVersions.size == 1 -> allKotlinVersions.single() - minVersion.endsWith("+") -> minVersion - else -> "$minVersion+" - } - - return resultVersion - } - - protected fun platformsOfItems(items: List): Set { - val platforms = items.asSequence().map { - when (it.kind) { - NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members) - NodeKind.GroupNode -> platformsOfItems(it.origins) - else -> it.platformsToShow.toSet() - } - } - - fun String.isKotlinVersion() = this.startsWith("Kotlin") - - if (platforms.count() == 0) return emptySet() - - // Calculating common platforms for items - return platforms.reduce { result, platformsOfItem -> - val otherKotlinVersion = result.find { it.isKotlinVersion() } - val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } - - // When no Kotlin version specified, it means that version is 1.0 - if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { - result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions) - } else { - result.intersect(platformsOfItem) - } - } - } - - protected fun unionPlatformsOfItems(items: List): Set { - val platforms = items.asSequence().map { - when (it.kind) { - NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) - else -> it.platformsToShow.toSet() - } - } - - fun String.isKotlinVersion() = this.startsWith("Kotlin") - - if (platforms.count() == 0) return emptySet() - - // Calculating common platforms for items - return platforms.reduce { result, platformsOfItem -> - val otherKotlinVersion = result.find { it.isKotlinVersion() } - val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } - - // When no Kotlin version specified, it means that version is 1.0 - if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { - result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions) - } else { - result.union(otherPlatforms) - } - }.let { - if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it - } - } - - val DocumentationNode.platformsToShow: List - get() = platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } + get() = effectivePlatformsForNode(this) + + +// protected fun platformsOfItems(items: List): Set { +// val platforms = items.asSequence().map { +// when (it.kind) { +// NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members) +// NodeKind.GroupNode -> platformsOfItems(it.origins) +// else -> it.platformsToShow.toSet() +// } +// } +// +// fun String.isKotlinVersion() = this.startsWith("Kotlin") +// +// if (platforms.count() == 0) return emptySet() +// +// // Calculating common platforms for items +// return platforms.reduce { result, platformsOfItem -> +// val otherKotlinVersion = result.find { it.isKotlinVersion() } +// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } +// +// // When no Kotlin version specified, it means that version is 1.0 +// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { +// result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions) +// } else { +// result.intersect(platformsOfItem) +// } +// } +// } +// +// protected fun unionPlatformsOfItems(items: List): Set { +// val platforms = items.asSequence().map { +// when (it.kind) { +// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) +// else -> it.platformsToShow.toSet() +// } +// } +// +// fun String.isKotlinVersion() = this.startsWith("Kotlin") +// +// if (platforms.count() == 0) return emptySet() +// +// // Calculating common platforms for items +// return platforms.reduce { result, platformsOfItem -> +// val otherKotlinVersion = result.find { it.isKotlinVersion() } +// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } +// +// // When no Kotlin version specified, it means that version is 1.0 +// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { +// result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions) +// } else { +// result.union(otherPlatforms) +// } +// } +// } + +// val DocumentationNode.platformsToShow: List +// get() = platforms private fun DocumentationNode.appendDescription() { if (content.description != ContentEmpty) { @@ -600,17 +582,17 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, SectionsBuilder(node).build() } } - - private fun unionPlatformsOfItems(items: List): Set { - val platforms = items.flatMapTo(mutableSetOf()) { - when (it.kind) { - NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) - else -> it.platforms - } - } - - return platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } - } +// +// private fun unionPlatformsOfItems(items: List): Set { +// val platforms = items.flatMapTo(mutableSetOf()) { +// when (it.kind) { +// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) +// else -> it.platforms +// } +// } +// +// return platforms +// } inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) { @@ -697,11 +679,11 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTable("Name", "Summary") { appendTableBody { for ((memberLocation, members) in membersMap) { - val elementPlatforms = platformsOfItems(members, omitSamePlatforms) - val platforms = if (platformsBasedOnMembers) - members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms - else - elementPlatforms + val platforms = effectivePlatformsForMembers(members) + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(members)) +// val platforms = if (platformsBasedOnMembers) +// members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms +// else +// elementPlatforms appendIndexRow(platforms) { appendTableCell { appendParagraph { @@ -720,17 +702,18 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - private fun platformsOfItems(items: List, omitSamePlatforms: Boolean = true): Set { - if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) { - return unionPlatformsOfItems(items) - } - - val platforms = platformsOfItems(items) - if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) { - return platforms - } - return emptySet() - } +// +// private fun platformsOfItems(items: List, omitSamePlatforms: Boolean = true): Set { +// if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) { +// return unionPlatformsOfItems(items) +// } +// +// val platforms = platformsOfItems(items) +// if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) { +// return platforms +// } +// return emptySet() +// } private fun appendSummarySignatures( items: List, @@ -740,16 +723,16 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, ) { val groupBySummary = items.groupBy { it.summary } - for ((summary, node) in groupBySummary) { - val nodesToAppend = if (node.all { it.kind == NodeKind.GroupNode }) { - node.flatMap { it.origins } + for ((summary, nodes) in groupBySummary) { + val nodesToAppend = if (nodes.all { it.kind == NodeKind.GroupNode }) { + nodes.flatMap { it.origins } } else { - node + nodes } val summarySignature = languageService.summarizeSignatures(nodesToAppend) if (summarySignature != null) { - appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) + appendSignatures(summarySignature, nodes, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) } else { val groupBySignature = nodesToAppend.groupBy { languageService.render(it, RenderMode.SUMMARY) @@ -759,12 +742,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - val platforms = platformsOfItems(node) - val platformsToAppend = if (platforms == parentPlatforms) { - emptySet() - } else { - platforms - } + val platforms = effectivePlatformsForMembers(nodes) + val platformsToAppend = platforms + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(nodes)) + NoBubbles appendAsBlockWithPlatforms(platformsToAppend) { appendContent(summary) appendSoftLineBreak() @@ -779,18 +758,14 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, omitSamePlatforms: Boolean, parentPlatforms: Set ) { - val elementPlatforms = platformsOfItems(items, omitSamePlatforms) - val platforms = if (platformsBasedOnMembers) - items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms - else - elementPlatforms + val platforms = effectivePlatformsForMembers(items) +// val platforms = if (platformsBasedOnMembers) +// items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms +// else +// elementPlatforms - - val platformsToAppend = if (platforms == parentPlatforms) { - emptySet() - } else { - platforms - } + print("signature>") + val platformsToAppend = platforms + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(items)) appendAsBlockWithPlatforms(platformsToAppend) { appendPlatforms(platforms) @@ -866,3 +841,66 @@ abstract class StructuredFormatService(val generator: NodeLocationAwareGenerator override final val linkExtension: String = extension) : FormatService { } + + +fun memberPlatforms(node: DocumentationNode): Sequence> { + val members = when { + node.kind == NodeKind.GroupNode -> node.origins + else -> node.members + } + + return members.asSequence() + .map { effectivePlatformsForNode(it) } +} + +fun effectivePlatformsForNode(node: DocumentationNode): Set { + val platforms = + sequenceOf(node.platforms.toSet()) + memberPlatforms(node) + + + // Calculating common platforms for items + return platforms.reduce { result, platformsOfItem -> + result.union(platformsOfItem) + } +} + +fun effectivePlatformsForMembers(nodes: List): Set { + return nodes.map { effectivePlatformsForNode(it) }.reduce { acc, set -> + acc.union(set) + } +} + +fun mergeVersions(kotlinVersions: List): String { + val allKotlinVersions = kotlinVersions.distinct() + + val minVersion = allKotlinVersions.min()!! + val resultVersion: String = when { + allKotlinVersions.size == 1 -> allKotlinVersions.single() + minVersion.endsWith("+") -> minVersion + else -> "$minVersion+" + } + + return resultVersion +} + +fun effectiveSinceKotlinForNode(node: DocumentationNode, baseVersion: String = "1.0"): String { + val members = when { + node.kind == NodeKind.GroupNode -> node.origins + node.kind in NodeKind.classLike -> emptyList() + node.kind in NodeKind.memberLike -> emptyList() + else -> node.members + } + + val nodeVersion = node.sinceKotlin ?: baseVersion + val memberVersion = if (members.isNotEmpty()) effectiveSinceKotlinForNodes(members, nodeVersion) else nodeVersion + + println("${node.path} > $nodeVersion, $memberVersion") + + return mergeVersions(listOf(memberVersion, nodeVersion)) +} + +fun effectiveSinceKotlinForNodes(nodes: List, baseVersion: String = "1.0"): String { + return mergeVersions(nodes.map { effectiveSinceKotlinForNode(it, baseVersion) }) +} + +fun sinceKotlinAsPlatform(version: String): String = "Kotlin $version" diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e5bc32ab..38d2df4a 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -275,7 +275,7 @@ class DocumentationBuilder .detail(NodeKind.Value) .name.removeSurrounding("\"") - append(platformNodeRegistry["Kotlin " + kotlinVersion], RefKind.Platform) + sinceKotlin = kotlinVersion } fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index f2b3a937..5607c6d3 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -116,6 +116,13 @@ open class DocumentationNode(val name: String, val externalType: DocumentationNode? get() = references(RefKind.ExternalType).map { it.to }.firstOrNull() + var sinceKotlin: String? + get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name + set(value) { + if(value == null) return dropReferences { it.kind == RefKind.SinceKotlin } + append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) + } + val supertypes: List get() = details(NodeKind.Supertype) diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index e10796d2..1f2fc0c9 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -20,7 +20,8 @@ enum class RefKind { TopLevelPage, Platform, ExternalType, - Origin + Origin, + SinceKotlin } data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { -- cgit From ebd4b15b8e96cfe6f88d3aed76609a8ce5f2dd67 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 26 Sep 2018 21:46:40 +0300 Subject: Don't show applicable to Any extensions for all declarations --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 38d2df4a..580ffb05 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -33,6 +33,9 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes +import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny +import org.jetbrains.kotlin.types.typeUtil.isTypeParameter import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.util.supertypesWithAny import com.google.inject.name.Named as GuiceNamed @@ -457,13 +460,20 @@ class DocumentationBuilder .filter { it.extensionReceiverParameter != null } val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name } + fun isIgnoredReceiverType(type: KotlinType) = + type.isDynamic() || + type.isAnyOrNullableAny() || + (type.isTypeParameter() && type.immediateSupertypes().all { it.isAnyOrNullableAny() }) + + for (extensionFunction in allExtensionFunctions) { + val extensionReceiverParameter = extensionFunction.extensionReceiverParameter!! if (extensionFunction.dispatchReceiverParameter != null) continue val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name] ?.filter { fn -> fn.canShadow(extensionFunction) } ?: emptyList() - if (extensionFunction.extensionReceiverParameter?.type?.isDynamic() == true) continue + if (isIgnoredReceiverType(extensionReceiverParameter.type)) continue val subclasses = classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) } if (subclasses.isEmpty()) continue -- cgit From cffc71e39f20a368f2ffe10bf0c8aa4432dee7fc Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 26 Sep 2018 22:14:40 +0300 Subject: Change logic of platforms rendering --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 22 +++-- .../main/kotlin/Formats/StructuredFormatService.kt | 110 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index e5dd57a7..66eb60c4 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -125,16 +125,16 @@ open class KotlinWebsiteHtmlOutputBuilder( fun calculateDataAttributes(platforms: Set): String { fun String.isKotlinVersion() = this.startsWith("Kotlin") fun String.isJREVersion() = this.startsWith("JRE") - fun String.isNoBubbles() = this.startsWith("NoBubbles") + val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion) val jreVersion = platforms.singleOrNull(String::isJREVersion) - val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() || it.isNoBubbles() } + val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } + val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: "" val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: "" val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: "" - val classes = if (NoBubbles in platforms) " class=\"no-bubbles\"" else "" - return "$classes$platformsAttr$kotlinVersionAttr$jreVersionAttr" + return "$platformsAttr$kotlinVersionAttr$jreVersionAttr" } override fun appendIndexRow(platforms: Set, block: () -> Unit) { @@ -144,7 +144,9 @@ open class KotlinWebsiteHtmlOutputBuilder( appendTableRow(block) } - override fun appendPlatforms(platforms: Set) {} + override fun appendPlatforms(platforms: Set) { + div(to, "tags") {} + } override fun appendBreadcrumbSeparator() { to.append(" / ") @@ -172,11 +174,13 @@ open class KotlinWebsiteHtmlOutputBuilder( } } - override fun appendAsBlockWithPlatforms(platforms: Set, block: () -> Unit) { + override fun appendAsPlatformDependentBlock(platforms: Set, block: (Set) -> Unit) { if (platforms.isNotEmpty()) - wrap("", "", block) + wrap("", "") { + block(platforms) + } else - block() + block(platforms) } } @@ -192,5 +196,3 @@ class KotlinWebsiteHtmlFormatService @Inject constructor( override fun createOutputBuilder(to: StringBuilder, location: Location) = KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) } - -val NoBubbles = "NoBubbles" \ No newline at end of file diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index c5b6c8eb..04710694 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -83,8 +83,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - open fun appendAsBlockWithPlatforms(platforms: Set, block: () -> Unit) { - block() + open fun appendAsPlatformDependentBlock(platforms: Set, block: (Set) -> Unit) { + block(platforms) } open fun appendSymbol(text: String) { @@ -311,11 +311,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, formatOverloadGroup(breakdownBySummary.values.single(), isSingleNode) } else { for ((_, items) in breakdownBySummary) { - - appendAsOverloadGroup(to, effectivePlatformsForMembers(items)) { + appendAsOverloadGroup(to, effectivePlatformAndVersion(items)) { formatOverloadGroup(items) } - } } } @@ -339,19 +337,23 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } if (item.kind == NodeKind.GroupNode) { - for (origin in item.origins) { - if (origin.content.isEmpty()) continue - appendParagraph { - appendStrong { to.append("Platform and version requirements:") } - to.append(" " + origin.actualPlatforms) - appendContent(origin.summary) + for ((content, origins) in item.origins.groupBy { it.content }) { + if (content.isEmpty()) continue + val platforms = effectivePlatformsForMembers(origins) + appendAsPlatformDependentBlock(platforms) { + appendPlatforms(platforms) + appendParagraph { + appendContent(content) + } } } } else { if (!item.content.isEmpty()) { - appendStrong { to.append("Platform and version requirements:") } - to.append(" " + item.actualPlatforms) - appendContent(item.content.summary) + val platforms = effectivePlatformsForNode(item) + appendAsPlatformDependentBlock(platforms) { + appendPlatforms(platforms) + appendContent(item.content) + } } } @@ -382,26 +384,19 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } for ((sign, nodes) in groupBySignature) { - val first = nodes.first() - first.detailOrNull(NodeKind.Signature)?.let { - if (item.kind !in NodeKind.classLike || !isSingleNode) - appendAnchor(it.name) - } - - appendAsSignature(sign) { - appendCode { appendContent(sign) } - } - first.appendOverrides() - first.appendDeprecation() - + appendAsPlatformDependentBlock(effectivePlatformAndVersion(nodes)) { platforms -> + val first = nodes.first() + first.detailOrNull(NodeKind.Signature)?.let { + if (item.kind !in NodeKind.classLike || !isSingleNode) + appendAnchor(it.name) + } - appendParagraph { - appendStrong { to.append("Platform and version requirements:") } - to.append(" " + nodes - .flatMap { it.actualPlatforms } - .distinct() - .joinToString() - ) + appendAsSignature(sign) { + appendCode { appendContent(sign) } + } + appendPlatforms(platforms) + first.appendOverrides() + first.appendDeprecation() } } @@ -463,7 +458,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } val DocumentationNode.actualPlatforms: Collection - get() = effectivePlatformsForNode(this) + get() = effectivePlatformAndVersion(listOf(this)) // protected fun platformsOfItems(items: List): Set { @@ -572,11 +567,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, renderGroupNode(node, true) - for (origin in node.origins) { - if (origin.content.isEmpty()) continue - appendStrong { to.append("Platform and version requirements:") } - to.append(" " + origin.actualPlatforms) - appendContent(origin.content.summary) + for ((content, origins) in node.origins.groupBy { it.content }) { + if (content.isEmpty()) continue + val platforms = effectivePlatformAndVersion(origins) + appendAsPlatformDependentBlock(platforms) { + appendPlatforms(platforms) + appendContent(content) + } } SectionsBuilder(node).build() @@ -679,7 +676,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTable("Name", "Summary") { appendTableBody { for ((memberLocation, members) in membersMap) { - val platforms = effectivePlatformsForMembers(members) + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(members)) + val platforms = emptySet() // val platforms = if (platformsBasedOnMembers) // members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms // else @@ -688,12 +685,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTableCell { appendParagraph { appendLink(memberLocation) - if (members.singleOrNull()?.kind != NodeKind.ExternalClass) { - appendPlatforms(platforms) - } +// if (members.singleOrNull()?.kind != NodeKind.ExternalClass) { +// appendPlatforms(platforms) +// } } - } - appendTableCell { appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms, platforms) } } @@ -742,9 +737,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - val platforms = effectivePlatformsForMembers(nodes) - val platformsToAppend = platforms + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(nodes)) + NoBubbles - appendAsBlockWithPlatforms(platformsToAppend) { + val platformsToAppend = effectivePlatformAndVersion(nodes) + appendAsPlatformDependentBlock(platformsToAppend) { appendContent(summary) appendSoftLineBreak() } @@ -758,21 +752,20 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, omitSamePlatforms: Boolean, parentPlatforms: Set ) { - val platforms = effectivePlatformsForMembers(items) + // val platforms = if (platformsBasedOnMembers) // items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms // else // elementPlatforms - print("signature>") - val platformsToAppend = platforms + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(items)) + val platformsToAppend = effectivePlatformAndVersion(items) - appendAsBlockWithPlatforms(platformsToAppend) { - appendPlatforms(platforms) - appendAsSignature(signature) { - signature.appendSignature() - } + appendAsPlatformDependentBlock(platformsToAppend) { + appendAsSignature(signature) { + signature.appendSignature() + } appendSoftLineBreak() + appendPlatforms(platformsToAppend) } } } @@ -904,3 +897,8 @@ fun effectiveSinceKotlinForNodes(nodes: List, baseVersion: St } fun sinceKotlinAsPlatform(version: String): String = "Kotlin $version" + + +fun effectivePlatformAndVersion(nodes: List, baseVersion: String = "1.0"): Set { + return effectivePlatformsForMembers(nodes) + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(nodes, baseVersion)) +} -- cgit From 960e022f7b94d858942f938dd9f7b877f2435964 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 26 Sep 2018 22:15:03 +0300 Subject: Take implied platforms back --- core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 66eb60c4..718c8d35 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -20,7 +20,7 @@ open class KotlinWebsiteHtmlOutputBuilder( generator: NodeLocationAwareGenerator, languageService: LanguageService, extension: String, - impliedPlatforms: List, + val impliedPlatforms: List, templateService: HtmlTemplateService ) : HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) { private var needHardLineBreaks = false @@ -128,7 +128,10 @@ open class KotlinWebsiteHtmlOutputBuilder( val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion) val jreVersion = platforms.singleOrNull(String::isJREVersion) - val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } + val targetPlatforms = + platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } + .takeUnless { it.intersect(impliedPlatforms).containsAll(impliedPlatforms) } + .orEmpty() val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: "" -- cgit From 31af10e09963096389a4201ec1b0f8d9a11bb7f6 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 27 Sep 2018 18:22:10 +0300 Subject: Insert platforms on dokka side --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 718c8d35..d2321ad9 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -122,22 +122,32 @@ open class KotlinWebsiteHtmlOutputBuilder( else -> "identifier" } - fun calculateDataAttributes(platforms: Set): String { + private fun calculatePlatforms(platforms: Set): Map> { + fun String.isKotlinVersion() = this.startsWith("Kotlin") fun String.isJREVersion() = this.startsWith("JRE") - val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion) + val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ") val jreVersion = platforms.singleOrNull(String::isJREVersion) val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } .takeUnless { it.intersect(impliedPlatforms).containsAll(impliedPlatforms) } .orEmpty() + return mapOf( + "platform" to targetPlatforms, + "kotlin-version" to listOfNotNull(kotlinVersion), + "jre-version" to listOfNotNull(jreVersion) + ) + } - val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: "" - val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: "" - val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: "" - return "$platformsAttr$kotlinVersionAttr$jreVersionAttr" + private fun calculateDataAttributes(platforms: Set): String { + val platformsByKind = calculatePlatforms(platforms) + return platformsByKind + .entries.filterNot { it.value.isEmpty() } + .joinToString(separator = " ") { (kind, values) -> + "data-$kind=\"${values.joinToString()}\"" + } } override fun appendIndexRow(platforms: Set, block: () -> Unit) { @@ -148,7 +158,16 @@ open class KotlinWebsiteHtmlOutputBuilder( } override fun appendPlatforms(platforms: Set) { - div(to, "tags") {} + val platformsToKind = calculatePlatforms(platforms) + div(to, "tags") { + platformsToKind.entries.forEach { (kind, values) -> + values.forEach { value -> + div(to, "tags__tag $kind") { + to.append(value) + } + } + } + } } override fun appendBreadcrumbSeparator() { @@ -179,7 +198,7 @@ open class KotlinWebsiteHtmlOutputBuilder( override fun appendAsPlatformDependentBlock(platforms: Set, block: (Set) -> Unit) { if (platforms.isNotEmpty()) - wrap("", "") { + wrap("
", "
") { block(platforms) } else -- cgit From 8422874793845c1bb5234b91f858d74e80c956f7 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 27 Sep 2018 18:22:49 +0300 Subject: Render signatures in platform dependent block --- .../main/kotlin/Formats/StructuredFormatService.kt | 40 ++++++++++++---------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 04710694..162976a6 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -362,19 +362,21 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean) { - // TODO: use summarizesignatures - val rendered = languageService.render(item) - item.detailOrNull(NodeKind.Signature)?.let { - if (item.kind !in NodeKind.classLike || !isSingleNode) - appendAnchor(it.name) - } - appendAsSignature(rendered) { - appendCode { appendContent(rendered) } - item.appendSourceLink() - } - item.appendOverrides() - item.appendDeprecation() - item.appendPlatforms() + appendAsPlatformDependentBlock(effectivePlatformAndVersion(listOf(item))) { platforms -> + // TODO: use summarizesignatures + val rendered = languageService.render(item) + item.detailOrNull(NodeKind.Signature)?.let { + if (item.kind !in NodeKind.classLike || !isSingleNode) + appendAnchor(it.name) + } + appendAsSignature(rendered) { + appendCode { appendContent(rendered) } + item.appendSourceLink() + } + item.appendOverrides() + item.appendDeprecation() + appendPlatforms(platforms) + } } fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean) { @@ -725,6 +727,12 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, nodes } + val platformsToAppend = effectivePlatformAndVersion(nodes) + appendAsPlatformDependentBlock(platformsToAppend) { + appendContent(summary) + appendSoftLineBreak() + } + val summarySignature = languageService.summarizeSignatures(nodesToAppend) if (summarySignature != null) { appendSignatures(summarySignature, nodes, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) @@ -736,12 +744,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) } } - - val platformsToAppend = effectivePlatformAndVersion(nodes) - appendAsPlatformDependentBlock(platformsToAppend) { - appendContent(summary) - appendSoftLineBreak() - } } } -- cgit From 51cb9c12e4db76a552ada7445b346fe1ac3e68ef Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 27 Sep 2018 18:24:00 +0300 Subject: Remove implied platforms --- core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index d2321ad9..1a674626 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -129,10 +129,7 @@ open class KotlinWebsiteHtmlOutputBuilder( val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ") val jreVersion = platforms.singleOrNull(String::isJREVersion) - val targetPlatforms = - platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } - .takeUnless { it.intersect(impliedPlatforms).containsAll(impliedPlatforms) } - .orEmpty() + val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } return mapOf( "platform" to targetPlatforms, -- cgit From 45495ebb61964ce853c4f1b5a4b63f28e18daa57 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 28 Sep 2018 20:10:45 +0300 Subject: Support new platform tags style --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 38 +++--- .../main/kotlin/Formats/StructuredFormatService.kt | 148 +++++++++++++++------ 2 files changed, 126 insertions(+), 60 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 1a674626..5bd346da 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -69,27 +69,29 @@ open class KotlinWebsiteHtmlOutputBuilder( override fun appendLink(href: String, body: () -> Unit) = wrap("", "", body) override fun appendTable(vararg columns: String, body: () -> Unit) { - to.appendln("") - body() - to.appendln("
") + //to.appendln("") + div(to, "api-declarations-list") { + body() + } + //to.appendln("
") } override fun appendTableBody(body: () -> Unit) { - to.appendln("") + //to.appendln("") body() - to.appendln("") + //to.appendln("") } override fun appendTableRow(body: () -> Unit) { - to.appendln("") + //to.appendln("") body() - to.appendln("") + //to.appendln("") } override fun appendTableCell(body: () -> Unit) { - to.appendln("") +// to.appendln("") body() - to.appendln("\n") +// to.appendln("\n") } override fun appendSymbol(text: String) { @@ -125,12 +127,11 @@ open class KotlinWebsiteHtmlOutputBuilder( private fun calculatePlatforms(platforms: Set): Map> { fun String.isKotlinVersion() = this.startsWith("Kotlin") - fun String.isJREVersion() = this.startsWith("JRE") + fun String.isJREVersion() = this.startsWith("JRE", ignoreCase=true) val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ") - val jreVersion = platforms.singleOrNull(String::isJREVersion) + val jreVersion = platforms.filter(String::isJREVersion).min()?.takeUnless { it.endsWith("6") } val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } - return mapOf( "platform" to targetPlatforms, "kotlin-version" to listOfNotNull(kotlinVersion), @@ -148,10 +149,13 @@ open class KotlinWebsiteHtmlOutputBuilder( } override fun appendIndexRow(platforms: Set, block: () -> Unit) { - if (platforms.isNotEmpty()) - wrap("", "", block) - else - appendTableRow(block) +// if (platforms.isNotEmpty()) +// wrap("", "", block) +// else +// appendTableRow(block) + div(to, "declarations", otherAttributes = " ${calculateDataAttributes(platforms)}") { + block() + } } override fun appendPlatforms(platforms: Set) { @@ -159,7 +163,7 @@ open class KotlinWebsiteHtmlOutputBuilder( div(to, "tags") { platformsToKind.entries.forEach { (kind, values) -> values.forEach { value -> - div(to, "tags__tag $kind") { + div(to, "tags__tag $kind tag-value-$value") { to.append(value) } } diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 162976a6..dabc0b2b 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -5,6 +5,48 @@ import java.util.* data class FormatLink(val text: String, val href: String) +private data class Summarized( + val data: List +) { + + constructor(data: Map>>) : this( + data.entries.map { (summary, signatureToMember) -> + SummarizedBySummary( + summary, + signatureToMember.map { (signature, nodes) -> + SummarizedNodes(signature, nodes) + } + ) + } + ) + + data class SummarizedNodes(val content: ContentNode, val nodes: List) { + val platforms = effectivePlatformAndVersion(nodes) + } + data class SummarizedBySummary(val content: ContentNode, val signatures: List) { + val platforms = effectivePlatformAndVersion(signatures.flatMap { it.nodes }) + val platformsOnSignature = !sameVersionAndPlatforms(signatures.map { it.platforms }) + } + + + fun computePlatformLevel(): PlatformPlacement { + if (data.any { it.platformsOnSignature }) { + return PlatformPlacement.Signature + } + if (sameVersionAndPlatforms(data.map { it.platforms })) { + return PlatformPlacement.Row + } + return PlatformPlacement.Summary + } + val platformPlacement: PlatformPlacement = computePlatformLevel() + val platforms = effectivePlatformAndVersion(data.flatMap { it.signatures.flatMap { it.nodes } }) + + + enum class PlatformPlacement { + Row, Summary, Signature + } +} + abstract class StructuredOutputBuilder(val to: StringBuilder, val location: Location, val generator: NodeLocationAwareGenerator, @@ -454,7 +496,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (platforms.isEmpty()) return appendParagraph { - appendStrong { to.append("Platform and version requirements:") } + appendStrong { to.append("WTF: Platform and version requirements:") } to.append(" " + platforms.joinToString()) } } @@ -678,20 +720,27 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTable("Name", "Summary") { appendTableBody { for ((memberLocation, members) in membersMap) { - val platforms = emptySet() + val platforms = effectivePlatformAndVersion(members) // val platforms = if (platformsBasedOnMembers) // members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms // else // elementPlatforms + + val summarized = computeSummarySignatures(members) + + appendIndexRow(platforms) { appendTableCell { + if (summarized.platformPlacement == Summarized.PlatformPlacement.Row) { + appendPlatforms(platforms) + } appendParagraph { appendLink(memberLocation) // if (members.singleOrNull()?.kind != NodeKind.ExternalClass) { // appendPlatforms(platforms) // } } - appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms, platforms) + appendSummarySignatures(summarized) } } } @@ -712,47 +761,52 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, // return emptySet() // } + + + private fun computeSummarySignatures(items: List): Summarized = + Summarized(items.groupBy { it.summary }.mapValues { (_, nodes) -> + val nodesToAppend = if (nodes.all { it.kind == NodeKind.GroupNode }) { + nodes.flatMap { it.origins } + } else { + nodes + } + val summarySignature = languageService.summarizeSignatures(nodesToAppend) + if (summarySignature != null) { + mapOf(summarySignature to nodes) + } else { + nodesToAppend.groupBy { + languageService.render(it, RenderMode.SUMMARY) + } + } + }) + + private fun appendSummarySignatures( - items: List, - platformsBasedOnMembers: Boolean, - omitSamePlatforms: Boolean, - parentPlatforms: Set + summarized: Summarized ) { - val groupBySummary = items.groupBy { it.summary } + for(summary in summarized.data) { - for ((summary, nodes) in groupBySummary) { - val nodesToAppend = if (nodes.all { it.kind == NodeKind.GroupNode }) { - nodes.flatMap { it.origins } - } else { - nodes - } - val platformsToAppend = effectivePlatformAndVersion(nodes) - appendAsPlatformDependentBlock(platformsToAppend) { - appendContent(summary) - appendSoftLineBreak() - } - val summarySignature = languageService.summarizeSignatures(nodesToAppend) - if (summarySignature != null) { - appendSignatures(summarySignature, nodes, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) - } else { - val groupBySignature = nodesToAppend.groupBy { - languageService.render(it, RenderMode.SUMMARY) - } - for ((sign, members) in groupBySignature) { - appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) + appendAsPlatformDependentBlock(summary.platforms) { + if (summarized.platformPlacement == Summarized.PlatformPlacement.Summary) { + appendPlatforms(summary.platforms) } + appendContent(summary.content) + appendSoftLineBreak() + } + for (signature in summary.signatures) { + appendSignatures( + signature, + summarized.platformPlacement == Summarized.PlatformPlacement.Signature + ) } } } private fun appendSignatures( - signature: ContentNode, - items: List, - platformsBasedOnMembers: Boolean, - omitSamePlatforms: Boolean, - parentPlatforms: Set + signature: Summarized.SummarizedNodes, + withPlatforms: Boolean ) { // val platforms = if (platformsBasedOnMembers) @@ -760,14 +814,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, // else // elementPlatforms - val platformsToAppend = effectivePlatformAndVersion(items) - appendAsPlatformDependentBlock(platformsToAppend) { - appendAsSignature(signature) { - signature.appendSignature() + appendAsPlatformDependentBlock(signature.platforms) { + if (withPlatforms) { + appendPlatforms(signature.platforms) + } + appendAsSignature(signature.content) { + signature.content.appendSignature() } appendSoftLineBreak() - appendPlatforms(platformsToAppend) } } } @@ -859,7 +914,7 @@ fun effectivePlatformsForNode(node: DocumentationNode): Set { } } -fun effectivePlatformsForMembers(nodes: List): Set { +fun effectivePlatformsForMembers(nodes: Collection): Set { return nodes.map { effectivePlatformsForNode(it) }.reduce { acc, set -> acc.union(set) } @@ -889,18 +944,25 @@ fun effectiveSinceKotlinForNode(node: DocumentationNode, baseVersion: String = " val nodeVersion = node.sinceKotlin ?: baseVersion val memberVersion = if (members.isNotEmpty()) effectiveSinceKotlinForNodes(members, nodeVersion) else nodeVersion - println("${node.path} > $nodeVersion, $memberVersion") - return mergeVersions(listOf(memberVersion, nodeVersion)) } -fun effectiveSinceKotlinForNodes(nodes: List, baseVersion: String = "1.0"): String { +fun effectiveSinceKotlinForNodes(nodes: Collection, baseVersion: String = "1.0"): String { return mergeVersions(nodes.map { effectiveSinceKotlinForNode(it, baseVersion) }) } fun sinceKotlinAsPlatform(version: String): String = "Kotlin $version" -fun effectivePlatformAndVersion(nodes: List, baseVersion: String = "1.0"): Set { +fun effectivePlatformAndVersion(nodes: Collection, baseVersion: String = "1.0"): Set { return effectivePlatformsForMembers(nodes) + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(nodes, baseVersion)) } + +fun effectivePlatformAndVersion(node: DocumentationNode, baseVersion: String = "1.0"): Set { + return effectivePlatformsForNode(node) + sinceKotlinAsPlatform(effectiveSinceKotlinForNode(node, baseVersion)) +} + +fun sameVersionAndPlatforms(platformsPerNode: Collection>): Boolean { + val first = platformsPerNode.firstOrNull() ?: return true + return platformsPerNode.all { it == first } +} \ No newline at end of file -- cgit From c3b0ede82b925517e4c4859388ae4c7129d29a0d Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 28 Sep 2018 23:32:30 +0300 Subject: Remove concept of 'Plus' versions --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index dabc0b2b..fffa9e3e 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -921,16 +921,7 @@ fun effectivePlatformsForMembers(nodes: Collection): Set): String { - val allKotlinVersions = kotlinVersions.distinct() - - val minVersion = allKotlinVersions.min()!! - val resultVersion: String = when { - allKotlinVersions.size == 1 -> allKotlinVersions.single() - minVersion.endsWith("+") -> minVersion - else -> "$minVersion+" - } - - return resultVersion + return kotlinVersions.distinct().min()!! } fun effectiveSinceKotlinForNode(node: DocumentationNode, baseVersion: String = "1.0"): String { -- cgit From f4ffd392a5673980c6c1bf77ed23efa53c10a628 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Mon, 1 Oct 2018 20:07:54 +0300 Subject: Eliminate tags shuffle --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index f6280fb9..e5186e72 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -130,7 +130,7 @@ class DocumentationMerger( val nodeWithMaxPlatforms = nodes.maxBy { it.platforms.size }!! val maxPlatforms = nodeWithMaxPlatforms.platforms.toSet() val notContained = nodes.filterNot { maxPlatforms.containsAll(it.platforms) } - val reducedDuplicates = notContained + nodeWithMaxPlatforms + val reducedDuplicates = listOf(nodeWithMaxPlatforms) + notContained if (!reducedDuplicates.containsAll(nodes)) { return mergeMembersWithEqualSignature(signature, reducedDuplicates) } -- cgit From 25381f71922b8aa665e8c9ceaca58785237cfdba Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Mon, 1 Oct 2018 21:24:12 +0300 Subject: Fixed duplicated descriptions --- .../main/kotlin/Formats/StructuredFormatService.kt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index fffa9e3e..7e21c30c 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -384,9 +384,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val platforms = effectivePlatformsForMembers(origins) appendAsPlatformDependentBlock(platforms) { appendPlatforms(platforms) - appendParagraph { - appendContent(content) - } + appendContent(content.summary) + content.appendDescription() } } } else { @@ -394,12 +393,11 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val platforms = effectivePlatformsForNode(item) appendAsPlatformDependentBlock(platforms) { appendPlatforms(platforms) - appendContent(item.content) + appendContent(item.summary) + item.content.appendDescription() } } } - - item.appendDescription() } @@ -561,15 +559,17 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, // val DocumentationNode.platformsToShow: List // get() = platforms - private fun DocumentationNode.appendDescription() { - if (content.description != ContentEmpty) { - appendContent(content.description) + private fun Content.appendDescription() { + if (description != ContentEmpty) { + appendContent(description) } - content.getSectionsWithSubjects().forEach { + + + getSectionsWithSubjects().forEach { appendSectionWithSubject(it.key, it.value) } - for (section in content.sections.filter { it.subjectName == null }) { + for (section in sections.filter { it.subjectName == null }) { appendSectionWithTag(section) } } -- cgit From 0741416fc19add9f83f3754eb99550b3c3578cf9 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 2 Oct 2018 03:21:11 +0300 Subject: Fix summarizing --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 7e21c30c..eda85031 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -765,14 +765,11 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, private fun computeSummarySignatures(items: List): Summarized = Summarized(items.groupBy { it.summary }.mapValues { (_, nodes) -> - val nodesToAppend = if (nodes.all { it.kind == NodeKind.GroupNode }) { - nodes.flatMap { it.origins } - } else { - nodes - } + val nodesToAppend = nodes.flatMap { if(it.kind == NodeKind.GroupNode) it.origins else listOf(it) } + val summarySignature = languageService.summarizeSignatures(nodesToAppend) if (summarySignature != null) { - mapOf(summarySignature to nodes) + mapOf(summarySignature to nodesToAppend) } else { nodesToAppend.groupBy { languageService.render(it, RenderMode.SUMMARY) -- cgit From 0f19897ef9de71f571b1af703ac33923640cb547 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 2 Oct 2018 03:23:01 +0300 Subject: Fix single node & group node pages platform display --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index eda85031..67e8c503 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -392,7 +392,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (!item.content.isEmpty()) { val platforms = effectivePlatformsForNode(item) appendAsPlatformDependentBlock(platforms) { - appendPlatforms(platforms) appendContent(item.summary) item.content.appendDescription() } @@ -409,13 +408,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (item.kind !in NodeKind.classLike || !isSingleNode) appendAnchor(it.name) } + appendPlatforms(platforms) appendAsSignature(rendered) { appendCode { appendContent(rendered) } item.appendSourceLink() } item.appendOverrides() item.appendDeprecation() - appendPlatforms(platforms) } } @@ -433,10 +432,11 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendAnchor(it.name) } + appendPlatforms(platforms) + appendAsSignature(sign) { appendCode { appendContent(sign) } } - appendPlatforms(platforms) first.appendOverrides() first.appendDeprecation() } @@ -611,11 +611,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, renderGroupNode(node, true) - for ((content, origins) in node.origins.groupBy { it.content }) { + val groupByContent = node.origins.groupBy { it.content } + for ((content, origins) in groupByContent) { if (content.isEmpty()) continue - val platforms = effectivePlatformAndVersion(origins) - appendAsPlatformDependentBlock(platforms) { - appendPlatforms(platforms) + appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> + if (groupByContent.keys.count { !it.isEmpty() } > 1) { + appendPlatforms(platforms) + } appendContent(content) } } -- cgit From 52d3e0e0de74c951651b6f3c9970d0ded7e15e1a Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 2 Oct 2018 16:19:05 +0300 Subject: Fix platform display for group node overloads --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 67e8c503..764fd50e 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -379,11 +379,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } if (item.kind == NodeKind.GroupNode) { - for ((content, origins) in item.origins.groupBy { it.content }) { + val groupByContent = item.origins.groupBy { it.content } + for ((content, origins) in groupByContent) { if (content.isEmpty()) continue - val platforms = effectivePlatformsForMembers(origins) - appendAsPlatformDependentBlock(platforms) { - appendPlatforms(platforms) + appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> + if (groupByContent.count { !it.key.isEmpty() } > 1) { + appendPlatforms(platforms) + } appendContent(content.summary) content.appendDescription() } -- cgit From 5c3007bfdcdaed03167a2b7997df6a98da397aaf Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 03:33:24 +0300 Subject: Fix yaml outline generation to use relative paths --- core/src/main/kotlin/Formats/YamlOutlineService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/YamlOutlineService.kt b/core/src/main/kotlin/Formats/YamlOutlineService.kt index c36f98eb..3c92d8ff 100644 --- a/core/src/main/kotlin/Formats/YamlOutlineService.kt +++ b/core/src/main/kotlin/Formats/YamlOutlineService.kt @@ -13,7 +13,7 @@ class YamlOutlineService @Inject constructor( override fun appendOutlineHeader(location: Location, node: DocumentationNode, to: StringBuilder) { val indent = " ".repeat(outlineLevel) to.appendln("$indent- title: ${languageService.renderName(node)}") - to.appendln("$indent url: ${generator.location(node).path}") + to.appendln("$indent url: ${generator.relativePathToLocation(node.path.first(), node)}") } override fun appendOutlineLevel(to: StringBuilder, body: () -> Unit) { -- cgit From 58f4badfb356335521abe0409845ea3cf1d348fc Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 03:33:42 +0300 Subject: Fix GroupNode internal inbound links --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index e5186e72..54485930 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -141,6 +141,7 @@ class DocumentationMerger( for (node in nodes) { node.dropReferences { it.kind == RefKind.Owner } groupNode.append(node, RefKind.Origin) + node.append(groupNode, RefKind.TopLevelPage) oldToNewNodeMap[node] = groupNode } -- cgit From 743c2a12aef65a10e2ec59a459c67a72b10a556b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 03:35:58 +0300 Subject: Build pages only once --- core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index c90d0735..ee2c068e 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -67,7 +67,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F it.writeText(formatService.format(location(items.first()), items)) } - buildPages(items.flatMap { it.members }) + buildPages(items.filterNot { it.kind == NodeKind.AllTypes }.flatMap { it.members }) } } -- cgit From 2f377659e7b5251dceb4df3a6a25fe922edf28c6 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 03:57:49 +0300 Subject: Use spacer to align tags to right --- core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 5bd346da..220f2f4d 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -161,6 +161,7 @@ open class KotlinWebsiteHtmlOutputBuilder( override fun appendPlatforms(platforms: Set) { val platformsToKind = calculatePlatforms(platforms) div(to, "tags") { + div(to, "spacer") {} platformsToKind.entries.forEach { (kind, values) -> values.forEach { value -> div(to, "tags__tag $kind tag-value-$value") { -- cgit From 896776306e15f1e5bbdc771a3e58d0ffd8b45198 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 03:59:57 +0300 Subject: Introduce block for grouped by summary items --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 6 ++++++ .../main/kotlin/Formats/StructuredFormatService.kt | 21 ++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 220f2f4d..65c93e72 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -206,6 +206,12 @@ open class KotlinWebsiteHtmlOutputBuilder( else block(platforms) } + + override fun appendAsSummaryGroup(platforms: Set, block: (Set) -> Unit) { + div(to, "summary-group", otherAttributes = " ${calculateDataAttributes(platforms)}") { + block(platforms) + } + } } class KotlinWebsiteHtmlFormatService @Inject constructor( diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 764fd50e..647f2dfb 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -129,6 +129,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, block(platforms) } + open fun appendAsSummaryGroup(platforms: Set, block: (Set) -> Unit) { + appendAsPlatformDependentBlock(platforms, block) + } + open fun appendSymbol(text: String) { appendText(text) } @@ -787,21 +791,20 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, ) { for(summary in summarized.data) { - - - appendAsPlatformDependentBlock(summary.platforms) { + appendAsSummaryGroup(summary.platforms) { if (summarized.platformPlacement == Summarized.PlatformPlacement.Summary) { appendPlatforms(summary.platforms) } appendContent(summary.content) appendSoftLineBreak() + for (signature in summary.signatures) { + appendSignatures( + signature, + summarized.platformPlacement == Summarized.PlatformPlacement.Signature + ) + } } - for (signature in summary.signatures) { - appendSignatures( - signature, - summarized.platformPlacement == Summarized.PlatformPlacement.Signature - ) - } + } } -- cgit From 5719e5c5f7d90aa606421381a0e4e4ffbf1b9066 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 04:09:09 +0300 Subject: Append notices platforms as header instead of tags --- .../main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 15 +++++++++++---- core/src/main/kotlin/Formats/StructuredFormatService.kt | 11 +++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 65c93e72..9ffefcab 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -125,10 +125,6 @@ open class KotlinWebsiteHtmlOutputBuilder( } private fun calculatePlatforms(platforms: Set): Map> { - - fun String.isKotlinVersion() = this.startsWith("Kotlin") - fun String.isJREVersion() = this.startsWith("JRE", ignoreCase=true) - val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ") val jreVersion = platforms.filter(String::isJREVersion).min()?.takeUnless { it.endsWith("6") } val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } @@ -176,6 +172,13 @@ open class KotlinWebsiteHtmlOutputBuilder( to.append(" / ") } + override fun appendPlatformsAsText(platforms: Set) { + appendHeader(5) { + to.append("For ") + platforms.filterNot { it.isJREVersion() }.joinTo(to) + } + } + override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) { div(to, "sample") { appendBlockCode(language) { @@ -226,3 +229,7 @@ class KotlinWebsiteHtmlFormatService @Inject constructor( override fun createOutputBuilder(to: StringBuilder, location: Location) = KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) } + + +private fun String.isKotlinVersion() = this.startsWith("Kotlin") +private fun String.isJREVersion() = this.startsWith("JRE", ignoreCase=true) \ No newline at end of file diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 647f2dfb..4496d652 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -281,6 +281,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTableRow(block) } + protected open fun appendPlatformsAsText(platforms: Set) { + if (platforms.isNotEmpty()) { + appendLine() + appendText(platforms.joinToString(prefix = "(", postfix = ")")) + } + } + protected open fun appendPlatforms(platforms: Set) { if (platforms.isNotEmpty()) { appendLine() @@ -388,7 +395,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (content.isEmpty()) continue appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> if (groupByContent.count { !it.key.isEmpty() } > 1) { - appendPlatforms(platforms) + appendPlatformsAsText(platforms) } appendContent(content.summary) content.appendDescription() @@ -622,7 +629,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (content.isEmpty()) continue appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> if (groupByContent.keys.count { !it.isEmpty() } > 1) { - appendPlatforms(platforms) + appendPlatformsAsText(platforms) } appendContent(content) } -- cgit From be3e435500246b971ac12ffccad9d11417f4717c Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 04:16:47 +0300 Subject: Wrap node's own description on full page into block --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 7 ++++++ .../main/kotlin/Formats/StructuredFormatService.kt | 27 ++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 9ffefcab..c412b34e 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -168,6 +168,13 @@ open class KotlinWebsiteHtmlOutputBuilder( } } + override fun appendAsNodeDescription(platforms: Set, block: () -> Unit) { + div(to, "node-page-main", otherAttributes = " ${calculateDataAttributes(platforms)}") { + block() + } + + } + override fun appendBreadcrumbSeparator() { to.append(" / ") } diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 4496d652..67a2f293 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -145,6 +145,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendText(text) } + open fun appendAsNodeDescription(platforms: Set, block: () -> Unit) { + block() + } + fun appendEntity(text: String) { to.append(text) } @@ -361,7 +365,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } if (breakdownBySummary.size == 1) { - formatOverloadGroup(breakdownBySummary.values.single(), isSingleNode) + val node = breakdownBySummary.values.single() + appendAsNodeDescription(effectivePlatformAndVersion(node)) { + formatOverloadGroup(node, isSingleNode) + } } else { for ((_, items) in breakdownBySummary) { appendAsOverloadGroup(to, effectivePlatformAndVersion(items)) { @@ -622,16 +629,18 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendLine() appendHeader { appendText(node.name) } - renderGroupNode(node, true) + appendAsNodeDescription(effectivePlatformAndVersion(node)) { + renderGroupNode(node, true) - val groupByContent = node.origins.groupBy { it.content } - for ((content, origins) in groupByContent) { - if (content.isEmpty()) continue - appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> - if (groupByContent.keys.count { !it.isEmpty() } > 1) { - appendPlatformsAsText(platforms) + val groupByContent = node.origins.groupBy { it.content } + for ((content, origins) in groupByContent) { + if (content.isEmpty()) continue + appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> + if (groupByContent.keys.count { !it.isEmpty() } > 1) { + appendPlatformsAsText(platforms) + } + appendContent(content) } - appendContent(content) } } -- cgit From aee7a8e76f2d593a6ba73db1f475acca68b7d693 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 04:18:03 +0300 Subject: Don't show platforms on package and module pages --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 67a2f293..e12a7923 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -344,7 +344,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val packageName = if (singleNode.name.isEmpty()) "" else singleNode.name appendHeader(2) { appendText("Package $packageName") } } - singleNode.appendPlatforms() appendContent(singleNode.content) } else { val breakdownByName = nodes.groupBy { node -> node.name } @@ -509,18 +508,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - private fun DocumentationNode.appendPlatforms() { - val platforms = actualPlatforms - if (platforms.isEmpty()) return - appendParagraph { - appendStrong { to.append("WTF: Platform and version requirements:") } - to.append(" " + platforms.joinToString()) - } - } - - val DocumentationNode.actualPlatforms: Collection - get() = effectivePlatformAndVersion(listOf(this)) // protected fun platformsOfItems(items: List): Set { -- cgit From 7b1020e2d413602a36b69071385e6b4f406961f3 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 04:20:22 +0300 Subject: Render platforms on overload group level if platforms are similar --- .../main/kotlin/Formats/StructuredFormatService.kt | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index e12a7923..8b66f187 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -378,13 +378,24 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } private fun formatOverloadGroup(items: List, isSingleNode: Boolean = false) { + + val platformsPerGroup = sameVersionAndPlatforms( + items.flatMap { if (it.kind == NodeKind.GroupNode) it.origins else listOf(it) } + .map { effectivePlatformAndVersion(it) } + ) + + if (platformsPerGroup) { + appendAsPlatformDependentBlock(effectivePlatformAndVersion(items)) { platforms -> + appendPlatforms(platforms) + } + } for ((index, item) in items.withIndex()) { if (index > 0) appendLine() if (item.kind == NodeKind.GroupNode) { - renderGroupNode(item, isSingleNode) + renderGroupNode(item, isSingleNode, !platformsPerGroup) } else { - renderSimpleNode(item, isSingleNode) + renderSimpleNode(item, isSingleNode, !platformsPerGroup) } } @@ -419,7 +430,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } - fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean) { + fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) { appendAsPlatformDependentBlock(effectivePlatformAndVersion(listOf(item))) { platforms -> // TODO: use summarizesignatures val rendered = languageService.render(item) @@ -427,7 +438,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (item.kind !in NodeKind.classLike || !isSingleNode) appendAnchor(it.name) } - appendPlatforms(platforms) + if (withPlatforms) { + appendPlatforms(platforms) + } appendAsSignature(rendered) { appendCode { appendContent(rendered) } item.appendSourceLink() @@ -437,7 +450,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean) { + fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) { // TODO: use summarizesignatures val groupBySignature = item.origins.groupBy { languageService.render(it) @@ -451,7 +464,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendAnchor(it.name) } - appendPlatforms(platforms) + if (withPlatforms) { + appendPlatforms(platforms) + } appendAsSignature(sign) { appendCode { appendContent(sign) } -- cgit From 3824b7d2a93711e98dd28e4a6371449d17f9483a Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 04:51:49 +0300 Subject: Suppress `external` modifier as it is implementation detail --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 5b565464..ba67d93d 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -198,7 +198,7 @@ class KotlinLanguageService : CommonLanguageService() { nowrap: Boolean ) { when (node.name) { - "final", "public", "var", "expect", "actual" -> { + "final", "public", "var", "expect", "actual", "external" -> { } else -> { if (node.name !in fullOnlyModifiers || renderMode == RenderMode.FULL) { -- cgit From c795ce373c20b9279d7de9e23202e0eab0eb1409 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 04:53:49 +0300 Subject: Show inline modifier only if fun has lambda, otherwise it is impl detail --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 580ffb05..d300cf4d 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -7,6 +7,7 @@ import com.intellij.psi.PsiJavaFile import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.coroutines.hasFunctionOrSuspendFunctionType import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor @@ -81,7 +82,7 @@ class DocumentationBuilder val knownModifiers = setOf( KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.INTERNAL_KEYWORD, KtTokens.PRIVATE_KEYWORD, KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.ABSTRACT_KEYWORD, KtTokens.SEALED_KEYWORD, - KtTokens.OVERRIDE_KEYWORD) + KtTokens.OVERRIDE_KEYWORD, KtTokens.INLINE_KEYWORD) fun link(node: DocumentationNode, descriptor: DeclarationDescriptor, kind: RefKind) { refGraph.link(node, descriptor.signature(), kind) @@ -139,6 +140,13 @@ class DocumentationBuilder appendTextNode(modifier, NodeKind.Modifier) } + fun DocumentationNode.appendInline(descriptor: DeclarationDescriptor, psi: KtModifierListOwner) { + if (!psi.hasModifier(KtTokens.INLINE_KEYWORD)) return + if (descriptor is FunctionDescriptor + && descriptor.valueParameters.none { it.hasFunctionOrSuspendFunctionType }) return + appendTextNode(KtTokens.INLINE_KEYWORD.value, NodeKind.Modifier) + } + fun DocumentationNode.appendVisibility(descriptor: DeclarationDescriptorWithVisibility) { val modifier = descriptor.visibility.normalize().displayName appendTextNode(modifier, NodeKind.Modifier) @@ -283,6 +291,7 @@ class DocumentationBuilder fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return + appendInline(descriptor, psi) KtTokens.MODIFIER_KEYWORDS_ARRAY.filter { it !in knownModifiers }.forEach { if (psi.hasModifier(it)) { appendTextNode(it.value, NodeKind.Modifier) -- cgit From 7d4e133fa46b9ab358472398ae03cbefbf49d9e3 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 07:59:04 +0300 Subject: Correctly lookup summary for group nodes --- core/src/main/kotlin/Model/DocumentationNode.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 5607c6d3..84f9a453 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -77,7 +77,10 @@ open class DocumentationNode(val name: String, private set val summary: ContentNode get() = when (kind) { - NodeKind.GroupNode -> this.origins.first().summary + NodeKind.GroupNode -> this.origins + .map { it.content } + .firstOrNull { !it.isEmpty() } + ?.summary ?: ContentEmpty else -> content.summary } -- cgit From 0370d016c95761b57f13b007cd8c2494601a1539 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 08:01:20 +0300 Subject: Introduce per-pass sinceKotlin --- core/src/main/kotlin/Generation/configurationImpl.kt | 3 ++- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 15 +++++++++++++++ .../src/main/kotlin/org/jetbrains/dokka/configuration.kt | 1 + runners/ant/src/main/kotlin/ant/dokka.kt | 2 ++ runners/cli/src/main/kotlin/cli/main.kt | 6 ++++++ 5 files changed, 26 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 2aa0e0d7..61f3f902 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -63,7 +63,8 @@ class PassConfigurationImpl ( override val suppressedFiles: List = listOf(), override val collectInheritedExtensionsFromLibraries: Boolean = false, override val analysisPlatform: Platform = Platform.DEFAULT, - override val targets: List = listOf() + override val targets: List = listOf(), + override val sinceKotlin: String = "1.0" ): DokkaConfiguration.PassConfiguration { private val defaultLinks = run { val links = mutableListOf() diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index d300cf4d..e003c2e7 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -289,6 +289,11 @@ class DocumentationBuilder sinceKotlin = kotlinVersion } + fun DocumentationNode.appendDefaultSinceKotlin() { + println("setting default sk ${passConfiguration.sinceKotlin} for $this") + sinceKotlin = passConfiguration.sinceKotlin + } + fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return appendInline(descriptor, psi) @@ -590,6 +595,7 @@ class DocumentationBuilder val node = nodeForDescriptor(this, NodeKind.TypeAlias) if (!external) { + node.appendDefaultSinceKotlin() node.appendAnnotations(this) } node.appendModifiers(this) @@ -627,6 +633,7 @@ class DocumentationBuilder for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) { node.appendClassMember(descriptor, inheritedLinkKind, extraModifier) } + node.appendDefaultSinceKotlin() node.appendAnnotations(this) } node.appendModifiers(this) @@ -687,6 +694,7 @@ class DocumentationBuilder val node = nodeForDescriptor(this, NodeKind.Constructor) node.appendInPageChildren(valueParameters, RefKind.Detail) node.appendDefaultPlatforms(this) + node.appendDefaultSinceKotlin() register(this, node) return node } @@ -711,6 +719,9 @@ class DocumentationBuilder extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) } node.appendInPageChildren(valueParameters, RefKind.Detail) node.appendType(returnType) + if (!external) { + node.appendDefaultSinceKotlin() + } node.appendAnnotations(this) node.appendModifiers(this) if (!external) { @@ -748,6 +759,9 @@ class DocumentationBuilder node.appendInPageChildren(typeParameters, RefKind.Detail) extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) } node.appendType(returnType) + if (!external) { + node.appendDefaultSinceKotlin() + } node.appendAnnotations(this) node.appendModifiers(this) if (!external) { @@ -817,6 +831,7 @@ class DocumentationBuilder } } } + node.appendDefaultSinceKotlin() node.appendAnnotations(this) node.appendModifiers(this) if (varargElementType != null && node.details(NodeKind.Modifier).none { it.name == "vararg" }) { diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 7eb1d3f2..12efd252 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -71,6 +71,7 @@ interface DokkaConfiguration { val collectInheritedExtensionsFromLibraries: Boolean val analysisPlatform: Platform val targets: List + val sinceKotlin: String } interface SourceRoot { diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 023b4b7f..5a4111e8 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -64,6 +64,8 @@ class AntPassConfig(task: Task) : DokkaConfiguration.PassConfiguration { get() = buildTargets.filter { it.value != "" } .map { it.value } + override var sinceKotlin: String = "1.0" + private val samplesPath: Path by lazy { Path(task.project) } private val includesPath: Path by lazy { Path(task.project) } private val buildClassPath: Path by lazy { Path(task.project) } diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index 655dfde5..d67a9875 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -120,6 +120,12 @@ class Arguments(val parser: DokkaArgumentsParser) : DokkaConfiguration.PassConfi "" ) + override val sinceKotlin: String by parser.stringOption( + listOf("-sinceKotlin"), + "Kotlin Api version to use as base version, if none specified", + "1.0" + ) + override val collectInheritedExtensionsFromLibraries: Boolean by parser.singleFlag( listOf("-collectInheritedExtensionsFromLibraries"), "Search for applicable extensions in libraries") -- cgit From eca90bfabc21a89b0d9ce40d2590c9383623ab79 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 08:02:17 +0300 Subject: Track sinceKotlin per platform and other attributes as well --- .../kotlin/Formats/KotlinWebsiteFormatService.kt | 10 +- .../Formats/KotlinWebsiteHtmlFormatService.kt | 63 ++++++------ .../main/kotlin/Formats/StructuredFormatService.kt | 106 ++++++++++----------- 3 files changed, 87 insertions(+), 92 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt index a98002d4..51ceb47e 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt @@ -57,8 +57,8 @@ open class KotlinWebsiteOutputBuilder( } } - override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set, block: () -> Unit) { - div(to, "overload-group", calculateDataAttributes(platforms), true) { + override fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) { + div(to, "overload-group", calculateDataAttributes(platforms.keys), true) { ensureParagraph() block() ensureParagraph() @@ -159,14 +159,14 @@ open class KotlinWebsiteOutputBuilder( return "$platformsAttr$kotlinVersionAttr$jreVersionAttr" } - override fun appendIndexRow(platforms: Set, block: () -> Unit) { + override fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) { if (platforms.isNotEmpty()) - wrap("", "", block) + wrap("", "", block) else appendTableRow(block) } - override fun appendPlatforms(platforms: Set) { + override fun appendPlatforms(platforms: PlatformsData) { } } diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index c412b34e..b12075fb 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -3,7 +3,6 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named import org.jetbrains.dokka.Utilities.impliedPlatformsName -import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty import java.io.File @@ -60,7 +59,7 @@ open class KotlinWebsiteHtmlOutputBuilder( } } - override fun appendAsOverloadGroup(to: StringBuilder, platforms: Set, block: () -> Unit) { + override fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) { div(to, "overload-group", calculateDataAttributes(platforms)) { block() } @@ -124,27 +123,29 @@ open class KotlinWebsiteHtmlOutputBuilder( else -> "identifier" } - private fun calculatePlatforms(platforms: Set): Map> { - val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ") - val jreVersion = platforms.filter(String::isJREVersion).min()?.takeUnless { it.endsWith("6") } - val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } - return mapOf( - "platform" to targetPlatforms, - "kotlin-version" to listOfNotNull(kotlinVersion), - "jre-version" to listOfNotNull(jreVersion) + private data class PlatformsForElement( + val platformToVersion: Map + ) + + private fun calculatePlatforms(platforms: PlatformsData): PlatformsForElement { + //val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion)?.removePrefix("Kotlin ") + val jreVersion = platforms.keys.filter(String::isJREVersion).min()?.takeUnless { it.endsWith("6") } + val targetPlatforms = platforms.filterNot { it.key.isJREVersion() } + + listOfNotNull(jreVersion?.let { it to platforms[it]!! }) + + return PlatformsForElement( + targetPlatforms.mapValues { (_, nodes) -> effectiveSinceKotlinForNodes(nodes) } ) } - private fun calculateDataAttributes(platforms: Set): String { - val platformsByKind = calculatePlatforms(platforms) - return platformsByKind - .entries.filterNot { it.value.isEmpty() } - .joinToString(separator = " ") { (kind, values) -> - "data-$kind=\"${values.joinToString()}\"" - } + private fun calculateDataAttributes(platforms: PlatformsData): String { + val platformToVersion = calculatePlatforms(platforms).platformToVersion + val (platformNames, versions) = platformToVersion.toList().unzip() + return "data-platform=\"${platformNames.joinToString()}\" "+ + "data-kotlin-version=\"${versions.joinToString()}\"" } - override fun appendIndexRow(platforms: Set, block: () -> Unit) { + override fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) { // if (platforms.isNotEmpty()) // wrap("", "", block) // else @@ -154,21 +155,23 @@ open class KotlinWebsiteHtmlOutputBuilder( } } - override fun appendPlatforms(platforms: Set) { - val platformsToKind = calculatePlatforms(platforms) + override fun appendPlatforms(platforms: PlatformsData) { + val platformToVersion = calculatePlatforms(platforms).platformToVersion div(to, "tags") { div(to, "spacer") {} - platformsToKind.entries.forEach { (kind, values) -> - values.forEach { value -> - div(to, "tags__tag $kind tag-value-$value") { - to.append(value) - } + platformToVersion.entries.forEach { (platform, version) -> + div(to, "tags__tag platform tag-value-$platform", + otherAttributes = " data-tag-version=\"$version\"") { + to.append(platform) } } + div(to, "tags__tag kotlin-version") { + to.append(mergeVersions(platformToVersion.values.toList())) + } } } - override fun appendAsNodeDescription(platforms: Set, block: () -> Unit) { + override fun appendAsNodeDescription(platforms: PlatformsData, block: () -> Unit) { div(to, "node-page-main", otherAttributes = " ${calculateDataAttributes(platforms)}") { block() } @@ -179,10 +182,10 @@ open class KotlinWebsiteHtmlOutputBuilder( to.append(" / ") } - override fun appendPlatformsAsText(platforms: Set) { + override fun appendPlatformsAsText(platforms: PlatformsData) { appendHeader(5) { to.append("For ") - platforms.filterNot { it.isJREVersion() }.joinTo(to) + platforms.keys.filterNot { it.isJREVersion() }.joinTo(to) } } @@ -208,7 +211,7 @@ open class KotlinWebsiteHtmlOutputBuilder( } } - override fun appendAsPlatformDependentBlock(platforms: Set, block: (Set) -> Unit) { + override fun appendAsPlatformDependentBlock(platforms: PlatformsData, block: (PlatformsData) -> Unit) { if (platforms.isNotEmpty()) wrap("
", "
") { block(platforms) @@ -217,7 +220,7 @@ open class KotlinWebsiteHtmlOutputBuilder( block(platforms) } - override fun appendAsSummaryGroup(platforms: Set, block: (Set) -> Unit) { + override fun appendAsSummaryGroup(platforms: PlatformsData, block: (PlatformsData) -> Unit) { div(to, "summary-group", otherAttributes = " ${calculateDataAttributes(platforms)}") { block(platforms) } diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 8b66f187..98414695 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka import org.jetbrains.dokka.LanguageService.RenderMode +import org.jetbrains.kotlin.utils.keysToMap import java.util.* data class FormatLink(val text: String, val href: String) @@ -21,11 +22,11 @@ private data class Summarized( ) data class SummarizedNodes(val content: ContentNode, val nodes: List) { - val platforms = effectivePlatformAndVersion(nodes) + val platforms = effectivePlatformsForMembers(nodes) } data class SummarizedBySummary(val content: ContentNode, val signatures: List) { - val platforms = effectivePlatformAndVersion(signatures.flatMap { it.nodes }) - val platformsOnSignature = !sameVersionAndPlatforms(signatures.map { it.platforms }) + val platforms = effectivePlatformsForMembers(signatures.flatMap { it.nodes }) + val platformsOnSignature = !samePlatforms(signatures.map { it.platforms }) } @@ -33,13 +34,13 @@ private data class Summarized( if (data.any { it.platformsOnSignature }) { return PlatformPlacement.Signature } - if (sameVersionAndPlatforms(data.map { it.platforms })) { + if (samePlatforms(data.map { it.platforms })) { return PlatformPlacement.Row } return PlatformPlacement.Summary } val platformPlacement: PlatformPlacement = computePlatformLevel() - val platforms = effectivePlatformAndVersion(data.flatMap { it.signatures.flatMap { it.nodes } }) + val platforms = effectivePlatformsForMembers(data.flatMap { it.signatures.flatMap { it.nodes } }) enum class PlatformPlacement { @@ -125,11 +126,11 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - open fun appendAsPlatformDependentBlock(platforms: Set, block: (Set) -> Unit) { + open fun appendAsPlatformDependentBlock(platforms: PlatformsData, block: (PlatformsData) -> Unit) { block(platforms) } - open fun appendAsSummaryGroup(platforms: Set, block: (Set) -> Unit) { + open fun appendAsSummaryGroup(platforms: PlatformsData, block: (PlatformsData) -> Unit) { appendAsPlatformDependentBlock(platforms, block) } @@ -145,7 +146,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendText(text) } - open fun appendAsNodeDescription(platforms: Set, block: () -> Unit) { + open fun appendAsNodeDescription(platforms: PlatformsData, block: () -> Unit) { block() } @@ -277,25 +278,25 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, block() } - protected open fun appendAsOverloadGroup(to: StringBuilder, platforms: Set, block: () -> Unit) { + protected open fun appendAsOverloadGroup(to: StringBuilder, platforms: PlatformsData, block: () -> Unit) { block() } - protected open fun appendIndexRow(platforms: Set, block: () -> Unit) { + protected open fun appendIndexRow(platforms: PlatformsData, block: () -> Unit) { appendTableRow(block) } - protected open fun appendPlatformsAsText(platforms: Set) { + protected open fun appendPlatformsAsText(platforms: PlatformsData) { if (platforms.isNotEmpty()) { appendLine() - appendText(platforms.joinToString(prefix = "(", postfix = ")")) + appendText(platforms.keys.joinToString(prefix = "(", postfix = ")")) } } - protected open fun appendPlatforms(platforms: Set) { + protected open fun appendPlatforms(platforms: PlatformsData) { if (platforms.isNotEmpty()) { appendLine() - appendText(platforms.joinToString(prefix = "(", postfix = ")")) + appendText(platforms.keys.joinToString(prefix = "(", postfix = ")")) } } @@ -358,19 +359,19 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, private fun appendDocumentation(overloads: Iterable, isSingleNode: Boolean) { val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> when (node.kind) { - NodeKind.GroupNode -> node.origins.first().content + NodeKind.GroupNode -> node.origins.map { it.content } else -> node.content } } if (breakdownBySummary.size == 1) { val node = breakdownBySummary.values.single() - appendAsNodeDescription(effectivePlatformAndVersion(node)) { + appendAsNodeDescription(effectivePlatformsForMembers(node)) { formatOverloadGroup(node, isSingleNode) } } else { for ((_, items) in breakdownBySummary) { - appendAsOverloadGroup(to, effectivePlatformAndVersion(items)) { + appendAsOverloadGroup(to, effectivePlatformsForMembers(items)) { formatOverloadGroup(items) } } @@ -379,13 +380,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, private fun formatOverloadGroup(items: List, isSingleNode: Boolean = false) { - val platformsPerGroup = sameVersionAndPlatforms( + val platformsPerGroup = samePlatforms( items.flatMap { if (it.kind == NodeKind.GroupNode) it.origins else listOf(it) } - .map { effectivePlatformAndVersion(it) } + .map { effectivePlatformsForNode(it) } ) if (platformsPerGroup) { - appendAsPlatformDependentBlock(effectivePlatformAndVersion(items)) { platforms -> + appendAsPlatformDependentBlock(effectivePlatformsForMembers(items)) { platforms -> appendPlatforms(platforms) } } @@ -411,6 +412,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, for ((content, origins) in groupByContent) { if (content.isEmpty()) continue appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> + println("FOG_GN_MULTI(${groupByContent.count { !it.key.isEmpty() }}):" + item.path.joinToString(" > ")) if (groupByContent.count { !it.key.isEmpty() } > 1) { appendPlatformsAsText(platforms) } @@ -431,7 +433,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean, withPlatforms: Boolean = true) { - appendAsPlatformDependentBlock(effectivePlatformAndVersion(listOf(item))) { platforms -> + appendAsPlatformDependentBlock(effectivePlatformsForMembers(listOf(item))) { platforms -> // TODO: use summarizesignatures val rendered = languageService.render(item) item.detailOrNull(NodeKind.Signature)?.let { @@ -457,7 +459,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } for ((sign, nodes) in groupBySignature) { - appendAsPlatformDependentBlock(effectivePlatformAndVersion(nodes)) { platforms -> + appendAsPlatformDependentBlock(effectivePlatformsForMembers(nodes)) { platforms -> val first = nodes.first() first.detailOrNull(NodeKind.Signature)?.let { if (item.kind !in NodeKind.classLike || !isSingleNode) @@ -632,7 +634,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendLine() appendHeader { appendText(node.name) } - appendAsNodeDescription(effectivePlatformAndVersion(node)) { + appendAsNodeDescription(effectivePlatformsForNode(node)) { renderGroupNode(node, true) val groupByContent = node.origins.groupBy { it.content } @@ -747,7 +749,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTable("Name", "Summary") { appendTableBody { for ((memberLocation, members) in membersMap) { - val platforms = effectivePlatformAndVersion(members) + val platforms = effectivePlatformsForMembers(members) // val platforms = if (platformsBasedOnMembers) // members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms // else @@ -915,32 +917,32 @@ abstract class StructuredFormatService(val generator: NodeLocationAwareGenerator } +typealias PlatformsData = Map> -fun memberPlatforms(node: DocumentationNode): Sequence> { +fun memberPlatforms(node: DocumentationNode): PlatformsData { val members = when { node.kind == NodeKind.GroupNode -> node.origins else -> node.members } - return members.asSequence() - .map { effectivePlatformsForNode(it) } + return members.map(::effectivePlatformsForNode).fold(mapOf(), ::mergePlatforms) } -fun effectivePlatformsForNode(node: DocumentationNode): Set { - val platforms = - sequenceOf(node.platforms.toSet()) + memberPlatforms(node) - - - // Calculating common platforms for items - return platforms.reduce { result, platformsOfItem -> - result.union(platformsOfItem) +fun mergePlatforms(a: PlatformsData, b: PlatformsData): PlatformsData { + val mutable = a.toMutableMap() + b.forEach { (name, declarations) -> + mutable.merge(name, declarations) { a, b -> a.union(b) } } + return mutable } -fun effectivePlatformsForMembers(nodes: Collection): Set { - return nodes.map { effectivePlatformsForNode(it) }.reduce { acc, set -> - acc.union(set) - } +fun effectivePlatformsForNode(node: DocumentationNode): PlatformsData { + val platforms = node.platforms + memberPlatforms(node).keys + return platforms.keysToMap { setOf(node) } +} + +fun effectivePlatformsForMembers(nodes: Collection): PlatformsData { + return nodes.map { effectivePlatformsForNode(it) }.reduce(::mergePlatforms) } fun mergeVersions(kotlinVersions: List): String { @@ -954,29 +956,19 @@ fun effectiveSinceKotlinForNode(node: DocumentationNode, baseVersion: String = " node.kind in NodeKind.memberLike -> emptyList() else -> node.members } + val newBase = node.sinceKotlin ?: baseVersion + val memberVersion = if (members.isNotEmpty()) effectiveSinceKotlinForNodes(members, newBase) else newBase - val nodeVersion = node.sinceKotlin ?: baseVersion - val memberVersion = if (members.isNotEmpty()) effectiveSinceKotlinForNodes(members, nodeVersion) else nodeVersion - - return mergeVersions(listOf(memberVersion, nodeVersion)) + return node.sinceKotlin ?: memberVersion } fun effectiveSinceKotlinForNodes(nodes: Collection, baseVersion: String = "1.0"): String { - return mergeVersions(nodes.map { effectiveSinceKotlinForNode(it, baseVersion) }) + val map = nodes.map { effectiveSinceKotlinForNode(it, baseVersion) } + return mergeVersions(map) } -fun sinceKotlinAsPlatform(version: String): String = "Kotlin $version" - - -fun effectivePlatformAndVersion(nodes: Collection, baseVersion: String = "1.0"): Set { - return effectivePlatformsForMembers(nodes) + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(nodes, baseVersion)) -} - -fun effectivePlatformAndVersion(node: DocumentationNode, baseVersion: String = "1.0"): Set { - return effectivePlatformsForNode(node) + sinceKotlinAsPlatform(effectiveSinceKotlinForNode(node, baseVersion)) -} +fun samePlatforms(platformsPerNode: Collection): Boolean { -fun sameVersionAndPlatforms(platformsPerNode: Collection>): Boolean { - val first = platformsPerNode.firstOrNull() ?: return true - return platformsPerNode.all { it == first } + val first = platformsPerNode.firstOrNull()?.keys ?: return true + return platformsPerNode.all { it.keys == first } } \ No newline at end of file -- cgit From 004df26993d479022b59353b55f31690b94f37cf Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 20:47:59 +0300 Subject: Remove debug print --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e003c2e7..b3e7c3aa 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -290,7 +290,6 @@ class DocumentationBuilder } fun DocumentationNode.appendDefaultSinceKotlin() { - println("setting default sk ${passConfiguration.sinceKotlin} for $this") sinceKotlin = passConfiguration.sinceKotlin } -- cgit From 5c7fd99bc38bdbd681d273b760868705341c5594 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 21:32:09 +0300 Subject: Fix module content lost on merging --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index 54485930..fc2bf0fa 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -181,6 +181,7 @@ class DocumentationMerger( fun merge(): DocumentationModule { val mergedDocumentationModule = DocumentationModule( name = documentationModules.first().name, + content = documentationModules.first().content, nodeRefGraph = producedNodeRefGraph ) -- cgit From 810fce90353f044de1531a2cf5b340ff7732b083 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 22:25:11 +0300 Subject: Use headers instead of paragraphs for section declaration block title --- .../main/kotlin/Formats/StructuredFormatService.kt | 28 ++++++++++------------ 1 file changed, 12 insertions(+), 16 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 98414695..282ea7d6 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -763,7 +763,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (summarized.platformPlacement == Summarized.PlatformPlacement.Row) { appendPlatforms(platforms) } - appendParagraph { + appendHeader(level = 4) { appendLink(memberLocation) // if (members.singleOrNull()?.kind != NodeKind.ExternalClass) { // appendPlatforms(platforms) @@ -871,27 +871,23 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTable("Name", "Summary") { appendTableBody { for (type in node.members) { - appendTableRow { - appendTableCell { + val platforms = effectivePlatformsForNode(type) + appendIndexRow(platforms) { + appendPlatforms(platforms) + appendHeader(level = 5) { appendLink(link(node, type) { if (it.kind == NodeKind.ExternalClass) it.name else it.qualifiedName() }) - if (type.kind == NodeKind.ExternalClass) { - val packageName = type.owner?.name - if (packageName != null) { - appendText(" (extensions in package $packageName)") - } - } } - appendTableCell { - val summary = if (type.isClassLikeGroupNode()) { - type.origins.first().summary - } else { - type.summary - } - appendContent(summary) + if (type.kind == NodeKind.ExternalClass) { + val packageName = type.owner?.name + if (packageName != null) { + appendText(" (extensions in package $packageName)") + } } + + appendContent(type.summary) } } } -- cgit From 234169e34e4362e598e1cecb50f116c8c1ea74d2 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 23:49:36 +0300 Subject: Fix platform merging on group by signature in overload group --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 282ea7d6..f989fad6 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -381,8 +381,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, private fun formatOverloadGroup(items: List, isSingleNode: Boolean = false) { val platformsPerGroup = samePlatforms( - items.flatMap { if (it.kind == NodeKind.GroupNode) it.origins else listOf(it) } - .map { effectivePlatformsForNode(it) } + items.flatMap { + if (it.kind == NodeKind.GroupNode) { + it.origins.groupBy { origin -> + languageService.render(origin) + }.values.map { origins -> effectivePlatformsForMembers(origins) } + } else { + listOf(effectivePlatformsForNode(it)) + } + } ) if (platformsPerGroup) { -- cgit From 76e3ec143e12f36d0fe8e6aaec37f7e26cea9a39 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 4 Oct 2018 06:29:13 +0300 Subject: Remove return type from signature to remain compatible --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index b3e7c3aa..3fb22589 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1067,7 +1067,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name -- cgit From 4e24de5649be49a186e67000b5cd0ddc415d0366 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 4 Oct 2018 06:30:00 +0300 Subject: Fix lost members of group nodes --- core/src/main/kotlin/Generation/DocumentationMerger.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index fc2bf0fa..b29c2915 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -148,7 +148,7 @@ class DocumentationMerger( // if nodes are classes, nested members should be also merged and // inserted at the same level with class - if (nodes.all { it.kind == NodeKind.Class }) { + if (nodes.all { it.kind in NodeKind.classLike }) { val members = nodes.flatMap { it.allReferences() }.filter { it.kind == RefKind.Member } val mergedMembers = mergeMemberReferences(groupNode, members) -- cgit From dd432c8283b9c4a4aa98ae79a5fa4cbc07ec63fd Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 4 Oct 2018 06:40:29 +0300 Subject: Add specialization instead of platform sub-duplication removal --- .../main/kotlin/Generation/DocumentationMerger.kt | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index b29c2915..f58d2f8e 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -127,12 +127,21 @@ class DocumentationMerger( singleNode.dropReferences { it.kind == RefKind.Owner } return singleNode } - val nodeWithMaxPlatforms = nodes.maxBy { it.platforms.size }!! - val maxPlatforms = nodeWithMaxPlatforms.platforms.toSet() - val notContained = nodes.filterNot { maxPlatforms.containsAll(it.platforms) } - val reducedDuplicates = listOf(nodeWithMaxPlatforms) + notContained - if (!reducedDuplicates.containsAll(nodes)) { - return mergeMembersWithEqualSignature(signature, reducedDuplicates) + + // Specialization processing + // Given (Common, JVM, JRE6, JS) and (JVM, JRE6) and (JVM, JRE7) + // Sorted: (JVM, JRE6), (JVM, JRE7), (Common, JVM, JRE6, JS) + // Should output: (JVM, JRE6), (JVM, JRE7), (Common, JS) + // Should not remove first platform + val nodesSortedByPlatformCount = nodes.sortedBy { it.platforms.size } + val allPlatforms = mutableSetOf() + nodesSortedByPlatformCount.forEach { node -> + node.platforms + .filterNot { allPlatforms.add(it) } + .filter { it != node.platforms.first() } + .forEach { platform -> + node.dropReferences { it.kind == RefKind.Platform && it.to.name == platform } + } } val groupNode = DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode) -- cgit From bf883d16819791f9ed66fda97560f5e2f02e7506 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 4 Oct 2018 06:42:59 +0300 Subject: Proper GroupNode members relocation condition --- core/src/main/kotlin/Formats/PackageListService.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/PackageListService.kt b/core/src/main/kotlin/Formats/PackageListService.kt index 7b68098e..e675d927 100644 --- a/core/src/main/kotlin/Formats/PackageListService.kt +++ b/core/src/main/kotlin/Formats/PackageListService.kt @@ -32,10 +32,13 @@ class DefaultPackageListService @Inject constructor( node.members.forEach { visit(it, relocated = true) } } NodeKind.GroupNode -> { - //only children of top-level GN records interesting for us, since link to top-level ones should point to GN - node.members.forEach { it.members.forEach { visit(it, relocated = true) } } - //record signature of GN as signature of type alias and class merged to GN, so link to it should point to GN - node.detailOrNull(NodeKind.Signature)?.let { visit(it, relocated = true) } + if (node.members.isNotEmpty()) { + // Only nodes only has single file is need to be relocated + // TypeAliases for example + node.origins + .filter { it.members.isEmpty() } + .forEach { visit(it, relocated = true) } + } } else -> { if (nodeKind in NodeKind.classLike || nodeKind in NodeKind.memberLike) { -- cgit From cbed7d1899481ec60256d9e26d47d75a3974f9ef Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 4 Oct 2018 06:43:27 +0300 Subject: Hacky sort platforms on display --- .../kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index b12075fb..3b2b2897 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -159,7 +159,9 @@ open class KotlinWebsiteHtmlOutputBuilder( val platformToVersion = calculatePlatforms(platforms).platformToVersion div(to, "tags") { div(to, "spacer") {} - platformToVersion.entries.forEach { (platform, version) -> + platformToVersion.entries.sortedBy { + platformSortWeight(it.key) + }.forEach { (platform, version) -> div(to, "tags__tag platform tag-value-$platform", otherAttributes = " data-tag-version=\"$version\"") { to.append(platform) @@ -184,8 +186,11 @@ open class KotlinWebsiteHtmlOutputBuilder( override fun appendPlatformsAsText(platforms: PlatformsData) { appendHeader(5) { - to.append("For ") - platforms.keys.filterNot { it.isJREVersion() }.joinTo(to) + val filtered = platforms.keys.filterNot { it.isJREVersion() }.sortedBy { platformSortWeight(it) } + if (filtered.isNotEmpty()) { + to.append("For ") + filtered.joinTo(to) + } } } @@ -225,6 +230,14 @@ open class KotlinWebsiteHtmlOutputBuilder( block(platforms) } } + + fun platformSortWeight(name: String) = when(name.toLowerCase()) { + "common" -> 0 + "jvm" -> 1 + "js" -> 3 + "native" -> 4 + else -> 2 // This is hack to support JRE/JUnit and so on + } } class KotlinWebsiteHtmlFormatService @Inject constructor( -- cgit From 712bb8ba9b146c769b84503e332fc449ff942141 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 4 Oct 2018 06:44:17 +0300 Subject: Take GroupNodes into account when computing node location --- .../main/kotlin/Formats/StructuredFormatService.kt | 75 ++++++++++++++-------- core/src/main/kotlin/Locations/Location.kt | 18 +++++- 2 files changed, 64 insertions(+), 29 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index f989fad6..33d26a93 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -55,8 +55,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val extension: String, impliedPlatforms: List) : FormattedOutputBuilder { - protected fun DocumentationNode.location() = generator.location(this) - protected fun wrap(prefix: String, suffix: String, body: () -> Unit) { to.append(prefix) body() @@ -209,7 +207,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, is ContentNodeLink -> { val node = content.node - val linkTo = if (node != null) locationHref(location, node) else "#" + val linkTo = if (node != null) locationHref(location, node, generator) else "#" appendLinkIfNotThisPage(linkTo, content) } is ContentExternalLink -> appendLinkIfNotThisPage(content.href, content) @@ -259,17 +257,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, extension: String, name: (DocumentationNode) -> String = DocumentationNode::name ): FormatLink = - FormatLink(name(to), from.location().relativePathTo(to.location())) - - - fun locationHref(from: Location, to: DocumentationNode): String { - val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to - if (topLevelPage != null) { - val signature = to.detailOrNull(NodeKind.Signature) - return from.relativePathTo(topLevelPage.location(), signature?.name ?: to.name) - } - return from.relativePathTo(to.location()) - } + FormatLink(name(to), generator.relativePathToLocation(from, to)) private fun DocumentationNode.isModuleOrPackage(): Boolean = kind == NodeKind.Module || kind == NodeKind.Package @@ -467,6 +455,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, for ((sign, nodes) in groupBySignature) { appendAsPlatformDependentBlock(effectivePlatformsForMembers(nodes)) { platforms -> + println("GNPM: ${platforms.toList().joinToString { "${it.first}->${it.second.map { it.path.joinToString(separator = ">") }}" }}") val first = nodes.first() first.detailOrNull(NodeKind.Signature)?.let { if (item.kind !in NodeKind.classLike || !isSingleNode) @@ -499,7 +488,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, overrides.forEach { appendParagraph { to.append("Overrides ") - val location = location().relativePathTo(it.location()) + val location = generator.relativePathToLocation(this, it) appendLink(FormatLink(it.owner!!.name + "." + it.name, location)) } @@ -533,8 +522,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } - - // protected fun platformsOfItems(items: List): Set { // val platforms = items.asSequence().map { // when (it.kind) { @@ -620,6 +607,29 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } } + + fun appendOriginsGroupByContent(node: DocumentationNode) { + require(node.kind == NodeKind.GroupNode) + val groupByContent = + node.origins.groupBy { it.content } + .mapValues { (_, origins) -> + effectivePlatformsForMembers(origins) + } + .filterNot { it.key.isEmpty() } + .toList() + .sortedByDescending { it.second.size } + + + for ((content, platforms) in groupByContent) { + appendAsPlatformDependentBlock(platforms) { + if (groupByContent.size > 1) { + appendPlatformsAsText(platforms) + } + appendContent(content.summary) + content.appendDescription() + } + } + } } inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false) : @@ -644,18 +654,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendAsNodeDescription(effectivePlatformsForNode(node)) { renderGroupNode(node, true) - val groupByContent = node.origins.groupBy { it.content } - for ((content, origins) in groupByContent) { - if (content.isEmpty()) continue - appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> - if (groupByContent.keys.count { !it.isEmpty() } > 1) { - appendPlatformsAsText(platforms) - } - appendContent(content) - } - } + appendOriginsGroupByContent(node) } + println("GN: ${node.path}") SectionsBuilder(node).build() } } @@ -925,6 +927,8 @@ typealias PlatformsData = Map> fun memberPlatforms(node: DocumentationNode): PlatformsData { val members = when { node.kind == NodeKind.GroupNode -> node.origins + node.kind in NodeKind.classLike -> emptyList() + node.kind in NodeKind.memberLike -> emptyList() else -> node.members } @@ -974,4 +978,21 @@ fun samePlatforms(platformsPerNode: Collection): Boolean { val first = platformsPerNode.firstOrNull()?.keys ?: return true return platformsPerNode.all { it.keys == first } +} + +fun locationHref( + from: Location, + to: DocumentationNode, + generator: NodeLocationAwareGenerator, + pathOnly: Boolean = false +): String { + val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to + if (topLevelPage != null) { + val signature = to.detailOrNull(NodeKind.Signature) + return from.relativePathTo( + generator.location(topLevelPage), + (signature?.name ?: to.name).takeUnless { pathOnly } + ) + } + return from.relativePathTo(generator.location(to)) } \ No newline at end of file diff --git a/core/src/main/kotlin/Locations/Location.kt b/core/src/main/kotlin/Locations/Location.kt index 4448fb99..ccefa6e3 100644 --- a/core/src/main/kotlin/Locations/Location.kt +++ b/core/src/main/kotlin/Locations/Location.kt @@ -26,7 +26,7 @@ data class FileLocation(val file: File) : Location { } val ownerFolder = file.parentFile!! val relativePath = ownerFolder.toPath().relativize(other.file.toPath()).toString().replace(File.separatorChar, '/') - return if (anchor == null) relativePath else relativePath + "#" + anchor + return if (anchor == null) relativePath else relativePath + "#" + anchor.urlEncoded() } } @@ -40,8 +40,22 @@ fun relativePathToNode(qualifiedName: List, hasMembers: Boolean): String } } +fun nodeActualQualifier(node: DocumentationNode): List { + val topLevelPage = node.references(RefKind.TopLevelPage).singleOrNull()?.to + if (topLevelPage != null) { + return nodeActualQualifier(topLevelPage) + } + return node.owner?.let { nodeActualQualifier(it) }.orEmpty() + node +} + +fun relativePathToNode(node: DocumentationNode): String { + val qualifier = nodeActualQualifier(node) + return relativePathToNode( + qualifier.map { it.name }, + qualifier.last().members.any() + ) +} -fun relativePathToNode(node: DocumentationNode) = relativePathToNode(node.path.map { it.name }, node.members.any()) fun identifierToFilename(path: String): String { if (path.isEmpty()) return "--root--" -- cgit From 15b408bb59546a65a9a4f3f47067b4fa174702be Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 15 Oct 2018 19:03:39 +0300 Subject: Fix sinceKotlin updating & default setting --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 4 +++- core/src/main/kotlin/Model/DocumentationNode.kt | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 3fb22589..205b44bd 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -290,7 +290,9 @@ class DocumentationBuilder } fun DocumentationNode.appendDefaultSinceKotlin() { - sinceKotlin = passConfiguration.sinceKotlin + if (sinceKotlin == null) { + sinceKotlin = passConfiguration.sinceKotlin + } } fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 84f9a453..617816b3 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -122,8 +122,10 @@ open class DocumentationNode(val name: String, var sinceKotlin: String? get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name set(value) { - if(value == null) return dropReferences { it.kind == RefKind.SinceKotlin } - append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) + dropReferences { it.kind == RefKind.SinceKotlin } + if (value != null) { + append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) + } } val supertypes: List -- cgit From a6ca887f1813777e7751f435b947095a20aafb58 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 18 Oct 2018 21:43:57 +0300 Subject: Remove debug logging --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 3 --- 1 file changed, 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 33d26a93..7b18fcb4 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -407,7 +407,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, for ((content, origins) in groupByContent) { if (content.isEmpty()) continue appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> - println("FOG_GN_MULTI(${groupByContent.count { !it.key.isEmpty() }}):" + item.path.joinToString(" > ")) if (groupByContent.count { !it.key.isEmpty() } > 1) { appendPlatformsAsText(platforms) } @@ -455,7 +454,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, for ((sign, nodes) in groupBySignature) { appendAsPlatformDependentBlock(effectivePlatformsForMembers(nodes)) { platforms -> - println("GNPM: ${platforms.toList().joinToString { "${it.first}->${it.second.map { it.path.joinToString(separator = ">") }}" }}") val first = nodes.first() first.detailOrNull(NodeKind.Signature)?.let { if (item.kind !in NodeKind.classLike || !isSingleNode) @@ -657,7 +655,6 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendOriginsGroupByContent(node) } - println("GN: ${node.path}") SectionsBuilder(node).build() } } -- cgit From 8a2e8f8ddc37a8c548a18714f2ad87fb511bcb82 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 18 Oct 2018 21:44:30 +0300 Subject: Add non-single documentation reporting --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 7b18fcb4..46c7f1af 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -404,6 +404,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, if (item.kind == NodeKind.GroupNode) { val groupByContent = item.origins.groupBy { it.content } + if (groupByContent.count { !it.key.isEmpty() } > 1) { + if (groupByContent.size > 1) println("[mult] Found ov diff: ${generator.location(item).path}") + } for ((content, origins) in groupByContent) { if (content.isEmpty()) continue appendAsPlatformDependentBlock(effectivePlatformsForMembers(origins)) { platforms -> @@ -617,7 +620,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, .toList() .sortedByDescending { it.second.size } - + if (groupByContent.size > 1) println("[mult] Found diff: ${generator.location(node).path}") for ((content, platforms) in groupByContent) { appendAsPlatformDependentBlock(platforms) { if (groupByContent.size > 1) { -- cgit From a9c91cb7dc54c1554be5cf8de90516c929c0c1cb Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 19 Oct 2018 18:14:36 +0300 Subject: Hard-code min compiler version for samples --- core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 3b2b2897..86bc9df9 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -195,7 +195,7 @@ open class KotlinWebsiteHtmlOutputBuilder( } override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) { - div(to, "sample") { + div(to, "sample", otherAttributes = " data-min-compiler-version=\"1.3\"") { appendBlockCode(language) { imports() wrap("\n\nfun main(args: Array) {".htmlEscape(), "}") { -- cgit