MPP: implement IdePlatformKind, its resolution and tooling for K/N

This commit is contained in:
Dmitriy Dolovov
2018-09-03 20:08:41 +03:00
committed by Mikhail Glukhikh
parent b86afb0bab
commit 7623169130
23 changed files with 398 additions and 365 deletions
+2 -4
View File
@@ -5,16 +5,14 @@ plugins {
dependencies {
compile(project(":idea"))
compile(project(":idea:idea-core"))
compile(project(":idea:idea-jvm"))
compile(project(":compiler:frontend"))
compileOnly(intellijDep())
compile(project(":konan:konan-serializer"))
}
sourceSets {
"main" {
projectDefault()
// java.srcDirs("$rootDir/core/runtime.jvm/src")
}
"main" { projectDefault() }
"test" { none() }
}
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.resolve.lazy.ResolveSession
/**
* @author Alefas
*/
class KonanAnalyzerFacade : ResolverForModuleFactory() {
object KonanAnalyzerFacade : ResolverForModuleFactory() {
override val targetPlatform: TargetPlatform
get() = KonanPlatform
@@ -16,8 +16,6 @@ class KonanDescriptorManager : ApplicationComponent {
companion object {
private const val currentAbiVersion = 1
@JvmStatic
fun getInstance(): KonanDescriptorManager = ApplicationManager.getApplication().getComponent(KonanDescriptorManager::class.java)
}
@@ -9,25 +9,22 @@ import com.intellij.util.indexing.FileBasedIndex
import org.jetbrains.kotlin.idea.vfilefinder.KotlinFileIndexBase
import org.jetbrains.kotlin.name.FqName
class KonanMetaFileIndex
: KotlinFileIndexBase<KonanMetaFileIndex>(KonanMetaFileIndex::class.java) {
object KonanMetaFileIndex : KotlinFileIndexBase<KonanMetaFileIndex>(KonanMetaFileIndex::class.java) {
companion object {
private const val VERSION = 4
}
override fun getIndexer() = INDEXER
/*todo: check version?!*/
private val dataIndexer = indexer { fileContent ->
val fragment = KonanDescriptorManager.getInstance().getCachedPackageFragment(fileContent.file)
FqName(fragment.fqName)
}
override fun getInputFilter() = FileBasedIndex.InputFilter { it.fileType === KonanMetaFileType }
override fun getVersion() = VERSION
// this is to express intention to index all Kotlin/Native metadata files irrespectively to file size
override fun getFileTypesWithSizeLimitNotApplicable() = listOf(KonanMetaFileType)
override fun getInputFilter() = FileBasedIndex.InputFilter { it.fileType === KonanMetaFileType }
private const val VERSION = 4
override fun getIndexer() = dataIndexer
override fun getVersion() = VERSION
/*todo: check version?!*/
private val INDEXER = indexer { fileContent ->
val fragment = KonanDescriptorManager.getInstance().getCachedPackageFragment(fileContent.file)
FqName(fragment.fqName)
}
}
@@ -13,7 +13,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.util.Collection;
@ApiStatus.Experimental
public interface KonanModelProvider {
@@ -21,11 +20,6 @@ public interface KonanModelProvider {
ExtensionPointName<KonanModelProvider> EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.native.konanModelProvider");
@NotNull
Collection<KonanArtifact> getArtifacts(@NotNull Project project);
@Nullable
Path getKonanHome(@NotNull Project project);
boolean reloadLibraries(@NotNull Project project, @NotNull Collection<Path> libraryPaths);
}
@@ -30,7 +30,7 @@ open class KonanPaths(protected val project: Project) : ProjectComponent {
open fun konanDist(): Path? {
for (provider in KonanModelProvider.EP_NAME.extensions) {
provider.getKonanHome(project)?.let { return it }
provider.getKonanHome(project)?.existing()?.let { return it }
}
return bundledKonanDist()
}
@@ -41,7 +41,7 @@ open class KonanPaths(protected val project: Project) : ProjectComponent {
val resolvedTargetName = HostManager.resolveAlias(target().name)
val klibPath =
konanDist()?.resolve(konanSpecificPlatformLibrariesPath(resolvedTargetName))?.takeIf { it.exists() } ?: return emptyList()
konanDist()?.resolve(konanSpecificPlatformLibrariesPath(resolvedTargetName))?.existing() ?: return emptyList()
return Files.walk(klibPath, 1).filter {
it.isDirectory() && it.fileName.toString() != KONAN_STDLIB_NAME && it != klibPath
@@ -51,3 +51,5 @@ open class KonanPaths(protected val project: Project) : ProjectComponent {
//todo: this is wrong, we are not allowing multiple targets in project
open fun target(): KonanTarget = HostManager.host
}
private fun Path.existing(): Path? = takeIf { exists() }
@@ -0,0 +1,75 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ide.konan
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.DummyLibraryProperties
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.LibraryType
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.konan.analyser.index.KonanMetaFileIndex
import org.jetbrains.kotlin.idea.configuration.KotlinWithLibraryConfigurator
import org.jetbrains.kotlin.idea.configuration.LibraryKindSearchScope
import org.jetbrains.kotlin.idea.configuration.hasKotlinFilesOnlyInTests
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.runWithAlternativeResolveEnabled
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
import org.jetbrains.kotlin.idea.vfilefinder.hasSomethingInPackage
import org.jetbrains.kotlin.konan.library.KONAN_STDLIB_NAME
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
open class KonanModuleConfigurator : KotlinWithLibraryConfigurator() {
override val name: String get() = NAME
override val targetPlatform get() = KonanPlatform
override val presentableText get() = PRESENTABLE_TEXT
override fun isConfigured(module: Module) = hasKonanRuntimeInScope(module)
override val libraryName get() = KonanStandardLibraryDescription.LIBRARY_NAME
override val dialogTitle get() = KonanStandardLibraryDescription.DIALOG_TITLE
override val libraryCaption get() = KonanStandardLibraryDescription.LIBRARY_CAPTION
override val messageForOverrideDialog get() = KonanStandardLibraryDescription.KONAN_LIBRARY_CREATION
override fun getLibraryJarDescriptors(sdk: Sdk?) = emptyList<LibraryJarDescriptor>()
override val libraryMatcher: (Library, Project) -> Boolean = { library, _ ->
library.getFiles(OrderRootType.CLASSES).firstOrNull { it.nameWithoutExtension == KONAN_STDLIB_NAME } != null
}
override val libraryType: LibraryType<DummyLibraryProperties>? get() = null
companion object {
const val NAME = "Konan"
const val PRESENTABLE_TEXT = "Native"
}
}
fun hasKonanRuntimeInScope(module: Module): Boolean {
return runReadAction {
val scope = module.getModuleWithDependenciesAndLibrariesScope(hasKotlinFilesOnlyInTests(module))
hasKonanMetadataFile(module.project, LibraryKindSearchScope(module, scope, KonanLibraryKind))
}
}
private val KONAN_FQ_NAME = FqName("kotlin.native")
fun hasKonanMetadataFile(project: Project, scope: GlobalSearchScope): Boolean {
return runReadAction {
project.runWithAlternativeResolveEnabled {
KonanMetaFileIndex.hasSomethingInPackage(KONAN_FQ_NAME, scope)
}
}
}
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ide.konan
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.konan.K2NativeCompilerArguments
import org.jetbrains.kotlin.config.TargetPlatformVersion
import org.jetbrains.kotlin.platform.IdePlatform
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
object KonanPlatformKind : IdePlatformKind<KonanPlatformKind>() {
override fun platformByCompilerArguments(arguments: CommonCompilerArguments): IdePlatform<KonanPlatformKind, CommonCompilerArguments>? {
return if (arguments is K2NativeCompilerArguments) Platform
else null
}
override val compilerPlatform get() = KonanPlatform
override val platforms get() = listOf(Platform)
override val defaultPlatform get() = Platform
override val argumentsClass get() = K2NativeCompilerArguments::class.java
override val name get() = "Native"
object Platform : IdePlatform<KonanPlatformKind, K2NativeCompilerArguments>() {
override val kind get() = KonanPlatformKind
override val version get() = TargetPlatformVersion.NoVersion
override fun createArguments(init: K2NativeCompilerArguments.() -> Unit) = K2NativeCompilerArguments().apply(init)
}
override fun equals(other: Any?): Boolean = other === KonanPlatformKind
override fun hashCode(): Int = javaClass.hashCode()
}
val IdePlatformKind<*>?.isKonan
get() = this === KonanPlatformKind
val IdePlatform<*, *>?.isKonan
get() = this === KonanPlatformKind.Platform
@@ -3,50 +3,50 @@
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.konan.analyser
package org.jetbrains.kotlin.ide.konan
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.io.exists
import org.jetbrains.konan.KONAN_CURRENT_ABI_VERSION
import org.jetbrains.konan.analyser.KonanAnalyzerFacade
import org.jetbrains.konan.settings.KonanPaths
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.caches.resolve.IdePlatformSupport
import org.jetbrains.kotlin.caches.resolve.IdePlatformKindResolution
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.idea.caches.resolve.PlatformAnalysisSettings
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.library.createKonanLibrary
import org.jetbrains.kotlin.konan.utils.KonanFactories.DefaultDeserializedDescriptorFactory
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.konan.platform.KonanPlatform
/**
* @author Alefas
*/
class KonanPlatformSupport : IdePlatformSupport() {
class KonanPlatformKindResolution : IdePlatformKindResolution {
override fun isLibraryFileForPlatform(virtualFile: VirtualFile): Boolean {
return virtualFile.extension == "klib"
|| virtualFile.isDirectory && virtualFile.children.any { it.name == "manifest" }
}
override val resolverForModuleFactory: ResolverForModuleFactory
get() = KonanAnalyzerFacade()
override val libraryKind: PersistentLibraryKind<*>?
get() = KonanLibraryKind
override val libraryKind: PersistentLibraryKind<*>? = null
override val kind get() = KonanPlatformKind
override val platform: TargetPlatform
get() = KonanPlatform
override val resolverForModuleFactory get() = KonanAnalyzerFacade
override fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl) = createKonanBuiltIns(sdkContext)
override fun isModuleForPlatform(module: Module) = true
override fun createBuiltIns(settings: PlatformAnalysisSettings, projectContext: ProjectContext) =
createKonanBuiltIns(projectContext)
}
private fun createKonanBuiltIns(sdkContext: GlobalContextImpl): KotlinBuiltIns {
private fun createKonanBuiltIns(projectContext: ProjectContext): KotlinBuiltIns {
// TODO: it depends on a random project's stdlib, propagate the actual project here
val stdlibPath = ProjectManager.getInstance().openProjects.asSequence().mapNotNull {
KonanPaths.getInstance(it).konanStdlib()?.takeIf { it.exists() }
val stdlibPath = ProjectManager.getInstance().openProjects.asSequence().mapNotNull { project ->
KonanPaths.getInstance(project).konanStdlib()?.takeIf { it.exists() }
}.firstOrNull()
if (stdlibPath != null) {
@@ -55,7 +55,7 @@ private fun createKonanBuiltIns(sdkContext: GlobalContextImpl): KotlinBuiltIns {
val builtInsModule = DefaultDeserializedDescriptorFactory.createDescriptorAndNewBuiltIns(
library,
LanguageVersionSettingsImpl.DEFAULT,
sdkContext.storageManager
projectContext.storageManager
)
builtInsModule.setDependencies(listOf(builtInsModule))
@@ -0,0 +1,71 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ide.konan
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.DummyLibraryProperties
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import org.jetbrains.konan.analyser.KonanAnalyzerFacade
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.gradle.KotlinPlatform
import org.jetbrains.kotlin.idea.framework.CustomLibraryDescriptorWithDeferredConfig
import org.jetbrains.kotlin.idea.framework.KotlinLibraryKind
import org.jetbrains.kotlin.idea.platform.IdePlatformKindTooling
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.resolve.TargetPlatform
import javax.swing.Icon
class KonanPlatformKindTooling : IdePlatformKindTooling() {
override val kind = KonanPlatformKind
override fun compilerArgumentsForProject(project: Project): CommonCompilerArguments? = null
override val resolverForModuleFactory get() = KonanAnalyzerFacade
override val mavenLibraryIds: List<String> get() = emptyList()
override val gradlePluginId: String get() = ""
override val gradlePlatformIds: List<KotlinPlatform> get() = listOf(KotlinPlatform.KONAN)
override val libraryKind: PersistentLibraryKind<*> = KonanLibraryKind
override fun getLibraryDescription(project: Project) = KonanStandardLibraryDescription(project)
override fun getLibraryVersionProvider(project: Project): (Library) -> String? = { null }
override fun getTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon? = null
override fun acceptsAsEntryPoint(function: KtFunction) = true
}
object KonanLibraryKind : PersistentLibraryKind<DummyLibraryProperties>("kotlin.native"), KotlinLibraryKind {
override val compilerPlatform: TargetPlatform
get() = KonanPlatformKind.compilerPlatform
override fun createDefaultProperties() = DummyLibraryProperties.INSTANCE!!
}
class KonanStandardLibraryDescription(project: Project?) :
CustomLibraryDescriptorWithDeferredConfig(
project,
KonanModuleConfigurator.NAME,
LIBRARY_NAME,
DIALOG_TITLE,
LIBRARY_CAPTION,
KonanLibraryKind,
SUITABLE_LIBRARY_KINDS
) {
companion object {
val LIBRARY_NAME = "KotlinNative"
val KONAN_LIBRARY_CREATION = "Native Library Creation"
val DIALOG_TITLE = "Create Kotlin Native Library"
val LIBRARY_CAPTION = "Kotlin Native Library"
val SUITABLE_LIBRARY_KINDS = setOf(KonanLibraryKind)
}
}