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? {
|
||||
val targetClass = gradleTarget.javaClass
|
||||
val getPlatformType = targetClass.getMethodOrNull("getPlatformType") ?: return null
|
||||
val getCompilations = targetClass.getMethodOrNull("getCompilations") ?: return null
|
||||
val getDisambiguationClassifier = targetClass.getMethodOrNull("getDisambiguationClassifier") ?: return null
|
||||
val platformId = (getPlatformType.invoke(gradleTarget) as? Named)?.name ?: return null
|
||||
val platform = KotlinPlatform.byId(platformId) ?: return null
|
||||
@@ -189,9 +188,8 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
} catch (e: Throwable) {
|
||||
"${e::class.java.name}:${e.message}"
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val gradleCompilations =
|
||||
(getCompilations.invoke(gradleTarget) as? NamedDomainObjectContainer<Named>)?.asMap?.values ?: emptyList<Named>()
|
||||
|
||||
val gradleCompilations = getCompilations(gradleTarget) ?: return null
|
||||
val compilations = gradleCompilations.mapNotNull {
|
||||
buildCompilation(it, disambiguationClassifier, sourceSetMap, dependencyResolver, project)
|
||||
}
|
||||
@@ -227,10 +225,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val kotlinGradleSourceSets = (getKotlinSourceSets(gradleCompilation) as? Collection<Named>) ?: return null
|
||||
val kotlinSourceSets = kotlinGradleSourceSets.mapNotNull { sourceSetMap[it.name] }
|
||||
val getCompileKotlinTaskName = compilationClass.getMethodOrNull("getCompileKotlinTaskName") ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val compileKotlinTaskName = (getCompileKotlinTaskName(gradleCompilation) as? String) ?: return null
|
||||
val compileKotlinTask = project.tasks.findByName(compileKotlinTaskName) ?: return null
|
||||
val compileKotlinTask = getCompileKotlinTaskName(project, gradleCompilation) ?: return null
|
||||
val output = buildCompilationOutput(gradleCompilation, compileKotlinTask) ?: return null
|
||||
val arguments = buildCompilationArguments(compileKotlinTask) ?: return null
|
||||
val dependencyClasspath = buildDependencyClasspath(compileKotlinTask)
|
||||
@@ -547,6 +542,20 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
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.ProjectKeys
|
||||
import com.intellij.openapi.externalSystem.model.project.*
|
||||
import org.gradle.api.Named
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.tooling.model.idea.IdeaModule
|
||||
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.plugins.gradle.model.data.GradleSourceSetData
|
||||
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
|
||||
@@ -140,8 +145,12 @@ class KaptModelBuilderService : AbstractKotlinGradleModelBuilder() {
|
||||
val sourceSets = mutableListOf<KaptSourceSetModel>()
|
||||
|
||||
if (kaptIsEnabled) {
|
||||
project.getAllTasks(false)[project]?.forEach { compileTask ->
|
||||
if (compileTask.javaClass.name !in kotlinCompileJvmTaskClasses) return@forEach
|
||||
val targets = project.getTargets()
|
||||
|
||||
fun handleCompileTask(moduleName: String, compileTask: Task) {
|
||||
if (compileTask.javaClass.name !in kotlinCompileJvmTaskClasses) {
|
||||
return
|
||||
}
|
||||
|
||||
val sourceSetName = compileTask.getSourceSetName()
|
||||
val isTest = sourceSetName.toLowerCase().endsWith("test")
|
||||
@@ -150,13 +159,41 @@ class KaptModelBuilderService : AbstractKotlinGradleModelBuilder() {
|
||||
val kaptGeneratedClassesDir = getKaptDirectory("getKaptGeneratedClassesDir", project, sourceSetName)
|
||||
val kaptGeneratedKotlinSourcesDir = getKaptDirectory("getKaptGeneratedKotlinSourcesDir", project, sourceSetName)
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
val kotlinKaptPlugin = project.plugins.findPlugin("kotlin-kapt") ?: return ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user