diff options
Diffstat (limited to 'core/src/main')
-rw-r--r-- | core/src/main/kotlin/Analysis/AnalysisEnvironment.kt | 195 | ||||
-rw-r--r-- | core/src/main/kotlin/Generation/DokkaGenerator.kt | 24 | ||||
-rw-r--r-- | core/src/main/kotlin/Generation/configurationImpl.kt | 13 |
3 files changed, 171 insertions, 61 deletions
diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index d31fe187..fe9ec2fa 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -18,6 +18,11 @@ 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.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.messages.MessageCollector @@ -33,14 +38,15 @@ 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 +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.* import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters @@ -60,7 +66,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 { @@ -69,7 +75,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, Platform.common -> 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, @@ -93,10 +104,11 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { return environment } - fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope { - // TODO: Fix when going to implement dokka for JS - return TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) - } + fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope = + when (analysisPlatform) { + Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) + Platform.js, Platform.common -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + } fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair<DokkaResolutionFacade, DokkaResolutionFacade> { @@ -105,7 +117,20 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { val sourceFiles = environment.getSourceFiles() - val library = object : ModuleInfo { + val targetPlatform = when (analysisPlatform) { + Platform.js -> JsPlatform + Platform.common -> TargetPlatform.Common + Platform.jvm -> JvmPlatform + } + + val library = object : LibraryModuleInfo { + override val platform: TargetPlatform + get() = targetPlatform + + override fun getLibraryRoots(): Collection<String> { + return classpath.map { it.absolutePath } + } + override val name: Name = Name.special("<library>") override fun dependencies(): List<ModuleInfo> = listOf(this) } @@ -115,47 +140,119 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) + val modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo> = { + when (it) { + library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(it, emptyList(), GlobalSearchScope.allScope(environment.project)) + else -> throw IllegalArgumentException("Unexpected module info") + } + } - val builtIns = JvmBuiltIns(projectContext.storageManager) + 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) - 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 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 created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) + val projectComponentManager = environment.project as MockComponentManager + projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) - rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } - } + return created to libraryResolutionFacade + } - val resolverForProject = ResolverForProjectImpl( - "Dokka", - projectContext, - listOf(library, module), - { - when (it) { - library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(it, emptyList(), sourcesScope) - else -> throw IllegalArgumentException("Unexpected module info") - } - }, - { - JvmPlatform.multiTargetPlatform + 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 = object : PlatformAnalysisParameters {}, + targetEnvironment = CompilerEnvironment, + packagePartProviderFactory = { content -> + environment.createPackagePartProvider(content.moduleContentScope) }, - LanguageSettingsProvider.Default /* TODO: Fix this */, - { JvmAnalyzerFacade }, + builtIns = DefaultBuiltIns.Instance + ) + } + + private fun createJsResolverForProject( + projectContext: ProjectContext, + 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 = { JsAnalyzerFacade }, + platformParameters = object : PlatformAnalysisParameters {}, + targetEnvironment = CompilerEnvironment, + packagePartProviderFactory = { PackagePartProvider.Empty }, + builtIns = JsPlatform.builtIns + ) + } + + private fun createJvmResolverForProject( + projectContext: ProjectContext, + module: ModuleInfo, + library: LibraryModuleInfo, + modulesContent: (ModuleInfo) -> ModuleContent<ModuleInfo>, + sourcesScope: GlobalSearchScope, + builtIns: KotlinBuiltIns + ): ResolverForProjectImpl<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) + } + + rootFile?.let { JavaRoot(it, JavaRoot.RootType.BINARY) } + } - JvmPlatformParameters { + return ResolverForProjectImpl( + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(module, library), + modulesContent = modulesContent, + 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) @@ -163,18 +260,6 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { }, builtIns = builtIns ) - - 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 created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) - val projectComponentManager = environment.project as MockComponentManager - projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) - - return created to libraryResolutionFacade } fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { @@ -194,6 +279,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * $paths: collection of files to add */ fun addClasspath(paths: List<File>) { + if (analysisPlatform == Platform.js) { + configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath }) + } + configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map { it.absolutePath }) configuration.addJvmClasspathRoots(paths) } @@ -202,6 +291,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * $path: path to add */ fun addClasspath(path: File) { + if (analysisPlatform == Platform.js) { + configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) + } + configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) configuration.addJvmClasspathRoot(path) } diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 46fdaf0a..9de4396b 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<SourceRoot>) { + private fun appendSourceModule(defaultPlatform: String?, + analysisPlatform: Platform, + sourceRoots: List<SourceRoot> + + ) { + 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<String>): AnalysisEnvironment { - val environment = AnalysisEnvironment(DokkaMessageCollector(logger)) + fun createAnalysisEnvironment(sourcePaths: List<String>, 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 90e27b4b..8829682a 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<String> = emptyList()) : SourceRoot { +class SourceRootImpl(path: String, override val platforms: List<String> = 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) } } } |