diff options
Diffstat (limited to 'core/src/main/kotlin')
11 files changed, 318 insertions, 308 deletions
diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index c816106e..f5705c89 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -3,8 +3,10 @@ package org.jetbrains.dokka import com.google.common.collect.ImmutableMap import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreModuleManager +import com.intellij.mock.MockApplication import com.intellij.mock.MockComponentManager import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.module.Module import com.intellij.openapi.module.ModuleManager @@ -16,16 +18,13 @@ import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope -import com.intellij.util.io.URLUtil -import org.jetbrains.dokka.Analysis.DokkaJsAnalyzerFacade -import org.jetbrains.dokka.Analysis.DokkaNativeAnalyzerFacade import org.jetbrains.kotlin.analyzer.* import org.jetbrains.kotlin.analyzer.common.CommonAnalysisParameters -import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade +import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices +import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns -import org.jetbrains.kotlin.caches.project.LibraryModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.config.ContentRoot @@ -42,20 +41,36 @@ import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext +import org.jetbrains.kotlin.context.withModule import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl +import org.jetbrains.kotlin.ide.konan.NativeLibraryInfo +import org.jetbrains.kotlin.ide.konan.analyzer.NativeResolverForModuleFactory +import org.jetbrains.kotlin.ide.konan.decompiler.KotlinNativeLoadingMetadataCache import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.js.config.JSConfigurationKeys -import org.jetbrains.kotlin.js.resolve.JsPlatform +import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices +import org.jetbrains.kotlin.js.resolve.JsResolverForModuleFactory +import org.jetbrains.kotlin.library.impl.createKotlinLibrary import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.CommonPlatforms +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.js.JsPlatforms +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms.unspecifiedJvmPlatform +import org.jetbrains.kotlin.platform.konan.KonanPlatforms import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics -import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform -import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform +import org.jetbrains.kotlin.resolve.jvm.JvmResolverForModuleFactory +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices +import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.types.KotlinType @@ -63,6 +78,9 @@ import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice import org.jetbrains.kotlin.util.slicedMap.WritableSlice import java.io.File +const val JAR_SEPARATOR = "!/" +const val KLIB_EXTENSION = "klib" + /** * Kotlin as a service entry point * @@ -86,65 +104,83 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl Platform.native -> EnvironmentConfigFiles.NATIVE_CONFIG_FILES Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES } + val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles) val projectComponentManager = environment.project as MockComponentManager - val projectFileIndex = CoreProjectFileIndex(environment.project, - environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) - + val projectFileIndex = CoreProjectFileIndex( + environment.project, + environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS) + ) val moduleManager = object : CoreModuleManager(environment.project, this) { override fun getModules(): Array<out Module> = arrayOf(projectFileIndex.module) } - CoreApplicationEnvironment.registerComponentInstance(projectComponentManager.picoContainer, - ModuleManager::class.java, moduleManager) + CoreApplicationEnvironment.registerComponentInstance( + projectComponentManager.picoContainer, + ModuleManager::class.java, moduleManager + ) Extensions.registerAreaClass("IDEA_MODULE", null) - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), - OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java) + CoreApplicationEnvironment.registerExtensionPoint( + Extensions.getRootArea(), + OrderEnumerationHandler.EP_NAME, OrderEnumerationHandler.Factory::class.java + ) + + projectComponentManager.registerService( + ProjectFileIndex::class.java, + projectFileIndex + ) + + projectComponentManager.registerService( + ProjectRootManager::class.java, + CoreProjectRootManager(projectFileIndex) + ) - projectComponentManager.registerService(ProjectFileIndex::class.java, - projectFileIndex) - projectComponentManager.registerService(ProjectRootManager::class.java, - CoreProjectRootManager(projectFileIndex)) return environment } - fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope = + private fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope = when (analysisPlatform) { Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - Platform.js, Platform.common, Platform.native -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + Platform.js, Platform.common, Platform.native -> GlobalSearchScope.filesScope( + project, + sourceFiles.map { it.virtualFile }.toSet() + ) } - fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair<DokkaResolutionFacade, DokkaResolutionFacade> { - - val projectContext = ProjectContext(environment.project) + val projectContext = ProjectContext(environment.project, "Dokka") val sourceFiles = environment.getSourceFiles() val targetPlatform = when (analysisPlatform) { - Platform.js -> JsPlatform - Platform.common -> TargetPlatform.Common - Platform.native -> KonanPlatform - Platform.jvm -> JvmPlatform + Platform.js -> JsPlatforms.defaultJsPlatform + Platform.common -> CommonPlatforms.defaultCommonPlatform + Platform.native -> KonanPlatforms.defaultKonanPlatform + Platform.jvm -> JvmPlatforms.defaultJvmPlatform } - val library = object : LibraryModuleInfo { - override val platform: TargetPlatform - get() = targetPlatform - - override fun getLibraryRoots(): Collection<String> { - return classpath.map { it.absolutePath } - } + val nativeLibraries = classpath.filter { it.extension == KLIB_EXTENSION } + .map { createNativeLibraryModuleInfo(it) } + val library = object : LibraryModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = + analysisPlatform.analyzerServices() override val name: Name = Name.special("<library>") + override val platform: TargetPlatform = targetPlatform override fun dependencies(): List<ModuleInfo> = listOf(this) + override fun getLibraryRoots(): Collection<String> = + classpath.filterNot { it.extension == KLIB_EXTENSION }.map { it.absolutePath } } + val module = object : ModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = + analysisPlatform.analyzerServices() override val name: Name = Name.special("<module>") - override fun dependencies(): List<ModuleInfo> = listOf(this, library) + override val platform: TargetPlatform = targetPlatform + override fun dependencies(): List<ModuleInfo> = listOf(this, library) + nativeLibraries } val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) @@ -152,6 +188,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl when (it) { library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) + in nativeLibraries -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) else -> throw IllegalArgumentException("Unexpected module info") } } @@ -160,20 +197,39 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl val resolverForProject = when (analysisPlatform) { Platform.jvm -> { - builtIns = JvmBuiltIns(projectContext.storageManager) - createJvmResolverForProject(projectContext, module, library, modulesContent, sourcesScope, builtIns) + builtIns = JvmBuiltIns( + projectContext.storageManager, + JvmBuiltIns.Kind.FROM_CLASS_LOADER + ) // TODO we should use FROM_DEPENDENCIES + createJvmResolverForProject( + projectContext, + module, + library, + modulesContent, + sourcesScope, + builtIns + ) } - Platform.common -> createCommonResolverForProject(projectContext, module, library, modulesContent, environment) + Platform.common -> createCommonResolverForProject( + projectContext, + module, + library, + modulesContent, + environment + ) Platform.js -> createJsResolverForProject(projectContext, module, library, modulesContent) Platform.native -> createNativeResolverForProject(projectContext, module, library, modulesContent) } - val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly - val resolverForModule = resolverForProject.resolverForModule(module) val libraryModuleDescriptor = resolverForProject.descriptorForModule(library) val moduleDescriptor = resolverForProject.descriptorForModule(module) builtIns?.initialize(moduleDescriptor, true) - val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary) + + val resolverForLibrary = + resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForModule = resolverForProject.resolverForModule(module) + val libraryResolutionFacade = + DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary) val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) val projectComponentManager = environment.project as MockComponentManager projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) @@ -181,29 +237,64 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl return created to libraryResolutionFacade } + private fun Platform.analyzerServices() = when (this) { + Platform.js -> JsPlatformAnalyzerServices + Platform.common -> CommonPlatformAnalyzerServices + Platform.native -> NativePlatformAnalyzerServices + Platform.jvm -> JvmPlatformAnalyzerServices + } + + private fun createNativeLibraryModuleInfo(libraryFile: File): LibraryModuleInfo { + val kotlinLibrary = createKotlinLibrary(org.jetbrains.kotlin.konan.file.File(libraryFile.absolutePath), false) + return object : LibraryModuleInfo { + override val analyzerServices: PlatformDependentAnalyzerServices = + analysisPlatform.analyzerServices() + override val name: Name = Name.special("<klib>") + override val platform: TargetPlatform = KonanPlatforms.defaultKonanPlatform + override fun dependencies(): List<ModuleInfo> = listOf(this) + override fun getLibraryRoots(): Collection<String> = listOf(libraryFile.absolutePath) + override val capabilities: Map<ModuleDescriptor.Capability<*>, Any?> + get() = super.capabilities + (NativeLibraryInfo.NATIVE_LIBRARY_CAPABILITY to kotlinLibrary) + } + } + private fun createCommonResolverForProject( projectContext: ProjectContext, module: ModuleInfo, library: LibraryModuleInfo, modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, environment: KotlinCoreEnvironment - ): ResolverForProjectImpl<ModuleInfo> { - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = modulesContent, - modulePlatforms = { MultiTargetPlatform.Common }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { CommonAnalyzerFacade }, - platformParameters = { _ -> - CommonAnalysisParameters { content -> - environment.createPackagePartProvider(content.moduleContentScope) - } - }, - targetEnvironment = CompilerEnvironment, - builtIns = DefaultBuiltIns.Instance - ) + ): ResolverForProject<ModuleInfo> { + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = listOf(module, library) + ) { + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) + + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance + + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule = + CommonResolverForModuleFactory( + CommonAnalysisParameters { content -> + environment.createPackagePartProvider(content.moduleContentScope) + }, + CompilerEnvironment, + unspecifiedJvmPlatform, + true + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + } } private fun createJsResolverForProject( @@ -211,19 +302,30 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module: ModuleInfo, library: LibraryModuleInfo, modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> - ): ResolverForProjectImpl<ModuleInfo> { - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = modulesContent, - modulePlatforms = { JsPlatform.multiTargetPlatform }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { DokkaJsAnalyzerFacade }, - platformParameters = { _ -> PlatformAnalysisParameters.Empty }, - targetEnvironment = CompilerEnvironment, - builtIns = JsPlatform.builtIns - ) + ): ResolverForProject<ModuleInfo> { + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = listOf(module, library) + ) { + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule = JsResolverForModuleFactory( + CompilerEnvironment + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance + + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + } } private fun createNativeResolverForProject( @@ -231,19 +333,39 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module: ModuleInfo, library: LibraryModuleInfo, modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> - ): ResolverForProjectImpl<ModuleInfo> { - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(module, library), - modulesContent = modulesContent, - modulePlatforms = { KonanPlatform.multiTargetPlatform }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { DokkaNativeAnalyzerFacade }, - platformParameters = { _ -> PlatformAnalysisParameters.Empty }, - targetEnvironment = CompilerEnvironment - ) + ): ResolverForProject<ModuleInfo> { + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = module.dependencies() + ) { + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = modulesContent(module) + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule { + (ApplicationManager.getApplication() as MockApplication).addComponent( + KotlinNativeLoadingMetadataCache::class.java, + KotlinNativeLoadingMetadataCache() + ) + + return NativeResolverForModuleFactory( + PlatformAnalysisParameters.Empty, + CompilerEnvironment, + KonanPlatforms.defaultKonanPlatform + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + } + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = DefaultBuiltIns.Instance + + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + } } private fun createJvmResolverForProject( @@ -253,38 +375,39 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, sourcesScope: GlobalSearchScope, builtIns: KotlinBuiltIns - ): ResolverForProjectImpl<ModuleInfo> { + ): ResolverForProject<ModuleInfo> { val javaRoots = classpath .mapNotNull { - val rootFile = when { - it.extension == "jar" -> - StandardFileSystems.jar().findFileByPath("${it.absolutePath}${URLUtil.JAR_SEPARATOR}") - else -> - StandardFileSystems.local().findFileByPath(it.absolutePath) + val rootFile = when (it.extension) { + "jar" -> StandardFileSystems.jar().findFileByPath("${it.absolutePath}${JAR_SEPARATOR}") + else -> StandardFileSystems.local().findFileByPath(it.absolutePath) } - rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } } - return ResolverForProjectImpl( - debugName = "Dokka", - projectContext = projectContext, - modules = listOf(library, module), - modulesContent = { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), sourcesScope) + return object : AbstractResolverForProject<ModuleInfo>( + "Dokka", + projectContext, + modules = listOf(module, library) + ) { + override fun modulesContent(module: ModuleInfo): ModuleContent<ModuleInfo> = + when (module) { + library -> ModuleContent(module, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(module, emptyList(), sourcesScope) else -> throw IllegalArgumentException("Unexpected module info") } - }, - modulePlatforms = { JvmPlatform.multiTargetPlatform }, - moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, - resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade }, - platformParameters = { - JvmPlatformParameters ({ content -> + + override fun builtInsForModule(module: ModuleInfo): KotlinBuiltIns = builtIns + + override fun createResolverForModule( + descriptor: ModuleDescriptor, + moduleInfo: ModuleInfo + ): ResolverForModule = JvmResolverForModuleFactory( + JvmPlatformParameters({ content -> JvmPackagePartProvider( configuration.languageVersionSettings, - content.moduleContentScope) + content.moduleContentScope + ) .apply { addRoots(javaRoots, messageCollector) } @@ -294,16 +417,25 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl module else library - }) - }, - targetEnvironment = CompilerEnvironment, - builtIns = builtIns - ) + }), + CompilerEnvironment, + KonanPlatforms.defaultKonanPlatform + ).createResolverForModule( + descriptor as ModuleDescriptorImpl, + projectContext.withModule(descriptor), + modulesContent(moduleInfo), + this, + LanguageVersionSettingsImpl.DEFAULT + ) + + override fun sdkDependency(module: ModuleInfo): ModuleInfo? = null + } } fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { val languageVersion = LanguageVersion.fromVersionString(languageVersionString) ?: LanguageVersion.LATEST_STABLE - val apiVersion = apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion) + val apiVersion = + apiVersionString?.let { ApiVersion.parse(it) } ?: ApiVersion.createByLanguageVersion(languageVersion) configuration.languageVersionSettings = LanguageVersionSettingsImpl(languageVersion, apiVersion) } @@ -340,8 +472,8 @@ class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPl */ val sources: List<String> get() = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) - ?.filterIsInstance<KotlinSourceRoot>() - ?.map { it.path } ?: emptyList() + ?.filterIsInstance<KotlinSourceRoot>() + ?.map { it.path } ?: emptyList() /** * Adds list of paths to source roots. @@ -375,9 +507,11 @@ fun contentRootFromPath(path: String): ContentRoot { } -class DokkaResolutionFacade(override val project: Project, - override val moduleDescriptor: ModuleDescriptor, - val resolverForModule: ResolverForModule) : ResolutionFacade { +class DokkaResolutionFacade( + override val project: Project, + override val moduleDescriptor: ModuleDescriptor, + val resolverForModule: ResolverForModule +) : ResolutionFacade { override fun analyzeWithAllCompilerChecks(elements: Collection<KtElement>): AnalysisResult { throw UnsupportedOperationException() } @@ -386,7 +520,10 @@ class DokkaResolutionFacade(override val project: Project, return resolverForModule.componentProvider.tryGetService(serviceClass) } - override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor { + override fun resolveToDescriptor( + declaration: KtDeclaration, + bodyResolveMode: BodyResolveMode + ): DeclarationDescriptor { return resolveSession.resolveToDescriptor(declaration) } diff --git a/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt b/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt index 31b8ffc7..d9093760 100644 --- a/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt +++ b/core/src/main/kotlin/Analysis/CoreKotlinCacheService.kt @@ -5,7 +5,6 @@ import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache @@ -14,11 +13,24 @@ class CoreKotlinCacheService(private val resolutionFacade: DokkaResolutionFacade return resolutionFacade } - override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade { + override fun getResolutionFacade( + elements: List<KtElement>, + platform: org.jetbrains.kotlin.platform.TargetPlatform + ): ResolutionFacade { return resolutionFacade } - override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? { + override fun getResolutionFacadeByFile( + file: PsiFile, + platform: org.jetbrains.kotlin.platform.TargetPlatform + ): ResolutionFacade? { + return resolutionFacade + } + + override fun getResolutionFacadeByModuleInfo( + moduleInfo: ModuleInfo, + platform: org.jetbrains.kotlin.platform.TargetPlatform + ): ResolutionFacade? { return resolutionFacade } diff --git a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt index f5fbf991..ef45e840 100644 --- a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt +++ b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt @@ -15,6 +15,7 @@ import com.intellij.openapi.util.Condition import com.intellij.openapi.util.Key import com.intellij.openapi.util.UserDataHolderBase import com.intellij.openapi.vfs.StandardFileSystems +import com.intellij.openapi.vfs.VfsUtilCore.getVirtualFileForJar import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileFilter import com.intellij.psi.search.GlobalSearchScope @@ -328,7 +329,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont throw UnsupportedOperationException() } - override fun <R : Any?> processOrder(p0: RootPolicy<R>?, p1: R): R { + override fun <R : Any?> processOrder(p0: RootPolicy<R>, p1: R): R { throw UnsupportedOperationException() } @@ -403,7 +404,7 @@ class CoreProjectFileIndex(private val project: Project, contentRoots: List<Cont throw UnsupportedOperationException() } - override fun isDependsOn(p0: Module?): Boolean { + override fun isDependsOn(p0: Module): Boolean { throw UnsupportedOperationException() } @@ -515,7 +516,7 @@ class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : Proje throw UnsupportedOperationException() } - override fun getContentRootsFromAllModules(): Array<out VirtualFile>? { + override fun getContentRootsFromAllModules(): Array<out VirtualFile> { throw UnsupportedOperationException() } @@ -523,7 +524,7 @@ class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : Proje throw UnsupportedOperationException() } - override fun setProjectSdkName(p0: String?) { + override fun setProjectSdkName(p0: String) { throw UnsupportedOperationException() } @@ -558,7 +559,7 @@ class CoreProjectRootManager(val projectFileIndex: CoreProjectFileIndex) : Proje fun ContentRoot.contains(file: VirtualFile) = when (this) { is JvmContentRoot -> { val path = if (file.fileSystem.protocol == StandardFileSystems.JAR_PROTOCOL) - StandardFileSystems.getVirtualFileForJar(file)?.path ?: file.path + getVirtualFileForJar(file)?.path ?: file.path else file.path File(path).startsWith(this.file.absoluteFile) diff --git a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt b/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt deleted file mode 100644 index 874341dd..00000000 --- a/core/src/main/kotlin/Analysis/DokkaAnalyzerFacades.kt +++ /dev/null @@ -1,164 +0,0 @@ -package org.jetbrains.dokka.Analysis - -import org.jetbrains.kotlin.analyzer.* -import org.jetbrains.kotlin.caches.project.LibraryModuleInfo -import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.config.TargetPlatformVersion -import org.jetbrains.kotlin.container.StorageComponentContainer -import org.jetbrains.kotlin.container.get -import org.jetbrains.kotlin.container.useImpl -import org.jetbrains.kotlin.container.useInstance -import org.jetbrains.kotlin.context.ModuleContext -import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider -import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl -import org.jetbrains.kotlin.frontend.di.configureModule -import org.jetbrains.kotlin.ide.konan.KOTLIN_NATIVE_CURRENT_ABI_VERSION -import org.jetbrains.kotlin.ide.konan.createPackageFragmentProvider -import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.js.resolve.JsPlatform -import org.jetbrains.kotlin.konan.file.File -import org.jetbrains.kotlin.konan.library.createKonanLibrary -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform -import org.jetbrains.kotlin.resolve.lazy.ResolveSession -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory -import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService -import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil -import org.jetbrains.kotlin.serialization.js.createKotlinJavascriptPackageFragmentProvider -import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils - -fun createContainerForLazyResolve( - moduleContext: ModuleContext, - declarationProviderFactory: DeclarationProviderFactory, - bindingTrace: BindingTrace, - platform: TargetPlatform, - targetPlatformVersion: TargetPlatformVersion, - targetEnvironment: TargetEnvironment, - languageVersionSettings: LanguageVersionSettings -): StorageComponentContainer = createContainer("LazyResolve", platform) { - configureModule(moduleContext, platform, targetPlatformVersion, bindingTrace) - - useInstance(declarationProviderFactory) - useInstance(languageVersionSettings) - - useImpl<AnnotationResolverImpl>() - useImpl<CompilerDeserializationConfiguration>() - targetEnvironment.configure(this) - - useImpl<ResolveSession>() - useImpl<LazyTopDownAnalyzer>() -} - - -object DokkaJsAnalyzerFacade : ResolverForModuleFactory() { - override fun <M : ModuleInfo> createResolverForModule( - moduleDescriptor: ModuleDescriptorImpl, - moduleContext: ModuleContext, - moduleContent: ModuleContent<M>, - platformParameters: PlatformAnalysisParameters, - targetEnvironment: TargetEnvironment, - resolverForProject: ResolverForProject<M>, - languageVersionSettings: LanguageVersionSettings, - targetPlatformVersion: TargetPlatformVersion - ): ResolverForModule { - val (moduleInfo, syntheticFiles, moduleContentScope) = moduleContent - val project = moduleContext.project - val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( - project, - moduleContext.storageManager, - syntheticFiles, - moduleContentScope, - moduleInfo - ) - - val container = createContainerForLazyResolve( - moduleContext, - declarationProviderFactory, - BindingTraceContext(), - JsPlatform, - TargetPlatformVersion.NoVersion, - targetEnvironment, - languageVersionSettings - ) - var packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider - - if (moduleInfo is LibraryModuleInfo && moduleInfo.platform == JsPlatform) { - val providers = moduleInfo.getLibraryRoots() - .flatMap { KotlinJavascriptMetadataUtils.loadMetadata(it) } - .filter { it.version.isCompatible() } - .map { metadata -> - val (header, packageFragmentProtos) = - KotlinJavascriptSerializationUtil.readModuleAsProto(metadata.body, metadata.version) - createKotlinJavascriptPackageFragmentProvider( - moduleContext.storageManager, moduleDescriptor, header, packageFragmentProtos, metadata.version, - container.get(), LookupTracker.DO_NOTHING - ) - } - - if (providers.isNotEmpty()) { - packageFragmentProvider = CompositePackageFragmentProvider(listOf(packageFragmentProvider) + providers) - } - } - - return ResolverForModule(packageFragmentProvider, container) - } - - override val targetPlatform: TargetPlatform - get() = JsPlatform -} - -object DokkaNativeAnalyzerFacade : ResolverForModuleFactory() { - override val targetPlatform: TargetPlatform - get() = KonanPlatform - - override fun <M : ModuleInfo> createResolverForModule( - moduleDescriptor: ModuleDescriptorImpl, - moduleContext: ModuleContext, - moduleContent: ModuleContent<M>, - platformParameters: PlatformAnalysisParameters, - targetEnvironment: TargetEnvironment, - resolverForProject: ResolverForProject<M>, - languageVersionSettings: LanguageVersionSettings, - targetPlatformVersion: TargetPlatformVersion - ): ResolverForModule { - - val declarationProviderFactory = DeclarationProviderFactoryService.createDeclarationProviderFactory( - moduleContext.project, - moduleContext.storageManager, - moduleContent.syntheticFiles, - moduleContent.moduleContentScope, - moduleContent.moduleInfo - ) - - val container = createContainerForLazyResolve( - moduleContext, - declarationProviderFactory, - BindingTraceContext(), - targetPlatform, - TargetPlatformVersion.NoVersion, - targetEnvironment, - languageVersionSettings - ) - - val packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider - val fragmentProviders = mutableListOf(packageFragmentProvider) - - val moduleInfo = moduleContent.moduleInfo - - if (moduleInfo is LibraryModuleInfo) { - moduleInfo.getLibraryRoots() - .filter { File(it).extension != "jar" } - .map { createKonanLibrary(File(it), KOTLIN_NATIVE_CURRENT_ABI_VERSION) } - .mapTo(fragmentProviders) { - it.createPackageFragmentProvider( - moduleContext.storageManager, - languageVersionSettings, - moduleDescriptor - ) - } - - } - - return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container) - } -} diff --git a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt index 4dc6b366..4a4c78e5 100644 --- a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt +++ b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt @@ -19,7 +19,6 @@ package org.jetbrains.dokka import com.intellij.psi.* -import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.unwrapped import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.descriptors.* @@ -29,11 +28,9 @@ import org.jetbrains.kotlin.load.java.sources.JavaSourceElement import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.impl.* import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.psiUtil.parameterIndex import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver -import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope @@ -128,4 +125,4 @@ private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElemen } fun PsiElement.javaResolutionFacade() = - KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)!! + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatforms.defaultJvmPlatform)!! diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 3b368329..d6743e60 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -29,7 +29,7 @@ fun getSignature(element: PsiElement?) = when(element) { } private fun methodSignature(method: PsiMethod): String { - return method.containingClass!!.qualifiedName + "$" + method.name + "(" + + return method.containingClass?.qualifiedName + "$" + method.name + "(" + method.parameterList.parameters.map { it.type.typeSignature() }.joinToString(",") + ")" } @@ -167,7 +167,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { element.isInternal()) private fun skipElementBySuppressedFiles(element: Any): Boolean = - element is PsiElement && element.containingFile.virtualFile.path in passConfiguration.suppressedFiles + element is PsiElement && element.containingFile.virtualFile?.path in passConfiguration.suppressedFiles private fun PsiElement.isInternal(): Boolean { val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false @@ -196,8 +196,16 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { link(superClass, node, RefKind.Inheritor) } } + + var methodsAndConstructors = methods + if (constructors.isEmpty()) { + // Having no constructor represents a class that only has an implicit/default constructor + // so we create one synthetically for documentation + val factory = JavaPsiFacade.getElementFactory(this.project) + methodsAndConstructors += factory.createMethodFromText("public $name() {}", this) + } node.appendDetails(typeParameters) { build() } - node.appendMembers(methods) { build() } + node.appendMembers(methodsAndConstructors) { build() } node.appendMembers(fields) { build() } node.appendMembers(innerClasses) { build() } register(this, node) diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 25a974a3..318bad28 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -4,7 +4,6 @@ import com.intellij.psi.* import com.intellij.psi.impl.source.tree.JavaDocElementType import com.intellij.psi.javadoc.* import com.intellij.psi.util.PsiTreeUtil -import com.intellij.util.containers.isNullOrEmpty import org.jetbrains.kotlin.utils.keysToMap import org.jsoup.Jsoup import org.jsoup.nodes.Element diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 3168e033..13bbbb11 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -423,7 +423,7 @@ class DocumentationBuilder fun DocumentationModule.appendFragments(fragments: Collection<PackageFragmentDescriptor>, packageContent: Map<String, Content>, packageDocumentationBuilder: PackageDocumentationBuilder) { - val allFqNames = fragments.filter{ it.isDocumented(passConfiguration) }.map { it.fqName }.distinct() + val allFqNames = fragments.filter { it.isDocumented(passConfiguration) }.map { it.fqName }.distinct() for (packageName in allFqNames) { if (packageName.isRoot && !passConfiguration.includeRootPackage) continue @@ -713,7 +713,7 @@ class DocumentationBuilder } fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode { - if (ErrorUtils.containsErrorType(this)) { + if (ErrorUtils.containsErrorTypeInParameters(this) || ErrorUtils.containsErrorType(this.returnType)) { logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}") } @@ -1157,7 +1157,9 @@ fun ClassDescriptor.supertypesWithAnyPrecise(): Collection<KotlinType> { fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions { val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated, false) - return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions + return perPackageOptions.firstOrNull { pack == it.prefix } + ?: perPackageOptions.firstOrNull { pack.startsWith(it.prefix + ".") } + ?: rootPackageOptions } fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString()) diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 793f9589..bd8b9cf5 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -42,7 +42,7 @@ class PackageListProvider @Inject constructor( configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") configuration.cacheRoot != null -> Paths.get(configuration.cacheRoot) else -> null - }?.resolve("packageListCache")?.apply { createDirectories() } + }?.resolve("packageListCache")?.apply { toFile().mkdirs() } val cachedProtocols = setOf("http", "https", "ftp") @@ -105,13 +105,13 @@ class PackageListProvider @Inject constructor( val digest = MessageDigest.getInstance("SHA-256") val hash = digest.digest(packageListLink.toByteArray(Charsets.UTF_8)).toHexString() - val cacheEntry = cacheDir.resolve(hash) + val cacheEntry = cacheDir.resolve(hash).toFile() if (cacheEntry.exists()) { try { val connection = packageListUrl.doOpenConnectionToReadContent() val originModifiedDate = connection.date - val cacheDate = cacheEntry.lastModified().toMillis() + val cacheDate = cacheEntry.lastModified() if (originModifiedDate > cacheDate || originModifiedDate == 0L) { if (originModifiedDate == 0L) logger.warn("No date header for $packageListUrl, downloading anyway") diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index 4525e9d9..a67306f4 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -165,7 +165,7 @@ open class KotlinWebsiteSampleProcessingService return sampleBuilder.text } - val importsToIgnore = arrayOf("samples.*").map { ImportPath.fromString(it) } + val importsToIgnore = arrayOf("samples.*", "samples.Sample").map { ImportPath.fromString(it) } override fun processImports(psiElement: PsiElement): ContentBlockCode { val psiFile = psiElement.containingFile diff --git a/core/src/main/kotlin/Utilities/Links.kt b/core/src/main/kotlin/Utilities/Links.kt new file mode 100644 index 00000000..34423e4e --- /dev/null +++ b/core/src/main/kotlin/Utilities/Links.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.Utilities + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.ExternalDocumentationLinkImpl + +fun DokkaConfiguration.PassConfiguration.defaultLinks(): List<ExternalDocumentationLinkImpl> { + val links = mutableListOf<ExternalDocumentationLinkImpl>() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink + .Builder("https://docs.oracle.com/javase/${jdkVersion}/docs/api/") + .build() as ExternalDocumentationLinkImpl + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink + .Builder("https://kotlinlang.org/api/latest/jvm/stdlib/") + .build() as ExternalDocumentationLinkImpl + return links +} |