Kapt: Fix source root importing in MPP projects
This commit is contained in:
+82
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.gradle
|
||||||
|
|
||||||
|
import com.intellij.openapi.roots.*
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.gradle.MultiplePluginVersionGradleImportingTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.util.sourceRoots
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class NewMultiplatformKaptProjectImportingTest : MultiplePluginVersionGradleImportingTestCase() {
|
||||||
|
override fun isApplicableTest(): Boolean {
|
||||||
|
val isOldGradlePlugin = gradleKotlinPluginVersion != MINIMAL_SUPPORTED_VERSION
|
||||||
|
&& StringUtil.compareVersionNumbers(gradleKotlinPluginVersion, "1.3.40") < 0
|
||||||
|
|
||||||
|
return !isOldGradlePlugin && !gradleVersion.startsWith("3.")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testKaptPaths() {
|
||||||
|
configureByFiles()
|
||||||
|
importProject()
|
||||||
|
|
||||||
|
checkProjectStructure(
|
||||||
|
project,
|
||||||
|
projectPath,
|
||||||
|
exhaustiveModuleList = true,
|
||||||
|
exhaustiveSourceSourceRootList = false,
|
||||||
|
exhaustiveDependencyList = false
|
||||||
|
) {
|
||||||
|
module("project")
|
||||||
|
|
||||||
|
module("project_main")
|
||||||
|
module("project_test")
|
||||||
|
|
||||||
|
module("project_commonMain")
|
||||||
|
module("project_commonTest") {
|
||||||
|
moduleDependency("project_commonMain", DependencyScope.TEST)
|
||||||
|
}
|
||||||
|
|
||||||
|
module("project_jvmMain") {
|
||||||
|
moduleDependency("project_commonMain", DependencyScope.COMPILE)
|
||||||
|
val basePath = File(projectPath).parentFile.path.replace(File.separatorChar, '/')
|
||||||
|
val actualSourceRoots = module.sourceRoots.map { it.path.replace(basePath, "") }.sorted()
|
||||||
|
|
||||||
|
val expectedSourceRoots = listOf(
|
||||||
|
"/project/build/generated/source/kapt/main",
|
||||||
|
"/project/build/generated/source/kaptKotlin/main",
|
||||||
|
"/project/src/jvmMain/java",
|
||||||
|
"/project/src/jvmMain/kotlin",
|
||||||
|
"/project/src/jvmMain/resources"
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(expectedSourceRoots, actualSourceRoots)
|
||||||
|
}
|
||||||
|
|
||||||
|
module("project_jvmTest") {
|
||||||
|
moduleDependency("project_commonMain", DependencyScope.TEST)
|
||||||
|
moduleDependency("project_commonTest", DependencyScope.TEST)
|
||||||
|
moduleDependency("project_jvmMain", DependencyScope.TEST)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun importProject() {
|
||||||
|
val isCreateEmptyContentRootDirectories = currentExternalProjectSettings.isCreateEmptyContentRootDirectories
|
||||||
|
currentExternalProjectSettings.isCreateEmptyContentRootDirectories = true
|
||||||
|
try {
|
||||||
|
super.importProject()
|
||||||
|
} finally {
|
||||||
|
currentExternalProjectSettings.isCreateEmptyContentRootDirectories = isCreateEmptyContentRootDirectories
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun testDataDirName(): String {
|
||||||
|
return "newMultiplatformImport"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -175,7 +175,6 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
|||||||
): KotlinTarget? {
|
): KotlinTarget? {
|
||||||
val targetClass = gradleTarget.javaClass
|
val targetClass = gradleTarget.javaClass
|
||||||
val getPlatformType = targetClass.getMethodOrNull("getPlatformType") ?: return null
|
val getPlatformType = targetClass.getMethodOrNull("getPlatformType") ?: return null
|
||||||
val getCompilations = targetClass.getMethodOrNull("getCompilations") ?: return null
|
|
||||||
val getDisambiguationClassifier = targetClass.getMethodOrNull("getDisambiguationClassifier") ?: return null
|
val getDisambiguationClassifier = targetClass.getMethodOrNull("getDisambiguationClassifier") ?: return null
|
||||||
val platformId = (getPlatformType.invoke(gradleTarget) as? Named)?.name ?: return null
|
val platformId = (getPlatformType.invoke(gradleTarget) as? Named)?.name ?: return null
|
||||||
val platform = KotlinPlatform.byId(platformId) ?: return null
|
val platform = KotlinPlatform.byId(platformId) ?: return null
|
||||||
@@ -189,9 +188,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
|||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
"${e::class.java.name}:${e.message}"
|
"${e::class.java.name}:${e.message}"
|
||||||
}
|
}
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val gradleCompilations =
|
val gradleCompilations = getCompilations(gradleTarget) ?: return null
|
||||||
(getCompilations.invoke(gradleTarget) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList<Named>()
|
|
||||||
val compilations = gradleCompilations.mapNotNull {
|
val compilations = gradleCompilations.mapNotNull {
|
||||||
buildCompilation(it, disambiguationClassifier, sourceSetMap, dependencyResolver, project)
|
buildCompilation(it, disambiguationClassifier, sourceSetMap, dependencyResolver, project)
|
||||||
}
|
}
|
||||||
@@ -227,10 +225,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val kotlinGradleSourceSets = (getKotlinSourceSets(gradleCompilation) as? Collection<Named>) ?: return null
|
val kotlinGradleSourceSets = (getKotlinSourceSets(gradleCompilation) as? Collection<Named>) ?: return null
|
||||||
val kotlinSourceSets = kotlinGradleSourceSets.mapNotNull { sourceSetMap[it.name] }
|
val kotlinSourceSets = kotlinGradleSourceSets.mapNotNull { sourceSetMap[it.name] }
|
||||||
val getCompileKotlinTaskName = compilationClass.getMethodOrNull("getCompileKotlinTaskName") ?: return null
|
val compileKotlinTask = getCompileKotlinTaskName(project, gradleCompilation) ?: return null
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
val compileKotlinTaskName = (getCompileKotlinTaskName(gradleCompilation) as? String) ?: return null
|
|
||||||
val compileKotlinTask = project.tasks.findByName(compileKotlinTaskName) ?: return null
|
|
||||||
val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null
|
val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null
|
||||||
val arguments = buildCompilationArguments(compileKotlinTask) ?: return null
|
val arguments = buildCompilationArguments(compileKotlinTask) ?: return null
|
||||||
val dependencyClasspath = buildDependencyClasspath(compileKotlinTask)
|
val dependencyClasspath = buildDependencyClasspath(compileKotlinTask)
|
||||||
@@ -547,6 +542,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return (getTargets.invoke(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList()
|
return (getTargets.invoke(kotlinExt) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getCompilations(target: Named): Collection<Named>? {
|
||||||
|
val getCompilationsMethod = target.javaClass.getMethodOrNull("getCompilations") ?: return null
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return (getCompilationsMethod.invoke(target) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCompileKotlinTaskName(project: Project, compilation: Named): Task? {
|
||||||
|
val compilationClass = compilation.javaClass
|
||||||
|
val getCompileKotlinTaskName = compilationClass.getMethodOrNull("getCompileKotlinTaskName") ?: return null
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val compileKotlinTaskName = (getCompileKotlinTaskName(compilation) as? String) ?: return null
|
||||||
|
return project.tasks.findByName(compileKotlinTaskName) ?: return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
apply from: "include.gradle"
|
||||||
|
def kotlinVersion = gradleKotlinPluginVersion('1.3.40-eap-67')
|
||||||
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin-multiplatform'
|
||||||
|
apply plugin: 'kotlin-kapt'
|
||||||
|
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url 'https://dl.bintray.com/kotlin/kotlin-dev' }
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm('jvm') { withJava() }
|
||||||
|
}
|
||||||
+40
-3
@@ -20,10 +20,15 @@ import com.intellij.openapi.diagnostic.Logger
|
|||||||
import com.intellij.openapi.externalSystem.model.DataNode
|
import com.intellij.openapi.externalSystem.model.DataNode
|
||||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||||
import com.intellij.openapi.externalSystem.model.project.*
|
import com.intellij.openapi.externalSystem.model.project.*
|
||||||
|
import org.gradle.api.Named
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
import org.gradle.tooling.model.idea.IdeaModule
|
import org.gradle.tooling.model.idea.IdeaModule
|
||||||
import org.jetbrains.kotlin.gradle.AbstractKotlinGradleModelBuilder
|
import org.jetbrains.kotlin.gradle.AbstractKotlinGradleModelBuilder
|
||||||
|
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder.Companion.getCompilations
|
||||||
|
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder.Companion.getCompileKotlinTaskName
|
||||||
|
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModelBuilder.Companion.getTargets
|
||||||
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
|
||||||
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
|
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
|
||||||
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
|
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
|
||||||
@@ -140,8 +145,12 @@ class KaptModelBuilderService : AbstractKotlinGradleModelBuilder() {
|
|||||||
val sourceSets = mutableListOf<KaptSourceSetModel>()
|
val sourceSets = mutableListOf<KaptSourceSetModel>()
|
||||||
|
|
||||||
if (kaptIsEnabled) {
|
if (kaptIsEnabled) {
|
||||||
project.getAllTasks(false)[project]?.forEach { compileTask ->
|
val targets = project.getTargets()
|
||||||
if (compileTask.javaClass.name !in kotlinCompileJvmTaskClasses) return@forEach
|
|
||||||
|
fun handleCompileTask(moduleName: String, compileTask: Task) {
|
||||||
|
if (compileTask.javaClass.name !in kotlinCompileJvmTaskClasses) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val sourceSetName = compileTask.getSourceSetName()
|
val sourceSetName = compileTask.getSourceSetName()
|
||||||
val isTest = sourceSetName.toLowerCase().endsWith("test")
|
val isTest = sourceSetName.toLowerCase().endsWith("test")
|
||||||
@@ -150,13 +159,41 @@ class KaptModelBuilderService : AbstractKotlinGradleModelBuilder() {
|
|||||||
val kaptGeneratedClassesDir = getKaptDirectory("getKaptGeneratedClassesDir", project, sourceSetName)
|
val kaptGeneratedClassesDir = getKaptDirectory("getKaptGeneratedClassesDir", project, sourceSetName)
|
||||||
val kaptGeneratedKotlinSourcesDir = getKaptDirectory("getKaptGeneratedKotlinSourcesDir", project, sourceSetName)
|
val kaptGeneratedKotlinSourcesDir = getKaptDirectory("getKaptGeneratedKotlinSourcesDir", project, sourceSetName)
|
||||||
sourceSets += KaptSourceSetModelImpl(
|
sourceSets += KaptSourceSetModelImpl(
|
||||||
sourceSetName, isTest, kaptGeneratedSourcesDir, kaptGeneratedClassesDir, kaptGeneratedKotlinSourcesDir)
|
moduleName, isTest, kaptGeneratedSourcesDir, kaptGeneratedClassesDir, kaptGeneratedKotlinSourcesDir
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targets != null && targets.isNotEmpty()) {
|
||||||
|
for (target in targets) {
|
||||||
|
if (!isWithJavaEnabled(target)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val compilations = getCompilations(target) ?: continue
|
||||||
|
for (compilation in compilations) {
|
||||||
|
val compileTask = getCompileKotlinTaskName(project, compilation) ?: continue
|
||||||
|
val moduleName = target.name + compilation.name.capitalize()
|
||||||
|
handleCompileTask(moduleName, compileTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
project.getAllTasks(false)[project]?.forEach { compileTask ->
|
||||||
|
val sourceSetName = compileTask.getSourceSetName()
|
||||||
|
handleCompileTask(sourceSetName, compileTask)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return KaptGradleModelImpl(kaptIsEnabled, project.buildDir, sourceSets)
|
return KaptGradleModelImpl(kaptIsEnabled, project.buildDir, sourceSets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isWithJavaEnabled(target: Named): Boolean {
|
||||||
|
val getWithJavaEnabledMethod = target.javaClass.methods
|
||||||
|
.firstOrNull { it.name == "getWithJavaEnabled" && it.parameterCount == 0 } ?: return false
|
||||||
|
|
||||||
|
return getWithJavaEnabledMethod.invoke(target) == true
|
||||||
|
}
|
||||||
|
|
||||||
private fun getKaptDirectory(funName: String, project: Project, sourceSetName: String): String {
|
private fun getKaptDirectory(funName: String, project: Project, sourceSetName: String): String {
|
||||||
val kotlinKaptPlugin = project.plugins.findPlugin("kotlin-kapt") ?: return ""
|
val kotlinKaptPlugin = project.plugins.findPlugin("kotlin-kapt") ?: return ""
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user