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
+7
View File
@@ -0,0 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="dmitriy.dolovov">
<words>
<w>konan</w>
</words>
</dictionary>
</component>
@@ -5,77 +5,10 @@
package org.jetbrains.konan.gradle
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.find
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil.findAll
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.util.BooleanFunction
import com.sun.media.jfxmediaimpl.platform.PlatformManager
import org.jetbrains.konan.settings.KonanArtifact
import org.jetbrains.konan.settings.KonanModelProvider
import org.jetbrains.kotlin.gradle.plugin.model.KonanModel
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
import org.jetbrains.kotlin.konan.target.PlatformManager
import org.jetbrains.kotlin.konan.target.customerDistribution
import org.jetbrains.plugins.gradle.settings.GradleSettings
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File
import java.nio.file.Path
class GradleKonanModelProvider : KonanModelProvider {
override fun reloadLibraries(project: Project, libraryPaths: Collection<Path>): Boolean =
GradleSettings.getInstance(project).linkedProjectsSettings.isNotEmpty()
override fun getKonanHome(project: Project): Path? {
val projectNode = ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID)
.mapNotNull { it.externalProjectStructure }
.firstOrNull() ?: return null
projectNode.getUserData(KONAN_HOME)?.let { return it }
var konanHomePath: Path? = null
find(projectNode, ProjectKeys.MODULE, BooleanFunction { moduleNode ->
find(moduleNode, KonanProjectResolver.KONAN_MODEL_KEY, BooleanFunction { konanModelNode ->
konanHomePath = konanModelNode.data.konanHome.toPath()
projectNode.putUserData(KONAN_HOME, konanHomePath)
konanHomePath != null
}) != null
})
return konanHomePath
}
override fun getArtifacts(project: Project): Collection<KonanArtifact> {
val artifacts = mutableListOf<KonanArtifact>()
ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID)
.mapNotNull { it.externalProjectStructure }
.forEach { projectStructure ->
findAll(projectStructure, ProjectKeys.MODULE)
.map { Pair(it.data.externalName, find<KonanModel>(it, KonanProjectResolver.KONAN_MODEL_KEY)) }
.filter { it.second != null }
.forEach { (moduleName, konanProjectNode) ->
konanProjectNode!!.data.artifacts.forEach { konanArtifact ->
val sources = konanArtifact.srcFiles.map { it.toPath() }
artifacts.add(
KonanArtifact(
konanArtifact.name,
moduleName,
konanArtifact.type,
konanTarget(konanProjectNode.data.konanHome, konanArtifact),
mutableListOf(), sources, konanArtifact.file.toPath()
)
)
}
}
}
return artifacts
}
private fun konanTarget(konanHome: File, konanArtifactEx: KonanModelArtifact) =
PlatformManager(customerDistribution(konanHome.absolutePath)).targetValues.find { it.name == konanArtifactEx.targetPlatform }
companion object {
val KONAN_HOME = Key.create<Path>("KONAN_HOME")
}
override fun getKonanHome(project: Project): Path? = null
}
@@ -1,75 +0,0 @@
/*
* 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.konan.gradle
import com.intellij.execution.RunManager
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.Key
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.model.project.ModuleData
import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.service.project.IdeModelsProvider
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.konan.settings.KonanArtifact
import org.jetbrains.konan.settings.KonanModelProvider
import org.jetbrains.konan.settings.isExecutable
import org.jetbrains.kotlin.gradle.plugin.model.KonanModel
import org.jetbrains.plugins.gradle.util.GradleConstants
class KonanProjectDataService : AbstractProjectDataService<KonanModel, Module>() {
override fun getTargetDataKey(): Key<KonanModel> = KonanProjectResolver.KONAN_MODEL_KEY
override fun postProcess(
toImport: Collection<DataNode<KonanModel>>,
projectData: ProjectData?,
project: Project,
modelsProvider: IdeModifiableModelsProvider
) {
}
override fun onSuccessImport(
imported: Collection<DataNode<KonanModel>>,
projectData: ProjectData?,
project: Project,
modelsProvider: IdeModelsProvider
) {
if (projectData?.owner != GradleConstants.SYSTEM_ID) return
project.messageBus.syncPublisher(KonanModelProvider.RELOAD_TOPIC).run()
}
companion object {
@JvmStatic
fun forEachKonanProject(
project: Project,
consumer: (konanProject: KonanModel, moduleData: ModuleData, rootProjectPath: String) -> Unit
) {
for (projectInfo in ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID)) {
val projectStructure = projectInfo.externalProjectStructure ?: continue
val projectData = projectStructure.data
val rootProjectPath = projectData.linkedExternalProjectPath
val modulesNodes = ExternalSystemApiUtil.findAll(projectStructure, ProjectKeys.MODULE)
for (moduleNode in modulesNodes) {
val projectNode = ExternalSystemApiUtil.find<KonanModel>(moduleNode, KonanProjectResolver.KONAN_MODEL_KEY)
if (projectNode != null) {
val konanProject = projectNode.data
val moduleData = moduleNode.data
consumer(konanProject, moduleData, rootProjectPath)
}
}
}
}
}
}
@@ -1,157 +0,0 @@
/*
* 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.konan.gradle
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.Key
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.model.project.*
import com.intellij.util.containers.ContainerUtil.set
import com.intellij.util.io.isDirectory
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.plugin.model.KonanModel
import org.jetbrains.kotlin.gradle.plugin.model.KonanModelArtifact
import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.MetaVersion
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File
import java.nio.file.Files.isDirectory
import java.nio.file.Files.walk
import java.nio.file.Path
import java.util.*
/**
* [KonanProjectResolver] creates IDE project model in terms of External System API
*/
class KonanProjectResolver : AbstractProjectResolverExtension() {
// to ask gradle for the model
override fun getExtraProjectModelClasses(): Set<Class<*>> {
return set<Class<*>>(KonanModel::class.java)
}
override fun populateModuleExtraModels(gradleModule: IdeaModule, ideModule: DataNode<ModuleData>) {
resolverCtx.getExtraProject(gradleModule, KonanModel::class.java)?.let {
// store a local process copy of the object to get rid of proxy types for further serialization
ideModule.createChild(KONAN_MODEL_KEY, MyKonanModel(it))
}
nextResolver.populateModuleExtraModels(gradleModule, ideModule)
}
override fun populateModuleContentRoots(gradleModule: IdeaModule, ideModule: DataNode<ModuleData>) {
resolverCtx.getExtraProject(gradleModule, KonanModel::class.java)?.let {
val added = mutableSetOf<String>()
for (artifact in it.artifacts) {
for (srcDir in artifact.srcDirs) {
val rootPath = srcDir.absolutePath
if (!added.add(rootPath)) continue
val ideContentRoot = ContentRootData(GradleConstants.SYSTEM_ID, rootPath)
ideContentRoot.storePath(ExternalSystemSourceType.SOURCE, rootPath)
ideModule.createChild(ProjectKeys.CONTENT_ROOT, ideContentRoot)
}
}
}
nextResolver.populateModuleContentRoots(gradleModule, ideModule)
}
// based on KonanCMakeProjectComponent.reloadLibraries but with the multi-module projects support
override fun populateModuleDependencies(
gradleModule: IdeaModule,
ideModule: DataNode<ModuleData>,
ideProject: DataNode<ProjectData>
) {
val konanModelEx = resolverCtx.getExtraProject(gradleModule, KonanModel::class.java)
if (konanModelEx != null) {
val libraryPaths = LinkedHashSet<Path>()
var konanHome: Path? = null
var targetPlatform: String? = null
for (konanArtifact in konanModelEx.artifacts) {
if (konanHome == null) {
konanHome = konanModelEx.konanHome.toPath()
targetPlatform = konanArtifact.targetPlatform
}
konanArtifact.libraries.forEach { libraryPaths.add(it.toPath()) }
}
if (konanHome != null) {
// add konanStdlib copied from KonanPaths.konanStdlib
libraryPaths.add(konanHome.resolve("klib/common/stdlib"))
// add konanPlatformLibraries, copied from KonanPaths.konanPlatformLibraries
if (targetPlatform != null) {
try {
val resolvedTargetName = HostManager.resolveAlias(targetPlatform)
val klibPath = konanHome.resolve("klib/platform/${resolvedTargetName}")
walk(klibPath, 1)
.filter { it.isDirectory() && it.fileName.toString() != "stdlib" && it != klibPath }
.forEach { libraryPaths.add(it) }
} catch (e: Exception) {
LOG.warn("Unable to collect konan platform libraries paths for '$targetPlatform'", e)
}
}
}
val moduleData = ideModule.data
for (path in libraryPaths) {
val library = LibraryData(moduleData.owner, path.fileName.toString())
library.addPath(LibraryPathType.BINARY, if (isDirectory(path)) path.toAbsolutePath().toString() else path.toString())
val data = LibraryDependencyData(moduleData, library, LibraryLevel.MODULE)
ideModule.createChild(ProjectKeys.LIBRARY_DEPENDENCY, data)
}
}
nextResolver.populateModuleDependencies(gradleModule, ideModule, ideProject)
}
private class MyKonanModel(konanModel: KonanModel) : KonanModel {
override val artifacts: List<KonanModelArtifact> = konanModel.artifacts.map { MyKonanArtifactEx(it) }
override val konanHome: File = konanModel.konanHome
override val konanVersion: KonanVersion = MyKonanVersionEx(konanModel.konanVersion)
override val apiVersion: String? = konanModel.apiVersion
override val languageVersion: String? = konanModel.languageVersion
private class MyKonanVersionEx(version: KonanVersion) : KonanVersion {
override val build: Int = version.build
override val maintenance: Int = version.maintenance
override val major: Int = version.major
override val meta: MetaVersion = version.meta
override val minor: Int = version.minor
override fun toString(showMeta: Boolean, showBuild: Boolean): String {
val sb = StringBuilder("$major.$minor.$maintenance")
if (showMeta) sb.append('-').append(meta)
if (showBuild) sb.append('-').append(build)
return sb.toString()
}
}
private class MyKonanArtifactEx(artifact: KonanModelArtifact) : KonanModelArtifact {
override val searchPaths: List<File> = artifact.searchPaths
override val name: String = artifact.name
override val type: CompilerOutputKind = artifact.type
override val targetPlatform: String = artifact.targetPlatform
override val file: File = artifact.file
override val buildTaskName: String = artifact.buildTaskName
override val srcDirs: List<File> = artifact.srcDirs.toList()
override val srcFiles: List<File> = artifact.srcFiles.toList()
override val libraries: List<File> = artifact.libraries.toList()
}
}
companion object {
val KONAN_MODEL_KEY = Key.create(KonanModel::class.java, ProjectKeys.MODULE.processingWeight + 1)
private val LOG = Logger.getInstance(KonanProjectResolver::class.java)
}
}
@@ -293,7 +293,7 @@ fun hasKotlinFilesInSources(module: Module): Boolean {
return FileTypeIndex.containsFileOfType(KotlinFileType.INSTANCE, module.getModuleScope(false))
}
private class LibraryKindSearchScope(
class LibraryKindSearchScope(
val module: Module,
val baseScope: GlobalSearchScope,
val libraryKind: PersistentLibraryKind<*>
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.idea.versions.findKotlinRuntimeLibrary
import java.io.File
import java.util.*
abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProjectConfigurator {
abstract class KotlinWithLibraryConfigurator protected constructor() : KotlinProjectConfigurator {
protected abstract val libraryName: String
protected abstract val messageForOverrideDialog: String
+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)
}
}
@@ -60,6 +60,7 @@ enum class KotlinPlatform(val id: String) {
COMMON("common"),
JVM("jvm"),
JS("js"),
KONAN("native"),
ANDROID("androidJvm");
companion object {
-9
View File
@@ -28,13 +28,4 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin.native">
<konanModelProvider implementation="org.jetbrains.konan.gradle.GradleKonanModelProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<projectResolve implementation="org.jetbrains.konan.gradle.KonanProjectResolver"/>
</extensions>
<extensions defaultExtensionNs="com.intellij">
<externalProjectDataService implementation="org.jetbrains.konan.gradle.KonanProjectDataService"/>
</extensions>
<!-- /NATIVE PART -->
</idea-plugin>
+6 -2
View File
@@ -32,6 +32,10 @@
<extensions defaultExtensionNs="org.jetbrains.kotlin">
<binaryExtension implementation="org.jetbrains.konan.analyser.index.KonanMetaBinary"/>
<idePlatformSupport implementation="org.jetbrains.konan.analyser.KonanPlatformSupport" order="first"/>
</extensions>
<!--<idePlatformSupport implementation="org.jetbrains.konan.analyser.KonanPlatformSupport" order="first"/>-->
<idePlatformKind implementation="org.jetbrains.kotlin.ide.konan.KonanPlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.ide.konan.KonanPlatformKindTooling"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.ide.konan.KonanPlatformKindResolution"/>
<projectConfigurator implementation="org.jetbrains.kotlin.ide.konan.KonanModuleConfigurator"/>
</extensions>
</idea-plugin>
+1
View File
@@ -12,6 +12,7 @@ dependencies {
// Compile-only dependencies are needed for compilation of this module:
compileOnly(project(":compiler:frontend"))
compileOnly(project(":compiler:frontend.java"))
compileOnly(project(":compiler:cli-common"))
// This dependency is necessary to keep the right dependency record inside of POM file:
compile(projectRuntimeJar(":kotlin-compiler"))
@@ -0,0 +1,148 @@
/*
* 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.cli.common.arguments.konan
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.Argument
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.config.AnalysisFlag
class K2NativeCompilerArguments : CommonCompilerArguments() {
// First go the options interesting to the general public.
// Prepend them with a single dash.
// Keep the list lexically sorted.
@Argument(value = "-enable_assertions", shortName = "-ea", description = "Enable runtime assertions in generated code")
var enableAssertions: Boolean = false
@Argument(value = "-g", description = "Enable emitting debug information")
var debug: Boolean = false
@Argument(value = "-generate_test_runner", shortName = "-tr", description = "Produce a runner for unit tests")
var generateTestRunner: Boolean = false
@Argument(value = "-includeBinary", shortName = "-ib", valueDescription = "<path>", description = "Pack external binary within the klib")
var includeBinaries: Array<String>? = null
@Argument(value = "-library", shortName = "-l", valueDescription = "<path>", description = "Link with the library")
var libraries: Array<String>? = null
@Argument(value = "-list_targets", description = "List available hardware targets")
var listTargets: Boolean = false
@Argument(value = "-manifest", valueDescription = "<path>", description = "Provide a maniferst addend file")
var manifestFile: String? = null
@Argument(value = "-module_name", valueDescription = "<name>", description = "Spicify a name for the compilation module")
var moduleName: String? = null
@Argument(value = "-nativelibrary", shortName = "-nl", valueDescription = "<path>", description = "Include the native bitcode library")
var nativeLibraries: Array<String>? = null
@Argument(value = "-nodefaultlibs", description = "Don't link the libraries from dist/klib automatically")
var nodefaultlibs: Boolean = false
@Argument(value = "-nomain", description = "Assume 'main' entry point to be provided by external libraries")
var nomain: Boolean = false
@Argument(value = "-nopack", description = "Don't pack the library into a klib file")
var nopack: Boolean = false
@Argument(value = "-linkerOpts", valueDescription = "<arg>", description = "Pass arguments to linker", delimiter = " ")
var linkerArguments: Array<String>? = null
@Argument(value = "-nostdlib", description = "Don't link with stdlib")
var nostdlib: Boolean = false
@Argument(value = "-opt", description = "Enable optimizations during compilation")
var optimization: Boolean = false
@Argument(value = "-output", shortName = "-o", valueDescription = "<name>", description = "Output name")
var outputName: String? = null
@Argument(value = "-entry", shortName = "-e", valueDescription = "<name>", description = "Qualified entry point name")
var mainPackage: String? = null
@Argument(value = "-produce", shortName = "-p",
valueDescription = "{program|static|dynamic|framework|library|bitcode}",
description = "Specify output file kind")
var produce: String? = null
@Argument(value = "-repo", shortName = "-r", valueDescription = "<path>", description = "Library search path")
var repositories: Array<String>? = null
@Argument(value = "-target", valueDescription = "<target>", description = "Set hardware target")
var target: String? = null
// The rest of the options are only interesting to the developers.
// Make sure to prepend them with a double dash.
// Keep the list lexically sorted.
@Argument(value = "--check_dependencies", description = "Check dependencies and download the missing ones")
var checkDependencies: Boolean = false
@Argument(value = "--disable", valueDescription = "<Phase>", description = "Disable backend phase")
var disablePhases: Array<String>? = null
@Argument(value = "--enable", valueDescription = "<Phase>", description = "Enable backend phase")
var enablePhases: Array<String>? = null
@Argument(value = "--list_phases", description = "List all backend phases")
var listPhases: Boolean = false
@Argument(value = "--print_bitcode", description = "Print llvm bitcode")
var printBitCode: Boolean = false
@Argument(value = "--print_descriptors", description = "Print descriptor tree")
var printDescriptors: Boolean = false
@Argument(value = "--print_ir", description = "Print IR")
var printIr: Boolean = false
@Argument(value = "--print_ir_with_descriptors", description = "Print IR with descriptors")
var printIrWithDescriptors: Boolean = false
@Argument(value = "--print_locations", description = "Print locations")
var printLocations: Boolean = false
@Argument(value = "--purge_user_libs", description = "Don't link unused libraries even explicitly specified")
var purgeUserLibs: Boolean = false
@Argument(value = "--runtime", valueDescription = "<path>", description = "Override standard 'runtime.bc' location")
var runtimeFile: String? = null
@Argument(value = "--temporary_files_dir", valueDescription = "<path>", description = "Save temporary files to the given directory")
var temporaryFilesDir: String? = null
@Argument(value = "--time", description = "Report execution time for compiler phases")
var timePhases: Boolean = false
@Argument(value = "--verbose", valueDescription = "<Phase>", description = "Trace phase execution")
var verbosePhases: Array<String>? = null
@Argument(value = "--verify_bitcode", description = "Verify llvm bitcode after each method")
var verifyBitCode: Boolean = false
@Argument(value = "--verify_descriptors", description = "Verify descriptor tree")
var verifyDescriptors: Boolean = false
@Argument(value = "--verify_ir", description = "Verify IR")
var verifyIr: Boolean = false
@Argument(
value = "-friend-modules",
valueDescription = "<path>",
description = "Paths to friend modules"
)
var friendModules: String? = null
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> =
super.configureAnalysisFlags(collector).also {
val useExperimental = it[AnalysisFlag.useExperimental] as List<*>
it[AnalysisFlag.useExperimental] = useExperimental + listOf("kotlin.ExperimentalUnsignedTypes")
}
}
+1 -1
View File
@@ -37,7 +37,7 @@ val projectsToShadow by extra(listOf(
":idea:idea-native",
":idea:idea-core",
":idea:idea-gradle",
//":idea:idea-gradle:native",
":idea:idea-gradle:native",
//":idea-ultimate",
":compiler:ir.psi2ir",
":compiler:ir.tree",
+1 -1
View File
@@ -77,7 +77,7 @@ include ":kotlin-build-common",
":idea:idea-android-output-parser",
":idea:idea-test-framework",
":idea:idea-native",
//":idea:idea-gradle:native",
":idea:idea-gradle:native",
":idea",
":idea-runner",
":eval4j",