*.gradle.kts: get java home from build environment instead of execution settings

Note that getting GradleExecutionSettings may lead to write action
because it link javaHome with existing sdks

^KT-39317
This commit is contained in:
Natalia Selezneva
2020-06-29 22:37:52 +03:00
parent 5cdf053c8e
commit c7c7ffb0e0
9 changed files with 88 additions and 36 deletions
@@ -46,7 +46,7 @@ import kotlin.script.templates.standard.ScriptTemplateWithArgs
class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionSourceAsContributor { class GradleScriptDefinitionsContributor(private val project: Project) : ScriptDefinitionSourceAsContributor {
companion object { companion object {
fun getDefinitions(project: Project, workingDir: String, gradleHome: String?): List<ScriptDefinition>? { fun getDefinitions(project: Project, workingDir: String, gradleHome: String?, javaHome: String?): List<ScriptDefinition>? {
val contributor = ScriptDefinitionContributor.EP_NAME.getExtensions(project) val contributor = ScriptDefinitionContributor.EP_NAME.getExtensions(project)
.filterIsInstance<GradleScriptDefinitionsContributor>() .filterIsInstance<GradleScriptDefinitionsContributor>()
.singleOrNull() .singleOrNull()
@@ -63,7 +63,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
return null return null
} }
val root = LightGradleBuildRoot(workingDir, gradleHome) val root = LightGradleBuildRoot(workingDir, gradleHome, javaHome)
val definitions = contributor.definitionsByRoots[root] val definitions = contributor.definitionsByRoots[root]
if (definitions == null) { if (definitions == null) {
scriptingInfoLog( scriptingInfoLog(
@@ -128,7 +128,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
override val id: String = "Gradle Kotlin DSL" override val id: String = "Gradle Kotlin DSL"
private data class LightGradleBuildRoot(val workingDir: String, val gradleHome: String?) private data class LightGradleBuildRoot(val workingDir: String, val gradleHome: String?, val javaHome: String?)
private val definitionsByRoots = ConcurrentHashMap<LightGradleBuildRoot, List<ScriptDefinition>>() private val definitionsByRoots = ConcurrentHashMap<LightGradleBuildRoot, List<ScriptDefinition>>()
@@ -148,8 +148,8 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
} }
// TODO: remove old roots // TODO: remove old roots
fun reloadIfNeeded(workingDir: String, gradleHome: String?) { fun reloadIfNeeded(workingDir: String, gradleHome: String?, javaHome: String?) {
val root = LightGradleBuildRoot(workingDir, gradleHome) val root = LightGradleBuildRoot(workingDir, gradleHome, javaHome)
val value = definitionsByRoots[root] val value = definitionsByRoots[root]
if (value != null) { if (value != null) {
if (root.isError()) { if (root.isError()) {
@@ -177,15 +177,17 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
loadGradleTemplates( loadGradleTemplates(
projectPath, projectPath,
templateClass = "org.gradle.kotlin.dsl.KotlinInitScript", templateClass = "org.gradle.kotlin.dsl.KotlinInitScript",
root.gradleHome, gradleHome = root.gradleHome,
templateClasspath, javaHome = root.javaHome,
additionalClassPath templateClasspath = templateClasspath,
additionalClassPath = additionalClassPath
).let { kotlinDslTemplates.addAll(it) } ).let { kotlinDslTemplates.addAll(it) }
loadGradleTemplates( loadGradleTemplates(
projectPath, projectPath,
templateClass = "org.gradle.kotlin.dsl.KotlinSettingsScript", templateClass = "org.gradle.kotlin.dsl.KotlinSettingsScript",
gradleHome = root.gradleHome, gradleHome = root.gradleHome,
javaHome = root.javaHome,
templateClasspath = templateClasspath, templateClasspath = templateClasspath,
additionalClassPath = additionalClassPath additionalClassPath = additionalClassPath
).let { kotlinDslTemplates.addAll(it) } ).let { kotlinDslTemplates.addAll(it) }
@@ -195,6 +197,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
projectPath, projectPath,
templateClass = "org.gradle.kotlin.dsl.KotlinBuildScript", templateClass = "org.gradle.kotlin.dsl.KotlinBuildScript",
gradleHome = root.gradleHome, gradleHome = root.gradleHome,
javaHome = root.javaHome,
templateClasspath = templateClasspath, templateClasspath = templateClasspath,
additionalClassPath = additionalClassPath additionalClassPath = additionalClassPath
).let { kotlinDslTemplates.addAll(it) } ).let { kotlinDslTemplates.addAll(it) }
@@ -223,6 +226,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
projectPath: String, projectPath: String,
templateClass: String, templateClass: String,
gradleHome: String?, gradleHome: String?,
javaHome: String?,
templateClasspath: List<File>, templateClasspath: List<File>,
additionalClassPath: List<File> additionalClassPath: List<File>
): List<ScriptDefinition> { ): List<ScriptDefinition> {
@@ -231,7 +235,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
projectPath, projectPath,
GradleConstants.SYSTEM_ID GradleConstants.SYSTEM_ID
) )
val hostConfiguration = createHostConfiguration(projectPath, gradleHome, gradleExeSettings) val hostConfiguration = createHostConfiguration(projectPath, gradleHome, javaHome, gradleExeSettings)
return loadDefinitionsFromTemplates( return loadDefinitionsFromTemplates(
listOf(templateClass), listOf(templateClass),
templateClasspath, templateClasspath,
@@ -253,6 +257,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
private fun createHostConfiguration( private fun createHostConfiguration(
projectPath: String, projectPath: String,
gradleHome: String?, gradleHome: String?,
javaHome: String?,
gradleExeSettings: GradleExecutionSettings gradleExeSettings: GradleExecutionSettings
): ScriptingHostConfiguration { ): ScriptingHostConfiguration {
val gradleJvmOptions = gradleExeSettings.daemonVmOptions?.let { vmOptions -> val gradleJvmOptions = gradleExeSettings.daemonVmOptions?.let { vmOptions ->
@@ -264,7 +269,7 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
val environment = mapOf( val environment = mapOf(
"gradleHome" to gradleHome?.let(::File), "gradleHome" to gradleHome?.let(::File),
"gradleJavaHome" to gradleExeSettings.javaHome, // TODO: should be taken from information from gradle sync "gradleJavaHome" to javaHome,
"projectRoot" to projectPath.let(::File), "projectRoot" to projectPath.let(::File),
@@ -317,19 +322,20 @@ class GradleScriptDefinitionsContributor(private val project: Project) : ScriptD
// otherwise KotlinDslSyncListener should run reloadIfNeeded for valid roots // otherwise KotlinDslSyncListener should run reloadIfNeeded for valid roots
GradleBuildRootsManager.getInstance(project).getAllRoots().forEach { GradleBuildRootsManager.getInstance(project).getAllRoots().forEach {
val workingDir = it.pathPrefix val workingDir = it.pathPrefix
val gradleHome = when (it) { val (gradleHome, javaHome) = when (it) {
is Imported -> { is Imported -> {
it.data.gradleHome it.data.gradleHome to it.data.javaHome
} }
is WithoutScriptModels -> { is WithoutScriptModels -> {
ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>( val settings = ExternalSystemApiUtil.getExecutionSettings<GradleExecutionSettings>(
project, project,
workingDir, workingDir,
GradleConstants.SYSTEM_ID GradleConstants.SYSTEM_ID
).gradleHome )
settings.gradleHome to settings.javaHome
} }
} }
val root = LightGradleBuildRoot(workingDir, gradleHome) val root = LightGradleBuildRoot(workingDir, gradleHome, javaHome)
definitionsByRoots[root] = loadGradleDefinitions(root) definitionsByRoots[root] = loadGradleDefinitions(root)
} }
} }
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.KotlinIdeaGradleBundle
import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp import org.jetbrains.kotlin.idea.scripting.gradle.getGradleScriptInputsStamp
import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager
import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel
import org.jetbrains.plugins.gradle.service.project.DefaultProjectResolverContext
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext
import java.io.File import java.io.File
@@ -28,6 +29,10 @@ fun saveGradleBuildEnvironment(resolverCtx: ProjectResolverContext) {
?: resolverCtx.settings?.gradleHome ?: resolverCtx.settings?.gradleHome
synchronized(sync) { synchronized(sync) {
sync.gradleVersion = resolverCtx.projectGradleVersion sync.gradleVersion = resolverCtx.projectGradleVersion
sync.javaHome = (resolverCtx as? DefaultProjectResolverContext)
?.buildEnvironment
?.java?.javaHome?.canonicalPath
?.let { toSystemIndependentName(it) }
if (gradleHome != null) { if (gradleHome != null) {
sync.gradleHome = toSystemIndependentName(gradleHome) sync.gradleHome = toSystemIndependentName(gradleHome)
@@ -125,6 +130,7 @@ class KotlinDslGradleBuildSync(val workingDir: String, val taskId: ExternalSyste
var project: Project? = null var project: Project? = null
var gradleVersion: String? = null var gradleVersion: String? = null
var gradleHome: String? = null var gradleHome: String? = null
var javaHome: String? = null
val projectRoots = mutableSetOf<String>() val projectRoots = mutableSetOf<String>()
val models = mutableListOf<KotlinDslScriptModel>() val models = mutableListOf<KotlinDslScriptModel>()
var failed = false var failed = false
@@ -10,11 +10,15 @@ import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor import org.jetbrains.kotlin.idea.core.script.ScriptDefinitionContributor
import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID
import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor import org.jetbrains.kotlin.idea.scripting.gradle.GradleScriptDefinitionsContributor
import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager import org.jetbrains.kotlin.idea.scripting.gradle.roots.GradleBuildRootsManager
import org.jetbrains.plugins.gradle.service.GradleInstallationManager import org.jetbrains.plugins.gradle.service.GradleInstallationManager
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.io.File
import java.util.* import java.util.*
class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() { class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
@@ -54,8 +58,16 @@ class KotlinDslSyncListener : ExternalSystemTaskNotificationListenerAdapter() {
?.canonicalPath ?.canonicalPath
} }
if (sync.javaHome == null) {
sync.javaHome = ExternalSystemApiUtil
.getExecutionSettings<GradleExecutionSettings>(project, sync.workingDir, GradleConstants.SYSTEM_ID)
.javaHome
}
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
ScriptDefinitionContributor.find<GradleScriptDefinitionsContributor>(project)?.reloadIfNeeded(sync.workingDir, sync.gradleHome) ScriptDefinitionContributor.find<GradleScriptDefinitionsContributor>(project)?.reloadIfNeeded(
sync.workingDir, sync.gradleHome, sync.javaHome
)
saveScriptModels(project, sync) saveScriptModels(project, sync)
} }
@@ -88,19 +88,20 @@ class New(
*/ */
class Imported( class Imported(
override val pathPrefix: String, override val pathPrefix: String,
val javaHome: File?,
val data: GradleBuildRootData, val data: GradleBuildRootData,
lastModifiedFiles: LastModifiedFiles lastModifiedFiles: LastModifiedFiles
) : GradleBuildRoot(lastModifiedFiles) { ) : GradleBuildRoot(lastModifiedFiles) {
override val projectRoots: Collection<String> override val projectRoots: Collection<String>
get() = data.projectRoots get() = data.projectRoots
val javaHome = data.javaHome?.takeIf { it.isNotBlank() }?.let { File(it) }
fun collectConfigurations(builder: ScriptClassRootsBuilder) { fun collectConfigurations(builder: ScriptClassRootsBuilder) {
if (javaHome != null) { if (javaHome != null) {
builder.sdks.addSdk(javaHome) builder.sdks.addSdk(javaHome)
} }
val definitions = GradleScriptDefinitionsContributor.getDefinitions(builder.project, pathPrefix, data.gradleHome) val definitions = GradleScriptDefinitionsContributor.getDefinitions(builder.project, pathPrefix, data.gradleHome, data.javaHome)
if (definitions == null) { if (definitions == null) {
// needed to recreate classRoots if correct script definitions weren't loaded at this moment // needed to recreate classRoots if correct script definitions weren't loaded at this moment
// in this case classRoots will be recreated after script definitions update // in this case classRoots will be recreated after script definitions update
@@ -11,5 +11,6 @@ data class GradleBuildRootData(
val importTs: Long, val importTs: Long,
val projectRoots: Collection<String>, val projectRoots: Collection<String>,
val gradleHome: String, val gradleHome: String,
val javaHome: String?,
val models: Collection<KotlinDslScriptModel> val models: Collection<KotlinDslScriptModel>
) )
@@ -19,7 +19,7 @@ import java.io.DataInputStream
import java.io.DataOutput import java.io.DataOutput
internal object GradleBuildRootDataSerializer { internal object GradleBuildRootDataSerializer {
private val attribute = FileAttribute("kotlin-dsl-script-models", 7, false) private val attribute = FileAttribute("kotlin-dsl-script-models", 8, false)
fun read(buildRoot: VirtualFile): GradleBuildRootData? { fun read(buildRoot: VirtualFile): GradleBuildRootData? {
return attribute.readAttribute(buildRoot)?.use { return attribute.readAttribute(buildRoot)?.use {
@@ -47,6 +47,7 @@ internal fun writeKotlinDslScriptModels(output: DataOutput, data: GradleBuildRoo
val strings = StringsPool.writer(output) val strings = StringsPool.writer(output)
strings.addStrings(data.projectRoots) strings.addStrings(data.projectRoots)
strings.addString(data.gradleHome) strings.addString(data.gradleHome)
strings.addString(data.javaHome)
data.models.forEach { data.models.forEach {
strings.addString(it.file) strings.addString(it.file)
strings.addStrings(it.classPath) strings.addStrings(it.classPath)
@@ -57,6 +58,7 @@ internal fun writeKotlinDslScriptModels(output: DataOutput, data: GradleBuildRoo
output.writeLong(data.importTs) output.writeLong(data.importTs)
strings.writeStringIds(data.projectRoots) strings.writeStringIds(data.projectRoots)
strings.writeStringId(data.gradleHome) strings.writeStringId(data.gradleHome)
strings.writeStringId(data.javaHome)
output.writeList(data.models) { output.writeList(data.models) {
strings.writeStringId(it.file) strings.writeStringId(it.file)
output.writeString(it.inputs.sections) output.writeString(it.inputs.sections)
@@ -73,6 +75,7 @@ internal fun readKotlinDslScriptModels(input: DataInputStream, buildRoot: String
val importTs = input.readLong() val importTs = input.readLong()
val projectRoots = strings.readStrings() val projectRoots = strings.readStrings()
val gradleHome = strings.readString() val gradleHome = strings.readString()
val javaHome = strings.readNullableString()
val models = input.readList { val models = input.readList {
KotlinDslScriptModel( KotlinDslScriptModel(
strings.readString(), strings.readString(),
@@ -84,7 +87,7 @@ internal fun readKotlinDslScriptModels(input: DataInputStream, buildRoot: String
) )
} }
return GradleBuildRootData(importTs, projectRoots, gradleHome, models) return GradleBuildRootData(importTs, projectRoots, gradleHome, javaHome, models)
} }
private object StringsPool { private object StringsPool {
@@ -99,8 +102,8 @@ private object StringsPool {
ids.size ids.size
} }
fun addString(string: String) { fun addString(string: String?) {
getStringId(string) getStringId(string ?: "null")
} }
fun addStrings(list: Collection<String>) { fun addStrings(list: Collection<String>) {
@@ -119,8 +122,8 @@ private object StringsPool {
} }
} }
fun writeStringId(it: String) { fun writeStringId(it: String?) {
output.writeInt(getStringId(it)) output.writeInt(getStringId(it ?: "null"))
} }
fun writeStringIds(strings: Collection<String>) { fun writeStringIds(strings: Collection<String>) {
@@ -140,6 +143,11 @@ private object StringsPool {
fun getString(id: Int) = strings[id] fun getString(id: Int) = strings[id]
fun readString() = getString(input.readInt()) fun readString() = getString(input.readInt())
fun readNullableString(): String? {
val string = getString(input.readInt())
if (string == "null") return null
return string
}
fun readStrings(): List<String> = input.readList { readString() } fun readStrings(): List<String> = input.readList { readString() }
} }
@@ -161,7 +161,10 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
return return
} }
val newData = GradleBuildRootData(sync.ts, sync.projectRoots, gradleHome, sync.models)
val newData = GradleBuildRootData(
sync.ts, sync.projectRoots, gradleHome, sync.javaHome, sync.models
)
val mergedData = if (sync.failed && oldRoot is Imported) merge(oldRoot.data, newData) else newData val mergedData = if (sync.failed && oldRoot is Imported) merge(oldRoot.data, newData) else newData
val lastModifiedFilesReset = LastModifiedFiles() val lastModifiedFilesReset = LastModifiedFiles()
@@ -183,7 +186,7 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
val models = old.models.associateByTo(mutableMapOf()) { it.file } val models = old.models.associateByTo(mutableMapOf()) { it.file }
new.models.associateByTo(models) { it.file } new.models.associateByTo(models) { it.file }
return GradleBuildRootData(new.importTs, roots, new.gradleHome, models.values) return GradleBuildRootData(new.importTs, roots, new.gradleHome, new.javaHome, models.values)
} }
private val modifiedFilesCheckScheduled = AtomicBoolean() private val modifiedFilesCheckScheduled = AtomicBoolean()
@@ -345,12 +348,8 @@ class GradleBuildRootsManager(val project: Project) : GradleBuildRootsLocator(),
): Imported? { ): Imported? {
val buildRoot = VfsUtil.findFile(Paths.get(externalProjectPath), true) ?: return null val buildRoot = VfsUtil.findFile(Paths.get(externalProjectPath), true) ?: return null
val data = dataProvider(buildRoot) ?: return null val data = dataProvider(buildRoot) ?: return null
// TODO: can be outdated, should be taken from sync
val javaHome = ExternalSystemApiUtil
.getExecutionSettings<GradleExecutionSettings>(project, externalProjectPath, GradleConstants.SYSTEM_ID)
.javaHome?.let { File(it) }
return Imported(externalProjectPath, javaHome, data, lastModifiedFiles) return Imported(externalProjectPath, data, lastModifiedFiles)
} }
private fun add(newRoot: GradleBuildRoot) { private fun add(newRoot: GradleBuildRoot) {
@@ -22,10 +22,11 @@ class GradleBuildRootDataSerializerTest {
val data = GradleBuildRootData( val data = GradleBuildRootData(
123, 123,
listOf("a", "b", "c"), listOf("a", "b", "c"),
"a", "gradleHome",
"javaHome",
listOf( listOf(
KotlinDslScriptModel( KotlinDslScriptModel(
"a", "gradleHome",
GradleKotlinScriptConfigurationInputs("b", 1, "a"), GradleKotlinScriptConfigurationInputs("b", 1, "a"),
listOf("c", "a", "b"), listOf("c", "a", "b"),
listOf("b", "c", "a"), listOf("b", "c", "a"),
@@ -33,7 +34,7 @@ class GradleBuildRootDataSerializerTest {
listOf() listOf()
), ),
KotlinDslScriptModel( KotlinDslScriptModel(
"a", "gradleHome",
GradleKotlinScriptConfigurationInputs("b", 1, "a"), GradleKotlinScriptConfigurationInputs("b", 1, "a"),
listOf("c", "a", "b"), listOf("c", "a", "b"),
listOf("b", "c", "a"), listOf("b", "c", "a"),
@@ -50,4 +51,22 @@ class GradleBuildRootDataSerializerTest {
assertEquals(data.toString(), restored.toString()) assertEquals(data.toString(), restored.toString())
} }
@Test
fun writeNullable() {
val data = GradleBuildRootData(
0,
listOf(),
"null",
null,
listOf()
)
val buffer = ByteArrayOutputStream()
writeKotlinDslScriptModels(DataOutputStream(buffer), data)
val restored = readKotlinDslScriptModels(DataInputStream(ByteArrayInputStream(buffer.toByteArray())), "a")
assertEquals(data.toString(), restored.toString())
}
} }
@@ -35,11 +35,11 @@ open class AbstractGradleBuildRootsLocatorTest {
val pathPrefix = "$dir/" val pathPrefix = "$dir/"
val root = Imported( val root = Imported(
dir, dir,
null,
GradleBuildRootData( GradleBuildRootData(
ts, ts,
relativeProjectRoots.map { (pathPrefix + it).removeSuffix("/") }, relativeProjectRoots.map { (pathPrefix + it).removeSuffix("/") },
"", "gradleHome",
"javaHome",
listOf() listOf()
), ),
LastModifiedFiles() LastModifiedFiles()