diff --git a/idea/idea-native/build.gradle.kts b/idea/idea-native/build.gradle.kts index 5794e58878e..d37c6fba238 100644 --- a/idea/idea-native/build.gradle.kts +++ b/idea/idea-native/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { compile(project(":idea")) + compileOnly(intellijPluginDep("gradle")) compile(project(":idea:idea-core")) compile(project(":idea:idea-jvm")) compile(project(":compiler:frontend")) diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/KotlinNativeRunConfigurationProducer.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/KotlinNativeRunConfigurationProducer.kt new file mode 100644 index 00000000000..4a9dfc69fe6 --- /dev/null +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/KotlinNativeRunConfigurationProducer.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.execution.actions.ConfigurationContext +import com.intellij.execution.actions.LazyRunConfigurationProducer +import com.intellij.execution.configurations.ConfigurationFactory +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil +import com.intellij.openapi.module.Module +import com.intellij.openapi.util.Ref +import com.intellij.psi.PsiElement +import com.intellij.psi.util.parentOfType +import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider +import org.jetbrains.kotlin.idea.facet.externalSystemNativeMainRunTasks +import org.jetbrains.kotlin.idea.isMainFunction +import org.jetbrains.kotlin.idea.project.platform +import org.jetbrains.kotlin.idea.util.module +import org.jetbrains.kotlin.platform.isCommon +import org.jetbrains.kotlin.platform.konan.isNative +import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType +import org.jetbrains.plugins.gradle.service.execution.GradleRunConfiguration +import org.jetbrains.plugins.gradle.util.GradleConstants + + +class KotlinNativeRunConfigurationProducer : + LazyRunConfigurationProducer(), + KotlinNativeRunConfigurationProvider { + + override val isForTests = false + + override fun getConfigurationFactory(): ConfigurationFactory = + GradleExternalTaskConfigurationType.getInstance().factory + + override fun isConfigurationFromContext(configuration: GradleRunConfiguration, context: ConfigurationContext): Boolean { + val location = context.location ?: return false + val function = location.psiElement.parentOfType() ?: return false + val module = function.module.asNativeModule() ?: return false + + val mainRunTasks = getDebugMainRunTasks(function) + if (mainRunTasks.isEmpty()) return false + + return configuration.settings.externalProjectPath == ExternalSystemApiUtil.getExternalProjectPath(module) + && configuration.settings.taskNames == mainRunTasks + } + + override fun setupConfigurationFromContext( + configuration: GradleRunConfiguration, + context: ConfigurationContext, + sourceElement: Ref + ): Boolean { + if (GradleConstants.SYSTEM_ID != configuration.settings.externalSystemId) return false + val function = sourceElement.get()?.parentOfType() ?: return false + val module = function.module.asNativeModule() ?: return false + + val mainRunTasks = getDebugMainRunTasks(function) + if (mainRunTasks.isEmpty()) return false + + configuration.settings.apply { + externalProjectPath = ExternalSystemApiUtil.getExternalProjectPath(module) + taskNames = mainRunTasks + } + configuration.name = mainRunTasks.first() + configuration.isScriptDebugEnabled = false + + return true + } + + private fun Module?.asNativeModule(): Module? = takeIf { it?.platform.isNative() } + + private fun getDebugMainRunTasks(function: KtFunction): List { + val functionName = function.fqName?.asString() ?: return emptyList() + val module = function.module ?: return emptyList() + + return module.externalSystemNativeMainRunTasks() + .filter { it.debuggable && it.entryPoint == functionName } + .map { it.taskName } + } +} \ No newline at end of file diff --git a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativeIdePlatformKindTooling.kt b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativeIdePlatformKindTooling.kt index 6de66628b94..fd523ee7746 100644 --- a/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativeIdePlatformKindTooling.kt +++ b/idea/idea-native/src/org/jetbrains/kotlin/ide/konan/NativeIdePlatformKindTooling.kt @@ -11,12 +11,18 @@ import com.intellij.openapi.roots.libraries.DummyLibraryProperties import com.intellij.openapi.roots.libraries.Library import com.intellij.openapi.roots.libraries.PersistentLibraryKind import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription +import com.intellij.psi.util.parentOfType import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments +import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.gradle.KotlinPlatform +import org.jetbrains.kotlin.idea.caches.project.isTestModule +import org.jetbrains.kotlin.idea.facet.externalSystemNativeMainRunTasks import org.jetbrains.kotlin.idea.framework.KotlinLibraryKind +import org.jetbrains.kotlin.idea.isMainFunction import org.jetbrains.kotlin.idea.platform.IdePlatformKindTooling import org.jetbrains.kotlin.idea.platform.getGenericTestIcon +import org.jetbrains.kotlin.idea.util.module import org.jetbrains.kotlin.platform.impl.NativeIdePlatformKind import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtNamedDeclaration @@ -54,7 +60,25 @@ class NativeIdePlatformKindTooling : IdePlatformKindTooling() { } } - override fun acceptsAsEntryPoint(function: KtFunction) = false + override fun acceptsAsEntryPoint(function: KtFunction): Boolean { + if (!function.isMainFunction()) return false + val functionName = function.fqName?.asString() ?: return false + + val module = function.module ?: return false + if (module.isTestModule) return false + + val hasRunTask = module.externalSystemNativeMainRunTasks().any { it.entryPoint == functionName } + if (!hasRunTask) return false + + val hasRunConfigurations = RunConfigurationProducer + .getProducers(function.project) + .asSequence() + .filterIsInstance() + .any { !it.isForTests } + if (!hasRunConfigurations) return false + + return true + } } object NativeLibraryKind : PersistentLibraryKind("kotlin.native"), KotlinLibraryKind { diff --git a/idea/resources/META-INF/native.xml b/idea/resources/META-INF/native.xml index 339fb374f3b..8ed78bec442 100644 --- a/idea/resources/META-INF/native.xml +++ b/idea/resources/META-INF/native.xml @@ -23,6 +23,7 @@ +