Import package prefix from gradle

#KT-19693 Fixed
This commit is contained in:
Andrey Uskov
2019-07-02 22:06:44 +03:00
parent dbec626a49
commit 2b6f566d58
3 changed files with 124 additions and 6 deletions
@@ -19,10 +19,7 @@ package org.jetbrains.kotlin.idea.configuration
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.ExternalSystemSourceType
import com.intellij.openapi.externalSystem.model.project.ModuleData
import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData
import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.model.project.*
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.util.Key
@@ -43,6 +40,7 @@ import org.jetbrains.plugins.gradle.model.FileCollectionDependency
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolver
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil
import java.io.File
import java.util.*
import kotlin.collections.HashMap
@@ -66,6 +64,8 @@ var DataNode<out ModuleData>.dependenciesCache
by DataNodeUserDataProperty(
Key.create<MutableMap<DataNode<ProjectData>, Collection<DataNode<out ModuleData>>>>("MODULE_DEPENDENCIES_CACHE")
)
var DataNode<out ContentRootData>.isPureKotlinSourceFolder
by NotNullableCopyableDataNodeUserDataProperty(Key.create<Boolean>("PURE_KOTLIN_SOURCE_FOLDER"), false)
class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() {
@@ -282,4 +282,35 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
@Suppress("UNCHECKED_CAST")
return ideProject.children.find { (it.data as? ModuleData)?.id == fullModuleId } as DataNode<ModuleData>?
}
override fun populateModuleContentRoots(gradleModule: IdeaModule, ideModule: DataNode<ModuleData>) {
nextResolver.populateModuleContentRoots(gradleModule, ideModule)
val moduleNamePrefix = GradleProjectResolverUtil.getModuleId(resolverCtx, gradleModule)
resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java)?.let { gradleModel ->
val gradleSourceSets = ideModule.children.filter { it.data is GradleSourceSetData } as Collection<DataNode<GradleSourceSetData>>
for (gradleSourceSetNode in gradleSourceSets) {
val propertiesForSourceSet =
gradleModel.kotlinTaskProperties.filter { (k, v) -> gradleSourceSetNode.data.externalName == "$moduleNamePrefix:$k" }
.toList().singleOrNull()
gradleSourceSetNode.children.forEach { dataNode ->
val data = dataNode.data as? ContentRootData
if (data != null) {
if (propertiesForSourceSet?.second?.pureKotlinSourceFolders?.contains(File(data.rootPath)) == true) {
@Suppress("UNCHECKED_CAST")
(dataNode as DataNode<ContentRootData>).isPureKotlinSourceFolder = true
}
val packagePrefix = propertiesForSourceSet?.second?.packagePrefix
if (packagePrefix != null) {
ExternalSystemSourceType.values().filter { !(it.isResource || it.isGenerated) }.forEach { type ->
val paths = data.getPaths(type)
val newPaths = paths.map { ContentRootData.SourceRoot(it.path, packagePrefix) }
paths.clear()
paths.addAll(newPaths)
}
}
}
}
}
}
}
}
@@ -65,6 +65,7 @@ interface KotlinGradleModel : Serializable {
val platformPluginId: String?
val implements: List<String>
val kotlinTarget: String?
val kotlinTaskProperties: KotlinTaskPropertiesBySourceSet
}
data class KotlinGradleModelImpl(
@@ -73,7 +74,8 @@ data class KotlinGradleModelImpl(
override val coroutines: String?,
override val platformPluginId: String?,
override val implements: List<String>,
override val kotlinTarget: String? = null
override val kotlinTarget: String? = null,
override val kotlinTaskProperties: KotlinTaskPropertiesBySourceSet
) : KotlinGradleModel
abstract class AbstractKotlinGradleModelBuilder : ModelBuilderService {
@@ -97,6 +99,9 @@ abstract class AbstractKotlinGradleModelBuilder : ModelBuilderService {
val kotlinPluginIds = listOf("kotlin", "kotlin2js", "kotlin-android")
val ABSTRACT_KOTLIN_COMPILE_CLASS = "org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile"
val kotlinProjectExtensionClass = "org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension"
val kotlinSourceSetClass = "org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet"
fun Task.getSourceSetName(): String {
return try {
javaClass.methods.firstOrNull { it.name.startsWith("getSourceSetName") && it.parameterTypes.isEmpty() }?.invoke(this) as? String
@@ -172,6 +177,7 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
val platformPluginId = platformPluginIds.singleOrNull { project.plugins.findPlugin(it) != null }
val compilerArgumentsBySourceSet = LinkedHashMap<String, ArgsInfo>()
val extraProperties = HashMap<String, KotlinTaskProperties>()
project.getAllTasks(false)[project]?.forEach { compileTask ->
if (compileTask.javaClass.name !in kotlinCompileTaskClasses) return@forEach
@@ -182,6 +188,7 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
val defaultArguments = compileTask.getCompilerArguments("getDefaultSerializedCompilerArguments").orEmpty()
val dependencyClasspath = compileTask.getDependencyClasspath()
compilerArgumentsBySourceSet[sourceSetName] = ArgsInfoImpl(currentArguments, defaultArguments, dependencyClasspath)
extraProperties.acknowledgeTask(compileTask)
}
val platform = platformPluginId ?: pluginToPlatform.entries.singleOrNull { project.plugins.findPlugin(it.key) != null }?.value
@@ -193,7 +200,8 @@ class KotlinGradleModelBuilder : AbstractKotlinGradleModelBuilder() {
getCoroutines(project),
platform,
implementedProjects.map { it.pathOrName() },
platform ?: kotlinPluginId
platform ?: kotlinPluginId,
extraProperties
)
}
}
@@ -0,0 +1,79 @@
/*
* 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 org.gradle.api.Task
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.internal.FactoryNamedDomainObjectContainer
import org.gradle.api.plugins.JavaPluginConvention
import org.jetbrains.kotlin.gradle.AbstractKotlinGradleModelBuilder.Companion.getSourceSetName
import org.jetbrains.kotlin.gradle.AbstractKotlinGradleModelBuilder.Companion.kotlinProjectExtensionClass
import org.jetbrains.kotlin.gradle.AbstractKotlinGradleModelBuilder.Companion.kotlinSourceSetClass
import java.io.File
import java.io.Serializable
import java.lang.Exception
interface KotlinTaskProperties : Serializable {
val incremental: Boolean?
val packagePrefix: String?
val pureKotlinSourceFolders: List<File>?
}
data class KotlinTaskPropertiesImpl(
override val incremental: Boolean?,
override val packagePrefix: String?,
override val pureKotlinSourceFolders: List<File>?
) : KotlinTaskProperties
typealias KotlinTaskPropertiesBySourceSet = MutableMap<String, KotlinTaskProperties>
private fun Task.getPackagePrefix(): String? {
try {
val getJavaPackagePrefix = this.javaClass.getMethod("getJavaPackagePrefix")
@Suppress("UNCHECKED_CAST")
return (getJavaPackagePrefix.invoke(this) as? String)
} catch (e: Exception) {
}
return null
}
private fun Task.getIsIncremental(): Boolean? {
try {
val abstractKotlinCompileClass = javaClass.classLoader.loadClass(AbstractKotlinGradleModelBuilder.ABSTRACT_KOTLIN_COMPILE_CLASS)
val getIncremental = abstractKotlinCompileClass.getDeclaredMethod("getIncremental")
@Suppress("UNCHECKED_CAST")
return (getIncremental.invoke(this) as? Boolean)
} catch (e: Exception) {
}
return null
}
private fun Task.getPureKotlinSourceRoots(sourceSet: String): List<File>? {
try {
val kotlinExtensionClass = project.extensions.findByType(javaClass.classLoader.loadClass(kotlinProjectExtensionClass))
val getKotlinMethod = javaClass.classLoader.loadClass(kotlinSourceSetClass).getMethod("getKotlin")
val kotlinSourceSet = (kotlinExtensionClass?.javaClass?.getMethod("getSourceSets")?.invoke(kotlinExtensionClass)
as? FactoryNamedDomainObjectContainer<Any>)?.asMap?.get(sourceSet) ?: return null
val javaSourceSet =
(project.convention.getPlugin(JavaPluginConvention::class.java) as JavaPluginConvention).sourceSets.asMap[sourceSet]
val pureJava = javaSourceSet?.java?.srcDirs
return (getKotlinMethod.invoke(kotlinSourceSet) as? SourceDirectorySet)?.srcDirs?.filter {
!(pureJava?.contains(it) ?: false)
}?.toList()
} catch (e: Exception) {
}
return null
}
fun KotlinTaskPropertiesBySourceSet.acknowledgeTask(compileTask: Task) {
this[compileTask.getSourceSetName()] =
KotlinTaskPropertiesImpl(
compileTask.getIsIncremental(),
compileTask.getPackagePrefix(),
compileTask.getPureKotlinSourceRoots(compileTask.getSourceSetName())
)
}